Add API token management for CLI authentication

- Add reviq auth login --token <token> command for CLI authentication
- Create /account/api-tokens page for token management (superuser only)
- Add me.apiTokens endpoints (list, create, delete)
- Require superuser status and trusted session for token creation
- Show API Tokens nav link only for superusers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
igm
2026-01-10 18:58:27 +08:00
parent 42badf3c52
commit a7d6beaf5a
8 changed files with 566 additions and 130 deletions

View File

@@ -13,6 +13,9 @@ import {
adminUpdateUserInputSchema,
} from "./schemas/admin.js";
import {
apiTokenOutputSchema,
createApiTokenInputSchema,
createApiTokenOutputSchema,
forgotPasswordInputSchema,
loginPasswordInputSchema,
loginRequestInputSchema,
@@ -160,6 +163,17 @@ export const contract = oc.router({
.input(z.object({ deviceId: z.number() }))
.output(successResponseSchema),
revokeAllTrustedDevices: oc.output(successResponseSchema),
// API tokens for CLI/programmatic access
apiTokens: oc.router({
list: oc.output(z.array(apiTokenOutputSchema)),
create: oc
.input(createApiTokenInputSchema)
.output(createApiTokenOutputSchema),
delete: oc
.input(z.object({ tokenId: z.number() }))
.output(successResponseSchema),
}),
}),
orgs: oc.router({

View File

@@ -81,3 +81,31 @@ export const resetPasswordInputSchema = z.object({
token: z.string(),
newPassword: z.string().min(8),
});
/**
* API token creation input schema
* Creates an API token for CLI/programmatic access
*/
export const createApiTokenInputSchema = z.object({
name: z.string().min(1).max(100),
});
/**
* API token creation output schema
* Returns the token (only shown once)
*/
export const createApiTokenOutputSchema = z.object({
token: z.string(),
expiresAt: z.string(),
});
/**
* API token output schema for listing tokens
*/
export const apiTokenOutputSchema = z.object({
id: z.number(),
name: z.string(),
lastUsedAt: z.string().nullable(),
createdAt: z.string(),
expiresAt: z.string(),
});