Programming
Querying Salesforce profiles in non-English environments
Short guide how to query standard user profiles in multilanguage Salesforce environments
When writing Salesforce tests for testing permissions developers need to create users. Quick search over StackExchange will give you a recipe to select a Standard User
profile and then insert a new user with this profile as follows:
Profile stdUserProfile = [SELECT Id FROM Profile WHERE Name='Standard User'];
insert new User(
ProfileId = stdUserProfile.Id,
UserName='joe@example.com',
Alias = 'joe',
Email='joe@example.com',
EmailEncodingKey='UTF-8',
LastName='Test',
LanguageLocaleKey='en_US',
LocaleSidKey='en_US',
TimeZoneSidKey='Asia/Tokyo',
);
If this code ends up in a managed package and gets installed to a customer org by a user who uses Salesforce in a different language then it will fail with System.QueryException: List has no rows for assignment to SObject
.
The reason behind this — Salesforce renames some of the profiles to a local language. Standard User
becomes 標準ユーザ
in Japanese or Utilisateur standard
in French.
One way to fix the SOQL query above is to write:
SELECT Id FROM Profile WHERE Name IN ('Standard User', '標準ユーザ', 'Utilisateur standard' … and another 32 languages that Salesforce supports )
Then pray that Salesforce does not change the names!
Another method is to look at the Permissions*
fields of the profiles and deduct which profile is our demanded Standard User.
I have gone through the list of all standard profiles and derived the least possible combination of the permissions that give you the Standard User profile:
SELECT Id FROM Profile
WHERE
UserType = 'Standard'
AND PermissionsPrivacyDataAccess = false
AND PermissionsSubmitMacrosAllowed = true
AND PermissionsMassInlineEdit = true
LIMIT 1
For the System Administrator it is even simpler:
SELECT Id FROM Profile
WHERE
UserType = 'Standard'
AND PermissionsPrivacyDataAccess = true
LIMIT 1
The code above is confirmed to be working for the API version 49.0 (Summer'20).
Now you can query the profiles in any language setting while praying that Salesforce won’t change the permissions on the standard profiles. If only Salesforce could add a DeveloperName
for this SObject!
For those wondering how to dump all available permissions for the Profile
SObject using anonymous Apex:
Schema.SObjectField[] fields = Schema.describeSObjects(new List<String>{'Profile'})[0].fields.getMap().values();
for(Schema.SObjectField field : fields) System.debug(field);
Then run sfdx force:data:soql:query -q "SELECT <fields from code above> FROM Profile"
with a --resultformat=csv
to get a CSV file with all profiles and their permissions.