- 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)
89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import { usePrisma } from "./prisma";
|
|
import { deleteAdGuardClient } from "./adguard";
|
|
|
|
/**
|
|
* Cron-Worker für RebreakMagic Release-Requests (24h Cooldown).
|
|
* Findet alle Devices mit abgelaufenem Release-Request und invalidiert Token.
|
|
*
|
|
* USAGE:
|
|
* - Via Nitro scheduled task (nitro.config.ts)
|
|
* - Via externer Cron (curl POST /api/cron/magic-releases mit Auth-Header)
|
|
* - Manuell für Testing: await processMagicReleases()
|
|
*/
|
|
export async function processMagicReleases(): Promise<{
|
|
processed: number;
|
|
errors: Array<{ deviceId: string; error: string }>;
|
|
}> {
|
|
const db = usePrisma();
|
|
const now = new Date();
|
|
const releaseThreshold = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
|
|
// Finde Devices mit abgelaufenem Release (24h Cooldown rum)
|
|
const devicesToRelease = await db.userDevice.findMany({
|
|
where: {
|
|
releaseRequestedAt: {
|
|
lte: releaseThreshold,
|
|
},
|
|
magicRevokedAt: null,
|
|
magicEnrolledAt: { not: null },
|
|
},
|
|
select: {
|
|
id: true,
|
|
deviceId: true,
|
|
userId: true,
|
|
magicDnsToken: true,
|
|
releaseRequestedAt: true,
|
|
},
|
|
});
|
|
|
|
console.log(
|
|
`[MagicCron] Processing ${devicesToRelease.length} devices for release`,
|
|
);
|
|
|
|
const errors: Array<{ deviceId: string; error: string }> = [];
|
|
let processed = 0;
|
|
|
|
for (const device of devicesToRelease) {
|
|
try {
|
|
// 1. Invalidate DNS-Token (AdGuard Client löschen)
|
|
const clientName = `magic_${device.deviceId}`;
|
|
try {
|
|
await deleteAdGuardClient(clientName);
|
|
console.log(`[MagicCron] Deleted AdGuard client: ${clientName}`);
|
|
} catch (err: any) {
|
|
console.warn(
|
|
`[MagicCron] AdGuard deletion failed for ${clientName}: ${err.message}`,
|
|
);
|
|
// Continue — DB-Invalidierung erfolgt trotzdem (Failsafe)
|
|
}
|
|
|
|
// 2. Setze magicRevokedAt (Token serverseitig tot)
|
|
await db.userDevice.update({
|
|
where: { id: device.id },
|
|
data: {
|
|
magicRevokedAt: now,
|
|
},
|
|
});
|
|
|
|
console.log(
|
|
`[MagicCron] Released Magic binding: userId=${device.userId} deviceId=${device.deviceId}`,
|
|
);
|
|
processed++;
|
|
} catch (err: any) {
|
|
console.error(
|
|
`[MagicCron] Failed to release device ${device.deviceId}:`,
|
|
err,
|
|
);
|
|
errors.push({
|
|
deviceId: device.deviceId,
|
|
error: err.message || String(err),
|
|
});
|
|
}
|
|
}
|
|
|
|
console.log(
|
|
`[MagicCron] Finished: ${processed} released, ${errors.length} errors`,
|
|
);
|
|
return { processed, errors };
|
|
}
|