// session.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const util = require('util'); const passport = require('passport'); const { SiteError, SiteService } = require('../../lib/site-lib'); class SessionService extends SiteService { constructor (dtp) { super(dtp, module.exports); } async start ( ) { await super.start(); this.log.info(`starting ${module.exports.name} service`); passport.serializeUser(this.serializeUser.bind(this)); passport.deserializeUser(this.deserializeUser.bind(this)); } async stop ( ) { this.log.info(`stopping ${module.exports.name} service`); await super.stop(); } middleware ( ) { return async (req, res, next) => { res.locals.util = util; res.locals.user = req.user; res.locals.query = req.query; res.locals.config = this.dtp.config; if (req.session) { res.locals.session = req.session; } return next(); }; } authCheckMiddleware (options) { options = Object.assign({ requireLogin: true, requireAdmin: false, useRedirect: true, loginUri: '/welcome/login', }, options); return async (req, res, next) => { if (options.requireLogin && !req.user) { if (options.useRedirect) { req.session.loginReturnTo = req.url; await this.saveSession(req); this.log.info('redirecting to login', { returnTo: req.url }); return res.redirect(options.loginUri); } return next(new SiteError(403, 'Must sign in to continue')); } if (options.requireAdmin && (!req.user || !req.user.flags.isAdmin)) { return next(new SiteError(403, 'Administrator privileges are required')); } return next(); }; } async serializeUser (user, done) { if (user.coreUserId) { return done(null, `core:${user._id}`); } return done(null, `local:${user._id}`); } async deserializeUser (userTag, done) { const { coreNode: coreNodeService, user: userService } = this.dtp.services; const [serviceName, userId] = userTag.split(':'); try { let user; switch (serviceName) { case 'core': user = await coreNodeService.getUserByLocalId(userId); user.type = 'CoreUser'; delete user.core.oauth; delete user.core.__v; delete user.__v; delete user.flags._id; delete user.permissions._id; delete user.stats._id; delete user.optIn._id; break; case 'local': user = await userService.getUserAccount(userId); user.type = 'User'; break; } return done(null, user); } catch (error) { this.log.error('failed to deserialize user from session', { error }); return done(null, null); } } } module.exports = { slug: 'session', name: 'session', create: (dtp) => { return new SessionService(dtp); }, };