import gamblingDomains from "../../data/gambling-domains.json"; import { usePrisma } from "../../utils/prisma"; const COUNTRY_KEYS = ["DE", "GB", "FR", "TN"] as const; type CountryKey = (typeof COUNTRY_KEYS)[number]; const GLOBAL_LISTS = gamblingDomains as unknown as Record; const MAX_PER_COUNTRY = 50; /** * GET /api/protection/webcontent-domains * * Liefert die Country-Curated-Domain-Liste für den WebKit-webContent-Filter * (Layer 2). Nach Layer-2-Country-Pivot (2026-05-25) ist Layer 2 vollständig * entkoppelt von User-Custom-Domains: * * Layer 1 (VPN/blocklist.bin) = User-Custom-Domains + globale Blocklist * Layer 2 (iOS NEFilter) = ausschliesslich Country-Curated (Admin-managed) * * Zusammensetzung pro Land: * 1. Statische gambling-domains.json (build-time gebundelt) * 2. DB-approved CuratedDomain-Rows (Admin-kuratiert + User-Vorschläge mit status="approved") * → dedupliziert → hart auf 50 gekappt (Apple-Limit) * * Optional: Query-Param ?travel=FR für Travel-Detection (Server-side Merge). * iOS sendet origin (OS-Region) + travel (Cellular-MCC-Land) wenn verfügbar. * Ohne Params: alle COUNTRY_KEYS werden zurückgegeben — iOS filtert selbst. * * Response-Shape unverändert: { _meta, DE: [], GB: [], FR: [], TN: [] } */ export default defineEventHandler(async (event) => { await requireUser(event); // Auth bleibt — kein User-Lookup, nur Authentifizierung const db = usePrisma(); const approvedCurated = await db.curatedDomain.findMany({ where: { status: "approved" }, select: { domain: true, country: true }, }); const curatedByCountry: Record = {}; for (const c of approvedCurated) { (curatedByCountry[c.country] ??= []).push(c.domain); } const composed: Record = {} as Record< CountryKey, string[] >; for (const country of COUNTRY_KEYS) { const merged = [ ...new Set([ ...(GLOBAL_LISTS[country] ?? []), ...(curatedByCountry[country] ?? []), ]), ]; composed[country] = merged.slice(0, MAX_PER_COUNTRY); } return { _meta: gamblingDomains._meta, ...composed, }; });