import { NextResponse } from 'next/server'; import { withAuth, withPermission } from '@/lib/api/helpers'; import { parseBody } from '@/lib/api/route-helpers'; import { errorResponse } from '@/lib/errors'; import { getSalesEmailConfig, getSalesImapConfig, getSalesContentConfig, redactSalesConfigForResponse, updateSalesEmailConfig, } from '@/lib/services/sales-email-config.service'; import { updateSalesEmailConfigSchema } from '@/lib/validators/sales-email-config'; /** * GET /api/v1/admin/email/sales-config * * Returns the redacted view of the sales-email config. Per §14.10 * "Permission escalation: who configures SMTP credentials?", reps cannot * see the decrypted password — the response only carries `*PassIsSet` * boolean markers. */ export const GET = withAuth( withPermission('admin', 'manage_settings', async (_req, ctx) => { try { const [email, imap, content] = await Promise.all([ getSalesEmailConfig(ctx.portId), getSalesImapConfig(ctx.portId), getSalesContentConfig(ctx.portId), ]); const redacted = redactSalesConfigForResponse(email, imap, content); return NextResponse.json({ data: redacted }); } catch (error) { return errorResponse(error); } }), ); /** * PATCH /api/v1/admin/email/sales-config * * Per-port admin only. Encrypts SMTP/IMAP passwords via AES-256-GCM before * storage; the API never returns decrypted secrets (mirror enforcement on * the GET handler). */ export const PATCH = withAuth( withPermission('admin', 'manage_settings', async (req, ctx) => { try { const input = await parseBody(req, updateSalesEmailConfigSchema); await updateSalesEmailConfig(ctx.portId, input, { userId: ctx.userId, portId: ctx.portId, ipAddress: ctx.ipAddress, userAgent: ctx.userAgent, }); // Return the freshly-redacted view so the UI can re-render. const [email, imap, content] = await Promise.all([ getSalesEmailConfig(ctx.portId), getSalesImapConfig(ctx.portId), getSalesContentConfig(ctx.portId), ]); return NextResponse.json({ data: redactSalesConfigForResponse(email, imap, content) }); } catch (error) { return errorResponse(error); } }), );