import * as plugins from '../plugins.js'; import { LoginSessionManager } from './classes.loginsessionmanager.js'; import { User } from './classes.user.js'; /** * a LoginSession keeps track of a login over the whole time of the user being loggedin */ @plugins.smartdata.Manager() export class LoginSession extends plugins.smartdata.SmartDataDbDoc< LoginSession, plugins.idpInterfaces.data.ILoginSession, LoginSessionManager > { // ====== // static // ====== public static async createLoginSessionForUser(userArg: User, deleteOtherSessions = false) { const loginSession = new LoginSession(); loginSession.id = plugins.smartunique.shortId(); loginSession.data.userId = userArg.id; await loginSession.save(); return loginSession; } public static async clearLoginSessionsForUser(userArg: User) { // lets find existing sessions const existingSessions = await LoginSession.getInstances({ id: userArg.id, }); for (const existingSession of existingSessions) { await existingSession.delete(); } } public static async getLoginSessionBySessionId(sessionIdArg: string) { return await LoginSession.getInstance({ id: sessionIdArg, }); } public static async getLoginSessionByRefreshToken(refreshTokenArg: string) { const loginSession = await LoginSession.getInstance({ data: { refreshToken: refreshTokenArg, }, }); return loginSession; } // ======== // INSTANCE // ======== @plugins.smartdata.unI() public id: string; @plugins.smartdata.svDb() public data: plugins.idpInterfaces.data.ILoginSession['data'] = { userId: null, validUntil: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ weeks: 1 }), invalidated: false, refreshToken: null, deviceId: null, deviceInfo: null, createdAt: Date.now(), lastActive: Date.now(), }; public transferToken: string; constructor() { super(); } /** * invalidates a session */ public async invalidate() { this.data.invalidated = true; await this.save(); } /** * a refresh token is unique to a login session and ONLY created once per login session * @returns */ public async getRefreshToken() { if (this.data.invalidated) { console.log('login session is invalidated. no refresh token can be generated.'); return null; } if (!this.data.refreshToken) { this.data.refreshToken = plugins.smartunique.uni('refresh_'); } await this.save(); return this.data.refreshToken; } public async getTransferToken() { this.transferToken = plugins.smartunique.uni('transfer_'); return this.transferToken; } public async validateRefreshToken(refreshTokenArg: string) { return this.data.refreshToken === refreshTokenArg; } public async validateTransferToken(transferTokenArg: string) { const result = this.transferToken === transferTokenArg; // a transfer token can only be used once, so we invalidate it here if (result) { this.transferToken = null; } return result; } }