feat(backend): add MDM health check cron
This commit is contained in:
parent
74784fc4da
commit
15b4441deb
106
backend/server/plugins/mdm-health-cron.ts
Normal file
106
backend/server/plugins/mdm-health-cron.ts
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* MDM Healthcheck Cron
|
||||
*
|
||||
* Läuft alle 5 Minuten. Prüft für alle mit NanoMDM verknüpften iOS-Geräte
|
||||
* den aktuellen Enrollment-/Supervision-Status und spiegelt ihn auf UserDevice.
|
||||
*/
|
||||
import { consola } from "consola";
|
||||
import {
|
||||
getLinkedUserDevices,
|
||||
getMdmEnrollmentStatusesByUdids,
|
||||
updateUserDeviceMdmHealth,
|
||||
type MdmEnrollmentStatus,
|
||||
} from "../db/mdm";
|
||||
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
const INITIAL_DELAY_MS = 30 * 1000;
|
||||
|
||||
let running = false;
|
||||
|
||||
export default defineNitroPlugin((nitro) => {
|
||||
if (import.meta.dev) {
|
||||
consola.info("[mdm-health-cron] Skipping cron in dev mode");
|
||||
return;
|
||||
}
|
||||
|
||||
consola.info("[mdm-health-cron] Starting (5min interval)");
|
||||
|
||||
const initialTimer = setTimeout(() => {
|
||||
runMdmHealthCheck().catch(() => {});
|
||||
}, INITIAL_DELAY_MS);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
runMdmHealthCheck().catch(() => {});
|
||||
}, FIVE_MINUTES);
|
||||
|
||||
nitro.hooks.hook("close", () => {
|
||||
clearTimeout(initialTimer);
|
||||
clearInterval(interval);
|
||||
});
|
||||
});
|
||||
|
||||
async function runMdmHealthCheck() {
|
||||
if (running) {
|
||||
consola.info("[mdm-health-cron] Previous run still in progress, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
running = true;
|
||||
const start = Date.now();
|
||||
|
||||
try {
|
||||
const devices = await getLinkedUserDevices();
|
||||
if (devices.length === 0) {
|
||||
consola.info("[mdm-health-cron] No linked iOS devices");
|
||||
return;
|
||||
}
|
||||
|
||||
const statuses = await getMdmEnrollmentStatusesByUdids(
|
||||
devices.map((d) => d.mdmId).filter((id): id is string => id != null),
|
||||
);
|
||||
|
||||
let updated = 0;
|
||||
let unchanged = 0;
|
||||
|
||||
for (const device of devices) {
|
||||
const status: MdmEnrollmentStatus = statuses.get(device.mdmId ?? "") ?? {
|
||||
enrolled: false,
|
||||
supervised: false,
|
||||
lastSeenAt: null,
|
||||
};
|
||||
|
||||
const changed =
|
||||
device.mdmEnrolled !== status.enrolled ||
|
||||
device.mdmSupervised !== status.supervised ||
|
||||
!sameNullableDate(device.mdmLastSeenAt, status.lastSeenAt);
|
||||
|
||||
if (!changed) {
|
||||
unchanged++;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await updateUserDeviceMdmHealth(device.id, status);
|
||||
updated++;
|
||||
} catch (err: any) {
|
||||
consola.error(
|
||||
`[mdm-health-cron] Failed to update device ${device.id}: ${err?.message ?? err}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
consola.success(
|
||||
`[mdm-health-cron] Checked ${devices.length} devices in ${Date.now() - start}ms (${updated} updated, ${unchanged} unchanged)`,
|
||||
);
|
||||
} catch (err: any) {
|
||||
consola.error("[mdm-health-cron] run failed:", err?.message ?? err);
|
||||
} finally {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
function sameNullableDate(a: Date | null, b: Date | null): boolean {
|
||||
if (a === null && b === null) return true;
|
||||
if (a === null || b === null) return false;
|
||||
return a.getTime() === b.getTime();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user