@kitiumai/auth-postgres
Version:
Enterprise-grade PostgreSQL storage adapter for @kitiumai/auth with full support for users, sessions, OAuth links, API keys, 2FA, RBAC, and SSO
112 lines (109 loc) • 6.28 kB
TypeScript
import { PoolConfig } from 'pg';
import { StorageAdapter, ApiKeyRecord, SessionRecord, OrganizationRecord, CreateUserInput, UserRecord, UpdateUserInput, OAuthLink, EmailVerificationToken, AuthEvent, RoleRecord, SSOLink, SSOSession, TwoFactorDevice, BackupCode, TwoFactorSession } from '@kitiumai/auth';
type DbRecord = Record<string, any>;
type PostgresAdapterOptions = PoolConfig & {
statementTimeoutMs?: number;
maxRetries?: number;
};
declare class PostgresStorageAdapter implements StorageAdapter {
private pool;
private readonly logger;
private readonly defaultQueryTimeoutMs;
private readonly defaultRetries;
constructor(connectionString: string, options?: PostgresAdapterOptions);
connect(): Promise<void>;
private maskConnectionString;
disconnect(): Promise<void>;
private withClient;
private query;
healthCheck(): Promise<{
status: 'ok' | 'error';
latencyMs: number;
}>;
private runMigrations;
private mapEmailVerificationToken;
/**
* Create an API key with plaintext secret (convenience method)
* @param principalId - Principal ID for the key
* @param scopes - Scopes for the key
* @param prefix - Optional prefix (default: 'api')
* @returns Object with the record and plaintext key
*/
createApiKeyWithSecret(principalId: string, scopes: string[], prefix?: string): Promise<{
record: ApiKeyRecord;
key: string;
}>;
createApiKey(data: Omit<ApiKeyRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiKeyRecord>;
getApiKey(id: string): Promise<ApiKeyRecord | null>;
getApiKeyByHash(hash: string): Promise<ApiKeyRecord | null>;
getApiKeysByPrefixAndLastFour(prefix: string, lastFour: string): Promise<ApiKeyRecord[]>;
updateApiKey(id: string, data: Partial<ApiKeyRecord>): Promise<ApiKeyRecord>;
deleteApiKey(id: string): Promise<void>;
listApiKeys(principalId: string): Promise<ApiKeyRecord[]>;
createSession(data: Omit<SessionRecord, 'id' | 'createdAt'>): Promise<SessionRecord>;
getSession(id: string): Promise<SessionRecord | null>;
updateSession(id: string, data: Partial<SessionRecord>): Promise<SessionRecord>;
deleteSession(id: string): Promise<void>;
createOrganization(data: Omit<OrganizationRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<OrganizationRecord>;
getOrganization(id: string): Promise<OrganizationRecord | null>;
updateOrganization(id: string, data: Partial<OrganizationRecord>): Promise<OrganizationRecord>;
deleteOrganization(id: string): Promise<void>;
createUser(data: CreateUserInput): Promise<UserRecord>;
getUser(id: string): Promise<UserRecord | null>;
getUserByEmail(email: string): Promise<UserRecord | null>;
getUserByOAuth(provider: string, sub: string): Promise<UserRecord | null>;
updateUser(id: string, data: UpdateUserInput): Promise<UserRecord>;
deleteUser(id: string): Promise<void>;
linkOAuthAccount(userId: string, provider: string, oauthLink: OAuthLink): Promise<UserRecord>;
createEmailVerificationToken(data: Omit<EmailVerificationToken, 'id'>): Promise<EmailVerificationToken>;
getEmailVerificationTokens(email: string, type?: string): Promise<EmailVerificationToken[]>;
getEmailVerificationTokenById(id: string): Promise<EmailVerificationToken | null>;
markEmailVerificationTokenAsUsed(id: string): Promise<EmailVerificationToken>;
deleteExpiredEmailVerificationTokens(): Promise<number>;
getEmailVerificationTokenAttempts(tokenId: string): Promise<number>;
incrementEmailVerificationTokenAttempts(tokenId: string): Promise<number>;
emitEvent(event: AuthEvent): Promise<void>;
createRole(data: Omit<RoleRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<RoleRecord>;
getRole(roleId: string): Promise<RoleRecord | null>;
updateRole(roleId: string, data: Partial<RoleRecord>): Promise<RoleRecord>;
deleteRole(roleId: string): Promise<void>;
listRoles(orgId: string): Promise<RoleRecord[]>;
assignRoleToUser(userId: string, roleId: string, orgId: string): Promise<RoleRecord>;
revokeRoleFromUser(userId: string, roleId: string, orgId: string): Promise<void>;
getUserRoles(userId: string, orgId: string): Promise<RoleRecord[]>;
createSSOProvider(data: DbRecord): Promise<unknown>;
getSSOProvider(providerId: string): Promise<unknown | null>;
updateSSOProvider(providerId: string, data: Partial<unknown>): Promise<unknown>;
deleteSSOProvider(providerId: string): Promise<void>;
listSSOProviders(orgId?: string): Promise<unknown[]>;
createSSOLink(data: Omit<SSOLink, 'id' | 'linkedAt'>): Promise<SSOLink>;
getSSOLink(linkId: string): Promise<SSOLink | null>;
getUserSSOLinks(userId: string): Promise<SSOLink[]>;
deleteSSOLink(linkId: string): Promise<void>;
createSSOSession(data: Omit<SSOSession, 'id' | 'linkedAt'>): Promise<SSOSession>;
getSSOSession(sessionId: string): Promise<SSOSession | null>;
createTwoFactorDevice(data: Omit<TwoFactorDevice, 'id' | 'createdAt'>): Promise<TwoFactorDevice>;
getTwoFactorDevice(deviceId: string): Promise<TwoFactorDevice | null>;
listTwoFactorDevices(userId: string): Promise<TwoFactorDevice[]>;
updateTwoFactorDevice(deviceId: string, data: Partial<TwoFactorDevice>): Promise<TwoFactorDevice>;
deleteTwoFactorDevice(deviceId: string): Promise<void>;
createBackupCodes(userId: string, codes: BackupCode[]): Promise<BackupCode[]>;
getBackupCodes(userId: string): Promise<BackupCode[]>;
markBackupCodeUsed(codeId: string): Promise<void>;
createTwoFactorSession(data: TwoFactorSession): Promise<TwoFactorSession>;
getTwoFactorSession(sessionId: string): Promise<TwoFactorSession | null>;
completeTwoFactorSession(sessionId: string): Promise<void>;
private mapApiKeyRecord;
private mapSessionRecord;
private mapOrganizationRecord;
private mapUserRecord;
private camelToSnake;
private mapRoleRecord;
private mapSSOProviderRecord;
private mapSSOLinkRecord;
private mapSSOSessionRecord;
private mapTwoFactorDeviceRecord;
private mapBackupCodeRecord;
private mapTwoFactorSessionRecord;
}
export { PostgresStorageAdapter as PostgresAdapter, PostgresStorageAdapter };