DTP Base provides a scalable and secure Node.js application development harness ready for production service.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 lines
2.9 KiB

// session.js
// Copyright (C) 2022,2023 DTP Technologies, LLC
// All Rights Reserved
'use strict';
import util from 'node:util';
import passport from 'passport';
import { SiteService, SiteError } from '../../lib/site-lib.js';
export default class SessionService extends SiteService {
static get slug () { return 'session'; }
static get name ( ) { return 'SessionService'; }
constructor (dtp) {
super(dtp, SessionService);
}
async start ( ) {
await super.start();
passport.serializeUser(this.serializeUser.bind(this));
passport.deserializeUser(this.deserializeUser.bind(this));
}
async stop ( ) {
this.log.info(`stopping ${SessionService.name} service`);
}
middleware ( ) {
return async (req, res, next) => {
res.locals.user = req.user;
res.locals.query = req.query;
if (req.user) {
if (req.user.flags.isAdmin) {
res.locals.config = this.dtp.config;
res.locals.session = req.session;
res.locals.util = util;
}
}
return next();
};
}
authCheckMiddleware (options) {
const { membership: membershipService } = this.dtp.services;
options = Object.assign({
requireLogin: true,
requireEmailVerified: false,
requireMembership: false,
requireModerator: false,
requireAdmin: false,
}, options);
return async (req, res, next) => {
if (options.requireLogin && !req.user) {
return next(new SiteError(403, 'Login required'));
}
if (options.requireEmailVerified && (!req.user || !req.user.flags.isEmailVerified)) {
return next(new SiteError(403, `Must verify your email address to continue. Please check your spam folder for a welcome email from ${this.dtp.config.site.name}`));
}
if (options.requireMembership) {
res.locals.membership = await membershipService.getForUser(req.user);
if (!res.locals.membership) {
return next(new SiteError(403, 'Membership required'));
}
}
if (options.requireModerator && (!req.user || !req.user.flags.isModerator)) {
return next(new SiteError(403, 'Platform moderator privileges are required'));
}
if (options.requireAdmin && (!req.user || !req.user.flags.isAdmin)) {
return next(new SiteError(403, 'Platform administrator privileges are required'));
}
return next();
};
}
async serializeUser (user, done) {
return done(null, user._id);
}
async deserializeUser (userId, done) {
const { user: userService } = this.dtp.services;
try {
const user = await userService.getUserAccount(userId);
if (user.permissions && !user.permissions.canLogin) {
return done(null, null); // destroys user session without error
}
return done(null, user);
} catch (error) {
this.log.error('failed to deserialize user from session', { error });
return done(null, null);
}
}
}