auth.ts (1688B)
1 import { Code } from "#core/domain/code.ts"; 2 import { nonceUUID } from "#core/domain/crypto.ts"; 3 import { Email } from "#core/domain/email.ts"; 4 import { EmailChallenge } from "#core/domain/email_challenge.ts"; 5 import { Password } from "#core/domain/password.ts"; 6 import { 7 ExpiredSessionToken, 8 SessionToken, 9 } from "#core/domain/session_token.ts"; 10 import { Token } from "#core/domain/token.ts"; 11 import { UUID } from "#core/domain/uuid.ts"; 12 import { Logger } from "#core/domain/logger.ts"; 13 14 export class Auth { 15 static register( 16 email: Email, 17 password: Password, 18 passwordConfirm: string, 19 ) { 20 password.attempt(passwordConfirm); 21 return new this( 22 nonceUUID(), 23 new EmailChallenge(email), 24 password, 25 ); 26 } 27 28 constructor( 29 readonly id: UUID, 30 readonly email: EmailChallenge, 31 readonly password: Password, 32 private _session: SessionToken = SessionToken.none(), 33 public version: number = 0, 34 ) {} 35 36 get session() { 37 return this._session; 38 } 39 40 requestEmailChallenge() { 41 return this.email.requestChallenge(); 42 } 43 44 verifyEmailChallenge(code: Code): void { 45 this.email.attemptChallenge(code); 46 } 47 48 login(candidatePassword: string): Token { 49 this.email.assertVerified(); 50 this.password.attempt(candidatePassword); 51 this._session = SessionToken.issue(); 52 return this._session.valueOf()!; 53 } 54 55 authenticate(token: Token): void { 56 this.email.assertVerified(); 57 if (!this._session.grant(token)) { 58 throw new ExpiredSessionToken(); 59 } 60 } 61 62 logout(token: Token): void { 63 this.email.assertVerified(); 64 if (this._session.grant(token)) { 65 this._session = SessionToken.none(); 66 } 67 } 68 }