3

To be clear, I do understand that this is a CONTRACTUAL limitation and not a TECHNICAL limitation, but in the event that Salesforce does want to take a peek at our org, we want to make sure we're not in breach of our contract.

We use a mix of Profile Object Settings and Permission Set settings to give access to our custom objects in our community, so we don't actually give any access to our custom objects from the profile settings. Each user has a different set of permissions too, so it's hard for us to tell whether or not individual users are exceeding the number of custom objects.

I don't want to skim every permission set to see what all we're granting access to, since we have quite a few. Is there an API or some other method to check these limits?

1 Answer 1

1

If you know the users that you want to check, you can do this through apex. I worked up a script that should help out. It will list all the users of a given profile and how many custom objects they have read access to. This won't list the objects they have access to, or which permission sets are granting that. I would have to modify the code to do that kind of functionality (it would be more work and I don't know if you need it, so I left it out).

// Enter the name of the community profile here
String profileName = 'System Administrator';
// If you only want to check for access through permission sets, set this to true. Otherwise, set it to false.
Boolean permissionSetsOnly = true;
// If you only want to check for access through profiles, set this to true. Otherwise, set it to false.
Boolean profilesOnly = false;



//Here's where the magic happens. You can leave this code as is
Map<Id, User> communityUsers = new Map<Id, User>( [SELECT Id, Name FROM User WHERE Profile.Name = :profileName] );
List<PermissionSetAssignment> psaList = new List<PermissionSetAssignment>();
if ( permissionSetsOnly ) {
    psaList = [SELECT PermissionSetId, PermissionSet.Name, AssigneeId, Assignee.Name FROM PermissionSetAssignment WHERE AssigneeId IN :communityUsers.keySet() AND PermissionSet.IsOwnedByProfile = false];
} else if ( profilesOnly ) {
    psaList = [SELECT PermissionSetId, PermissionSet.Name, AssigneeId, Assignee.Name FROM PermissionSetAssignment WHERE AssigneeId IN :communityUsers.keySet() AND PermissionSet.IsOwnedByProfile = true];
} else {
    psaList = [SELECT PermissionSetId, PermissionSet.Name, AssigneeId, Assignee.Name FROM PermissionSetAssignment WHERE AssigneeId IN :communityUsers.keySet()];
}
Set<Id> permissionSetIds = new Set<Id>();
for ( PermissionSetAssignment psa : psaList ) {
    permissionSetIds.add( psa.PermissionSetId );
}
List<ObjectPermissions> objPermissionList = [SELECT Id, ParentId, Parent.Name, Parent.Label, SObjectType FROM ObjectPermissions WHERE PermissionsRead = true AND ParentId IN :permissionSetIds];
Map<Id, Set<Id>> userPermissionSets = new Map<Id, Set<Id>>();
for ( PermissionSetAssignment psa : psaList ) {
    if ( !userPermissionSets.containsKey( psa.AssigneeId ) ) {
        userPermissionSets.put( psa.AssigneeId, new Set<Id>() );
    }
    userPermissionSets.get( psa.AssigneeId ).add( psa.PermissionSetId );
}
Map<Id, Set<String>> userObjectAccessCount = new Map<Id, Set<String>>();
for ( ObjectPermissions objPermission : objPermissionList ) {
    if ( String.isNotBlank( objPermission.SObjectType ) && objPermission.SObjectType.endsWith( '__c' ) ) {
        for ( Id userId : userPermissionSets.keySet() ) {
            if ( userPermissionSets.get( userId ).contains( objPermission.ParentId ) ) {
                if ( !userObjectAccessCount.containsKey( userId ) ) {
                    userObjectAccessCount.put( userId, new Set<String>() );
                }
                userObjectAccessCount.get( userId ).add( objPermission.SObjectType );
            }
        }
    }
}
for ( Id userId : communityUsers.keySet() ) {
    Set<String> objAccess = new Set<String>();
    if ( userObjectAccessCount.containsKey( userId ) ) {
        objAccess = userObjectAccessCount.get( userId );
    }
    System.debug( 'User: ' + communityUsers.get( userId ).Name + '\n# of custom objects with read access: ' + objAccess.size() );
}

The first 6 lines of the code provide some variables that you can modify. You can use that to select the profile name that you want to check and the whether you want to check only permission sets, profiles, or both. Just copy the code and paste it in the execute anonymous window of the developer console, adjust the variables in the first 6 lines, and click on execute. Make sure to select the "open log" checkbox next to the execute button before clicking on it. Hopefully, that provides the information that you're looking for.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .