import type { IUserMeData } from "#shared/types"; import { clearNewApiAuthCookies, createErrorResponse, createSuccessResponse, newApiAuthedFetch } from "~~/server/utils"; interface INewApiWrappedUserResponse { /** 获取成功时上游返回的当前用户信息 */ data?: INewApiSelfUserData | null; /** 上游提示信息,失败时优先返回给前端 */ message?: string; /** 上游业务成功状态 */ success?: boolean; } type NewApiUserResponse = INewApiSelfUserData | INewApiWrappedUserResponse; interface INewApiSelfUserData extends IUserMeData { /** NewAPI /api/user/self 可能返回配额、设置、第三方绑定等额外字段 */ [key: string]: unknown; } export default defineEventHandler(async (event) => { try { // 从本站 httpOnly cookie 读取登录态,并转发给 NewAPI 查询当前用户。 const result = await newApiAuthedFetch( event, "/api/user/self", { method: "GET" } ); const normalized = normalizeUserResponse(result); if (!normalized.user) { // 上游业务失败代表当前 cookie 不再可靠,清理后返回统一 401。 clearNewApiAuthCookies(event); return createErrorResponse(401, normalized.message); } return createSuccessResponse( normalized.user, normalized.message ); } catch { // cookie 缺失或上游鉴权异常时统一视为未登录。 clearNewApiAuthCookies(event); return createErrorResponse(401, "未登录"); } }); /** 兼容上游直接返回用户对象和 { success, message, data } 包装结构 */ const normalizeUserResponse = ( response: NewApiUserResponse ): { message: string; user: IUserMeData | null } => { if (isUser(response)) { return { message: "获取用户信息成功", user: pickUserBasicData(response) }; } if (!isRecord(response)) { return { message: "未登录", user: null }; } const wrapped = response as INewApiWrappedUserResponse; const message = wrapped.message || (wrapped.success ? "获取用户信息成功" : "未登录"); if (wrapped.success !== true || !isUser(wrapped.data)) { return { message, user: null }; } return { message, user: pickUserBasicData(wrapped.data) }; }; /** 只返回前端需要的基础用户字段,避免泄露上游完整 self 信息 */ const pickUserBasicData = (user: INewApiSelfUserData): IUserMeData => { return { id: user.id, username: user.username, display_name: user.display_name, group: user.group, role: user.role, status: user.status }; }; const isUser = (value: unknown): value is INewApiSelfUserData => { return ( isRecord(value) && typeof value.id === "number" && typeof value.username === "string" && typeof value.display_name === "string" && typeof value.group === "string" && typeof value.role === "number" && typeof value.status === "number" ); }; const isRecord = (value: unknown): value is Record => { return value !== null && typeof value === "object"; };