User generiert 4-stelligen Code in der App, setzt ihn manuell als Screen Time Passcode → ReBreak speichert ihn auf dem Backend. Damit kann niemand Screen Time deaktivieren → deny-removal bleibt aktiv → App nicht deinstallierbar ohne den Passcode. Backend: - Profile.screentimePasscode Feld (Migration add_screentime_passcode) - POST /api/protection/screentime-passcode — Code speichern - GET /api/protection/screentime-passcode — Code abrufen (nach Cooldown) iOS UI (blocker.tsx): - ScreentimePasscodeCard erscheint wenn Layer 1 + 2 aktiv (iOS only) - Code-Generierung → Einmal-Anzeige → Deep-Link zu Settings → Screen Time - Bestätigung speichert Code auf Backend, Card zeigt Confirmed-State Locales: DE/EN/FR/AR screentime_* Keys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { requireUser } from "../../utils/auth";
|
|
import { usePrisma } from "../../utils/prisma";
|
|
import { getActiveCooldown, resolveCooldown } from "../../db/cooldown";
|
|
|
|
/**
|
|
* GET /api/protection/screentime-passcode
|
|
*
|
|
* Gibt den Screen-Time-Passcode zurück — aber NUR wenn kein aktiver
|
|
* Cooldown läuft (canDisableProtection = true). Das stellt sicher dass
|
|
* der Code erst nach der 24h-Wartezeit abrufbar ist.
|
|
*
|
|
* Gibt { passcode: null } zurück wenn noch kein Code gesetzt wurde
|
|
* oder Cooldown noch läuft (kein Error, kein 403 — Client unterscheidet
|
|
* anhand passcode=null ob Code fehlt oder gesperrt ist).
|
|
*/
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event);
|
|
const db = usePrisma();
|
|
|
|
const cooldown = await getActiveCooldown(user.id);
|
|
if (cooldown) {
|
|
const expired = new Date() >= cooldown.cooldownEndsAt;
|
|
if (!expired) {
|
|
return { success: true, data: { passcode: null, reason: "cooldown_active" } };
|
|
}
|
|
await resolveCooldown(cooldown.id);
|
|
}
|
|
|
|
const profile = await db.profile.findUnique({
|
|
where: { id: user.id },
|
|
select: { screentimePasscode: true },
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
data: { passcode: profile?.screentimePasscode ?? null },
|
|
};
|
|
});
|