Files
zclaw_openfang/desktop/src/lib/saas-auth.ts
iven f79560a911 refactor(desktop): split kernel_commands/pipeline_commands into modules, add SaaS client libs and gateway modules
Split monolithic kernel_commands.rs (2185 lines) and pipeline_commands.rs (1391 lines)
into focused sub-modules under kernel_commands/ and pipeline_commands/ directories.
Add gateway module (commands, config, io, runtime), health_check, and 15 new
TypeScript client libraries for SaaS relay, auth, admin, telemetry, and kernel
sub-systems (a2a, agent, chat, hands, skills, triggers).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 11:12:47 +08:00

98 lines
3.6 KiB
TypeScript

/**
* SaaS Auth Methods — Mixin
*
* Installs authentication-related methods onto SaaSClient.prototype.
* Uses the same mixin pattern as gateway-api.ts.
*/
import type {
SaaSAccountInfo,
SaaSLoginResponse,
SaaSRefreshResponse,
TotpSetupResponse,
TotpResultResponse,
} from './saas-types';
export function installAuthMethods(ClientClass: { prototype: any }): void {
const proto = ClientClass.prototype;
/**
* Login with username and password.
* Auto-sets the client token on success.
*/
proto.login = async function (this: { token: string | null; request<T>(method: string, path: string, body?: unknown): Promise<T> }, username: string, password: string, totpCode?: string): Promise<SaaSLoginResponse> {
const body: Record<string, string> = { username, password };
if (totpCode) body.totp_code = totpCode;
// Clear stale token before login — avoid sending expired token on auth endpoint
this.token = null;
const data = await this.request<SaaSLoginResponse>(
'POST', '/api/v1/auth/login', body,
);
this.token = data.token;
return data;
};
/**
* Register a new account.
* Auto-sets the client token on success.
*/
proto.register = async function (this: { token: string | null; request<T>(method: string, path: string, body?: unknown): Promise<T> }, data: {
username: string;
email: string;
password: string;
display_name?: string;
}): Promise<SaaSLoginResponse> {
// Clear stale token before register
this.token = null;
const result = await this.request<SaaSLoginResponse>(
'POST', '/api/v1/auth/register', data,
);
this.token = result.token;
return result;
};
/**
* Get the current authenticated user's account info.
*/
proto.me = async function (this: { request<T>(method: string, path: string, body?: unknown): Promise<T> }): Promise<SaaSAccountInfo> {
return this.request<SaaSAccountInfo>('GET', '/api/v1/auth/me');
};
/**
* Refresh the current token.
* Auto-updates the client token on success.
*/
proto.refreshToken = async function (this: { token: string | null; request<T>(method: string, path: string, body?: unknown): Promise<T> }): Promise<string> {
const data = await this.request<SaaSRefreshResponse>('POST', '/api/v1/auth/refresh');
this.token = data.token;
return data.token;
};
/**
* Change the current user's password.
*/
proto.changePassword = async function (this: { request<T>(method: string, path: string, body?: unknown): Promise<T> }, oldPassword: string, newPassword: string): Promise<void> {
await this.request<unknown>('PUT', '/api/v1/auth/password', {
old_password: oldPassword,
new_password: newPassword,
});
};
// --- TOTP Endpoints ---
/** Generate a TOTP secret and otpauth URI */
proto.setupTotp = async function (this: { request<T>(method: string, path: string, body?: unknown): Promise<T> }): Promise<TotpSetupResponse> {
return this.request<TotpSetupResponse>('POST', '/api/v1/auth/totp/setup');
};
/** Verify a TOTP code and enable 2FA */
proto.verifyTotp = async function (this: { request<T>(method: string, path: string, body?: unknown): Promise<T> }, code: string): Promise<TotpResultResponse> {
return this.request<TotpResultResponse>('POST', '/api/v1/auth/totp/verify', { code });
};
/** Disable 2FA (requires password confirmation) */
proto.disableTotp = async function (this: { request<T>(method: string, path: string, body?: unknown): Promise<T> }, password: string): Promise<TotpResultResponse> {
return this.request<TotpResultResponse>('POST', '/api/v1/auth/totp/disable', { password });
};
}