chahinebrini 8e562c982d feat(backend): MDM-Managed Flag — migration + endpoint + guards
- Prisma migration: users.mdm_managed (Boolean DEFAULT false) + users.mdm_detected_at (DateTime?)
- setMdmManaged() helper in server/db/profile.ts
- POST /api/users/me/mdm-status — App reports MDM status to backend
- cooldown/status + cooldown/request — early-return 400 when mdm_managed
- protection/state — response extended with mdmManaged: boolean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 00:46:44 +02:00

46 lines
1.3 KiB
TypeScript

import { requireUser } from "../../../utils/auth";
import { setMdmManaged } from "../../../db/profile";
import { z } from "zod";
const Body = z.object({
mdmManaged: z.boolean(),
});
/**
* POST /api/users/me/mdm-status
*
* App ruft diesen Endpoint auf nachdem nativ via NEFilterManager.shared()
* .loadFromPreferences() der MDM-NEFilter-Active-State detektiert wurde.
*
* Body: { mdmManaged: boolean }
* true → MDM-Profil aktiv auf Device — setzt mdm_managed=true in DB
* false → Profil nicht aktiv (z.B. nach Trustee-Deactivation, Reset) →
* setzt mdm_managed=false (mdm_detected_at bleibt als Audit-Trail)
*
* Response: { ok: true, mdmManaged: boolean, mdmDetectedAt: string | null }
*/
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const raw = await readBody(event).catch(() => ({}));
const parsed = Body.safeParse(raw);
if (!parsed.success) {
throw createError({
statusCode: 400,
data: { error: "INVALID_BODY", detail: parsed.error.flatten() },
});
}
const { mdmManaged } = parsed.data;
const result = await setMdmManaged(user.id, mdmManaged);
return {
success: true,
data: {
ok: true,
mdmManaged: result.mdmManaged,
mdmDetectedAt: result.mdmDetectedAt?.toISOString() ?? null,
},
};
});