feat: multi-server JMAP support

This commit is contained in:
Linus Rath
2026-05-06 17:33:55 +02:00
parent 43475945bf
commit d3d79be64c
20 changed files with 818 additions and 108 deletions
+18
View File
@@ -3,6 +3,7 @@ import { configManager } from '@/lib/admin/config-manager';
import { requireAdminAuth, getClientIP } from '@/lib/admin/session';
import { auditLog } from '@/lib/admin/audit';
import { CONFIG_ENV_MAP } from '@/lib/admin/types';
import { parseJmapServers } from '@/lib/admin/jmap-servers';
import { logger } from '@/lib/logger';
/**
@@ -47,6 +48,23 @@ export async function PATCH(request: NextRequest) {
return NextResponse.json({ error: `Unknown config keys: ${invalidKeys.join(', ')}` }, { status: 400 });
}
// Normalize jmapServers: pass through the parser so invalid entries are
// rejected (bad ids, duplicate ids, non-HTTP URLs) before they're persisted.
if ('jmapServers' in updates) {
const incoming = updates.jmapServers;
if (incoming != null && !Array.isArray(incoming)) {
return NextResponse.json({ error: 'jmapServers must be an array' }, { status: 400 });
}
const sanitized = parseJmapServers(incoming);
const incomingCount = Array.isArray(incoming) ? incoming.length : 0;
if (sanitized.length !== incomingCount) {
return NextResponse.json({
error: 'One or more jmapServers entries are invalid (each needs a unique id, label, and HTTP(S) url).',
}, { status: 400 });
}
updates.jmapServers = sanitized;
}
// Get old values for audit
const oldValues: Record<string, unknown> = {};
for (const key of Object.keys(updates)) {