Skip to content
Snippets Groups Projects
AuthService.js 2.36 KiB
Newer Older
const ContextualModule = require('core/injection/ContextualModule')
const crypto = require('core/utils/crypto')
const HttpError = require('core/errors/HttpError')
const { User } = require('database/models')
Louis's avatar
Louis committed
const BEARER_PREFIX = 'Bearer '

module.exports = class AuthService extends ContextualModule {
	static getServiceName() {
		return 'authService'
	}

	constructor(ctx) {
		super(ctx);
		this._user = null
		this._stack = [] // TODO: Support user impersonation
	}

	async attemptLogin(email, password) {
		if (this._user) {
			if (this._user.email === email && await this._user.checkPassword(password)) {
				return this._user
			} else {
				throw new HttpError(401, 'Forbidden')
			}
		} else {
			const user = await this.ctx.services.userService.findByEmail(email)
			if (user) {
				if (await user.checkPassword(password)) {
					this.authenticateAs(user)
					return user
				} else {
					throw new HttpError(403, 'Huh')
				}
			} else {
				throw new HttpError(403, 'Wha')
			}
		}
	}

	async getUser() {
		if (this._user) {
			return this._user
		} else if (this.ctx.session && this.ctx.session.user) {
			try {
				const value = JSON.parse(await crypto.decrypt(this.ctx.session.user))
				const user = await this.ctx.services.userService.findUser(value.id)
				if (user) {
					this.authenticateAs(user)
					return user
				} else {
					return null
				}
			} catch(e) {
				console.error(e)
				this.clearSessionAuth()
				return null
			}
Louis's avatar
Louis committed
		} else if (this.ctx.get('Authorization')) {
			const token = this.ctx.get('Authorization').substr(BEARER_PREFIX.length)
Louis's avatar
Louis committed
			const user = await this.ctx.services.userService.findByAccessToken(token)
Louis's avatar
Louis committed
			if (user) {
				this.authenticateAs(user)
				return user
			}
		} else if (this.ctx.get('x-api-token')) {
			const token = this.ctx.get('x-api-token')
			let user = null
			try {
				user = await User.fromToken(token)
			} catch(e) {
				console.error(e)
			}
			if (user) {
				this.authenticateAs(user)
			}
			return user
Louis's avatar
Louis committed
		return null
	}

	authenticateAs(user) {
		this._user = user
	}

	async saveToSession(logoutIfEmpty = true) {
		const user = await this.getUser()
		if (user) {
			this.ctx.session.user = await crypto.encrypt(JSON.stringify({ id: user.id }))
		} else if (logoutIfEmpty) {
			this.ctx.session.user = null
		}
	}

	async clearSessionAuth() {
		this.ctx.session.token = null
	}
}