import { all, run } from "../db"; import { notFoundError } from "../errors"; import { lfsUsage } from "../lfs/quota"; import { parseTokenPermissions } from "../token-scope"; import { noContent, requireAccountScope } from "./http"; import type { ApiContext } from "./http"; export function getUser(ctx: ApiContext): Response { return Response.json({ login: ctx.viewer.name, id: ctx.viewer.id, name: ctx.viewer.displayName ?? ctx.viewer.name }); } export async function getLfsUsage(ctx: ApiContext): Promise { const usage = await lfsUsage(ctx.viewer.id); return Response.json({ bytes: usage.storageBytes }); } type TokenRow = { id: string; name: string; token_prefix: string; permissions: string | null; all_repos: number; last_used_at: number | null; expires_at: number | null; created_at: number; }; export async function listTokens(ctx: ApiContext): Promise { requireAccountScope(ctx); const rows = await all( `SELECT id, name, token_prefix, permissions, all_repos, last_used_at, expires_at, created_at FROM access_tokens WHERE user_id = ? ORDER BY created_at DESC`, ctx.viewer.id, ); return Response.json( rows.map((row) => ({ id: row.id, name: row.name, prefix: row.token_prefix, fine_grained: row.permissions !== null, permissions: row.permissions === null ? {} : parseTokenPermissions(row.permissions), all_repos: row.all_repos === 1, last_used_at: row.last_used_at, expires_at: row.expires_at, created_at: row.created_at, })), ); } export async function revokeToken(ctx: ApiContext, id: string): Promise { requireAccountScope(ctx); const result = await run("DELETE FROM access_tokens WHERE id = ? AND user_id = ?", id, ctx.viewer.id); if (result.meta.changes === 0) throw notFoundError("Token not found"); return noContent(); }