I have to give Read only permission for Single Specific Object on all profile.Currently in our org only system admin can access the object.
Is it possible to automatically update all those profile with read only permission of object via Apex?
My first thought was that no, this wasn't possible.
However, doing a little digging, I came across this other SFSE question asking something similar
From the accepted answer:
Actually, the PermissionSet SObject has a field in it called IsOwnedByProfile. Take a look at this blog post by Adam Torman, http://blogs.developerforce.com/engineering/2012/06/using-soql-to-determine-your-users-permissions-2.html:
This field determines whether a permission set is a custom one or if it is parented by a profile. This is made possible because for every profile, there is one underlying permission set. That way, permissions layer equally across permission sets without having to treat a profile differently.
So, if you want to find the CRUD permissions of a profile you can do something like this:
SELECT Id, SObjectType, PermissionsRead, PermissionsCreate FROM ObjectPermissions WHERE parentid in (select id from permissionset where PermissionSet.Profile.Name = 'System Administrator')
From the SOAP API page for ObjectPermissions, PermissionsRead
field is createable and updateable. That's a pretty strong hint that we'd be able to do this in Apex.
One big gotcha with that is that standard profiles cannot be modified, and Salesforce still doesn't provide us with a reliable way to determine whether or not a profile is standard or custom.
If you're going to update profiles via apex, having a custom setting or custom metadata type to hold the Ids of the standard profiles (so you can exclude processing them), or using database.update(records, false);
to allow the update to fail for the standard profiles would be wise.
Another gotcha to keep in mind is that some Object permissions depend on others. This is especially true of Standard SObjects
. If there are permissions that depend on being able to read records for a given SObject type, you would need to disable or enable all of those dependent permissions before you could disable the permission you really want to disable/enable.
For example, when I try to disable PermissionsRead
on Account
for a custom profile, I get the following error:
Permission Activate Contracts depends on permission(s): Read Account;
Permission Approve Contracts depends on permission(s): Read Account;
Permission Create Account depends on permission(s): Read Account;
Permission Create Contract depends on permission(s): Read Account;
Permission Create Credit__c depends on permission(s): Read Account;
Permission Create Debit__c depends on permission(s): Read Account;
Permission Delete Account depends on permission(s): Read Account;
Permission Delete Contract depends on permission(s): Read Account;
Permission Delete Credit__c depends on permission(s): Read Account;
Permission Delete Debit__c depends on permission(s): Read Account;
Permission Edit Account depends on permission(s): Read Account;
Permission Edit Contract depends on permission(s): Read Account;
Permission Edit Credit__c depends on permission(s): Read Account;
Permission Edit Debit__c depends on permission(s): Read Account;
Permission Manage All Contract depends on permission(s): Read Account;
Permission Manage All Credit__c depends on permission(s): Read Account;
Permission Manage All Debit__c depends on permission(s): Read Account;
Permission Read All Account depends on permission(s): Read Account;
Permission Read All Asset depends on permission(s): Read Account;
Permission Read All Contract depends on permission(s): Read Account;
Permission Read All Credit__c depends on permission(s): Read Account;
Permission Read All Debit__c depends on permission(s): Read Account;
Permission Read Asset depends on permission(s): Read Account;
Permission Read Contract depends on permission(s): Read Account;
Permission Read Credit__c depends on permission(s): Read Account;
Permission Read Debit__c depends on permission(s): Read Account
The first two issues, activate and approve Contracts, are "App Permissions", all the others are "Object Permissions".
Master-Detail relationships, and some standard relationships require the SObject
on the Master/Parent side to have some permissions (e.g. you couldn't create a detail record if you can't read the master record).
It sounds like you are trying to update permissions for a new SObject
. That's probably the easiest case, as, save for the System Administrator profile, all profiles have all permissions set to false when you deploy a new object between environments.
Permission dependencies are as follows:
PermissionsRead
)
PermissionsCreate
)
PermissionsEdit
)
PermissionsDelete
)
PermissionsViewAllRecords
)
PermissionsModifyAllRecords
)
The apex I used to test if this was possible is:
List<ObjectPermissions> objPermToUpdate = new List<ObjectPermissions>();
for(ObjectPermissions objPerm :[SELECT Id, Parent.Profile.Name, Parent.Profile.CreatedBy.Name, SObjectType, PermissionsRead, PermissionsCreate FROM ObjectPermissions WHERE SObjectType = 'Account' AND parentId IN (SELECT Id FROM PermissionSet WHERE isOwnedByProfile = true)]){
system.debug(objPerm);
system.debug(objPerm.Parent.Profile);
system.debug(objPerm.Parent.Profile.CreatedBy);
if(objPerm.Parent.Profile.Name != 'System Administrator'){
objPerm.PermissionsRead = true;
objPermToUpdate.add(objPerm);
}
}
database.update(objPermToUpdate, false);