-
Notifications
You must be signed in to change notification settings - Fork 41
/
check.ts
147 lines (130 loc) · 6.29 KB
/
check.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// for a given object and optionally field, which profiles/permsets have access, and optionally, what all users are those?
import { flags, SfdxCommand } from '@salesforce/command';
export default class PermCheck extends SfdxCommand {
public static description = 'who has access to what';
public static examples = [
`sfdx shane:permset:check -o Project__c --profiles --permsets
// list the profiles and permsets that have Read access to the object
`,
`sfdx shane:permset:check -o Project__c -f Due_Date__c --fieldlevel Edit --profiles --permsets
// list the profiles and permsets that have Edit access to the field on the object
`,
`sfdx shane:permset:check -o Project__c -f Due_Date__c --users
// list the users that have Read access to the field on the object, and the profile/permset(s) that are granting it
`
];
protected static flagsConfig = {
object: flags.string({ char: 'o', description: 'what object to check perms on', required: true }),
field: flags.string({ char: 'f', description: 'what field to check' }),
profiles: flags.boolean({ description: 'return names/ids of profiles' }),
permsets: flags.boolean({ description: 'return names/ids of permission sets' }),
users: flags.boolean({
description: 'return names/ids of users with those profiles and/or permission sets',
exclusive: ['permsets', 'profiles']
}),
fieldlevel: flags.string({ description: 'what level of perms are you looking for', default: 'Read', options: ['Read', 'Edit'] }),
objectlevel: flags.string({
description: 'what level of perms are you looking for',
default: 'Read',
options: ['Read', 'Edit', 'Create', 'Delete', 'ViewAll', 'ModifyAll']
})
};
protected static requiresUsername = true;
public async run(): Promise<any> {
const output = [];
if (!this.flags.profiles && !this.flags.permsets && !this.flags.users) {
throw new Error('add --profiles, --permsets or --users to say what you want in your table');
}
// this.org is guaranteed because requiresUsername=true, as opposed to supportsUsername
const conn = this.org.getConnection();
let withAccess;
if (this.flags.field) {
withAccess = (
await conn.query(
`select ParentId, Parent.Name, Parent.IsOwnedByProfile, Parent.ProfileId from FieldPermissions where ${levelMap.get(
this.flags.fieldlevel
)} = true and SobjectType = '${this.flags.object}' and Field = '${this.flags.object}.${this.flags.field}'`
)
).records as any[];
} else {
withAccess = (
await conn.query(
`select ParentId, Parent.Name, Parent.IsOwnedByProfile, Parent.ProfileId from ObjectPermissions where ${levelMap.get(
this.flags.objectlevel
)} = true and SobjectType = '${this.flags.object}'`
)
).records as any[];
}
const profileswithAccess = withAccess.filter(ps => ps.Parent.IsOwnedByProfile);
const permsetswithAccess = withAccess.filter(ps => !ps.Parent.IsOwnedByProfile);
const profilesById = async permsetsList => {
if (permsetsList.length === 0) {
return [];
}
const query = `select id, Name from Profile where id in (${permsetsList.map(ps => `'${ps.Parent.ProfileId}'`).join(',')})`;
return (await conn.query(query)).records;
};
if (this.flags.profiles || this.flags.users) {
output.concat((await profilesById(profileswithAccess)) as any[]).map(profile => ({
type: 'Profile',
name: profile.Name,
id: profile.Id
}));
}
if (this.flags.permsets || this.flags.users) {
output.concat(
permsetswithAccess.map(ps => ({
type: 'PermissionSet',
name: ps.Parent.Name,
id: ps.ParentId
}))
);
}
if (this.flags.users) {
// which users have that profile?
const query = `select id, username, Name, Profile.Name from User where ProfileId in (${output
.filter(i => i.type === 'Profile')
.map(profile => `'${profile.id}'`)
.join(',')})`;
const userOutput = ((await conn.query(query)).records as any[]).map(user => ({
userid: user.Id,
name: user.Name,
username: user.Username,
profile: user.Profile.Name,
permsets: []
}));
const psaQuery = `select AssigneeId, Assignee.Username, Assignee.Name, PermissionSet.Name from PermissionSetAssignment where PermissionSetId in (${output
.filter(i => i.type === 'PermissionSet')
.map(ps => `'${ps.id}'`)
.join(',')})`;
const psaUsers = (await conn.query(psaQuery)).records as any[];
psaUsers.forEach(psaUser => {
// if in the list, add the permset to the permsets columns
const index = userOutput.findIndex(user => user.userid === psaUser.AssigneeId);
if (index >= 0) {
userOutput[index].permsets.push(psaUser.PermissionSet.Name);
} else {
userOutput.push({
userid: psaUser.AssigneeId,
name: psaUser.Assignee.Name,
username: psaUser.Assignee.Username,
profile: null,
permsets: [psaUser.PermissionSet.Name]
});
}
});
this.ux.table(userOutput, ['userid', 'name', 'username', 'profile', 'permsets']);
return userOutput;
}
this.ux.table(output, ['type', 'name', 'id']);
return output;
}
}
const levelMap = new Map([
['Read', 'PermissionsRead'],
['Create', 'PermissionsCreate'],
['Edit', 'PermissionsEdit'],
['Delete', 'PermissionsDelete'],
['ViewAll', 'PermissionsViewAllRecords'],
['ModifyAll', 'PermissionsModifyAllRecords']
]);