67 lines
2.4 KiB
JavaScript
67 lines
2.4 KiB
JavaScript
// 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 };
|
|
}
|