Skip to content

Instantly share code, notes, and snippets.

@jkentjnr
Created July 7, 2016 10:28
Show Gist options
  • Save jkentjnr/599d6df0332e7fa6efb493b8156ddac3 to your computer and use it in GitHub Desktop.
Save jkentjnr/599d6df0332e7fa6efb493b8156ddac3 to your computer and use it in GitHub Desktop.
Salesforce Apex: Check for permission (both User and Permission Sets)
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;
}
}
@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;
}
}
@SemiConscious
Copy link

SemiConscious commented Oct 29, 2019

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:

    static void createPermissionSetAndAssignUser(User u) {

        PermissionSet ps = new PermissionSet();
        ps.Name = 'SystemPermissionUtilityTest';
        ps.Label = 'SystemPermissionUtilityTest';
        ps.PermissionsModifyAllData = true;

        // ModifyAllData will depend on many other permissions, and those permissions
        // will vary according to the features enabled on the org on which this test runs.
        // use the validation exception to find the permissions needed.

        while(true) {
            try {
                insert ps;
                break;
            } catch (Exception e) {
                String msg = e.getMessage();
                if (msg.contains('FIELD_INTEGRITY_EXCEPTION')) {
                    msg = msg.substringBeforeLast(':').substringAfterLast(':').replace(' ', '');
                    Pattern p = Pattern.compile('([A-Za-z]+)(,|$)');
                    Matcher mo = p.matcher(msg);
                    Boolean found = false;
                    while (mo.find()) {
                        System.debug('Adding permission: ' + mo.group(1));
                        ps.put('Permissions' + mo.group(1), true);
                        found = true;
                    }
                    if (!found) {
                        throw e;
                    }
                } else {
                    throw e;
                }
            }
        }

        PermissionSetAssignment psa = new PermissionSetAssignment();
        psa.AssigneeId = u.Id;
        psa.PermissionSetId = ps.Id;
        insert psa;
    }

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment