import { NextResponse } from 'next/server'; import { inArray } from 'drizzle-orm'; import { z } from 'zod'; import { withAuth, withPermission } from '@/lib/api/helpers'; import { parseBody } from '@/lib/api/route-helpers'; import { db } from '@/lib/db'; import { systemSettings } from '@/lib/db/schema/system'; import { TEMPLATE_CATALOG, TEMPLATE_KEYS, settingKeyForSubject, type TemplateKey, } from '@/lib/email/template-catalog'; import { upsertSetting, deleteSetting } from '@/lib/services/settings.service'; import { errorResponse } from '@/lib/errors'; const upsertSchema = z.object({ key: z.enum(TEMPLATE_KEYS), subject: z.string().max(300).nullable(), }); export const GET = withAuth( withPermission('admin', 'manage_settings', async (_req, ctx) => { try { const subjectKeys = TEMPLATE_KEYS.map(settingKeyForSubject); const rows = await db .select({ key: systemSettings.key, value: systemSettings.value, portId: systemSettings.portId, }) .from(systemSettings) .where(inArray(systemSettings.key, subjectKeys)); const byKey = new Map(); for (const r of rows) { const slot = byKey.get(r.key) ?? {}; if (r.portId === ctx.portId && typeof r.value === 'string') slot.port = r.value; if (r.portId === null && typeof r.value === 'string') slot.global = r.value; byKey.set(r.key, slot); } const data = TEMPLATE_KEYS.map((key) => { const meta = TEMPLATE_CATALOG[key]; const settingKey = settingKeyForSubject(key); const overrides = byKey.get(settingKey) ?? {}; const effective = overrides.port ?? overrides.global ?? meta.defaultSubject; return { key, label: meta.label, description: meta.description, mergeTokens: meta.mergeTokens, defaultSubject: meta.defaultSubject, subjectOverride: overrides.port ?? null, effectiveSubject: effective, }; }); return NextResponse.json({ data }); } catch (error) { return errorResponse(error); } }), ); export const PUT = withAuth( withPermission('admin', 'manage_settings', async (req, ctx) => { try { const body = await parseBody(req, upsertSchema); const settingKey = settingKeyForSubject(body.key as TemplateKey); const meta = { userId: ctx.userId, portId: ctx.portId, ipAddress: ctx.ipAddress, userAgent: ctx.userAgent, }; if (body.subject === null || body.subject === '') { // Clear the override (and only at the per-port level — never touch global). await deleteSetting(settingKey, ctx.portId, meta); } else { await upsertSetting(settingKey, body.subject, ctx.portId, meta); } return NextResponse.json({ data: { ok: true } }); } catch (error) { return errorResponse(error); } }), );