Manual Sharing Using Apex in Salesforce - Best Practices
Apex Managed Sharing
Sharing rules, they enable us to make exceptions to organization wide defaults for certain users as per our requirement.We cannot make give more stricter settings than our org-wide default settings but we can surely extend our default setting with sharing rules.
Example-if any object is private in our org-wide default then we can only level up our access not restrict it any further than it is already in our OWD.
Salesforce does gives us a way through which we can create sharing rules as per our requirement by simple point and click in Salesforce standard. We can set criterias as per our requirement for our object and which user should be granted access for that.
Don't miss to check out: Salesforce Sharing and Security Features
But, there are some scenarios where we can’t use the standard sharing rule functionalities that’s the point where apex based sharing or manual sharing comes into picture, this particular method has certain functionalities and is best suited in certain scenarios.
To access programmatic sharing, a shared object must be used, now what is a share object? Every object has a related share object which can be accessed in our code by extending share to the standard objects and__Share to the custom objects, for ex:- Account- AccountShare and for any custom object, say Custom we have Custom_share object which will be associated to the respective object.
Sharing Table
Now we know what is a share object, but there are some properties related to it, a share object supports all three types of sharing:-
- Force.com managed sharing
- user managed sharing
- Apex managed sharing
Share object be it custom or standard has following fields:-
- objectNameAccessLevel
- ParentID
- RowCause
- UserOrGroupId
You can study about the above mentioned fields and share objects through:-
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing.htm
A sample code to demonstrate manual sharing is:-
In this case we have to grant lead’s access to a user which will be fetched from a custom field in lead User_lookup__c.
trigger leadAccessShareTrigger on Lead (after insert, after update){ //Insert Lead details and give access to user if (Trigger.isAfter && Trigger.isInsert){ List<leadShare>sharesToCreate = new List<leadShare>(); leadShare testShare; for (Lead l : Trigger.new){ if (l.User_lookup__c!=null ){ testShare= new leadShare(); testShare.LeadId = l.Id; testShare.UserOrGroupId = l.User_lookup__c; testShare.leadAccessLevel='edit'; testShare.RowCause= 'Manual'; sharesToCreate.add(testShare); system.debug('@sharesToCreate '+sharesToCreate); } } if (!sharesToCreate.isEmpty()){ insert sharesToCreate; system.debug('@sharesToCreate '+sharesToCreate); } } //Update Lead details and give access to user else if(trigger.isAfter && trigger.isUpdate){ List<leadShare>sharesToUpdate = new List<leadShare>(); leadShare testShare; //we have to remove access from the previous user set<id> shareIdsToDelete = new set<Id>(); string Userlookup; for(lead l:trigger.new){ Lead oldLeads = Trigger.Oldmap.get(l.id); system.debug('oldLeads' +oldLeads); if(oldLeads.User_lookup__c != l.User_lookup__c){ shareIdsToDelete.add(oldLeads.User_lookup__c); system.debug('shareIdsToDelete '+shareIdsToDelete); Userlookup = l.User_lookup__c; } } List<leadShare>listShareToDelete =[select id, LeadId, UserorGroupID from LeadShare where UserorGroupID IN: shareIdsToDelete ]; system.debug('listShareToDelete'+listShareToDelete); if (Userlookup!= null && listShareToDelete.size() > 0) { Delete listShareToDelete; } //give access to updated user for(lead l:trigger.new){ if (l.User_lookup__c!=null){ testShare= new leadShare(); testShare.LeadId = l.Id; testShare.UserOrGroupId = l.User_lookup__c; testShare.leadAccessLevel='edit'; testShare.RowCause= 'Manual'; sharesToUpdate.add(testShare); system.debug('sharesToUpdate '+sharesToUpdate); } } if (!sharesToUpdate.isEmpty()){ insert sharesToUpdate; system.debug('sharesToUpdate '+sharesToUpdate); } } }
Check out another amazing article by Shubham here: Things to Consider Before Changing Field Data Type in Salesforce
Some considerations to be taken are:-
- Sharing rules can’t be made stricter than our OWD, sharing rules are only used to extend our access not restrict it.
- We can only have individual records for manual sharing.
- Sharing rules can only be applied on records which have Private or Public Read only access.