rebreak-monorepo/backend/server/api/protection/screentime-passcode.post.ts
chahinebrini ab4b9c48e5 feat(ios): Screen Time Passcode als Layer 3 (setup flow)
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>
2026-06-01 04:19:43 +02:00

30 lines
914 B
TypeScript

import { requireUser } from "../../utils/auth";
import { usePrisma } from "../../utils/prisma";
/**
* POST /api/protection/screentime-passcode
*
* Speichert den vom Client generierten Screen-Time-Passcode.
* User setzt diesen Code manuell in iOS Settings → Screen Time.
* Nach Cooldown abrufbar via GET /api/protection/screentime-passcode.
*
* Body: { passcode: string } — 4-stelliger numerischer Code
*/
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const body = await readBody(event);
const passcode = body?.passcode;
if (typeof passcode !== "string" || !/^\d{4}$/.test(passcode)) {
throw createError({ statusCode: 400, message: "passcode must be a 4-digit string" });
}
const db = usePrisma();
await db.profile.update({
where: { id: user.id },
data: { screentimePasscode: passcode },
});
return { success: true };
});