/**
* @module flitter-auth/middleware/Utility
*/
const Middleware = require('libflitter/middleware/Middleware')
const helpers = require('../Helpers')
const SecurityContext = require('../SecurityContext')
/**
* This should be applied globally. Ensures basic things about the request
* are true. For example, it provides the auth session data and handles auth
* flow redirects.
* @extends module:libflitter/middleware/Middleware~Middleware
*/
class Utility extends Middleware {
/**
* Defines the services required by this unit.
* @returns {Array<string>}
*/
static get services() {
return [...super.services, 'models', 'output']
}
/**
* Applies the middleware. Creates an unauthenticated auth session if one doesn't already exist.
* If the user is authenticated, injects an instance of {module:flitter-auth/model/User~User} into
* the request as 'request.user'.
*
* Also instantiates a {@link module:flitter-auth/SecurityContext~SecurityContext} for the request
* and injects it as 'request.security'.
*
* If the session has a key_action_key property, the respective {@link module:flitter-auth/model/KeyAction~KeyAction}
* will be inserted into "request.key_action".
*
* @param {express/request} req - the request
* @param {express/response} res - the response
* @param {function} next - the next function in the stack
* @param {object} [args] - optional args
* @returns {Promise<void>}
*/
async test(req, res, next, args) {
// Guarantees that req.session.auth is available.
helpers.guarantee_auth_session(req)
req.is_auth = !!req.session.auth.user_id
// Inject the user object
if ( req.is_auth ) {
req.user = await this.models.get('auth:User').findById(req.session.auth.user_id)
if ( !req.user ) {
// If we have a user_id, but can't find a user in the database,
// something has gone horribly wrong. To prevent security flaws,
// reset the session to the logged-out state.
this.output.warn(`Authenticated session with invalid user_id: ${req.session.auth.user_id}. Kicking user.`)
delete req.user
req.session.auth.user_id = false
req.is_auth = false
}
}
// Create a security context for the request
const security = new SecurityContext(req, res)
req.security = security
if ( req.session.key_action_key ) {
const KeyAction = this.models.get('auth:KeyAction')
const ka = await KeyAction.findOne({key: req.session.key_action_key})
if ( ka ) {
req.key_action = ka
} else {
delete req.session.key_action_key
}
}
/*
* Call the next function in the stack.
*/
next()
}
}
module.exports = Utility