Files
hertzbeat/web-next/lib/setting-token/controller.ts
T
Logic 2de48d2caa feat: complete HertzBeat 2.0 novice workflows
Refine entity, monitor, alert, settings, observability, and shared operator workflows; add scale guards, route compatibility, release validation, and Product Design coverage.

AI assistance: used for draft implementation and test iteration.\nHuman validation: Node 22 production build; 426 frontend files and 3,398 tests; 59-route matrix; release budget 7.84 MiB / 8.00 MiB; focused backend tests and Browser QA.\nRisk notes: local scale proof covers 2,005 entities; sustained concurrent-ingestion SLA remains deployment-specific.
2026-07-10 14:54:43 +08:00

58 lines
2.2 KiB
TypeScript

import type { AuthToken } from '@/lib/types';
type ApiGetter = <T>(url: string) => Promise<T>;
type ApiPoster = <T>(url: string, body: unknown) => Promise<T>;
type ApiDeleter = <T>(url: string) => Promise<T>;
type RawTokenResponse = { code: number; msg?: string; data?: { token?: string } };
type RawMessageResponse = { code: number; msg?: string };
export type TokenScope = 'api-admin' | 'readonly-query' | 'otlp-ingest';
export type GenerateTokenOptions = {
scope?: string | null;
workspaceId?: string | null;
};
export const DEFAULT_TOKEN_SCOPE: TokenScope = 'api-admin';
export const TOKEN_SCOPES: TokenScope[] = ['api-admin', 'otlp-ingest', 'readonly-query'];
export async function loadTokenData(apiGet: ApiGetter) {
const tokens = await apiGet<AuthToken[]>('/account/token');
return { tokens };
}
export function normalizeTokenScope(scope: string | null | undefined): TokenScope {
const normalized = scope?.trim().toLowerCase();
return TOKEN_SCOPES.includes(normalized as TokenScope) ? normalized as TokenScope : DEFAULT_TOKEN_SCOPE;
}
export function buildGenerateTokenUrl(name: string, expireSeconds: string, options: GenerateTokenOptions = {}) {
const params = new URLSearchParams({ name: name.trim() });
const expireValue = Number(expireSeconds);
if (!Number.isNaN(expireValue)) params.set('expireSeconds', String(expireValue));
if (options.scope) params.set('scope', normalizeTokenScope(options.scope));
const workspaceId = options.workspaceId?.trim();
if (workspaceId) params.set('workspaceId', workspaceId);
return `/account/token/generate?${params.toString()}`;
}
export async function generateTokenValue(
apiPost: ApiPoster,
name: string,
expireSeconds: string,
failureMessage: string,
options: GenerateTokenOptions = {}
) {
const message = await apiPost<RawTokenResponse>(buildGenerateTokenUrl(name, expireSeconds, options), {});
if (message.code !== 0) {
throw new Error(message.msg || failureMessage);
}
return message.data?.token || '';
}
export async function deleteTokenById(apiDelete: ApiDeleter, id: number | string, failureMessage: string) {
const message = await apiDelete<RawMessageResponse>(`/account/token/${id}`);
if (message.code !== 0) {
throw new Error(message.msg || failureMessage);
}
}