feat(protection): VIP umfasst auch approved Custom-Domains
getWebCustomDomains schliesst nur noch 'rejected' aus — 'approved' Domains bleiben in der Layer-2-VIP (Zweitschutz, falls Layer 1 aus ist). Reihenfolge: pending zuerst (keine Layer-1-Deckung → duerfen nie aus dem 50er-Cap fallen), dann approved neueste-zuerst (Ueberlauf = aelteste approved, via Layer 1 gedeckt). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ced749018b
commit
a713070d25
@ -22,24 +22,35 @@ export const CUSTOM_DOMAIN_TYPES: CustomDomainType[] = [
|
||||
// ─── Custom Domains ───────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Gibt die aktiven Web-Custom-Domains eines Users zurück (nur type='web').
|
||||
* Status 'approved' und 'rejected' werden ausgeschlossen:
|
||||
* - approved → Domain ist in der globalen Blocklist, kein Slot mehr nötig
|
||||
* - rejected → Domain wurde abgelehnt und Slot wurde freigegeben
|
||||
* Wird von GET /api/protection/webcontent-domains für die VIP-Komposition genutzt.
|
||||
* Web-Custom-Domains eines Users für die Layer-2-VIP-Komposition (type='web').
|
||||
* Nur 'rejected' wird ausgeschlossen — 'approved' Domains BLEIBEN in der VIP:
|
||||
* Layer 2 ist der Zweitschutz für den Fall, dass Layer 1 (VPN/URL-Filter) aus
|
||||
* ist. Eine approved Domain ist zwar in der globalen Layer-1-Blocklist, muss
|
||||
* aber auch in Layer 2 gedeckt sein.
|
||||
*
|
||||
* Reihenfolge = Priorität für den 50er-Cap im Endpoint:
|
||||
* 1. pending zuerst — KEINE Layer-1-Deckung, die VIP ist ihre einzige
|
||||
* Absicherung → dürfen nie aus dem Cap fallen (≤ Slot-Limit, passen immer).
|
||||
* 2. approved danach, neueste zuerst — bei Überlauf fallen die ältesten
|
||||
* approved weg (via Layer 1 weiter gedeckt, daher vertretbar).
|
||||
*
|
||||
* Wird von GET /api/protection/webcontent-domains genutzt.
|
||||
*/
|
||||
export async function getWebCustomDomains(userId: string): Promise<string[]> {
|
||||
const db = usePrisma();
|
||||
const rows = await db.userCustomDomain.findMany({
|
||||
where: {
|
||||
userId,
|
||||
type: "web",
|
||||
status: { notIn: ["approved", "rejected"] },
|
||||
},
|
||||
// pending = alles außer approved/rejected — älteste zuerst (passen alle rein)
|
||||
const pending = await db.userCustomDomain.findMany({
|
||||
where: { userId, type: "web", status: { notIn: ["approved", "rejected"] } },
|
||||
orderBy: { addedAt: "asc" },
|
||||
select: { domain: true },
|
||||
});
|
||||
return rows.map((r) => r.domain);
|
||||
// approved — neueste zuerst, damit bei Cap-Überlauf die ältesten wegfallen
|
||||
const approved = await db.userCustomDomain.findMany({
|
||||
where: { userId, type: "web", status: "approved" },
|
||||
orderBy: { addedAt: "desc" },
|
||||
select: { domain: true },
|
||||
});
|
||||
return [...pending.map((r) => r.domain), ...approved.map((r) => r.domain)];
|
||||
}
|
||||
|
||||
export async function getUserCustomDomains(userId: string) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user