21

I would like to be able to execute a SOQL query that will allow me to see which users have access to a certain record type for a certain object.

For example, if I have a case record type called Phone Team, I would like to make a query that returns the names of all the users that have been assigned the Phone Team record type, as can be seen in the native user interface in a profile's Object Settings page.

So far I have managed to get a query that can get the names of all the users that have, for example, read access to the case object:

SELECT Assignee.Name FROM PermissionSetAssignment 
    WHERE PermissionSetId IN 
        (SELECT ParentId FROM ObjectPermissions WHERE SObjectType = 'Case' 
             AND PermissionsRead = true AND Parent.IsOwnedByProfile = true)

However, there doesn't seem to be any way to access record type assignment in the same way that you can object permissions.

I see from this post that the info can be obtained via the metadata API, but I would much prefer to do it by SOQL if possible.

Thanks

20

This is possible through Apex, but not SOQL --- and no Metadata API required.

To determine whether a given SObject's RecordType is available to a given user's profile, you will need to use the Apex DescribeSObjectResult getRecordTypeInfos() call on that SObject (see the docs here). This returns a list of RecordTypeInfo objects corresponding to all RecordTypes on that SObject, each of which has an isAvailable() method which will tell you if the RecordType is available to the running user's Profile.

For example, say that you have 2 Case Record Types, 'Phone Team' and 'Web Team', with both available to your Profile. Let's make 'Phone Team' unavailable to test. Go into your Profile, and scroll down to the Record Types area, and click on Case, and then remove 'Phone Team' from the list of available Record Types.

Now, add the following method to a utility class:

// Returns a List of the Names of all RecordTypes
// available to the running user for a given SOBject type
public static List<String> GetAvailableRecordTypeNamesForSObject(
    Schema.SObjectType objType
) {
    List<String> names = new List<String>();
    List<RecordTypeInfo> infos = objType.getDescribe().getRecordTypeInfos();
    // If there are 2 or more RecordTypes...
    if (infos.size() > 1) {
        for (RecordTypeInfo i : infos) {
           if (i.isAvailable() 
           // Ignore the Master Record Type, whose Id always ends with 'AAA'.
           // We check the Id because Name can change depending on the user's language.
            && !String.valueOf(i.getRecordTypeId()).endsWith('AAA'))
                names.add(i.getName());
        }
    } 
    // Otherwise there's just the Master record type,
    // so add it in, since it MUST always be available
    else names.add(infos[0].getName());
    return names;
}

And run the following from Anonymous Apex to get the available Case record types:

 List<String> availableCaseTypes = 
      GetAvailableRecordTypeNamesForSObject(Case.SObjectType);

 System.debug(availableCaseTypes);
 // returns ('Web Team')

Just FYI, the reason this is not possible from SOQL is that the only RecordType-related SObject exposed in SOQL is the RecordType object, whose IsActive field will tell you whether or not a RecordType is globally active/inactive, but provides no information whatsoever on whether a given RecordType is available to a user or profile.

  • 1
    Thanks for a great post @zachelrath. This solution works great for the currently running user, but I was really hoping to be able to see all the users that had access to a certain record type. Even going a long way round, I can't see any way to run the code as different users apart from in tests. I have looked at examples using the Metadata API, which seems quite a long way round and I wanted to call it from Apex because I intended to make a VF page. Possibly I could use WSDL2APEX. – Joe Dec 5 '12 at 22:21
  • This worked really well for me, but the line that ignores the master record type caused problems. It hid a lot of record types I needed available. – Jacob Raccuia Nov 7 '16 at 17:08
1

I don't believe this is going to be possible in soql.

Only the ProfileRecordTypeVisibility construct in the Metadata API gives you access. (http://www.salesforce.com/us/developer/docs/api_meta/Content/meta_profile.htm)

A twisted way to do it would be to do a soql query for all the RecordTypes for an entity via soql and then try to create a record of each RecordType. For the ones where exceptions occur, remove them from the list and ones that are left behind will be the ones the logged in user has access to (for purposes of create, they will be able to view records of all RecordTypes as long as they have the right sharing settings)

  • 2
    You are correct that it is not possible from SOQL, but not correct that it is impossible without the Metadata API --- with Apex Schema information this is perfectly possible and completely supported. – zachelrath Dec 4 '12 at 21:27
0

Instead of checking the record type id as in the line

&& !String.valueOf(i.getRecordTypeId()).endsWith('AAA'))

you could check with

i.isMaster()

(https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_class_Schema_RecordTypeInfo.htm?search_text=recordtype#apex_Schema_RecordTypeInfo_methods)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.