From 86ed603a45e8e194c9b45586f1395fa89c60bdab Mon Sep 17 00:00:00 2001 From: chahinebrini Date: Thu, 21 May 2026 20:21:54 +0200 Subject: [PATCH] =?UTF-8?q?feat(protection):=20GET=20/api/protection/webco?= =?UTF-8?q?ntent-domains=20=E2=80=94=20runtime-updatebare=20Layer-2-Domain?= =?UTF-8?q?-Liste?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Neuer Nitro-Endpoint serviert die kuratierte Gambling-Domain-Liste pro Land (DE/GB/FR) aus backend/data/gambling-domains.json. Auth wie alle /api/protection/*-Routen (requireUser). 50-Domain-Cap pro Land serverseitig erzwungen. Liste pflegen = JSON editieren + _meta.version hochzaehlen + deploy. Co-Authored-By: Claude Opus 4.7 --- backend/data/gambling-domains.json | 95 +++++++++++++++++++ backend/nitro.config.ts | 7 ++ .../api/protection/webcontent-domains.get.ts | 55 +++++++++++ 3 files changed, 157 insertions(+) create mode 100644 backend/data/gambling-domains.json create mode 100644 backend/server/api/protection/webcontent-domains.get.ts diff --git a/backend/data/gambling-domains.json b/backend/data/gambling-domains.json new file mode 100644 index 0000000..7ab6687 --- /dev/null +++ b/backend/data/gambling-domains.json @@ -0,0 +1,95 @@ +{ + "_comment": "Kuratierte Gambling-Domain-Liste pro Land. APPLE-HARTLIMIT: max. 50 Domains pro Land-Key — NIE überschreiten. Schlüssel = ISO-3166-1-alpha-2 (Locale.current.region). Werte = registrierbare Domains ohne Schema/Subdomain (ManagedSettings WebDomain matched inkl. aller Subdomains). Pflege: Datei editieren, version hochzählen, updatedAt setzen, dann neu deployen.", + "_meta": { + "version": 1, + "updatedAt": "2026-05-21", + "maxDomainsPerCountry": 50, + "status": "starter" + }, + "DE": [ + "tipico.de", + "tipico.com", + "bwin.de", + "bwin.com", + "interwetten.de", + "interwetten.com", + "betano.de", + "bet-at-home.com", + "sportwetten.de", + "merkur-bets.de", + "merkurbets.de", + "happybet.de", + "neobet.de", + "winamax.de", + "betway.de", + "admiralbet.de", + "oddset.de", + "lottohelden.de", + "lotto.de", + "lotto24.de", + "jackpot.de", + "drueckglueck.de", + "loewen-play.de", + "merkur24.com", + "casino.de", + "casinos.de", + "betsson.de", + "leovegas.de", + "lapalingo.com", + "sunmaker.de" + ], + "GB": [ + "bet365.com", + "williamhill.com", + "skybet.com", + "skyvegas.com", + "ladbrokes.com", + "coral.co.uk", + "paddypower.com", + "betfair.com", + "betfred.com", + "unibet.co.uk", + "888.com", + "888sport.com", + "888casino.com", + "betway.com", + "virginbet.com", + "boylesports.com", + "betvictor.com", + "10bet.com", + "mrgreen.com", + "casumo.com", + "leovegas.com", + "grosvenorcasinos.com", + "mecca-bingo.com", + "gala-bingo.com", + "tombola.co.uk", + "lottoland.co.uk", + "national-lottery.co.uk", + "kwikfit-pools.co.uk", + "parimatch.co.uk", + "smarkets.com" + ], + "FR": [ + "winamax.fr", + "betclic.fr", + "betclic.com", + "pmu.fr", + "unibet.fr", + "parionssport.fdj.fr", + "fdj.fr", + "zebet.fr", + "vbet.fr", + "netbet.fr", + "bwin.fr", + "genybet.fr", + "zeturf.fr", + "feeling-bet.fr", + "barrierebet.fr", + "pokerstars.fr", + "partypoker.fr", + "lucien-barriere.com", + "casinobarriere.com", + "circus.be" + ] +} diff --git a/backend/nitro.config.ts b/backend/nitro.config.ts index c873a84..38832c4 100644 --- a/backend/nitro.config.ts +++ b/backend/nitro.config.ts @@ -12,6 +12,13 @@ export default defineNitroConfig({ { baseURL: "/", dir: "../public", maxAge: 60 * 60 }, ], + // Server-Assets: werden ins Build-Artifact gebundelt und sind via + // useStorage('assets:server') abrufbar. Kein process.cwd()-Trick nötig. + // gambling-domains.json: runtime-updatebare iOS-Layer-2-Domain-Liste. + serverAssets: [ + { baseName: "data", dir: "../data" }, + ], + // Supabase als external dep — nicht bundlen externals: { inline: [/^(?!@supabase\/supabase-js)/], diff --git a/backend/server/api/protection/webcontent-domains.get.ts b/backend/server/api/protection/webcontent-domains.get.ts new file mode 100644 index 0000000..9dfefeb --- /dev/null +++ b/backend/server/api/protection/webcontent-domains.get.ts @@ -0,0 +1,55 @@ +import { requireUser } from "../../utils/auth"; + +const MAX_DOMAINS_PER_COUNTRY = 50; + +/** + * GET /api/protection/webcontent-domains + * + * Liefert die runtime-updatebare iOS-Layer-2-Gambling-Domain-Liste. + * Datenquelle: backend/data/gambling-domains.json (file-based, v1). + * Im Build über Nitro serverAssets gebundelt → kein process.cwd()-Trick. + * + * Pflege: backend/data/gambling-domains.json editieren, + * _meta.version hochzählen, _meta.updatedAt setzen, dann neu deployen. + * + * Apple-Hartlimit: max. 50 Domains pro Land-Key. Wird serverseitig + * enforced (slice), damit ein versehentlicher Überschuss in der JSON-Datei + * nie zur App durchdringt. + * + * Auth: identisch zu allen anderen /api/protection/*-Routen (requireUser). + */ +export default defineEventHandler(async (event) => { + await requireUser(event); + + const storage = useStorage("assets:server"); + const raw = await storage.getItem<{ + _meta: { version: number; updatedAt: string; [k: string]: unknown }; + _comment?: string; + [country: string]: unknown; + }>("data:gambling-domains.json"); + + if (!raw) { + throw createError({ + statusCode: 500, + message: "GAMBLING_DOMAINS_UNAVAILABLE", + }); + } + + const { _meta, _comment: _c, ...countryEntries } = raw; + + const countries: Record = {}; + for (const [key, value] of Object.entries(countryEntries)) { + if (Array.isArray(value)) { + // Apple-Hartlimit: niemals mehr als 50 Domains pro Land ausliefern + countries[key] = (value as string[]).slice(0, MAX_DOMAINS_PER_COUNTRY); + } + } + + return { + _meta: { + version: _meta.version, + updatedAt: _meta.updatedAt, + }, + ...countries, + }; +});