Created
July 7, 2016 10:28
-
-
Save jkentjnr/599d6df0332e7fa6efb493b8156ddac3 to your computer and use it in GitHub Desktop.
Salesforce Apex: Check for permission (both User and Permission Sets)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public without sharing class SystemPermissionUtility { | |
// The permissions required by the application. | |
private static List<String> getPermissionList() { | |
return new List<String>{ | |
'PermissionsApiEnabled', | |
'PermissionsModifyAllData' | |
}; | |
} | |
public static Map<String, Boolean> permissionCache; | |
private static User p_userWithPermissions { get; set; } | |
public static User getUserWithPermissions() { | |
if (p_userWithPermissions == null) { | |
List<String> permissionList = SystemPermissionUtility.getPermissionList(); | |
List<String> userFieldsList = new List<String>{ 'Id', 'Name' }; | |
for (String permission : permissionList) { | |
userFieldsList.add('Profile.' + permission); | |
} | |
List<String> permissionSetAssignmentFieldsList = new List<String>(); | |
for (String permission : permissionList) { | |
permissionSetAssignmentFieldsList.add('PermissionSet.' + permission); | |
} | |
p_userWithPermissions = Database.Query( | |
String.join( | |
new List<String> { | |
'SELECT', | |
String.join(userFieldsList, ', '), | |
',', | |
'(SELECT Id,', | |
String.join(permissionSetAssignmentFieldsList, ', '), | |
'FROM PermissionSetAssignments WHERE', | |
String.join(permissionSetAssignmentFieldsList, ' = TRUE OR '), | |
' = TRUE)', | |
'FROM User WHERE Id = \'' + UserInfo.getUserId() + '\' LIMIT 1' | |
}, | |
' ' | |
) | |
); | |
} | |
return p_userWithPermissions; | |
} | |
public static Boolean userHasPermission(String permissionName) { | |
if (permissionCache == null) | |
// Lazy load the permission cache. | |
permissionCache = new Map<String, Boolean>(); | |
else { | |
// Check the cache for permission. | |
if (permissionCache.containsKey(permissionName) == true) { | |
return permissionCache.get(permissionName); | |
} | |
} | |
// Get the user with permissions (cached if possible) | |
User u = getUserWithPermissions(); | |
// Determine whether the running user has a given Permission | |
Boolean hasPermission = false; | |
if (u != null) { | |
// First check the Profile | |
SObject profile = u.getSObject('Profile'); | |
if (profile != null && Boolean.valueOf(profile.get(permissionName)) == true) { | |
hasPermission = true; | |
} | |
// Then check Permission Set Assignments | |
else { | |
List<SObject> psaList = u.getSObjects('PermissionSetAssignments'); | |
System.Debug('psaList: ' + psaList); | |
if (psaList != null && psaList.isEmpty() == false) { | |
for (SObject psa : psaList) { | |
SObject ps = psa.getSObject('PermissionSet'); | |
if (ps.get(permissionName) != null && Boolean.valueOf(ps.get(permissionName)) == true) { | |
hasPermission = true; | |
break; | |
} | |
} | |
} | |
} | |
} | |
// Cache the permission and return the result. | |
permissionCache.put(permissionName, hasPermission); | |
return hasPermission; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@isTest | |
private class SystemPermissionUtilityTest { | |
@isTest | |
static void testUserHasPermission_Valid_Profile_Missing_PermissionSet_Success() { | |
// Get a basic user. | |
User u = ApplicationMock.getStandardUser(); | |
// Create PermissionSet and assign to test user | |
SystemPermissionUtilityTest.createPermissionSetAndAssignUser(u); | |
System.runAs(u) { | |
System.assertEquals(true, SystemPermissionUtility.userHasPermission('PermissionsModifyAllData')); | |
} | |
} | |
@isTest | |
static void testUserHasPermission_Valid_Profile_Missing_PermissionSet_Missing() { | |
// Get a basic user. | |
User u = ApplicationMock.getStandardUser(); | |
System.runAs(u) { | |
System.assertEquals(false, SystemPermissionUtility.userHasPermission('PermissionsModifyAllData')); | |
} | |
} | |
@isTest | |
static void testUserHasPermission_Valid_Profile_Success_PermissionSet_Success() { | |
// Get a sys admin user. | |
User u = ApplicationMock.getSysAdminUser(); | |
// Create PermissionSet and assign to test user | |
SystemPermissionUtilityTest.createPermissionSetAndAssignUser(u); | |
System.runAs(u) { | |
System.assertEquals(true, SystemPermissionUtility.userHasPermission('PermissionsModifyAllData')); | |
} | |
} | |
@isTest | |
static void testUserHasPermission_Valid_Profile_Success_PermissionSet_Missing() { | |
// Get a sys admin user. | |
User u = ApplicationMock.getSysAdminUser(); | |
System.runAs(u) { | |
System.assertEquals(true, SystemPermissionUtility.userHasPermission('PermissionsModifyAllData')); | |
} | |
} | |
static void createPermissionSetAndAssignUser(User u) { | |
PermissionSet ps = new PermissionSet(); | |
ps.Name = 'SystemPermissionUtilityTest'; | |
ps.Label = 'SystemPermissionUtilityTest'; | |
ps.PermissionsModifyAllData = true; | |
ps.PermissionsAssignTopics = true; | |
ps.PermissionsConnectOrgToEnvironmentHub = true; | |
ps.PermissionsConvertLeads = true; | |
ps.PermissionsCreateCustomizeFilters = true; | |
ps.PermissionsCreateTopics = true; | |
ps.PermissionsDeleteTopics = true; | |
ps.PermissionsEditEvent = true; | |
ps.PermissionsEditPublicDocuments = true; | |
ps.PermissionsEditPublicFilters = true; | |
ps.PermissionsEditPublicReports = true; | |
ps.PermissionsEditPublicTemplates = true; | |
ps.PermissionsEditReports = true; | |
ps.PermissionsEditTask = true; | |
ps.PermissionsEditTopics = true; | |
ps.PermissionsImportLeads = true; | |
ps.PermissionsManageCategories = true; | |
ps.PermissionsManageDashboards = true; | |
ps.PermissionsManageNetworks = true; | |
ps.PermissionsRunReports = true; | |
ps.PermissionsSolutionImport = true; | |
ps.PermissionsTransferAnyEntity = true; | |
ps.PermissionsTransferAnyLead = true; | |
ps.PermissionsUseTeamReassignWizards = true; | |
ps.PermissionsViewAllData = true; | |
ps.PermissionsViewEventLogFiles = true; | |
ps.PermissionsViewSetup = true; | |
insert ps; | |
PermissionSetAssignment psa = new PermissionSetAssignment(); | |
psa.AssigneeId = u.Id; | |
psa.PermissionSetId = ps.Id; | |
insert psa; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks so much for this - it was a lifesaver. One comment: in the test class, I found that almost every org I tested or installed onto required a different set of permissions for the test PermissionSet. My solution was to detect the permissions required from the exception thrown:
Obviously this depends on the text of the exception message staying consistent, but it is after all a test not code that runs in production.
Hope this helps you or someone else.