115 lines
3.0 KiB
TypeScript
115 lines
3.0 KiB
TypeScript
|
|
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.lointReception.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.lointReception.data.ILoginSession['data'] = {
|
||
|
|
userId: null,
|
||
|
|
validUntil: Date.now() + plugins.smarttime.getMilliSecondsFromUnits({ weeks: 1 }),
|
||
|
|
invalidated: false,
|
||
|
|
refreshToken: null,
|
||
|
|
deviceId: null
|
||
|
|
};
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
}
|