sf-plugin-permission-sets 0.0.0-dev.3 → 0.0.0-dev.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -85
- package/lib/adapters/connection-org-client.d.ts +17 -0
- package/lib/adapters/connection-org-client.d.ts.map +1 -0
- package/lib/adapters/connection-org-client.js +248 -0
- package/lib/adapters/connection-org-client.js.map +1 -0
- package/lib/commands/ps/apply.d.ts +28 -0
- package/lib/commands/ps/apply.d.ts.map +1 -0
- package/lib/commands/ps/apply.js +125 -0
- package/lib/commands/ps/apply.js.map +1 -0
- package/lib/commands/ps/check.d.ts +19 -0
- package/lib/commands/ps/check.d.ts.map +1 -0
- package/lib/commands/ps/check.js +46 -0
- package/lib/commands/ps/check.js.map +1 -0
- package/lib/commands/ps/export.d.ts +18 -0
- package/lib/commands/ps/export.d.ts.map +1 -0
- package/lib/commands/ps/export.js +29 -0
- package/lib/commands/ps/export.js.map +1 -0
- package/lib/commands/ps/plan.d.ts +23 -0
- package/lib/commands/ps/plan.d.ts.map +1 -0
- package/lib/commands/ps/plan.js +78 -0
- package/lib/commands/ps/plan.js.map +1 -0
- package/lib/commands/ps/validate.d.ts +20 -0
- package/lib/commands/ps/validate.d.ts.map +1 -0
- package/lib/commands/ps/validate.js +48 -0
- package/lib/commands/ps/validate.js.map +1 -0
- package/lib/core/diff.d.ts +10 -0
- package/lib/core/diff.d.ts.map +1 -0
- package/lib/core/diff.js +53 -0
- package/lib/core/diff.js.map +1 -0
- package/lib/core/finding.d.ts +40 -0
- package/lib/core/finding.d.ts.map +1 -0
- package/lib/core/finding.js +68 -0
- package/lib/core/finding.js.map +1 -0
- package/lib/core/load.d.ts +4 -0
- package/lib/core/load.d.ts.map +1 -0
- package/lib/core/load.js +53 -0
- package/lib/core/load.js.map +1 -0
- package/lib/core/model.d.ts +69 -0
- package/lib/core/model.d.ts.map +1 -0
- package/lib/core/model.js +2 -0
- package/lib/core/model.js.map +1 -0
- package/lib/core/normalize.d.ts +15 -0
- package/lib/core/normalize.d.ts.map +1 -0
- package/lib/core/normalize.js +62 -0
- package/lib/core/normalize.js.map +1 -0
- package/lib/core/parse.d.ts +10 -0
- package/lib/core/parse.d.ts.map +1 -0
- package/lib/core/parse.js +20 -0
- package/lib/core/parse.js.map +1 -0
- package/lib/core/report.d.ts +8 -0
- package/lib/core/report.d.ts.map +1 -0
- package/lib/core/report.js +62 -0
- package/lib/core/report.js.map +1 -0
- package/lib/core/resolve.d.ts +20 -0
- package/lib/core/resolve.d.ts.map +1 -0
- package/lib/core/resolve.js +88 -0
- package/lib/core/resolve.js.map +1 -0
- package/lib/core/schema.d.ts +33 -0
- package/lib/core/schema.d.ts.map +1 -0
- package/lib/core/schema.js +35 -0
- package/lib/core/schema.js.map +1 -0
- package/lib/core/serialize.d.ts +9 -0
- package/lib/core/serialize.d.ts.map +1 -0
- package/lib/core/serialize.js +34 -0
- package/lib/core/serialize.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/services/adapters/org-client.d.ts +22 -0
- package/lib/services/adapters/org-client.d.ts.map +1 -0
- package/lib/services/adapters/org-client.js +2 -0
- package/lib/services/adapters/org-client.js.map +1 -0
- package/lib/services/apply.d.ts +40 -0
- package/lib/services/apply.d.ts.map +1 -0
- package/lib/services/apply.js +94 -0
- package/lib/services/apply.js.map +1 -0
- package/lib/services/check.d.ts +18 -0
- package/lib/services/check.d.ts.map +1 -0
- package/lib/services/check.js +25 -0
- package/lib/services/check.js.map +1 -0
- package/lib/services/export.d.ts +14 -0
- package/lib/services/export.d.ts.map +1 -0
- package/lib/services/export.js +25 -0
- package/lib/services/export.js.map +1 -0
- package/lib/services/plan.d.ts +35 -0
- package/lib/services/plan.d.ts.map +1 -0
- package/lib/services/plan.js +47 -0
- package/lib/services/plan.js.map +1 -0
- package/lib/services/resolution.d.ts +17 -0
- package/lib/services/resolution.d.ts.map +1 -0
- package/lib/services/resolution.js +36 -0
- package/lib/services/resolution.js.map +1 -0
- package/lib/services/validate.d.ts +21 -0
- package/lib/services/validate.d.ts.map +1 -0
- package/lib/services/validate.js +43 -0
- package/lib/services/validate.js.map +1 -0
- package/messages/ps.apply.md +81 -0
- package/messages/ps.check.md +33 -0
- package/messages/ps.export.md +25 -0
- package/messages/ps.plan.md +45 -0
- package/messages/ps.validate.md +29 -0
- package/package.json +116 -181
- package/lib/commands/hello/world.d.ts +0 -14
- package/lib/commands/hello/world.js +0 -27
- package/lib/commands/hello/world.js.map +0 -1
- package/messages/hello.world.md +0 -29
- package/oclif.lock +0 -7618
- package/oclif.manifest.json +0 -62
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** Construct an error-level finding. Private: callers use the named constructors below. */
|
|
2
|
+
function error(code, message, where = {}) {
|
|
3
|
+
return { level: 'error', code, message, ...where };
|
|
4
|
+
}
|
|
5
|
+
/** Construct a warning-level finding. Private: callers use the named constructors below. */
|
|
6
|
+
function warning(code, message, where = {}) {
|
|
7
|
+
return { level: 'warning', code, message, ...where };
|
|
8
|
+
}
|
|
9
|
+
// Offline findings, raised while reading and structurally checking a file.
|
|
10
|
+
/** Invalid YAML: the parser rejected the document. */
|
|
11
|
+
export function yamlError(message, file, line) {
|
|
12
|
+
return error('YAML', message, { file, line });
|
|
13
|
+
}
|
|
14
|
+
/** The document parsed to nothing. */
|
|
15
|
+
export function emptyFileWarning(file) {
|
|
16
|
+
return warning('EMPTY_FILE', 'file is empty', { file });
|
|
17
|
+
}
|
|
18
|
+
/** The file violates the schema at `path`. */
|
|
19
|
+
export function schemaError(path, message, file) {
|
|
20
|
+
return error('SCHEMA', `${path}: ${message}`, { file });
|
|
21
|
+
}
|
|
22
|
+
/** A scope key is present but its list is empty. */
|
|
23
|
+
export function emptyListWarning(username, scopeKey, file) {
|
|
24
|
+
return warning('EMPTY_LIST', `${username}: ${scopeKey} is empty`, { file });
|
|
25
|
+
}
|
|
26
|
+
/** A target appears more than once under one scope for one user. */
|
|
27
|
+
export function dupTargetWarning(username, target, scopeKey, file) {
|
|
28
|
+
return warning('DUP_TARGET', `${username}: ${target} is listed twice under ${scopeKey}`, { file });
|
|
29
|
+
}
|
|
30
|
+
/** A user declares no scopes at all. */
|
|
31
|
+
export function emptyUserWarning(username, file) {
|
|
32
|
+
return warning('EMPTY_USER', `${username}: no scopes declared`, { file });
|
|
33
|
+
}
|
|
34
|
+
/** No file on disk matched the given glob patterns. */
|
|
35
|
+
export function noFilesError(patterns) {
|
|
36
|
+
return error('NO_FILES', `no files matched: ${patterns.join(', ')}`);
|
|
37
|
+
}
|
|
38
|
+
// Org-side findings, raised while resolving declarations against the org. No file or line.
|
|
39
|
+
/** A declared user does not exist in the org. */
|
|
40
|
+
export function userNotFoundError(username) {
|
|
41
|
+
return error('USER_NOT_FOUND', `${username}: user not found in org`);
|
|
42
|
+
}
|
|
43
|
+
/** A declared user exists but is inactive. */
|
|
44
|
+
export function userInactiveError(username) {
|
|
45
|
+
return error('USER_INACTIVE', `${username}: user is inactive`);
|
|
46
|
+
}
|
|
47
|
+
/** A declared target does not exist in the org. `label` is the kind's human name. */
|
|
48
|
+
export function targetNotFoundError(target, label) {
|
|
49
|
+
return error('TARGET_NOT_FOUND', `${target}: ${label} not found in org`);
|
|
50
|
+
}
|
|
51
|
+
/** A declared target resolves to more than one record in the org. */
|
|
52
|
+
export function targetAmbiguousError(target, label) {
|
|
53
|
+
return error('TARGET_AMBIGUOUS', `${target}: ${label} is not unique in org`);
|
|
54
|
+
}
|
|
55
|
+
/** Render findings as human-readable lines. Shared by check, validate, and apply. */
|
|
56
|
+
export function formatFindings(findings) {
|
|
57
|
+
return findings.map((finding) => {
|
|
58
|
+
const where = finding.file ? `${finding.file}${finding.line ? `:${finding.line}` : ''} ` : '';
|
|
59
|
+
return `${finding.level}: ${where}${finding.message}`;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/** Count findings by level. */
|
|
63
|
+
export function countFindings(findings) {
|
|
64
|
+
const errors = findings.filter((finding) => finding.level === 'error');
|
|
65
|
+
const warnings = findings.filter((finding) => finding.level === 'warning');
|
|
66
|
+
return { errors: errors.length, warnings: warnings.length };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=finding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../../src/core/finding.ts"],"names":[],"mappings":"AA2BA,2FAA2F;AAC3F,SAAS,KAAK,CAAC,IAAiB,EAAE,OAAe,EAAE,QAAe,EAAE;IAChE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACvD,CAAC;AAED,4FAA4F;AAC5F,SAAS,OAAO,CAAC,IAAiB,EAAE,OAAe,EAAE,QAAe,EAAE;IAClE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACzD,CAAC;AAED,2EAA2E;AAE3E,sDAAsD;AACtD,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY,EAAE,IAAa;IAClE,OAAO,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,gBAAgB,CAAC,IAAY;IACzC,OAAO,OAAO,CAAC,YAAY,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,OAAe,EAAE,IAAY;IACnE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,IAAI,KAAK,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,QAAgB,EAAE,IAAY;IAC7E,OAAO,OAAO,CAAC,YAAY,EAAE,GAAG,QAAQ,KAAK,QAAQ,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,MAAc,EAAE,QAAgB,EAAE,IAAY;IAC7F,OAAO,OAAO,CAAC,YAAY,EAAE,GAAG,QAAQ,KAAK,MAAM,0BAA0B,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AACvG,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,IAAY;IAC3D,OAAO,OAAO,CAAC,YAAY,EAAE,GAAG,QAAQ,sBAAsB,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC3C,OAAO,KAAK,CAAC,UAAU,EAAE,qBAAqB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,2FAA2F;AAE3F,iDAAiD;AACjD,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAC9C,OAAO,KAAK,CAAC,gBAAgB,EAAE,GAAG,QAAQ,yBAAyB,CAAC,CAAC;AACzE,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAC9C,OAAO,KAAK,CAAC,eAAe,EAAE,GAAG,QAAQ,oBAAoB,CAAC,CAAC;AACnE,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,KAAa;IAC7D,OAAO,KAAK,CAAC,kBAAkB,EAAE,GAAG,MAAM,KAAK,KAAK,mBAAmB,CAAC,CAAC;AAC7E,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,KAAa;IAC9D,OAAO,KAAK,CAAC,kBAAkB,EAAE,GAAG,MAAM,KAAK,KAAK,uBAAuB,CAAC,CAAC;AACjF,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,cAAc,CAAC,QAAmB;IAC9C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC5B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,OAAO,GAAG,OAAO,CAAC,KAAK,KAAK,KAAK,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,aAAa,CAAC,QAAmB;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAE3E,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/core/load.ts"],"names":[],"mappings":"AAKA,OAAO,EAAqB,UAAU,EAAE,MAAM,YAAY,CAAC;AAsB3D,oFAAoF;AACpF,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CA+BvE"}
|
package/lib/core/load.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { globby } from 'globby';
|
|
3
|
+
import { parseFile } from './parse.js';
|
|
4
|
+
import { validateFile } from './schema.js';
|
|
5
|
+
import { normalize } from './normalize.js';
|
|
6
|
+
import { noFilesError } from './finding.js';
|
|
7
|
+
/** Process one file's text through parse, validate, and normalize. Pure, no disk. */
|
|
8
|
+
function checkContent(text, file) {
|
|
9
|
+
const parsed = parseFile(text, file);
|
|
10
|
+
if (!parsed.data) {
|
|
11
|
+
return { assignments: [], findings: parsed.findings };
|
|
12
|
+
}
|
|
13
|
+
const validated = validateFile(parsed.data, file);
|
|
14
|
+
if (!validated.data) {
|
|
15
|
+
return { assignments: [], findings: [...parsed.findings, ...validated.findings] };
|
|
16
|
+
}
|
|
17
|
+
const normalized = normalize(validated.data, file);
|
|
18
|
+
return {
|
|
19
|
+
assignments: normalized.assignments,
|
|
20
|
+
findings: [...parsed.findings, ...validated.findings, ...normalized.findings],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Expand the globs, read every matched file, and merge into one model by union. */
|
|
24
|
+
export async function loadFiles(patterns) {
|
|
25
|
+
const files = await globby(patterns);
|
|
26
|
+
if (files.length === 0) {
|
|
27
|
+
return {
|
|
28
|
+
files,
|
|
29
|
+
assignments: [],
|
|
30
|
+
findings: [noFilesError(patterns)],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const findings = [];
|
|
34
|
+
const collected = [];
|
|
35
|
+
for (const file of files) {
|
|
36
|
+
// eslint-disable-next-line no-await-in-loop
|
|
37
|
+
const text = await readFile(file, 'utf8');
|
|
38
|
+
const res = checkContent(text, file);
|
|
39
|
+
findings.push(...res.findings);
|
|
40
|
+
collected.push(...res.assignments);
|
|
41
|
+
}
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
const assignments = [];
|
|
44
|
+
for (const assignment of collected) {
|
|
45
|
+
const dedupeKey = `${assignment.assignee} ${assignment.kind} ${assignment.target}`;
|
|
46
|
+
if (seen.has(dedupeKey))
|
|
47
|
+
continue;
|
|
48
|
+
seen.add(dedupeKey);
|
|
49
|
+
assignments.push(assignment);
|
|
50
|
+
}
|
|
51
|
+
return { files, assignments, findings };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/core/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAW,YAAY,EAAE,MAAM,cAAc,CAAC;AAErD,qFAAqF;AACrF,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC5C,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC1D,CAAC;IAED,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,OAAO;QACH,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;KAChF,CAAC;AACN,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IAC9C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACH,KAAK;YACL,WAAW,EAAE,EAAE;YACf,QAAQ,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;SACrC,CAAC;IACN,CAAC;IAED,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAwB,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,4CAA4C;QAC5C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC/B,SAAS,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,WAAW,GAAwB,EAAE,CAAC;IAE5C,KAAK,MAAM,UAAU,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,GAAG,UAAU,CAAC,QAAQ,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACnF,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,SAAS;QAClC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACpB,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Finding } from './finding.js';
|
|
2
|
+
export type Kind = 'permissionSet' | 'permissionSetGroup' | 'permissionSetLicense';
|
|
3
|
+
export type DesiredAssignment = {
|
|
4
|
+
assignee: string;
|
|
5
|
+
kind: Kind;
|
|
6
|
+
target: string;
|
|
7
|
+
/** ISO 8601 datetime the grant should expire, if any. Only permission sets and groups support it. */
|
|
8
|
+
expiration?: string;
|
|
9
|
+
};
|
|
10
|
+
/** A user as it exists in the org, in domain terms (no SObject field names). */
|
|
11
|
+
export type OrgUser = {
|
|
12
|
+
id: string;
|
|
13
|
+
username: string;
|
|
14
|
+
isActive: boolean;
|
|
15
|
+
};
|
|
16
|
+
/** A target (permission set, group, or license) as it exists in the org. */
|
|
17
|
+
export type OrgTarget = {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
/** An assignment that currently exists in the org, carrying its record id for deletion. */
|
|
22
|
+
export type ActualAssignment = {
|
|
23
|
+
recordId: string;
|
|
24
|
+
assignee: string;
|
|
25
|
+
kind: Kind;
|
|
26
|
+
target: string;
|
|
27
|
+
/** The expiration the org has on record, if any. */
|
|
28
|
+
expiration?: string;
|
|
29
|
+
};
|
|
30
|
+
/** An existing assignment whose expiration should change. `expiration` undefined clears it. */
|
|
31
|
+
export type AssignmentUpdate = {
|
|
32
|
+
recordId: string;
|
|
33
|
+
assignee: string;
|
|
34
|
+
kind: Kind;
|
|
35
|
+
target: string;
|
|
36
|
+
expiration?: string;
|
|
37
|
+
};
|
|
38
|
+
/** A resolved managed target: its kind and the org id it resolved to. */
|
|
39
|
+
export type TargetRef = {
|
|
40
|
+
kind: Kind;
|
|
41
|
+
id: string;
|
|
42
|
+
};
|
|
43
|
+
/** A desired assignment resolved to the ids needed to insert it. */
|
|
44
|
+
export type ResolvedAddition = DesiredAssignment & {
|
|
45
|
+
assigneeId: string;
|
|
46
|
+
targetId: string;
|
|
47
|
+
};
|
|
48
|
+
/** The change set between the desired model and the org's current state. */
|
|
49
|
+
export type Diff = {
|
|
50
|
+
toAdd: DesiredAssignment[];
|
|
51
|
+
toUpdate: AssignmentUpdate[];
|
|
52
|
+
toRemove: ActualAssignment[];
|
|
53
|
+
unchanged: ActualAssignment[];
|
|
54
|
+
};
|
|
55
|
+
/** The per-record result of one add or remove, for partial-success reporting. */
|
|
56
|
+
export type AssignmentOutcome = {
|
|
57
|
+
assignee: string;
|
|
58
|
+
kind: Kind;
|
|
59
|
+
target: string;
|
|
60
|
+
operation: 'add' | 'update' | 'remove';
|
|
61
|
+
success: boolean;
|
|
62
|
+
message?: string;
|
|
63
|
+
};
|
|
64
|
+
export type LoadResult = {
|
|
65
|
+
files: string[];
|
|
66
|
+
assignments: DesiredAssignment[];
|
|
67
|
+
findings: Finding[];
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,MAAM,IAAI,GAAG,eAAe,GAAG,oBAAoB,GAAG,sBAAsB,CAAC;AAEnF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,OAAO,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,SAAS,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,+FAA+F;AAC/F,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG;IACpB,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,oEAAoE;AACpE,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GAAG;IACf,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,gBAAgB,EAAE,CAAC;CACjC,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,QAAQ,EAAE,OAAO,EAAE,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/core/model.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FileShape } from './schema.js';
|
|
2
|
+
import { DesiredAssignment, Kind } from './model.js';
|
|
3
|
+
import { Finding } from './finding.js';
|
|
4
|
+
export type ScopeKey = 'permissionSets' | 'permissionSetGroups' | 'permissionSetLicenses';
|
|
5
|
+
/** The (kind, file scope key) pairing, in canonical order. Shared with serialize. */
|
|
6
|
+
export declare const kindKeys: Array<[Kind, ScopeKey]>;
|
|
7
|
+
/**
|
|
8
|
+
* Turn a validated file into canonical (assignee, kind, target) tuples, and
|
|
9
|
+
* emit the structural findings: duplicate targets, empty lists, empty users.
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalize(data: FileShape, file: string): {
|
|
12
|
+
assignments: DesiredAssignment[];
|
|
13
|
+
findings: Finding[];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,OAAO,EAAwD,MAAM,cAAc,CAAC;AAE7F,MAAM,MAAM,QAAQ,GAAG,gBAAgB,GAAG,qBAAqB,GAAG,uBAAuB,CAAC;AAE1F,qFAAqF;AACrF,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAI5C,CAAC;AA8DF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAWlH"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { emptyListWarning, dupTargetWarning, emptyUserWarning } from './finding.js';
|
|
2
|
+
/** The (kind, file scope key) pairing, in canonical order. Shared with serialize. */
|
|
3
|
+
export const kindKeys = [
|
|
4
|
+
['permissionSet', 'permissionSets'],
|
|
5
|
+
['permissionSetGroup', 'permissionSetGroups'],
|
|
6
|
+
['permissionSetLicense', 'permissionSetLicenses'],
|
|
7
|
+
];
|
|
8
|
+
function normalizeScope(username, kind, key, list, file) {
|
|
9
|
+
const items = list.map((item) => ({
|
|
10
|
+
target: typeof item === 'string' ? item : item.name,
|
|
11
|
+
expiration: typeof item === 'string' ? undefined : item.expiration,
|
|
12
|
+
}));
|
|
13
|
+
const assignments = [];
|
|
14
|
+
const findings = [];
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
for (const { target, expiration } of items) {
|
|
17
|
+
if (seen.has(target)) {
|
|
18
|
+
findings.push(dupTargetWarning(username, target, key, file));
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
seen.add(target);
|
|
22
|
+
assignments.push({ assignee: username, kind, target, ...(expiration ? { expiration } : {}) });
|
|
23
|
+
}
|
|
24
|
+
return { assignments, findings };
|
|
25
|
+
}
|
|
26
|
+
function normalizeUser(username, entry, file) {
|
|
27
|
+
const assignments = [];
|
|
28
|
+
const findings = [];
|
|
29
|
+
let scopeCount = 0;
|
|
30
|
+
for (const [kind, key] of kindKeys) {
|
|
31
|
+
const list = entry[key];
|
|
32
|
+
if (!list)
|
|
33
|
+
continue;
|
|
34
|
+
if (list.length === 0) {
|
|
35
|
+
findings.push(emptyListWarning(username, key, file));
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
scopeCount += 1;
|
|
39
|
+
const scope = normalizeScope(username, kind, key, list, file);
|
|
40
|
+
assignments.push(...scope.assignments);
|
|
41
|
+
findings.push(...scope.findings);
|
|
42
|
+
}
|
|
43
|
+
if (scopeCount === 0) {
|
|
44
|
+
findings.push(emptyUserWarning(username, file));
|
|
45
|
+
}
|
|
46
|
+
return { assignments, findings };
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Turn a validated file into canonical (assignee, kind, target) tuples, and
|
|
50
|
+
* emit the structural findings: duplicate targets, empty lists, empty users.
|
|
51
|
+
*/
|
|
52
|
+
export function normalize(data, file) {
|
|
53
|
+
const assignments = [];
|
|
54
|
+
const findings = [];
|
|
55
|
+
for (const [username, entry] of Object.entries(data.users)) {
|
|
56
|
+
const user = normalizeUser(username, entry, file);
|
|
57
|
+
assignments.push(...user.assignments);
|
|
58
|
+
findings.push(...user.findings);
|
|
59
|
+
}
|
|
60
|
+
return { assignments, findings };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/core/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Finding } from './finding.js';
|
|
2
|
+
/**
|
|
3
|
+
* Read one file's text into a plain object. Reports invalid YAML and duplicate
|
|
4
|
+
* keys (uniqueKeys), and treats an empty document as a warning.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseFile(text: string, file: string): {
|
|
7
|
+
data?: unknown;
|
|
8
|
+
findings: Finding[];
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/core/parse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAA+B,MAAM,cAAc,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAe7F"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { parseDocument } from 'yaml';
|
|
2
|
+
import { yamlError, emptyFileWarning } from './finding.js';
|
|
3
|
+
/**
|
|
4
|
+
* Read one file's text into a plain object. Reports invalid YAML and duplicate
|
|
5
|
+
* keys (uniqueKeys), and treats an empty document as a warning.
|
|
6
|
+
*/
|
|
7
|
+
export function parseFile(text, file) {
|
|
8
|
+
const doc = parseDocument(text, { uniqueKeys: true });
|
|
9
|
+
if (doc.errors.length > 0) {
|
|
10
|
+
return {
|
|
11
|
+
findings: doc.errors.map((err) => yamlError(err.message, file, err.linePos?.[0]?.line)),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const data = doc.toJS();
|
|
15
|
+
if (data == null) {
|
|
16
|
+
return { findings: [emptyFileWarning(file)] };
|
|
17
|
+
}
|
|
18
|
+
return { data, findings: [] };
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/core/parse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAW,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEpE;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IAChD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACH,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;SAC1F,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAa,CAAC;IACnC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACf,OAAO,EAAE,QAAQ,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Diff } from './model.js';
|
|
2
|
+
/**
|
|
3
|
+
* Render a diff as a plan, grouped by kind then target, with `+` adds, `~` expiration
|
|
4
|
+
* updates, `-` removes, and `=` unchanged. Timed grants carry their expiration. Shared
|
|
5
|
+
* by plan and apply.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatDiff(diff: Diff): string[];
|
|
8
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,MAAM,YAAY,CAAC;AA8BxC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAqC/C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { kindKeys } from './normalize.js';
|
|
2
|
+
function bucketFor(byKind, kind, target) {
|
|
3
|
+
let byTarget = byKind.get(kind);
|
|
4
|
+
if (!byTarget) {
|
|
5
|
+
byTarget = new Map();
|
|
6
|
+
byKind.set(kind, byTarget);
|
|
7
|
+
}
|
|
8
|
+
let bucket = byTarget.get(target);
|
|
9
|
+
if (!bucket) {
|
|
10
|
+
bucket = { adds: new Map(), updates: new Map(), removes: new Set(), unchanged: new Map() };
|
|
11
|
+
byTarget.set(target, bucket);
|
|
12
|
+
}
|
|
13
|
+
return bucket;
|
|
14
|
+
}
|
|
15
|
+
/** An assignee line, annotated with its expiration when there is one. */
|
|
16
|
+
function withExpiry(assignee, expiration) {
|
|
17
|
+
return expiration ? `${assignee} (expires ${expiration})` : assignee;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Render a diff as a plan, grouped by kind then target, with `+` adds, `~` expiration
|
|
21
|
+
* updates, `-` removes, and `=` unchanged. Timed grants carry their expiration. Shared
|
|
22
|
+
* by plan and apply.
|
|
23
|
+
*/
|
|
24
|
+
export function formatDiff(diff) {
|
|
25
|
+
const byKind = new Map();
|
|
26
|
+
for (const assignment of diff.toAdd) {
|
|
27
|
+
bucketFor(byKind, assignment.kind, assignment.target).adds.set(assignment.assignee, assignment.expiration);
|
|
28
|
+
}
|
|
29
|
+
for (const update of diff.toUpdate) {
|
|
30
|
+
bucketFor(byKind, update.kind, update.target).updates.set(update.assignee, update.expiration);
|
|
31
|
+
}
|
|
32
|
+
for (const assignment of diff.toRemove) {
|
|
33
|
+
bucketFor(byKind, assignment.kind, assignment.target).removes.add(assignment.assignee);
|
|
34
|
+
}
|
|
35
|
+
for (const assignment of diff.unchanged) {
|
|
36
|
+
bucketFor(byKind, assignment.kind, assignment.target).unchanged.set(assignment.assignee, assignment.expiration);
|
|
37
|
+
}
|
|
38
|
+
const lines = [];
|
|
39
|
+
for (const [kind, scopeKey] of kindKeys) {
|
|
40
|
+
const byTarget = byKind.get(kind);
|
|
41
|
+
if (!byTarget)
|
|
42
|
+
continue;
|
|
43
|
+
lines.push(`${scopeKey}:`);
|
|
44
|
+
for (const [target, bucket] of [...byTarget].sort((left, right) => left[0].localeCompare(right[0]))) {
|
|
45
|
+
lines.push(` ${target}`);
|
|
46
|
+
for (const assignee of [...bucket.adds.keys()].sort()) {
|
|
47
|
+
lines.push(` + ${withExpiry(assignee, bucket.adds.get(assignee))}`);
|
|
48
|
+
}
|
|
49
|
+
for (const assignee of [...bucket.updates.keys()].sort()) {
|
|
50
|
+
const expiration = bucket.updates.get(assignee);
|
|
51
|
+
lines.push(` ~ ${expiration ? withExpiry(assignee, expiration) : `${assignee} (expiry cleared)`}`);
|
|
52
|
+
}
|
|
53
|
+
for (const assignee of [...bucket.removes].sort())
|
|
54
|
+
lines.push(` - ${assignee}`);
|
|
55
|
+
for (const assignee of [...bucket.unchanged.keys()].sort()) {
|
|
56
|
+
lines.push(` = ${withExpiry(assignee, bucket.unchanged.get(assignee))}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return lines;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/core/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DesiredAssignment, Kind, OrgTarget, OrgUser } from './model.js';
|
|
2
|
+
import { Finding } from './finding.js';
|
|
3
|
+
export declare const kinds: Kind[];
|
|
4
|
+
/** The distinct usernames assigned across all assignments. */
|
|
5
|
+
export declare function distinctAssignees(assignments: DesiredAssignment[]): string[];
|
|
6
|
+
/** The distinct targets of one kind across all assignments. */
|
|
7
|
+
export declare function distinctTargets(assignments: DesiredAssignment[], kind: Kind): string[];
|
|
8
|
+
/** Every declared user must exist in the org and be active. */
|
|
9
|
+
export declare function evaluateUsers(declared: string[], found: OrgUser[]): Finding[];
|
|
10
|
+
/**
|
|
11
|
+
* Every declared target of one kind must resolve to exactly one record in the
|
|
12
|
+
* org. `found` is the list of matching identifiers the org returned; matching is
|
|
13
|
+
* case-insensitive, mirroring how the org compares them.
|
|
14
|
+
*/
|
|
15
|
+
export declare function evaluateTargets(kind: Kind, declared: string[], found: string[]): Finding[];
|
|
16
|
+
/** Index active users by lowercased username to their org id, for building assignments. */
|
|
17
|
+
export declare function indexUsersById(found: OrgUser[]): Map<string, string>;
|
|
18
|
+
/** Index targets by lowercased name to their org id, skipping names that resolve ambiguously. */
|
|
19
|
+
export declare function indexTargetsById(found: OrgTarget[]): Map<string, string>;
|
|
20
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,EAAE,OAAO,EAAmF,MAAM,cAAc,CAAC;AASxH,eAAO,MAAM,KAAK,QAAoC,CAAC;AAMvD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,MAAM,EAAE,CAE5E;AAED,+DAA+D;AAC/D,wBAAgB,eAAe,CAAC,WAAW,EAAE,iBAAiB,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,CAItF;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAgB7E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAmB1F;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQpE;AAED,iGAAiG;AACjG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAexE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { userNotFoundError, userInactiveError, targetNotFoundError, targetAmbiguousError } from './finding.js';
|
|
2
|
+
/** Human label per kind, used in findings. Domain wording, not SObject names. */
|
|
3
|
+
const kindLabels = {
|
|
4
|
+
permissionSet: 'permission set',
|
|
5
|
+
permissionSetGroup: 'permission set group',
|
|
6
|
+
permissionSetLicense: 'permission set license',
|
|
7
|
+
};
|
|
8
|
+
export const kinds = Object.keys(kindLabels);
|
|
9
|
+
function distinct(values) {
|
|
10
|
+
return [...new Set(values)];
|
|
11
|
+
}
|
|
12
|
+
/** The distinct usernames assigned across all assignments. */
|
|
13
|
+
export function distinctAssignees(assignments) {
|
|
14
|
+
return distinct(assignments.map((assignment) => assignment.assignee));
|
|
15
|
+
}
|
|
16
|
+
/** The distinct targets of one kind across all assignments. */
|
|
17
|
+
export function distinctTargets(assignments, kind) {
|
|
18
|
+
return distinct(assignments.filter((assignment) => assignment.kind === kind).map((assignment) => assignment.target));
|
|
19
|
+
}
|
|
20
|
+
/** Every declared user must exist in the org and be active. */
|
|
21
|
+
export function evaluateUsers(declared, found) {
|
|
22
|
+
const byName = new Map();
|
|
23
|
+
for (const user of found) {
|
|
24
|
+
byName.set(user.username.toLowerCase(), user);
|
|
25
|
+
}
|
|
26
|
+
const findings = [];
|
|
27
|
+
for (const username of declared) {
|
|
28
|
+
const user = byName.get(username.toLowerCase());
|
|
29
|
+
if (!user) {
|
|
30
|
+
findings.push(userNotFoundError(username));
|
|
31
|
+
}
|
|
32
|
+
else if (!user.isActive) {
|
|
33
|
+
findings.push(userInactiveError(username));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return findings;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Every declared target of one kind must resolve to exactly one record in the
|
|
40
|
+
* org. `found` is the list of matching identifiers the org returned; matching is
|
|
41
|
+
* case-insensitive, mirroring how the org compares them.
|
|
42
|
+
*/
|
|
43
|
+
export function evaluateTargets(kind, declared, found) {
|
|
44
|
+
const label = kindLabels[kind];
|
|
45
|
+
const counts = new Map();
|
|
46
|
+
for (const name of found) {
|
|
47
|
+
const key = name.toLowerCase();
|
|
48
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
49
|
+
}
|
|
50
|
+
const findings = [];
|
|
51
|
+
for (const target of declared) {
|
|
52
|
+
const count = counts.get(target.toLowerCase()) ?? 0;
|
|
53
|
+
if (count === 0) {
|
|
54
|
+
findings.push(targetNotFoundError(target, label));
|
|
55
|
+
}
|
|
56
|
+
else if (count > 1) {
|
|
57
|
+
findings.push(targetAmbiguousError(target, label));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return findings;
|
|
61
|
+
}
|
|
62
|
+
/** Index active users by lowercased username to their org id, for building assignments. */
|
|
63
|
+
export function indexUsersById(found) {
|
|
64
|
+
const byName = new Map();
|
|
65
|
+
for (const user of found) {
|
|
66
|
+
if (user.isActive) {
|
|
67
|
+
byName.set(user.username.toLowerCase(), user.id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return byName;
|
|
71
|
+
}
|
|
72
|
+
/** Index targets by lowercased name to their org id, skipping names that resolve ambiguously. */
|
|
73
|
+
export function indexTargetsById(found) {
|
|
74
|
+
const counts = new Map();
|
|
75
|
+
for (const target of found) {
|
|
76
|
+
const key = target.name.toLowerCase();
|
|
77
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
78
|
+
}
|
|
79
|
+
const byName = new Map();
|
|
80
|
+
for (const target of found) {
|
|
81
|
+
const key = target.name.toLowerCase();
|
|
82
|
+
if (counts.get(key) === 1) {
|
|
83
|
+
byName.set(key, target.id);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return byName;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/core/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,iBAAiB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAExH,iFAAiF;AACjF,MAAM,UAAU,GAAyB;IACrC,aAAa,EAAE,gBAAgB;IAC/B,kBAAkB,EAAE,sBAAsB;IAC1C,oBAAoB,EAAE,wBAAwB;CACjD,CAAC;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAW,CAAC;AAEvD,SAAS,QAAQ,CAAC,MAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,iBAAiB,CAAC,WAAgC;IAC9D,OAAO,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,eAAe,CAAC,WAAgC,EAAE,IAAU;IACxE,OAAO,QAAQ,CACX,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,CACtG,CAAC;AACN,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,QAAkB,EAAE,KAAgB;IAC9D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmB,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,QAAkB,EAAE,KAAe;IAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAE/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QACtD,CAAC;aAAM,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QACvD,CAAC;IACL,CAAC;IACD,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,KAAgB;IAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Finding } from './finding.js';
|
|
3
|
+
export declare const userEntrySchema: z.ZodObject<{
|
|
4
|
+
permissionSets: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
5
|
+
name: z.ZodString;
|
|
6
|
+
expiration: z.ZodISODateTime;
|
|
7
|
+
}, z.core.$strict>]>>>;
|
|
8
|
+
permissionSetGroups: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
9
|
+
name: z.ZodString;
|
|
10
|
+
expiration: z.ZodISODateTime;
|
|
11
|
+
}, z.core.$strict>]>>>;
|
|
12
|
+
permissionSetLicenses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13
|
+
}, z.core.$strict>;
|
|
14
|
+
export declare const fileSchema: z.ZodObject<{
|
|
15
|
+
users: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
16
|
+
permissionSets: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
17
|
+
name: z.ZodString;
|
|
18
|
+
expiration: z.ZodISODateTime;
|
|
19
|
+
}, z.core.$strict>]>>>;
|
|
20
|
+
permissionSetGroups: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
21
|
+
name: z.ZodString;
|
|
22
|
+
expiration: z.ZodISODateTime;
|
|
23
|
+
}, z.core.$strict>]>>>;
|
|
24
|
+
permissionSetLicenses: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
}, z.core.$strict>>;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
export type FileShape = z.infer<typeof fileSchema>;
|
|
28
|
+
/** Validate a parsed object against the file contract, turning issues into findings. */
|
|
29
|
+
export declare function validateFile(data: unknown, file: string): {
|
|
30
|
+
data?: FileShape;
|
|
31
|
+
findings: Finding[];
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAe,MAAM,cAAc,CAAC;AAsBpD,eAAO,MAAM,eAAe;;;;;;;;;;kBAI1B,CAAC;AAEH,eAAO,MAAM,UAAU;;;;;;;;;;;;kBAErB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEnD,wFAAwF;AACxF,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CAUnG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { schemaError } from './finding.js';
|
|
3
|
+
// The permission set name
|
|
4
|
+
const name = z.string().min(1);
|
|
5
|
+
// The permission set expiration date
|
|
6
|
+
const expiration = z.iso.datetime({ offset: true });
|
|
7
|
+
/** An entry is either a bare target name or a name with an expiration. */
|
|
8
|
+
const expiringList = z.array(z.union([
|
|
9
|
+
name,
|
|
10
|
+
z.strictObject({
|
|
11
|
+
name,
|
|
12
|
+
expiration,
|
|
13
|
+
}),
|
|
14
|
+
]));
|
|
15
|
+
/** Licenses cannot expire (PermissionSetLicenseAssign has no ExpirationDate), so names only. */
|
|
16
|
+
const plainList = z.array(name);
|
|
17
|
+
export const userEntrySchema = z.strictObject({
|
|
18
|
+
permissionSets: expiringList.optional(),
|
|
19
|
+
permissionSetGroups: expiringList.optional(),
|
|
20
|
+
permissionSetLicenses: plainList.optional(),
|
|
21
|
+
});
|
|
22
|
+
export const fileSchema = z.strictObject({
|
|
23
|
+
users: z.record(z.string().min(1), userEntrySchema),
|
|
24
|
+
});
|
|
25
|
+
/** Validate a parsed object against the file contract, turning issues into findings. */
|
|
26
|
+
export function validateFile(data, file) {
|
|
27
|
+
const parsed = fileSchema.safeParse(data);
|
|
28
|
+
if (parsed.success) {
|
|
29
|
+
return { data: parsed.data, findings: [] };
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
findings: parsed.error.issues.map((issue) => schemaError(issue.path.join('.') || '(root)', issue.message, file)),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=schema.js.map
|