Public-Domain-Guard (icloud.com/gmail.com etc. nie blockbar/veröffentlichbar): - neue utils/public-email-domains.ts (shared Freemail-Liste) - custom-domains/index.post + custom-domains/suggest + curated-domains/suggest lehnen Public-Domains mit 400 PUBLIC_DOMAIN ab (defense-in-depth) Mail-Detection (mo): "spins" zu GAMBLING_KEYWORDS + Subject-%-Pattern (Score 10) → fängt "Spins + 400% Bonus"-Spam von Freemail-Absendern. 61/61 Tests grün. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import { usePrisma } from "../../utils/prisma";
|
|
import { isPublicEmailDomain } from "../../utils/public-email-domains";
|
|
|
|
// Domain muss mindestens eine TLD haben (z.B. "mbet216.com").
|
|
const DOMAIN_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/;
|
|
// Unterstützte VIP-Länder — muss zu COUNTRY_KEYS in webcontent-domains.get.ts passen.
|
|
const VALID_COUNTRIES = ["DE", "GB", "FR", "TN"];
|
|
|
|
/**
|
|
* POST /api/curated-domains/suggest
|
|
*
|
|
* Ein User schlägt eine länderspezifische Glücksspielseite für die kuratierte
|
|
* VIP-Layer-2-Liste seines Landes vor. Der Eintrag landet als `suggested` in
|
|
* der curated_domains-Tabelle; ein ReBreak-Admin gibt ihn frei (`approved`) —
|
|
* erst dann komponiert ihn der webcontent-domains-Endpoint in die Länderliste.
|
|
*
|
|
* Body: { domain: string, country: string (ISO-2) }
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event);
|
|
const body = await readBody(event);
|
|
|
|
// Domain normalisieren — lowercase, Schema/Pfad/www. strippen.
|
|
const domain = (typeof body?.domain === "string" ? body.domain : "")
|
|
.trim()
|
|
.toLowerCase()
|
|
.replace(/^https?:\/\//, "")
|
|
.replace(/\/.*$/, "")
|
|
.replace(/^www\./, "");
|
|
const country =
|
|
typeof body?.country === "string" ? body.country.toUpperCase() : "";
|
|
|
|
if (!domain || domain.length > 253 || !DOMAIN_RE.test(domain)) {
|
|
throw createError({ statusCode: 400, data: { error: "INVALID_DOMAIN" } });
|
|
}
|
|
// Public-/Freemail-Domains nie in die kuratierte VIP-Liste (icloud.com etc.).
|
|
if (isPublicEmailDomain(domain)) {
|
|
throw createError({ statusCode: 400, data: { error: "PUBLIC_DOMAIN" } });
|
|
}
|
|
if (!VALID_COUNTRIES.includes(country)) {
|
|
throw createError({ statusCode: 400, data: { error: "INVALID_COUNTRY" } });
|
|
}
|
|
|
|
const db = usePrisma();
|
|
|
|
// Schon vorhanden (egal welcher Status)? Dann nicht doppelt anlegen.
|
|
const existing = await db.curatedDomain.findUnique({
|
|
where: { country_domain: { country, domain } },
|
|
select: { status: true },
|
|
});
|
|
if (existing) {
|
|
return { ok: false, alreadyExists: true, status: existing.status };
|
|
}
|
|
|
|
await db.curatedDomain.create({
|
|
data: { domain, country, status: "suggested", suggestedByUserId: user.id },
|
|
});
|
|
|
|
return { ok: true };
|
|
});
|