197 lines
4.4 KiB
TypeScript
197 lines
4.4 KiB
TypeScript
/**
|
|
* 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 })
|
|
};
|
|
}
|
|
}
|