90 lines
3.0 KiB
TypeScript
90 lines
3.0 KiB
TypeScript
import AuthProof from "../AuthProof";
|
|
import User from "../models/User";
|
|
import UserPasswordComponent from "./UserPasswordComponent";
|
|
import {Session, SessionData} from "express-session";
|
|
|
|
|
|
export default class PasswordAuthProof implements AuthProof<User> {
|
|
public static getProofForSession(session: Session & Partial<SessionData>): PasswordAuthProof | null {
|
|
return session.auth_password_proof ? new PasswordAuthProof(session) : null;
|
|
}
|
|
|
|
public static createAuthorizedProofForRegistration(session: Session): PasswordAuthProof {
|
|
const proofForSession = new PasswordAuthProof(session);
|
|
proofForSession.authorized = true;
|
|
proofForSession.forRegistration = true;
|
|
proofForSession.save();
|
|
return proofForSession;
|
|
}
|
|
|
|
public static createProofForLogin(session: Session & Partial<SessionData>): PasswordAuthProof {
|
|
return new PasswordAuthProof(session);
|
|
}
|
|
|
|
private readonly session: Session & Partial<SessionData>;
|
|
private authorized: boolean;
|
|
private forRegistration: boolean = false;
|
|
private userId: number | null;
|
|
private userPassword: UserPasswordComponent | null = null;
|
|
|
|
private constructor(session: Session & Partial<SessionData>) {
|
|
this.session = session;
|
|
this.authorized = session.auth_password_proof?.authorized || false;
|
|
this.forRegistration = session.auth_password_proof?.forRegistration || false;
|
|
this.userId = session.auth_password_proof?.userId || null;
|
|
}
|
|
|
|
public async getResource(): Promise<User | null> {
|
|
if (typeof this.userId !== 'number') return null;
|
|
return await User.getById(this.userId);
|
|
}
|
|
|
|
public setResource(user: User): void {
|
|
this.userId = user.getOrFail('id');
|
|
this.save();
|
|
}
|
|
|
|
public async isAuthorized(): Promise<boolean> {
|
|
return this.authorized;
|
|
}
|
|
|
|
public async isValid(): Promise<boolean> {
|
|
return (this.forRegistration || Boolean(await this.getResource())) &&
|
|
await this.isAuthorized();
|
|
}
|
|
|
|
public async revoke(): Promise<void> {
|
|
this.session.auth_password_proof = undefined;
|
|
}
|
|
|
|
private async getUserPassword(): Promise<UserPasswordComponent | null> {
|
|
if (!this.userPassword) {
|
|
this.userPassword = (await User.getById(this.userId))?.as(UserPasswordComponent) || null;
|
|
}
|
|
return this.userPassword;
|
|
}
|
|
|
|
public async authorize(passwordGuess: string): Promise<boolean> {
|
|
const password = await this.getUserPassword();
|
|
if (!password || !await password.verifyPassword(passwordGuess)) return false;
|
|
|
|
this.authorized = true;
|
|
this.save();
|
|
return true;
|
|
}
|
|
|
|
private save() {
|
|
this.session.auth_password_proof = {
|
|
authorized: this.authorized,
|
|
forRegistration: this.forRegistration,
|
|
userId: this.userId,
|
|
};
|
|
}
|
|
}
|
|
|
|
export type PasswordAuthProofSessionData = {
|
|
authorized: boolean,
|
|
forRegistration: boolean,
|
|
userId: number | null,
|
|
};
|