chahinebrini 77edd67cbe fix(magic): explicit imports + staging defaults + sheet height
- backend/api/magic/register: explicit import of MAGIC_DEVICE_LIMIT
  and createAdGuardClient (Nitro auto-import was missing them
  → ReferenceError → HTTP 500 on /api/magic/register)
- mac-app: default backendBaseUrl falls back to staging.rebreak.org
  (app.rebreak.org serves wrong TLS cert)
- native MagicSheet: fallback download/dmg URLs point to staging
- native settings: Magic sheet capped at detents=[0.85] so AppHeader
  stays visible
- bundles all in-flight Magic feature work (pair create/redeem,
  device endpoints, schema, adguard utils, mac-app, locales)
2026-06-03 08:25:02 +02:00

79 lines
2.0 KiB
TypeScript

import { randomInt } from "crypto";
import { requireUser } from "../../../utils/auth";
/**
* POST /api/magic/pair/create
*
* Native-App ruft auf (Supabase-Auth). Generiert einen 6-stelligen numerischen
* Code mit 10min Lebenszeit. Mac-App tauscht den Code via /pair/redeem gegen
* einen MagicSession-Token.
*
* Returns: { code: "482913", expiresAt: ISO, expiresInSeconds: 600 }
*/
const CODE_TTL_MS = 10 * 60 * 1000; // 10 Minuten
export default defineEventHandler(async (event) => {
const user = await requireUser(event);
const db = usePrisma();
// Alte unbenutzte Codes des Users invalidieren (max 1 aktiv pro User)
await db.magicPairingCode.deleteMany({
where: {
userId: user.id,
redeemedAt: null,
},
});
// Generiere unique 6-digit Code (sehr unwahrscheinlich dass dieselbe
// Zahl gleichzeitig aktiv ist, aber wir retry-en sicherheitshalber).
let code: string | null = null;
let attempts = 0;
while (attempts < 5 && code === null) {
const candidate = String(randomInt(0, 1_000_000)).padStart(6, "0");
const exists = await db.magicPairingCode.findUnique({
where: { code: candidate },
select: { id: true, expiresAt: true, redeemedAt: true },
});
if (
!exists ||
exists.redeemedAt !== null ||
exists.expiresAt < new Date()
) {
// Falls expired/redeemed: löschen damit Unique-Constraint frei wird
if (exists) {
await db.magicPairingCode
.delete({ where: { id: exists.id } })
.catch(() => {});
}
code = candidate;
}
attempts++;
}
if (!code) {
throw createError({
statusCode: 500,
message: "Konnte keinen freien Pairing-Code generieren",
});
}
const expiresAt = new Date(Date.now() + CODE_TTL_MS);
await db.magicPairingCode.create({
data: {
userId: user.id,
code,
expiresAt,
},
});
return {
success: true,
data: {
code,
expiresAt: expiresAt.toISOString(),
expiresInSeconds: Math.floor(CODE_TTL_MS / 1000),
},
};
});