Initial
This commit is contained in:
66
server/services/intuneDriftService.js
Normal file
66
server/services/intuneDriftService.js
Normal file
@@ -0,0 +1,66 @@
|
||||
// Pure drift computation: compares the POSHManager plan (expected) against what
|
||||
// Microsoft Graph currently reports (live), for the win32LobApp metadata, its
|
||||
// assignments, and its supersedence/dependency relationships. No I/O — the
|
||||
// controller fetches live state and feeds it here, so this is fully unit-tested.
|
||||
|
||||
// Fields on the win32LobApp we treat as authoritative from the plan.
|
||||
const APP_DRIFT_FIELDS = [
|
||||
'displayName',
|
||||
'publisher',
|
||||
'installCommandLine',
|
||||
'uninstallCommandLine',
|
||||
'applicableArchitectures'
|
||||
];
|
||||
|
||||
function fieldDrift(expected = {}, actual = {}, fields = APP_DRIFT_FIELDS) {
|
||||
const drift = [];
|
||||
for (const field of fields) {
|
||||
const want = expected[field] ?? '';
|
||||
const got = actual[field] ?? '';
|
||||
if (String(want) !== String(got)) drift.push({ field, expected: want, actual: got });
|
||||
}
|
||||
return drift;
|
||||
}
|
||||
|
||||
function assignmentKey(assignment = {}) {
|
||||
const target = assignment.target || {};
|
||||
const type = (target['@odata.type'] || '').replace('#microsoft.graph.', '');
|
||||
return `${assignment.intent || ''}|${type}|${target.groupId || ''}`;
|
||||
}
|
||||
|
||||
function relationshipKey(rel = {}) {
|
||||
const type = (rel['@odata.type'] || '').replace('#microsoft.graph.', '');
|
||||
return `${type}|${rel.targetId || ''}`;
|
||||
}
|
||||
|
||||
// Generic set diff by key: returns items present only in expected (missing in
|
||||
// tenant) and only in actual (extra in tenant).
|
||||
function setDiff(expected, actual, keyFn) {
|
||||
const expectedKeys = new Map(expected.map((item) => [keyFn(item), item]));
|
||||
const actualKeys = new Map(actual.map((item) => [keyFn(item), item]));
|
||||
const missing = [...expectedKeys.keys()].filter((k) => !actualKeys.has(k));
|
||||
const extra = [...actualKeys.keys()].filter((k) => !expectedKeys.has(k));
|
||||
return { missing, extra };
|
||||
}
|
||||
|
||||
export function computeDrift({
|
||||
expectedApp = {},
|
||||
liveApp = {},
|
||||
expectedAssignments = [],
|
||||
liveAssignments = [],
|
||||
expectedRelationships = [],
|
||||
liveRelationships = []
|
||||
} = {}) {
|
||||
const appDrift = fieldDrift(expectedApp, liveApp);
|
||||
const assignmentDrift = setDiff(expectedAssignments, liveAssignments, assignmentKey);
|
||||
const relationshipDrift = setDiff(expectedRelationships, liveRelationships, relationshipKey);
|
||||
|
||||
const inSync =
|
||||
appDrift.length === 0 &&
|
||||
assignmentDrift.missing.length === 0 &&
|
||||
assignmentDrift.extra.length === 0 &&
|
||||
relationshipDrift.missing.length === 0 &&
|
||||
relationshipDrift.extra.length === 0;
|
||||
|
||||
return { inSync, appDrift, assignmentDrift, relationshipDrift };
|
||||
}
|
||||
Reference in New Issue
Block a user