@syntax-syllogism/warden-core 0.2.0
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/CHANGELOG.md +22 -0
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/lib/access/assignees.d.ts +27 -0
- package/lib/access/assignees.js +139 -0
- package/lib/access/assignees.js.map +1 -0
- package/lib/access/messages.d.ts +1 -0
- package/lib/access/messages.js +24 -0
- package/lib/access/messages.js.map +1 -0
- package/lib/access/metadata.d.ts +41 -0
- package/lib/access/metadata.js +168 -0
- package/lib/access/metadata.js.map +1 -0
- package/lib/access/muting.d.ts +7 -0
- package/lib/access/muting.js +22 -0
- package/lib/access/muting.js.map +1 -0
- package/lib/access/output.d.ts +12 -0
- package/lib/access/output.js +108 -0
- package/lib/access/output.js.map +1 -0
- package/lib/access/resolvers/field.d.ts +2 -0
- package/lib/access/resolvers/field.js +93 -0
- package/lib/access/resolvers/field.js.map +1 -0
- package/lib/access/resolvers/index.d.ts +2 -0
- package/lib/access/resolvers/index.js +22 -0
- package/lib/access/resolvers/index.js.map +1 -0
- package/lib/access/resolvers/object.d.ts +2 -0
- package/lib/access/resolvers/object.js +101 -0
- package/lib/access/resolvers/object.js.map +1 -0
- package/lib/access/resolvers/recordType.d.ts +2 -0
- package/lib/access/resolvers/recordType.js +181 -0
- package/lib/access/resolvers/recordType.js.map +1 -0
- package/lib/access/resolvers/setupEntity.d.ts +4 -0
- package/lib/access/resolvers/setupEntity.js +43 -0
- package/lib/access/resolvers/setupEntity.js.map +1 -0
- package/lib/access/resolvers/tab.d.ts +2 -0
- package/lib/access/resolvers/tab.js +36 -0
- package/lib/access/resolvers/tab.js.map +1 -0
- package/lib/access/reverse.d.ts +9 -0
- package/lib/access/reverse.js +429 -0
- package/lib/access/reverse.js.map +1 -0
- package/lib/access/soql.d.ts +6 -0
- package/lib/access/soql.js +31 -0
- package/lib/access/soql.js.map +1 -0
- package/lib/access/targetValidation.d.ts +7 -0
- package/lib/access/targetValidation.js +110 -0
- package/lib/access/targetValidation.js.map +1 -0
- package/lib/access/types.d.ts +88 -0
- package/lib/access/types.js +20 -0
- package/lib/access/types.js.map +1 -0
- package/lib/errors.d.ts +18 -0
- package/lib/errors.js +39 -0
- package/lib/errors.js.map +1 -0
- package/lib/index.d.ts +37 -0
- package/lib/index.js +33 -0
- package/lib/index.js.map +1 -0
- package/lib/lifecycle/assignmentState.d.ts +62 -0
- package/lib/lifecycle/assignmentState.js +89 -0
- package/lib/lifecycle/assignmentState.js.map +1 -0
- package/lib/lifecycle/conformance.d.ts +10 -0
- package/lib/lifecycle/conformance.js +59 -0
- package/lib/lifecycle/conformance.js.map +1 -0
- package/lib/lifecycle/diffOutput.d.ts +7 -0
- package/lib/lifecycle/diffOutput.js +94 -0
- package/lib/lifecycle/diffOutput.js.map +1 -0
- package/lib/lifecycle/dmlRunner.d.ts +30 -0
- package/lib/lifecycle/dmlRunner.js +45 -0
- package/lib/lifecycle/dmlRunner.js.map +1 -0
- package/lib/lifecycle/errors.d.ts +5 -0
- package/lib/lifecycle/errors.js +8 -0
- package/lib/lifecycle/errors.js.map +1 -0
- package/lib/lifecycle/freezeState.d.ts +28 -0
- package/lib/lifecycle/freezeState.js +88 -0
- package/lib/lifecycle/freezeState.js.map +1 -0
- package/lib/lifecycle/messages.d.ts +1 -0
- package/lib/lifecycle/messages.js +20 -0
- package/lib/lifecycle/messages.js.map +1 -0
- package/lib/lifecycle/output.d.ts +23 -0
- package/lib/lifecycle/output.js +148 -0
- package/lib/lifecycle/output.js.map +1 -0
- package/lib/lifecycle/snapshotState.d.ts +12 -0
- package/lib/lifecycle/snapshotState.js +353 -0
- package/lib/lifecycle/snapshotState.js.map +1 -0
- package/lib/lifecycle/stripApply.d.ts +3 -0
- package/lib/lifecycle/stripApply.js +17 -0
- package/lib/lifecycle/stripApply.js.map +1 -0
- package/lib/lifecycle/stripPlan.d.ts +75 -0
- package/lib/lifecycle/stripPlan.js +192 -0
- package/lib/lifecycle/stripPlan.js.map +1 -0
- package/lib/lifecycle/targeting.d.ts +32 -0
- package/lib/lifecycle/targeting.js +195 -0
- package/lib/lifecycle/targeting.js.map +1 -0
- package/lib/lifecycle/types.d.ts +88 -0
- package/lib/lifecycle/types.js +2 -0
- package/lib/lifecycle/types.js.map +1 -0
- package/lib/lifecycle/userDiff.d.ts +70 -0
- package/lib/lifecycle/userDiff.js +393 -0
- package/lib/lifecycle/userDiff.js.map +1 -0
- package/lib/matching/index.d.ts +53 -0
- package/lib/matching/index.js +181 -0
- package/lib/matching/index.js.map +1 -0
- package/lib/provisioning/assignmentPlan.d.ts +53 -0
- package/lib/provisioning/assignmentPlan.js +90 -0
- package/lib/provisioning/assignmentPlan.js.map +1 -0
- package/lib/provisioning/definitionReader.d.ts +38 -0
- package/lib/provisioning/definitionReader.js +77 -0
- package/lib/provisioning/definitionReader.js.map +1 -0
- package/lib/provisioning/errors.d.ts +9 -0
- package/lib/provisioning/errors.js +14 -0
- package/lib/provisioning/errors.js.map +1 -0
- package/lib/provisioning/licenseUsage.d.ts +15 -0
- package/lib/provisioning/licenseUsage.js +53 -0
- package/lib/provisioning/licenseUsage.js.map +1 -0
- package/lib/provisioning/messages.d.ts +4 -0
- package/lib/provisioning/messages.js +72 -0
- package/lib/provisioning/messages.js.map +1 -0
- package/lib/provisioning/planner.d.ts +63 -0
- package/lib/provisioning/planner.js +407 -0
- package/lib/provisioning/planner.js.map +1 -0
- package/lib/provisioning/provisionUserUseCase.d.ts +52 -0
- package/lib/provisioning/provisionUserUseCase.js +200 -0
- package/lib/provisioning/provisionUserUseCase.js.map +1 -0
- package/lib/provisioning/referenceResolution.d.ts +4 -0
- package/lib/provisioning/referenceResolution.js +173 -0
- package/lib/provisioning/referenceResolution.js.map +1 -0
- package/lib/provisioning/userPlan.d.ts +85 -0
- package/lib/provisioning/userPlan.js +162 -0
- package/lib/provisioning/userPlan.js.map +1 -0
- package/lib/provisioning/userSave.d.ts +24 -0
- package/lib/provisioning/userSave.js +119 -0
- package/lib/provisioning/userSave.js.map +1 -0
- package/lib/relatedRecords/apply.d.ts +18 -0
- package/lib/relatedRecords/apply.js +121 -0
- package/lib/relatedRecords/apply.js.map +1 -0
- package/lib/relatedRecords/catalog.d.ts +7 -0
- package/lib/relatedRecords/catalog.js +108 -0
- package/lib/relatedRecords/catalog.js.map +1 -0
- package/lib/relatedRecords/errors.d.ts +5 -0
- package/lib/relatedRecords/errors.js +8 -0
- package/lib/relatedRecords/errors.js.map +1 -0
- package/lib/relatedRecords/messages.d.ts +1 -0
- package/lib/relatedRecords/messages.js +2 -0
- package/lib/relatedRecords/messages.js.map +1 -0
- package/lib/relatedRecords/plan.d.ts +22 -0
- package/lib/relatedRecords/plan.js +271 -0
- package/lib/relatedRecords/plan.js.map +1 -0
- package/lib/relatedRecords/preflight.d.ts +29 -0
- package/lib/relatedRecords/preflight.js +164 -0
- package/lib/relatedRecords/preflight.js.map +1 -0
- package/lib/relatedRecords/sources.d.ts +25 -0
- package/lib/relatedRecords/sources.js +65 -0
- package/lib/relatedRecords/sources.js.map +1 -0
- package/lib/relatedRecords/types.d.ts +46 -0
- package/lib/relatedRecords/types.js +2 -0
- package/lib/relatedRecords/types.js.map +1 -0
- package/lib/shared/csv.d.ts +26 -0
- package/lib/shared/csv.js +237 -0
- package/lib/shared/csv.js.map +1 -0
- package/lib/shared/output.d.ts +25 -0
- package/lib/shared/output.js +74 -0
- package/lib/shared/output.js.map +1 -0
- package/lib/shared/prompt.d.ts +4 -0
- package/lib/shared/prompt.js +15 -0
- package/lib/shared/prompt.js.map +1 -0
- package/lib/shared/sfUtils.d.ts +19 -0
- package/lib/shared/sfUtils.js +42 -0
- package/lib/shared/sfUtils.js.map +1 -0
- package/lib/shared/userFields.d.ts +23 -0
- package/lib/shared/userFields.js +41 -0
- package/lib/shared/userFields.js.map +1 -0
- package/lib/spec/index.d.ts +10 -0
- package/lib/spec/index.js +6 -0
- package/lib/spec/index.js.map +1 -0
- package/lib/spec/parse.d.ts +32 -0
- package/lib/spec/parse.js +77 -0
- package/lib/spec/parse.js.map +1 -0
- package/lib/spec/personaDefinitions.d.ts +56 -0
- package/lib/spec/personaDefinitions.js +25 -0
- package/lib/spec/personaDefinitions.js.map +1 -0
- package/lib/spec/relatedCatalog.d.ts +61 -0
- package/lib/spec/relatedCatalog.js +32 -0
- package/lib/spec/relatedCatalog.js.map +1 -0
- package/lib/spec/snapshot.d.ts +42 -0
- package/lib/spec/snapshot.js +32 -0
- package/lib/spec/snapshot.js.map +1 -0
- package/lib/spec/usersDefinition.d.ts +19 -0
- package/lib/spec/usersDefinition.js +21 -0
- package/lib/spec/usersDefinition.js.map +1 -0
- package/package.json +78 -0
- package/schemas/persona-definitions.schema.json +108 -0
- package/schemas/related-catalog.schema.json +141 -0
- package/schemas/snapshot.schema.json +128 -0
- package/schemas/users-definition.schema.json +36 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { esc, queryAll } from './soql.js';
|
|
2
|
+
import { UserAccessError } from './types.js';
|
|
3
|
+
const setupEntityDefinitions = {
|
|
4
|
+
'apex-class': { objectName: 'ApexClass', nameField: 'Name', notFoundCode: 'errorApexClassNotFound' },
|
|
5
|
+
'vf-page': { objectName: 'ApexPage', nameField: 'Name', notFoundCode: 'errorVisualforcePageNotFound' },
|
|
6
|
+
'custom-permission': {
|
|
7
|
+
objectName: 'CustomPermission',
|
|
8
|
+
nameField: 'DeveloperName',
|
|
9
|
+
notFoundCode: 'errorCustomPermissionNotFound',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
const describeObject = async (conn, sobjectType) => {
|
|
13
|
+
try {
|
|
14
|
+
return (await conn.describe(sobjectType));
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
throw new UserAccessError('errorObjectNotFound', [sobjectType], error);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export const validateObjectTarget = async (conn, target) => {
|
|
21
|
+
const trimmed = target.trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
throw new UserAccessError('errorInvalidTarget', [target]);
|
|
24
|
+
const describe = await describeObject(conn, trimmed);
|
|
25
|
+
return { type: 'object', targetName: describe.name, sobjectType: describe.name };
|
|
26
|
+
};
|
|
27
|
+
export const validateFieldTarget = async (conn, target) => {
|
|
28
|
+
const trimmed = target.trim();
|
|
29
|
+
const parts = trimmed.split('.');
|
|
30
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
31
|
+
throw new UserAccessError('errorFieldTargetMustBeQualified', [target]);
|
|
32
|
+
}
|
|
33
|
+
const [inputObjectApiName, inputFieldApiName] = parts;
|
|
34
|
+
const describe = await describeObject(conn, inputObjectApiName);
|
|
35
|
+
const fieldMap = new Map();
|
|
36
|
+
for (const field of describe.fields)
|
|
37
|
+
fieldMap.set(field.name.toLowerCase(), field.name);
|
|
38
|
+
const canonicalFieldApiName = fieldMap.get(inputFieldApiName.toLowerCase());
|
|
39
|
+
if (!canonicalFieldApiName) {
|
|
40
|
+
throw new UserAccessError('errorFieldNotFound', [inputObjectApiName, inputFieldApiName]);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
type: 'field',
|
|
44
|
+
targetName: `${describe.name}.${canonicalFieldApiName}`,
|
|
45
|
+
sobjectType: describe.name,
|
|
46
|
+
fieldApiName: canonicalFieldApiName,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export const validateSetupEntityTarget = async (conn, type, target) => {
|
|
50
|
+
const trimmed = target.trim();
|
|
51
|
+
if (!trimmed)
|
|
52
|
+
throw new UserAccessError('errorInvalidTarget', [target]);
|
|
53
|
+
const definition = setupEntityDefinitions[type];
|
|
54
|
+
const rows = await queryAll(conn, `SELECT Id, ${definition.nameField} FROM ${definition.objectName} WHERE ${definition.nameField} = '${esc(trimmed)}' LIMIT 1`);
|
|
55
|
+
const row = rows[0];
|
|
56
|
+
if (!row)
|
|
57
|
+
throw new UserAccessError(definition.notFoundCode, [trimmed]);
|
|
58
|
+
return {
|
|
59
|
+
type,
|
|
60
|
+
targetName: row[definition.nameField] ?? trimmed,
|
|
61
|
+
setupEntityId: row.Id,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export const validateTabTarget = async (conn, target) => {
|
|
65
|
+
const trimmed = target.trim();
|
|
66
|
+
if (!trimmed)
|
|
67
|
+
throw new UserAccessError('errorInvalidTarget', [target]);
|
|
68
|
+
const rows = await queryAll(conn, `SELECT DurableId, Name FROM TabDefinition WHERE DurableId = '${esc(trimmed)}' LIMIT 1`);
|
|
69
|
+
if (!rows[0])
|
|
70
|
+
throw new UserAccessError('errorTabNotFound', [trimmed]);
|
|
71
|
+
return { type: 'tab', targetName: rows[0].DurableId ?? trimmed };
|
|
72
|
+
};
|
|
73
|
+
export const validateRecordTypeTarget = async (conn, target) => {
|
|
74
|
+
const trimmed = target.trim();
|
|
75
|
+
const parts = trimmed.split('.');
|
|
76
|
+
if (!trimmed ||
|
|
77
|
+
(trimmed.startsWith('012') && !trimmed.includes('.')) ||
|
|
78
|
+
parts.length !== 2 ||
|
|
79
|
+
parts.some((part) => !part)) {
|
|
80
|
+
throw new UserAccessError('errorRecordTypeTargetMustBeQualified', [target]);
|
|
81
|
+
}
|
|
82
|
+
const [inputSobjectType, inputDeveloperName] = parts;
|
|
83
|
+
if (inputDeveloperName.toLowerCase() === 'master') {
|
|
84
|
+
throw new UserAccessError('errorMasterRecordTypeUnsupported', [trimmed]);
|
|
85
|
+
}
|
|
86
|
+
const rows = await queryAll(conn, [
|
|
87
|
+
'SELECT Id, SobjectType, DeveloperName, Name, IsActive',
|
|
88
|
+
'FROM RecordType',
|
|
89
|
+
`WHERE SobjectType = '${esc(inputSobjectType)}'`,
|
|
90
|
+
`AND DeveloperName = '${esc(inputDeveloperName)}'`,
|
|
91
|
+
'LIMIT 2',
|
|
92
|
+
].join(' '));
|
|
93
|
+
if (rows.length === 0)
|
|
94
|
+
throw new UserAccessError('errorRecordTypeNotFound', [trimmed]);
|
|
95
|
+
if (rows.length > 1)
|
|
96
|
+
throw new UserAccessError('errorRecordTypeAmbiguous', [trimmed]);
|
|
97
|
+
const row = rows[0];
|
|
98
|
+
if (row.IsActive !== true)
|
|
99
|
+
throw new UserAccessError('errorRecordTypeInactive', [trimmed]);
|
|
100
|
+
if (!row.SobjectType || !row.DeveloperName || !row.Id) {
|
|
101
|
+
throw new UserAccessError('errorRecordTypeNotFound', [trimmed]);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
type: 'record-type',
|
|
105
|
+
targetName: `${row.SobjectType}.${row.DeveloperName}`,
|
|
106
|
+
sobjectType: row.SobjectType,
|
|
107
|
+
recordTypeId: row.Id,
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=targetValidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"targetValidation.js","sourceRoot":"","sources":["../../src/access/targetValidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Connection } from '@salesforce/core';
|
|
2
|
+
import { WardenError } from '../errors.js';
|
|
3
|
+
export type AccessTargetType = 'field' | 'object' | 'apex-class' | 'vf-page' | 'custom-permission' | 'tab' | 'record-type';
|
|
4
|
+
export type AssignmentType = 'Profile' | 'PermissionSet' | 'PermissionSetGroup';
|
|
5
|
+
export type FieldAccess = {
|
|
6
|
+
kind: 'field';
|
|
7
|
+
read: boolean;
|
|
8
|
+
edit: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type ObjectAccess = {
|
|
11
|
+
kind: 'object';
|
|
12
|
+
read: boolean;
|
|
13
|
+
create: boolean;
|
|
14
|
+
edit: boolean;
|
|
15
|
+
delete: boolean;
|
|
16
|
+
viewAll: boolean;
|
|
17
|
+
modifyAll: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type EnabledAccess = {
|
|
20
|
+
kind: 'enabled';
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
};
|
|
23
|
+
export type TabAccess = {
|
|
24
|
+
kind: 'tab';
|
|
25
|
+
visibility: string;
|
|
26
|
+
};
|
|
27
|
+
export type RecordTypeAccess = {
|
|
28
|
+
kind: 'record-type';
|
|
29
|
+
visible: boolean;
|
|
30
|
+
default: boolean | null;
|
|
31
|
+
};
|
|
32
|
+
export type UserAccessRow = {
|
|
33
|
+
userId: string;
|
|
34
|
+
userName: string;
|
|
35
|
+
username: string;
|
|
36
|
+
targetType: AccessTargetType;
|
|
37
|
+
targetName: string;
|
|
38
|
+
assignmentType: AssignmentType;
|
|
39
|
+
sourceId: string;
|
|
40
|
+
sourceName: string;
|
|
41
|
+
sourceApiName?: string;
|
|
42
|
+
sourceLabel?: string;
|
|
43
|
+
viaPermissionSetId?: string;
|
|
44
|
+
viaPermissionSetName?: string;
|
|
45
|
+
access: FieldAccess | ObjectAccess | EnabledAccess | TabAccess | RecordTypeAccess;
|
|
46
|
+
};
|
|
47
|
+
export type UserAccessStats = {
|
|
48
|
+
totalActiveUsersWithAccess: number;
|
|
49
|
+
profileGrants: number;
|
|
50
|
+
permissionSetGrants: number;
|
|
51
|
+
permissionSetGroupGrants: number;
|
|
52
|
+
};
|
|
53
|
+
export type UserAccessResult = {
|
|
54
|
+
targetType: AccessTargetType;
|
|
55
|
+
targetName: string;
|
|
56
|
+
sobjectType?: string;
|
|
57
|
+
fieldApiName?: string;
|
|
58
|
+
rows: UserAccessRow[];
|
|
59
|
+
stats: UserAccessStats;
|
|
60
|
+
warnings: string[];
|
|
61
|
+
};
|
|
62
|
+
export type ValidatedAccessTarget = {
|
|
63
|
+
type: AccessTargetType;
|
|
64
|
+
targetName: string;
|
|
65
|
+
sobjectType?: string;
|
|
66
|
+
fieldApiName?: string;
|
|
67
|
+
setupEntityId?: string;
|
|
68
|
+
recordTypeId?: string;
|
|
69
|
+
};
|
|
70
|
+
export type AccessTargetResolver = {
|
|
71
|
+
type: AccessTargetType;
|
|
72
|
+
validateTarget(conn: Connection, target: string): Promise<ValidatedAccessTarget>;
|
|
73
|
+
resolve(conn: Connection, target: ValidatedAccessTarget): Promise<UserAccessResult>;
|
|
74
|
+
csvColumns(): string[];
|
|
75
|
+
};
|
|
76
|
+
export type AccessErrorCode = 'errorUnsupportedAccessType' | 'errorInvalidTarget' | 'errorFieldTargetMustBeQualified' | 'errorObjectNotFound' | 'errorFieldNotFound' | 'errorApexClassNotFound' | 'errorVisualforcePageNotFound' | 'errorCustomPermissionNotFound' | 'errorTabNotFound' | 'errorRecordTypeTargetMustBeQualified' | 'errorMasterRecordTypeUnsupported' | 'errorRecordTypeNotFound' | 'errorRecordTypeAmbiguous' | 'errorRecordTypeInactive' | 'errorRecordTypeMetadataReadFailed' | 'errorAccessQueryFailed';
|
|
77
|
+
export declare class AccessError extends WardenError<AccessErrorCode, {
|
|
78
|
+
args: string[];
|
|
79
|
+
cause?: unknown;
|
|
80
|
+
}> {
|
|
81
|
+
readonly args: string[];
|
|
82
|
+
readonly cause?: unknown;
|
|
83
|
+
constructor(code: AccessErrorCode, args?: string[], cause?: unknown);
|
|
84
|
+
}
|
|
85
|
+
/** Backward-compatible name retained for callers of the extracted modules. */
|
|
86
|
+
export declare class UserAccessError extends AccessError {
|
|
87
|
+
constructor(code: AccessErrorCode, args?: string[], cause?: unknown);
|
|
88
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { WardenError } from '../errors.js';
|
|
2
|
+
import { accessMessage } from './messages.js';
|
|
3
|
+
export class AccessError extends WardenError {
|
|
4
|
+
args;
|
|
5
|
+
cause;
|
|
6
|
+
constructor(code, args = [], cause) {
|
|
7
|
+
super(code, accessMessage(code, args), { args, cause });
|
|
8
|
+
this.name = 'AccessError';
|
|
9
|
+
this.args = args;
|
|
10
|
+
this.cause = cause;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Backward-compatible name retained for callers of the extracted modules. */
|
|
14
|
+
export class UserAccessError extends AccessError {
|
|
15
|
+
constructor(code, args = [], cause) {
|
|
16
|
+
super(code, args, cause);
|
|
17
|
+
this.name = 'UserAccessError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/access/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA+G9C,MAAM,OAAO,WAAY,SAAQ,WAAiE;IAChF,IAAI,CAAW;IACf,KAAK,CAAW;IAEhC,YAAmB,IAAqB,EAAE,OAAiB,EAAE,EAAE,KAAe;QAC5E,KAAK,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,8EAA8E;AAC9E,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAC9C,YAAmB,IAAqB,EAAE,OAAiB,EAAE,EAAE,KAAe;QAC5E,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
|
package/lib/errors.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for everything warden-core throws on purpose.
|
|
3
|
+
*
|
|
4
|
+
* `code` and the shape of `data` are part of the public API and are
|
|
5
|
+
* semver-covered; `message` is default English text that callers may show
|
|
6
|
+
* as is or replace using `code`. Area-specific subclasses narrow `C` to a
|
|
7
|
+
* string-literal union of their codes.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WardenError<C extends string = string, D = unknown> extends Error {
|
|
10
|
+
readonly code: C;
|
|
11
|
+
readonly data?: D | undefined;
|
|
12
|
+
constructor(code: C, message: string, data?: D | undefined);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Structural check for {@link WardenError}. Prefer this over `instanceof`,
|
|
16
|
+
* which fails when a consumer ends up with two copies of this package.
|
|
17
|
+
*/
|
|
18
|
+
export declare const isWardenError: (error: unknown) => error is WardenError;
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error for everything warden-core throws on purpose.
|
|
3
|
+
*
|
|
4
|
+
* `code` and the shape of `data` are part of the public API and are
|
|
5
|
+
* semver-covered; `message` is default English text that callers may show
|
|
6
|
+
* as is or replace using `code`. Area-specific subclasses narrow `C` to a
|
|
7
|
+
* string-literal union of their codes.
|
|
8
|
+
*/
|
|
9
|
+
export class WardenError extends Error {
|
|
10
|
+
code;
|
|
11
|
+
data;
|
|
12
|
+
constructor(code, message, data) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.data = data;
|
|
16
|
+
this.name = 'WardenError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const WARDEN_ERROR_NAMES = new Set([
|
|
20
|
+
'WardenError',
|
|
21
|
+
'AccessError',
|
|
22
|
+
'UserAccessError',
|
|
23
|
+
'LifecycleError',
|
|
24
|
+
'ProvisioningError',
|
|
25
|
+
'DefinitionError',
|
|
26
|
+
'CsvReadError',
|
|
27
|
+
'RelatedRecordsError',
|
|
28
|
+
]);
|
|
29
|
+
/**
|
|
30
|
+
* Structural check for {@link WardenError}. Prefer this over `instanceof`,
|
|
31
|
+
* which fails when a consumer ends up with two copies of this package.
|
|
32
|
+
*/
|
|
33
|
+
export const isWardenError = (error) => error instanceof WardenError ||
|
|
34
|
+
(typeof error === 'object' &&
|
|
35
|
+
error !== null &&
|
|
36
|
+
WARDEN_ERROR_NAMES.has(typeof error.name === 'string' ? error.name : '') &&
|
|
37
|
+
typeof error.code === 'string' &&
|
|
38
|
+
typeof error.message === 'string');
|
|
39
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,OAAO,WAAoD,SAAQ,KAAK;IACzC;IAA0C;IAA7E,YAAmC,IAAO,EAAE,OAAe,EAAkB,IAAQ;QACnF,KAAK,CAAC,OAAO,CAAC,CAAC;QADkB,SAAI,GAAJ,IAAI,CAAG;QAAmC,SAAI,GAAJ,IAAI,CAAI;QAEnF,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,aAAa;IACb,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,mBAAmB;IACnB,iBAAiB;IACjB,cAAc;IACd,qBAAqB;CACtB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAc,EAAwB,EAAE,CACpE,KAAK,YAAY,WAAW;IAC5B,CAAC,OAAO,KAAK,KAAK,QAAQ;QACxB,KAAK,KAAK,IAAI;QACd,kBAAkB,CAAC,GAAG,CACpB,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,KAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAC/F;QACD,OAAQ,KAA4B,CAAC,IAAI,KAAK,QAAQ;QACtD,OAAQ,KAA+B,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export { WardenError, isWardenError } from './errors.js';
|
|
2
|
+
export { AccessError, UserAccessError } from './access/types.js';
|
|
3
|
+
export { flattenAccessRow, renderEnabledTable, renderFieldTable, renderObjectTable, renderRecordTypeTable, renderTabTable, } from './access/output.js';
|
|
4
|
+
export { getResolver } from './access/resolvers/index.js';
|
|
5
|
+
export { resolveReverseAccess, reverseCsvColumns } from './access/reverse.js';
|
|
6
|
+
export { LifecycleError } from './lifecycle/errors.js';
|
|
7
|
+
export { executeFreezeToggle, FREEZE, UNFREEZE } from './lifecycle/freezeState.js';
|
|
8
|
+
export { failedResult, makeNotice, renderLifecycleResult, resolvedTargetResult, summarizeLifecycle, } from './lifecycle/output.js';
|
|
9
|
+
export { executeStrip } from './lifecycle/stripPlan.js';
|
|
10
|
+
export { buildSnapshotFile, readSnapshotFile, writeSnapshotFile } from './lifecycle/snapshotState.js';
|
|
11
|
+
export { buildTargetRequests, parseUserFlag, resolveTargetField, resolveTargets } from './lifecycle/targeting.js';
|
|
12
|
+
export { executePersonaDiff, executeUserToUserDiff } from './lifecycle/userDiff.js';
|
|
13
|
+
export { renderUserDiffCsv, renderUserDiffHuman } from './lifecycle/diffOutput.js';
|
|
14
|
+
export { renderUserConformanceCsv, renderUserConformanceHuman, verifyUserDiff } from './lifecycle/conformance.js';
|
|
15
|
+
export { loadAssignmentState } from './lifecycle/assignmentState.js';
|
|
16
|
+
export { runAssignmentCreates, runRecordUpdate } from './lifecycle/dmlRunner.js';
|
|
17
|
+
export { ProvisioningError, DefinitionError } from './provisioning/errors.js';
|
|
18
|
+
export { ProvisionUserUseCase } from './provisioning/provisionUserUseCase.js';
|
|
19
|
+
export { readProvisionDefinitions } from './provisioning/definitionReader.js';
|
|
20
|
+
export { RelatedRecordsError } from './relatedRecords/errors.js';
|
|
21
|
+
export { personaDefinitionsFileSchema, personaSchema, relatedCatalogSchema, relationshipDefSchema, snapshotFileSchema, userInputSchema, userSnapshotEntrySchema, usersDefinitionFileSchema, USERS_CSV_COLUMNS, } from './spec/index.js';
|
|
22
|
+
export { parsePersonaDefinitions, parseRelatedCatalog, parseSnapshot, parseUsersDefinition, safeParsePersonaDefinitions, safeParseRelatedCatalog, safeParseSnapshot, safeParseUsersDefinition, validatePersonaDefinitionsText, validateRelatedCatalogText, validateSnapshotText, validateUsersDefinitionText, } from './spec/index.js';
|
|
23
|
+
export { confirmWithTimeout } from './shared/prompt.js';
|
|
24
|
+
export { detectInputFormat, serializeCsv } from './shared/csv.js';
|
|
25
|
+
export { describeUserFields } from './shared/userFields.js';
|
|
26
|
+
export { renderLifecycleCsv, renderProvisionCsv, renderRestoreCsv, renderSnapshotCsv, renderStripCsv, } from './shared/output.js';
|
|
27
|
+
export { soqlIn } from './shared/sfUtils.js';
|
|
28
|
+
export type { InputFormat } from './shared/csv.js';
|
|
29
|
+
export type { AccessTargetType, UserAccessResult, UserAccessRow, ValidatedAccessTarget } from './access/types.js';
|
|
30
|
+
export type { AssignmentState } from './lifecycle/assignmentState.js';
|
|
31
|
+
export type { IdentityReview, LabelBundle, LifecycleResult, LifecycleUserResult, ResolvedTargetUser, TargetRequest, } from './lifecycle/types.js';
|
|
32
|
+
export type { ProvisionResult } from './provisioning/provisionUserUseCase.js';
|
|
33
|
+
export type { StripFlags } from './lifecycle/stripPlan.js';
|
|
34
|
+
export type { UserDiffResult } from './lifecycle/userDiff.js';
|
|
35
|
+
export type { UserConformanceVerdict } from './lifecycle/conformance.js';
|
|
36
|
+
export type { UserSnapshotEntry } from './lifecycle/snapshotState.js';
|
|
37
|
+
export type { PersonaDefinition, PersonaDefinitionsFile, RelatedCatalog, RelationshipDef, RelationshipMode, RelationshipPhase, SchemaFailure, SchemaIssue, SchemaResult, SchemaSuccess, SourceExpr, UserInput, UserSnapshotFile, UsersDefinitionFile, } from './spec/index.js';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Everything exported from this file is warden-core's public API and is
|
|
2
|
+
// semver-covered: adding an export is a minor change, but removing or renaming
|
|
3
|
+
// one, or changing a signature or result shape, is breaking.
|
|
4
|
+
// `test/index.test.ts` pins the exported-key list so an accidental removal
|
|
5
|
+
// fails a test instead of shipping. See docs/design/0001-warden-core-boundaries.md.
|
|
6
|
+
export { WardenError, isWardenError } from './errors.js';
|
|
7
|
+
export { AccessError, UserAccessError } from './access/types.js';
|
|
8
|
+
export { flattenAccessRow, renderEnabledTable, renderFieldTable, renderObjectTable, renderRecordTypeTable, renderTabTable, } from './access/output.js';
|
|
9
|
+
export { getResolver } from './access/resolvers/index.js';
|
|
10
|
+
export { resolveReverseAccess, reverseCsvColumns } from './access/reverse.js';
|
|
11
|
+
export { LifecycleError } from './lifecycle/errors.js';
|
|
12
|
+
export { executeFreezeToggle, FREEZE, UNFREEZE } from './lifecycle/freezeState.js';
|
|
13
|
+
export { failedResult, makeNotice, renderLifecycleResult, resolvedTargetResult, summarizeLifecycle, } from './lifecycle/output.js';
|
|
14
|
+
export { executeStrip } from './lifecycle/stripPlan.js';
|
|
15
|
+
export { buildSnapshotFile, readSnapshotFile, writeSnapshotFile } from './lifecycle/snapshotState.js';
|
|
16
|
+
export { buildTargetRequests, parseUserFlag, resolveTargetField, resolveTargets } from './lifecycle/targeting.js';
|
|
17
|
+
export { executePersonaDiff, executeUserToUserDiff } from './lifecycle/userDiff.js';
|
|
18
|
+
export { renderUserDiffCsv, renderUserDiffHuman } from './lifecycle/diffOutput.js';
|
|
19
|
+
export { renderUserConformanceCsv, renderUserConformanceHuman, verifyUserDiff } from './lifecycle/conformance.js';
|
|
20
|
+
export { loadAssignmentState } from './lifecycle/assignmentState.js';
|
|
21
|
+
export { runAssignmentCreates, runRecordUpdate } from './lifecycle/dmlRunner.js';
|
|
22
|
+
export { ProvisioningError, DefinitionError } from './provisioning/errors.js';
|
|
23
|
+
export { ProvisionUserUseCase } from './provisioning/provisionUserUseCase.js';
|
|
24
|
+
export { readProvisionDefinitions } from './provisioning/definitionReader.js';
|
|
25
|
+
export { RelatedRecordsError } from './relatedRecords/errors.js';
|
|
26
|
+
export { personaDefinitionsFileSchema, personaSchema, relatedCatalogSchema, relationshipDefSchema, snapshotFileSchema, userInputSchema, userSnapshotEntrySchema, usersDefinitionFileSchema, USERS_CSV_COLUMNS, } from './spec/index.js';
|
|
27
|
+
export { parsePersonaDefinitions, parseRelatedCatalog, parseSnapshot, parseUsersDefinition, safeParsePersonaDefinitions, safeParseRelatedCatalog, safeParseSnapshot, safeParseUsersDefinition, validatePersonaDefinitionsText, validateRelatedCatalogText, validateSnapshotText, validateUsersDefinitionText, } from './spec/index.js';
|
|
28
|
+
export { confirmWithTimeout } from './shared/prompt.js';
|
|
29
|
+
export { detectInputFormat, serializeCsv } from './shared/csv.js';
|
|
30
|
+
export { describeUserFields } from './shared/userFields.js';
|
|
31
|
+
export { renderLifecycleCsv, renderProvisionCsv, renderRestoreCsv, renderSnapshotCsv, renderStripCsv, } from './shared/output.js';
|
|
32
|
+
export { soqlIn } from './shared/sfUtils.js';
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,+EAA+E;AAC/E,6DAA6D;AAC7D,2EAA2E;AAC3E,oFAAoF;AAEpF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACnF,OAAO,EACL,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtG,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAClH,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAClH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEjF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAC;AAE9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EACL,4BAA4B,EAC5B,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,uBAAuB,EACvB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,EACjB,wBAAwB,EACxB,8BAA8B,EAC9B,0BAA0B,EAC1B,oBAAoB,EACpB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Connection } from '@salesforce/core';
|
|
2
|
+
import type { LabelBundle } from './types.js';
|
|
3
|
+
export type UserLoginRow = {
|
|
4
|
+
Id: string;
|
|
5
|
+
UserId: string;
|
|
6
|
+
IsFrozen: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type PermissionSetAssignmentRow = {
|
|
9
|
+
Id: string;
|
|
10
|
+
AssigneeId: string;
|
|
11
|
+
PermissionSetId?: string | null;
|
|
12
|
+
PermissionSetGroupId?: string | null;
|
|
13
|
+
PermissionSet?: {
|
|
14
|
+
IsOwnedByProfile?: boolean;
|
|
15
|
+
Name?: string;
|
|
16
|
+
Label?: string;
|
|
17
|
+
} | null;
|
|
18
|
+
PermissionSetGroup?: {
|
|
19
|
+
DeveloperName?: string;
|
|
20
|
+
MasterLabel?: string;
|
|
21
|
+
} | null;
|
|
22
|
+
};
|
|
23
|
+
export type GroupMemberRow = {
|
|
24
|
+
Id: string;
|
|
25
|
+
GroupId: string;
|
|
26
|
+
UserOrGroupId: string;
|
|
27
|
+
Group?: {
|
|
28
|
+
Type?: string;
|
|
29
|
+
DeveloperName?: string;
|
|
30
|
+
Name?: string;
|
|
31
|
+
} | null;
|
|
32
|
+
};
|
|
33
|
+
export type PermissionSetLicenseAssignRow = {
|
|
34
|
+
Id: string;
|
|
35
|
+
AssigneeId: string;
|
|
36
|
+
PermissionSetLicenseId: string;
|
|
37
|
+
PermissionSetLicense?: {
|
|
38
|
+
DeveloperName?: string;
|
|
39
|
+
MasterLabel?: string;
|
|
40
|
+
} | null;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Describe a permission set assignment by its group when it came from one,
|
|
44
|
+
* otherwise by the permission set itself. Rows identifying neither assignment
|
|
45
|
+
* type are ignored; loadAssignmentState's query always projects PermissionSetId.
|
|
46
|
+
*/
|
|
47
|
+
export declare const permissionSetAssignmentLabel: (row: PermissionSetAssignmentRow) => LabelBundle | undefined;
|
|
48
|
+
export declare const groupMemberLabel: (row: GroupMemberRow) => LabelBundle;
|
|
49
|
+
export declare const permissionSetLicenseLabel: (row: PermissionSetLicenseAssignRow) => LabelBundle;
|
|
50
|
+
export type AssignmentState = {
|
|
51
|
+
userLoginByUserId: Map<string, UserLoginRow[]>;
|
|
52
|
+
psaByUserId: Map<string, PermissionSetAssignmentRow[]>;
|
|
53
|
+
groupByUserId: Map<string, GroupMemberRow[]>;
|
|
54
|
+
pslByUserId: Map<string, PermissionSetLicenseAssignRow[]>;
|
|
55
|
+
};
|
|
56
|
+
export type AssignmentStateOptions = {
|
|
57
|
+
userLogin?: boolean;
|
|
58
|
+
permissionSetAssignments?: boolean;
|
|
59
|
+
groupMemberships?: boolean;
|
|
60
|
+
permissionSetLicenses?: boolean;
|
|
61
|
+
};
|
|
62
|
+
export declare const loadAssignmentState: (conn: Connection, targetIds: string[], options?: AssignmentStateOptions) => Promise<AssignmentState>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { batch, soqlIn } from '../shared/sfUtils.js';
|
|
2
|
+
/**
|
|
3
|
+
* Describe a permission set assignment by its group when it came from one,
|
|
4
|
+
* otherwise by the permission set itself. Rows identifying neither assignment
|
|
5
|
+
* type are ignored; loadAssignmentState's query always projects PermissionSetId.
|
|
6
|
+
*/
|
|
7
|
+
export const permissionSetAssignmentLabel = (row) => {
|
|
8
|
+
if (row.PermissionSetGroupId) {
|
|
9
|
+
return {
|
|
10
|
+
id: row.PermissionSetGroupId,
|
|
11
|
+
apiName: row.PermissionSetGroup?.DeveloperName,
|
|
12
|
+
label: row.PermissionSetGroup?.MasterLabel,
|
|
13
|
+
type: 'PermissionSetGroup',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (row.PermissionSetId) {
|
|
17
|
+
return {
|
|
18
|
+
id: row.PermissionSetId,
|
|
19
|
+
apiName: row.PermissionSet?.Name,
|
|
20
|
+
label: row.PermissionSet?.Label,
|
|
21
|
+
type: 'PermissionSet',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return undefined;
|
|
25
|
+
};
|
|
26
|
+
export const groupMemberLabel = (row) => ({
|
|
27
|
+
id: row.GroupId,
|
|
28
|
+
apiName: row.Group?.DeveloperName,
|
|
29
|
+
label: row.Group?.Name,
|
|
30
|
+
type: row.Group?.Type === 'Queue' ? 'Queue' : 'PublicGroup',
|
|
31
|
+
});
|
|
32
|
+
export const permissionSetLicenseLabel = (row) => ({
|
|
33
|
+
id: row.PermissionSetLicenseId,
|
|
34
|
+
apiName: row.PermissionSetLicense?.DeveloperName,
|
|
35
|
+
label: row.PermissionSetLicense?.MasterLabel,
|
|
36
|
+
type: 'PermissionSetLicense',
|
|
37
|
+
});
|
|
38
|
+
const QUERY_BATCH_SIZE = 100;
|
|
39
|
+
const emptyState = () => ({
|
|
40
|
+
userLoginByUserId: new Map(),
|
|
41
|
+
psaByUserId: new Map(),
|
|
42
|
+
groupByUserId: new Map(),
|
|
43
|
+
pslByUserId: new Map(),
|
|
44
|
+
});
|
|
45
|
+
const queryRowsByUser = async (conn, soql, keyField) => {
|
|
46
|
+
const rows = (await conn.query(soql)).records;
|
|
47
|
+
const map = new Map();
|
|
48
|
+
for (const row of rows) {
|
|
49
|
+
const key = String(row[keyField] ?? '');
|
|
50
|
+
const group = map.get(key) ?? [];
|
|
51
|
+
group.push(row);
|
|
52
|
+
map.set(key, group);
|
|
53
|
+
}
|
|
54
|
+
return map;
|
|
55
|
+
};
|
|
56
|
+
const mergeMaps = (maps) => {
|
|
57
|
+
const merged = new Map();
|
|
58
|
+
for (const map of maps) {
|
|
59
|
+
for (const [key, rows] of map.entries()) {
|
|
60
|
+
merged.set(key, (merged.get(key) ?? []).concat(rows));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return merged;
|
|
64
|
+
};
|
|
65
|
+
const queryRowsByUserBatched = async (conn, targetIds, buildSoql, keyField) => {
|
|
66
|
+
const maps = await Promise.all(batch(targetIds, QUERY_BATCH_SIZE).map((idBatch) => queryRowsByUser(conn, buildSoql(soqlIn(idBatch)), keyField)));
|
|
67
|
+
return mergeMaps(maps);
|
|
68
|
+
};
|
|
69
|
+
const shouldLoad = (options, key) => options ? options[key] === true : true;
|
|
70
|
+
export const loadAssignmentState = async (conn, targetIds, options) => {
|
|
71
|
+
if (targetIds.length === 0)
|
|
72
|
+
return emptyState();
|
|
73
|
+
const [userLoginByUserId, psaByUserId, groupByUserId, pslByUserId] = await Promise.all([
|
|
74
|
+
shouldLoad(options, 'userLogin')
|
|
75
|
+
? queryRowsByUserBatched(conn, targetIds, (inClause) => `SELECT Id, UserId, IsFrozen FROM UserLogin WHERE UserId IN (${inClause})`, 'UserId')
|
|
76
|
+
: Promise.resolve(new Map()),
|
|
77
|
+
shouldLoad(options, 'permissionSetAssignments')
|
|
78
|
+
? queryRowsByUserBatched(conn, targetIds, (inClause) => `SELECT Id, AssigneeId, PermissionSetId, PermissionSetGroupId, PermissionSet.IsOwnedByProfile, PermissionSet.Name, PermissionSet.Label, PermissionSetGroup.DeveloperName, PermissionSetGroup.MasterLabel FROM PermissionSetAssignment WHERE AssigneeId IN (${inClause})`, 'AssigneeId')
|
|
79
|
+
: Promise.resolve(new Map()),
|
|
80
|
+
shouldLoad(options, 'groupMemberships')
|
|
81
|
+
? queryRowsByUserBatched(conn, targetIds, (inClause) => `SELECT Id, GroupId, UserOrGroupId, Group.Type, Group.DeveloperName, Group.Name FROM GroupMember WHERE UserOrGroupId IN (${inClause}) AND Group.Type IN ('Regular', 'Queue')`, 'UserOrGroupId')
|
|
82
|
+
: Promise.resolve(new Map()),
|
|
83
|
+
shouldLoad(options, 'permissionSetLicenses')
|
|
84
|
+
? queryRowsByUserBatched(conn, targetIds, (inClause) => `SELECT Id, AssigneeId, PermissionSetLicenseId, PermissionSetLicense.DeveloperName, PermissionSetLicense.MasterLabel FROM PermissionSetLicenseAssign WHERE AssigneeId IN (${inClause})`, 'AssigneeId')
|
|
85
|
+
: Promise.resolve(new Map()),
|
|
86
|
+
]);
|
|
87
|
+
return { userLoginByUserId, psaByUserId, groupByUserId, pslByUserId };
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=assignmentState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assignmentState.js","sourceRoot":"","sources":["../../src/lifecycle/assignmentState.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { UserDiffResult } from './userDiff.js';
|
|
2
|
+
import { type MessageLookup } from './diffOutput.js';
|
|
3
|
+
export type UserConformanceVerdict = {
|
|
4
|
+
key: string;
|
|
5
|
+
conformant: boolean;
|
|
6
|
+
violations: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare const verifyUserDiff: (result: UserDiffResult, lookup: MessageLookup) => UserConformanceVerdict[];
|
|
9
|
+
export declare const renderUserConformanceCsv: (verdicts: UserConformanceVerdict[]) => string;
|
|
10
|
+
export declare const renderUserConformanceHuman: (verdicts: UserConformanceVerdict[], lookup: MessageLookup) => string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { serializeCsv } from '../shared/csv.js';
|
|
2
|
+
import { displayValue } from './diffOutput.js';
|
|
3
|
+
const conformanceViolationsForCategory = (result, category, delta, lookup) => {
|
|
4
|
+
const violations = [];
|
|
5
|
+
if (delta.adds.length > 0) {
|
|
6
|
+
violations.push(lookup('verify.violation.missing', [category, delta.adds.map((value) => displayValue(result, value)).join(', ')]));
|
|
7
|
+
}
|
|
8
|
+
if (delta.mode === 'sync' && delta.removes.length > 0) {
|
|
9
|
+
violations.push(lookup('verify.violation.extra', [category, delta.removes.map((value) => displayValue(result, value)).join(', ')]));
|
|
10
|
+
}
|
|
11
|
+
return violations;
|
|
12
|
+
};
|
|
13
|
+
const conformanceViolationsForUser = (result, user, lookup) => {
|
|
14
|
+
if (user.status === 'would-create')
|
|
15
|
+
return [lookup('verify.violation.notFound')];
|
|
16
|
+
if (user.status === 'failed') {
|
|
17
|
+
return user.errors.length > 0
|
|
18
|
+
? user.errors.map((error) => lookup('verify.violation.error', [error]))
|
|
19
|
+
: [lookup('verify.violation.error', ['user diff failed'])];
|
|
20
|
+
}
|
|
21
|
+
const violations = [];
|
|
22
|
+
if (!user.profile.matches) {
|
|
23
|
+
violations.push(lookup('verify.violation.profile', [
|
|
24
|
+
displayValue(result, user.profile.current ?? ''),
|
|
25
|
+
displayValue(result, user.profile.intended ?? ''),
|
|
26
|
+
]));
|
|
27
|
+
}
|
|
28
|
+
if (!user.role.matches) {
|
|
29
|
+
violations.push(lookup('verify.violation.role', [
|
|
30
|
+
displayValue(result, user.role.current ?? ''),
|
|
31
|
+
displayValue(result, user.role.intended ?? ''),
|
|
32
|
+
]));
|
|
33
|
+
}
|
|
34
|
+
for (const [category, delta] of Object.entries(user.assignments)) {
|
|
35
|
+
violations.push(...conformanceViolationsForCategory(result, category, delta, lookup));
|
|
36
|
+
}
|
|
37
|
+
return violations;
|
|
38
|
+
};
|
|
39
|
+
export const verifyUserDiff = (result, lookup) => result.users.map((user) => {
|
|
40
|
+
const violations = conformanceViolationsForUser(result, user, lookup);
|
|
41
|
+
return { key: user.key, conformant: violations.length === 0, violations };
|
|
42
|
+
});
|
|
43
|
+
export const renderUserConformanceCsv = (verdicts) => serializeCsv(verdicts.map((verdict) => ({
|
|
44
|
+
key: verdict.key,
|
|
45
|
+
conformant: String(verdict.conformant),
|
|
46
|
+
violations: verdict.violations.join('; '),
|
|
47
|
+
})), ['key', 'conformant', 'violations']);
|
|
48
|
+
export const renderUserConformanceHuman = (verdicts, lookup) => {
|
|
49
|
+
const conformant = verdicts.filter((verdict) => verdict.conformant).length;
|
|
50
|
+
const nonConformant = verdicts.length - conformant;
|
|
51
|
+
const lines = [lookup('verify.summary', [String(verdicts.length), String(conformant), String(nonConformant)])];
|
|
52
|
+
for (const verdict of verdicts.filter((candidate) => !candidate.conformant)) {
|
|
53
|
+
lines.push('', lookup('verify.user', [verdict.key]));
|
|
54
|
+
for (const violation of verdict.violations)
|
|
55
|
+
lines.push(` - ${violation}`);
|
|
56
|
+
}
|
|
57
|
+
return lines.join('\n');
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conformance.js","sourceRoot":"","sources":["../../src/lifecycle/conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UserDiffResult } from './userDiff.js';
|
|
2
|
+
export type MessageLookup = (key: string, args?: string[]) => string;
|
|
3
|
+
export declare const renderUserDiffCsv: (result: UserDiffResult) => string;
|
|
4
|
+
export declare const displayValue: (result: UserDiffResult, value: string) => string;
|
|
5
|
+
export declare const renderUserDiffHuman: (result: UserDiffResult, lookup: MessageLookup, options?: {
|
|
6
|
+
verbose?: boolean;
|
|
7
|
+
}) => string;
|