/** * Identity implementation classes for Mail Manager services */ import type { ServiceIdentity, ServiceIdentityNone, ServiceIdentityBasic, ServiceIdentityToken, ServiceIdentityOAuth, ServiceIdentityCertificate } from '@/types/service'; /** * Base Identity class */ export abstract class Identity { abstract toJson(): ServiceIdentity; static fromJson(data: ServiceIdentity): Identity { switch (data.type) { case 'NA': return IdentityNone.fromJson(data); case 'BA': return IdentityBasic.fromJson(data); case 'TA': return IdentityToken.fromJson(data); case 'OA': return IdentityOAuth.fromJson(data); case 'CC': return IdentityCertificate.fromJson(data); default: throw new Error(`Unknown identity type: ${(data as any).type}`); } } } /** * No authentication */ export class IdentityNone extends Identity { readonly type = 'NA' as const; static fromJson(_data: ServiceIdentityNone): IdentityNone { return new IdentityNone(); } toJson(): ServiceIdentityNone { return { type: this.type }; } } /** * Basic authentication (username/password) */ export class IdentityBasic extends Identity { readonly type = 'BA' as const; identity: string; secret: string; constructor(identity: string = '', secret: string = '') { super(); this.identity = identity; this.secret = secret; } static fromJson(data: ServiceIdentityBasic): IdentityBasic { return new IdentityBasic(data.identity, data.secret); } toJson(): ServiceIdentityBasic { return { type: this.type, identity: this.identity, secret: this.secret }; } } /** * Token authentication (API key, static token) */ export class IdentityToken extends Identity { readonly type = 'TA' as const; token: string; constructor(token: string = '') { super(); this.token = token; } static fromJson(data: ServiceIdentityToken): IdentityToken { return new IdentityToken(data.token); } toJson(): ServiceIdentityToken { return { type: this.type, token: this.token }; } } /** * OAuth authentication */ export class IdentityOAuth extends Identity { readonly type = 'OA' as const; accessToken: string; accessScope?: string[]; accessExpiry?: number; refreshToken?: string; refreshLocation?: string; constructor( accessToken: string = '', accessScope?: string[], accessExpiry?: number, refreshToken?: string, refreshLocation?: string ) { super(); this.accessToken = accessToken; this.accessScope = accessScope; this.accessExpiry = accessExpiry; this.refreshToken = refreshToken; this.refreshLocation = refreshLocation; } static fromJson(data: ServiceIdentityOAuth): IdentityOAuth { return new IdentityOAuth( data.accessToken, data.accessScope, data.accessExpiry, data.refreshToken, data.refreshLocation ); } toJson(): ServiceIdentityOAuth { return { type: this.type, accessToken: this.accessToken, ...(this.accessScope && { accessScope: this.accessScope }), ...(this.accessExpiry && { accessExpiry: this.accessExpiry }), ...(this.refreshToken && { refreshToken: this.refreshToken }), ...(this.refreshLocation && { refreshLocation: this.refreshLocation }) }; } isExpired(): boolean { if (!this.accessExpiry) return false; return Date.now() / 1000 >= this.accessExpiry; } expiresIn(): number { if (!this.accessExpiry) return Infinity; return Math.max(0, this.accessExpiry - Date.now() / 1000); } } /** * Client certificate authentication (mTLS) */ export class IdentityCertificate extends Identity { readonly type = 'CC' as const; certificate: string; privateKey: string; passphrase?: string; constructor(certificate: string = '', privateKey: string = '', passphrase?: string) { super(); this.certificate = certificate; this.privateKey = privateKey; this.passphrase = passphrase; } static fromJson(data: ServiceIdentityCertificate): IdentityCertificate { return new IdentityCertificate( data.certificate, data.privateKey, data.passphrase ); } toJson(): ServiceIdentityCertificate { return { type: this.type, certificate: this.certificate, privateKey: this.privateKey, ...(this.passphrase && { passphrase: this.passphrase }) }; } }