import { requireUser } from "../../utils/auth"; import { getActiveCooldown, resolveCooldown } from "../../db/cooldown"; import { getProfile } from "../../db/profile"; import { usePrisma } from "../../utils/prisma"; /** * GET /api/protection/state * Combined protection + cooldown state polled every 30 s by the app. */ export default defineEventHandler(async (event) => { const user = await requireUser(event); const [cooldown, profile] = await Promise.all([ getActiveCooldown(user.id), getProfile(user.id), ]); const now = new Date(); let active = false; let remainingSeconds = 0; let cooldownEndsAt: string | null = null; // True wenn dieser Request gerade einen abgelaufenen Cooldown resolved hat. let cooldownJustResolved = false; if (cooldown) { const expired = now >= cooldown.cooldownEndsAt; if (expired) { await resolveCooldown(cooldown.id); // Anti-Auto-Reactivation: Cooldown wurde durchgehalten → Schutz bleibt // jetzt AUS, User muss explizit reaktivieren. MUSS hier passieren — // dieser Endpoint wird alle 5s während Cooldown gepollt und gewinnt das // Race gegen /api/cooldown/status fast immer. Ohne dieses Update bliebe // protectionDisabledAt null → protectionShouldBeActive=true → Frontend- // Bypass-Detection würde den Schutz automatisch wieder anschalten. await usePrisma() .profile.update({ where: { id: user.id }, data: { protectionDisabledAt: new Date() }, }) .catch(() => {}); cooldownJustResolved = true; // After resolve: no active cooldown } else { active = true; remainingSeconds = Math.max( 0, Math.floor((cooldown.cooldownEndsAt.getTime() - now.getTime()) / 1000), ); cooldownEndsAt = cooldown.cooldownEndsAt.toISOString(); } } const plan = (profile?.plan ?? "free") as "free" | "pro" | "legend"; // protectionShouldBeActive = "der Schutz sollte gerade auf dem Device laufen" // - false wenn Cooldown aktiv ist (User darf grad nicht zurück-reaktivieren) // - false wenn User per Cooldown-Resolve explizit abgeschaltet hat // (protectionDisabledAt gesetzt) → Frontend macht KEINE Auto-Reactivation, // User muss explizit re-aktivieren via /api/protection/mark-active. // - true sonst (Normal-Zustand: Schutz sollte laufen) const protectionShouldBeActive = !active && profile?.protectionDisabledAt === null && !cooldownJustResolved; return { success: true, data: { protectionShouldBeActive, cooldown: { active, remainingSeconds, cooldownEndsAt, }, plan, }, }; });