| 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 { |
| |
| } |
| 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); |
| } |
| }), |
| ); |
| } |
|
|