chahinebrini 1215356990 feat(backend): add POST /api/devices/check-lock for native auth flow
Native app uses supabase.auth.signInWithPassword directly, bypassing
/api/auth/login. This authenticated endpoint runs the same device-lock
check post-auth: 409 DEVICE_LOCKED if bound to another user, 200+bind
if Pro/Legend user, no-op bind for Free users. CORS headers extended
to include x-device-name/model/os. 34 tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 02:38:59 +02:00

39 lines
1.4 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* CORS Middleware läuft vor jedem API-Request.
*
* Warum Middleware statt routeRules:
* - routeRules mit cors:true + headers:{} setzt den Header doppelt → Browser blockiert
* - Nur hier kann OPTIONS-Preflight korrekt mit 204 beantwortet werden
*
* Origin-Strategie: echo zurück statt *, damit Capacitor-Webview (capacitor://localhost),
* iOS-Scheme (rebreakapp://), Android (http://localhost) und alle Staging/Prod-Domains
* funktionieren ohne explizite Whitelist pflegen zu müssen.
* Das API verwendet Bearer-Token-Auth (kein Cookie/credentials), daher ist das sicher.
*/
export default defineEventHandler((event) => {
if (!event.path.startsWith("/api/")) return;
const origin = getHeader(event, "origin") ?? "*";
setHeader(event, "Access-Control-Allow-Origin", origin);
setHeader(event, "Access-Control-Allow-Credentials", "true");
setHeader(
event,
"Access-Control-Allow-Methods",
"GET, POST, PUT, PATCH, DELETE, OPTIONS"
);
setHeader(
event,
"Access-Control-Allow-Headers",
"Content-Type, Authorization, apikey, x-client-info, x-device-id, x-platform, x-device-name, x-device-model, x-device-os"
);
setHeader(event, "Access-Control-Max-Age", "3600");
setHeader(event, "Vary", "Origin");
// OPTIONS Preflight → sofort 204 zurück, kein Handler nötig
if (getMethod(event) === "OPTIONS") {
event.node.res.statusCode = 204;
event.node.res.end();
}
});