import type { NextFunction, Request, Response } from 'express' import { safeEqual, sha256 } from './signature' import { AdminApiError, getAdminToken, type AdminAuditActor } from './admin-project-registry' const clean = (value: unknown) => String(value || '').trim() const parseBearerToken = (value: unknown) => { const raw = clean(value) if (!raw) return '' const matched = raw.match(/^Bearer\s+(.+)$/i) return clean(matched?.[1] || '') } export type AdminRequest = Request & { adminActor?: AdminAuditActor } export const extractAdminActor = (req: Request): AdminAuditActor => ({ actorType: 'admin', actorId: clean(req.header('x-yyd-admin-actor')) || 'admin', requestId: clean(req.header('x-request-id')) || undefined, ipAddress: clean(req.ip || req.socket.remoteAddress) || undefined, }) export const authenticateAdmin = (req: AdminRequest, _res: Response, next: NextFunction) => { try { const expectedToken = getAdminToken() if (!expectedToken) { throw new AdminApiError(503, 'ADMIN_AUTH_NOT_CONFIGURED', '管理员鉴权未配置') } const actualToken = parseBearerToken(req.header('authorization')) if (!actualToken) { throw new AdminApiError(401, 'ADMIN_AUTH_REQUIRED', '缺少管理员 Bearer Token') } if (!safeEqual(sha256(actualToken), sha256(expectedToken))) { throw new AdminApiError(401, 'ADMIN_TOKEN_INVALID', '管理员 Token 无效') } req.adminActor = extractAdminActor(req) next() } catch (error) { next(error) } }