import { parseAdminAuth } from "@/lib/api/admin-auth-context"; import { fail, ok } from "@/lib/response"; import { writeAudit } from "@/modules/audit/service"; import { AuthError } from "@/modules/auth/errors"; import { hasCustomerProviderCredential, isProviderCredentialProvider, listCustomerProviderCredentialsForAdmin, upsertCustomerProviderCredential, } from "@/modules/customer/provider-credentials"; type RouteContext = { params: Promise<{ customer_id: string }>; }; export async function GET(request: Request, context: RouteContext) { let auth; try { auth = parseAdminAuth(request); } catch (error) { if (error instanceof AuthError) { return fail(error.code, error.message, error.httpStatus); } throw error; } const { customer_id: customerId } = await context.params; const list = await listCustomerProviderCredentialsForAdmin(customerId); await writeAudit( "customer:provider_credential_view", auth.userId, customerId, { providers: list.filter((x) => x.has_password).map((x) => x.provider) }, ); return ok({ customer_id: customerId, list }); } export async function PUT(request: Request, context: RouteContext) { let auth; try { auth = parseAdminAuth(request); } catch (error) { if (error instanceof AuthError) { return fail(error.code, error.message, error.httpStatus); } throw error; } const { customer_id: customerId } = await context.params; let body: unknown; try { body = await request.json(); } catch { return fail("VALIDATION_FAILED", "请求体格式无效", 400); } const payload = body as { provider?: unknown; email?: unknown; password?: unknown; clear?: unknown; }; if (!isProviderCredentialProvider(payload.provider)) { return fail("VALIDATION_FAILED", "provider 须为 mothership 或 flock", 400); } // 产品约束:查价网站账密仅支持新建客户时首次写入,禁止事后修改/清除 if (payload.clear === true) { return fail( "VALIDATION_FAILED", "不支持清除查价网站账密;如需更换请新建客户并重新绑定", 400, ); } if (typeof payload.email !== "string") { return fail("VALIDATION_FAILED", "登录邮箱无效", 400); } const password = typeof payload.password === "string" ? payload.password : undefined; try { if (await hasCustomerProviderCredential(customerId, payload.provider)) { return fail( "VALIDATION_FAILED", "该承运商账密已绑定,不支持修改;仅可在管理端查看", 400, ); } const saved = await upsertCustomerProviderCredential( customerId, payload.provider, { email: payload.email, password, updatedBy: auth.userId, }, ); await writeAudit( "customer:provider_credential_upsert", auth.userId, customerId, { provider: payload.provider, email: saved.email, password_updated: Boolean(password?.trim()), }, ); return ok(saved); } catch (error) { const message = error instanceof Error ? error.message : "保存失败"; return fail("VALIDATION_FAILED", message, 400); } }