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