Spaces:
Paused
Paused
| import type { Command } from "commander"; | |
| import { | |
| getStoredBoardCredential, | |
| loginBoardCli, | |
| removeStoredBoardCredential, | |
| revokeStoredBoardCredential, | |
| } from "../../client/board-auth.js"; | |
| import { | |
| addCommonClientOptions, | |
| handleCommandError, | |
| printOutput, | |
| resolveCommandContext, | |
| type BaseClientOptions, | |
| } from "./common.js"; | |
| interface AuthLoginOptions extends BaseClientOptions { | |
| instanceAdmin?: boolean; | |
| } | |
| interface AuthLogoutOptions extends BaseClientOptions {} | |
| interface AuthWhoamiOptions extends BaseClientOptions {} | |
| export function registerClientAuthCommands(auth: Command): void { | |
| addCommonClientOptions( | |
| auth | |
| .command("login") | |
| .description("Authenticate the CLI for board-user access") | |
| .option("--instance-admin", "Request instance-admin approval instead of plain board access", false) | |
| .action(async (opts: AuthLoginOptions) => { | |
| try { | |
| const ctx = resolveCommandContext(opts); | |
| const login = await loginBoardCli({ | |
| apiBase: ctx.api.apiBase, | |
| requestedAccess: opts.instanceAdmin ? "instance_admin_required" : "board", | |
| requestedCompanyId: ctx.companyId ?? null, | |
| command: "paperclipai auth login", | |
| }); | |
| printOutput( | |
| { | |
| ok: true, | |
| apiBase: ctx.api.apiBase, | |
| userId: login.userId ?? null, | |
| approvalUrl: login.approvalUrl, | |
| }, | |
| { json: ctx.json }, | |
| ); | |
| } catch (err) { | |
| handleCommandError(err); | |
| } | |
| }), | |
| { includeCompany: true }, | |
| ); | |
| addCommonClientOptions( | |
| auth | |
| .command("logout") | |
| .description("Remove the stored board-user credential for this API base") | |
| .action(async (opts: AuthLogoutOptions) => { | |
| try { | |
| const ctx = resolveCommandContext(opts); | |
| const credential = getStoredBoardCredential(ctx.api.apiBase); | |
| if (!credential) { | |
| printOutput({ ok: true, apiBase: ctx.api.apiBase, revoked: false, removedLocalCredential: false }, { json: ctx.json }); | |
| return; | |
| } | |
| let revoked = false; | |
| try { | |
| await revokeStoredBoardCredential({ | |
| apiBase: ctx.api.apiBase, | |
| token: credential.token, | |
| }); | |
| revoked = true; | |
| } catch { | |
| // Remove the local credential even if the server-side revoke fails. | |
| } | |
| const removedLocalCredential = removeStoredBoardCredential(ctx.api.apiBase); | |
| printOutput( | |
| { | |
| ok: true, | |
| apiBase: ctx.api.apiBase, | |
| revoked, | |
| removedLocalCredential, | |
| }, | |
| { json: ctx.json }, | |
| ); | |
| } catch (err) { | |
| handleCommandError(err); | |
| } | |
| }), | |
| ); | |
| addCommonClientOptions( | |
| auth | |
| .command("whoami") | |
| .description("Show the current board-user identity for this API base") | |
| .action(async (opts: AuthWhoamiOptions) => { | |
| try { | |
| const ctx = resolveCommandContext(opts); | |
| const me = await ctx.api.get<{ | |
| user: { id: string; name: string; email: string } | null; | |
| userId: string; | |
| isInstanceAdmin: boolean; | |
| companyIds: string[]; | |
| source: string; | |
| keyId: string | null; | |
| }>("/api/cli-auth/me"); | |
| printOutput(me, { json: ctx.json }); | |
| } catch (err) { | |
| handleCommandError(err); | |
| } | |
| }), | |
| ); | |
| } | |