import { getReasonPhrase, StatusCodes } from 'http-status-codes'; import * as jwt from 'jsonwebtoken'; import { JwtPayload } from 'jsonwebtoken'; import Config from '../config/Config'; import express from 'express'; import UserManager from '../managers/UserManager'; import { User } from '../types/DatabaseTypes'; import DojoBackendResponse from '../shared/types/Dojo/DojoBackendResponse'; class Session { private _profile!: User; get profile(): User { return this._profile; } set profile(newProfile: User) { delete newProfile.password; this._profile = newProfile; } constructor() { } async initSession(req: express.Request, res: express.Response) { const authorization = req.headers.authorization; if ( authorization ) { if ( authorization.startsWith('Bearer ') ) { const jwtToken = authorization.replace('Bearer ', ''); try { const jwtData = jwt.verify(jwtToken, Config.jwtConfig.secret) as JwtPayload; if ( jwtData.profile ) { this.profile = jwtData.profile; this.profile = await UserManager.getById(this.profile.id!) ?? this.profile; } } catch ( err ) { res.sendStatus(StatusCodes.UNAUTHORIZED).end(); } } } } private static getToken(profileJson: any): string | null { return profileJson === null ? null : jwt.sign({ profile: profileJson }, Config.jwtConfig.secret, Config.jwtConfig.expiresIn > 0 ? { expiresIn: Config.jwtConfig.expiresIn } : {}); } private async getResponse<T>(code: number, data: T, descriptionOverride?: string): Promise<DojoBackendResponse<T>> { const profileJson = this.profile; let reasonPhrase = ''; try { reasonPhrase = getReasonPhrase(code); } catch {} return { timestamp : (new Date()).toISOString(), code : code, description : descriptionOverride ? descriptionOverride : reasonPhrase, sessionToken: Session.getToken(profileJson), data : data }; } /* Send a response to the client Information: Data could be a promise or an object. If it's a promise, we wait on the data to be resolved before sending the response */ sendResponse(res: express.Response, code: number, data?: any, descriptionOverride?: string, internalCode?: number) { Promise.resolve(data).then((toReturn: any) => { this.getResponse(internalCode ?? code, toReturn, descriptionOverride).then(response => { res.status(code).json(response); }); }); } } export default Session;