Sharing A Record Using Apex - Apex Developer Guide - Salesforce Developers

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

4/24/2019 Sharing a Record Using Apex | Apex Developer Guide | Salesforce Developers

(/)

DEVELOPER DOCUMENTATION (/DOCS)


CONTENTS 
Apex Developer Guide
Documentation Version
Spring '19 (API version 45.0) 

Language
English 

Sharing a Record Using Apex


To access sharing programmatically, you must use the share object associated with the standard or
custom object for which you want to share. For example, AccountShare is the sharing object for the
Account object, ContactShare is the sharing object for the Contact object. In addition, all custom object
sharing objects are named as follows, where MyCustomObject is the name of the custom object:
MyCustomObject__Share
Objects on the detail side of a master-detail relationship do not have an associated sharing object. The
detail record’s access is determined by the master’s sharing object and the relationship’s sharing setting.
For more information, see “Custom Object Security” in the Salesforce online help.
A share object includes records supporting all three types of sharing: managed sharing, user managed
sharing, and Apex managed sharing. Sharing granted to users implicitly through organization-wide
defaults, the role hierarchy, and permissions such as the “View All” and “Modify All” permissions for the
given object, “View All Data,” and “Modify All Data” are not tracked with this object.
Every share object has the following properties:

Property Name Description

objectNameAccessLevel The level of access that the specified user or group has been granted for a
share sObject. The name of the property is AccessLevel appended to the
object name. For example, the property name for LeadShare object is
LeadShareAccessLevel. Valid values are:
Edit
Read
All

The All access level is an internal value and can’t be


granted.

This field must be set to an access level that is higher than the organization’s
default access level for the parent object. For more information, see
Understanding Sharing (atlas.en-
us.apexcode.meta/apexcode/apex_bulk_sharing_understanding.htm).

ParentID The ID of the object. This field cannot be updated.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 1/8
4/24/2019 Sharing a Record Using Apex | Apex Developer Guide | Salesforce Developers
Property Name Description

RowCause The reason why the user or group is being granted access. The reason
determines the type of sharing, which controls who can alter the sharing
record. This field cannot be updated.

UserOrGroupId The user or group IDs to which you are granting access. A group can be:
A public group or a sharing group associated with a role.
A territory group.

To enable manual account sharing with territory groups


in Enterprise Territory Management, go to Critical
Updates in Setup, and then click Activate next to Enable Manual
Account Sharing in Enterprise Territory Management.

This field cannot be updated.

You can share a standard or custom object with users or groups. For more information about the types of
users and groups you can share an object with, see User (https://developer.salesforce.com/docs/atlas.en-
us.218.0.object_reference.meta/object_reference/sforce_api_objects_user.htm) and Group
(https://developer.salesforce.com/docs/atlas.en-
us.218.0.object_reference.meta/object_reference/sforce_api_objects_group.htm) in the Object
Reference for Salesforce (https://developer.salesforce.com/docs/atlas.en-
us.218.0.object_reference.meta/object_reference/).

Creating User Managed Sharing Using Apex


It is possible to manually share a record to a user or a group using Apex or the SOAP API. If the owner of
the record changes, the sharing is automatically deleted. The following example class contains a method
that shares the job specified by the job ID with the specified user or group ID with read access. It also
includes a test method that validates this method. Before you save this example class, create a custom
object called Job.

Manual shares written using Apex contains RowCause="Manual" by default. Only shares
with this condition are removed when ownership changes.

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 2/8
01
4/24/2019 public class JobSharing { a Record Using Apex | Apex Developer Guide | Salesforce Developers
Sharing
02
03 public static boolean manualShareRead(Id recordId, Id userOrGroupId){
04 // Create new sharing object for the custom object Job.
05 Job__Share jobShr = new Job__Share();
06
07 // Set the ID of record being shared.
08 jobShr.ParentId = recordId;
09
10 // Set the ID of user or group being granted access.
11 jobShr.UserOrGroupId = userOrGroupId;
12
13 // Set the access level.
14 jobShr.AccessLevel = 'Read';
15
16 // Set rowCause to 'manual' for manual sharing.
17 // This line can be omitted as 'manual' is the default value for sharing obj
18 jobShr.RowCause = Schema.Job__Share.RowCause.Manual;
19
20 // Insert the sharing record and capture the save result.
21 // The false parameter allows for partial processing if multiple records pas
22 // into the operation.
23 Database.SaveResult sr = Database.insert(jobShr,false);
24
25 // Process the save results.
26 if(sr.isSuccess()){
27 // Indicates success
28 return true;
29 }
30 else {
31 // Get first save result error.
32 Database.Error err = sr.getErrors()[0];
33
34 // Check if the error is related to trival access level.
35 // Access level must be more permissive than the object's default.
36 // These sharing records are not required and thus an insert exception is
37 if(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION &
38 err.getMessage().contains('AccessLevel')){
39 // Indicates success.
40 return true;
41 }
42 else{
43 // Indicates failure.
44 return false;
45 }
46 }
47 }
48
49 }

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 3/8
01
4/24/2019 @isTest Sharing a Record Using Apex | Apex Developer Guide | Salesforce Developers
02 private class JobSharingTest {
03 // Test for the manualShareRead method
04 static testMethod void testManualShareRead(){
05 // Select users for the test.
06 List<User> users = [SELECT Id FROM User WHERE IsActive = true LIMIT 2];
07 Id User1Id = users[0].Id;
08 Id User2Id = users[1].Id;
09
10 // Create new job.
11 Job__c j = new Job__c();
12 j.Name = 'Test Job';
13 j.OwnerId = user1Id;
14 insert j;
15
16 // Insert manual share for user who is not record owner.
17 System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), true);
18
19 // Query job sharing records.
20 List<Job__Share> jShrs = [SELECT Id, UserOrGroupId, AccessLevel,
21 RowCause FROM job__share WHERE ParentId = :j.Id AND UserOrGroupId= :user2
22
23 // Test for only one manual share on job.
24 System.assertEquals(jShrs.size(), 1, 'Set the object\'s sharing model to Pri
25
26 // Test attributes of manual share.
27 System.assertEquals(jShrs[0].AccessLevel, 'Read');
28 System.assertEquals(jShrs[0].RowCause, 'Manual');
29 System.assertEquals(jShrs[0].UserOrGroupId, user2Id);
30
31 // Test invalid job Id.
32 delete j;
33
34 // Insert manual share for deleted job id.
35 System.assertEquals(JobSharing.manualShareRead(j.Id, user2Id), false);
36 }
37 }

The object’s organization-wide default access level must not be set to the most
permissive access level. For custom objects, this level is Public Read/Write. For more
information, see Understanding Sharing (atlas.en-
us.apexcode.meta/apexcode/apex_bulk_sharing_understanding.htm).

Creating Apex Managed Sharing


Apex managed sharing enables developers to programmatically manipulate sharing to support their
application’s behavior through Apex or the SOAP API. This type of sharing is similar to managed sharing.
Only users with “Modify All Data” permission can add or change Apex managed sharing on a record. Apex
managed sharing is maintained across record owner changes.
Apex managed sharing must use an Apex sharing reason. Apex sharing reasons are a way for developers
to track why they shared a record with a user or group of users. Using multiple Apex sharing reasons
simplifies the coding required to make updates and deletions of sharing records. They also enable
developers to share with the same user or group multiple times using different reasons.
Apex sharing reasons are defined on an object's detail page. Each Apex sharing reason has a label and a
name:
The label displays in the Reason column when viewing the sharing for a record in the user interface.
This label allows users and administrators to understand the source of the sharing. The label is also
enabled for translation through the Translation Workbench.
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 4/8
The name
4/24/2019 is used when referencing the reason
Sharing a Record in |the
Using Apex ApexAPI and Guide
Developer Apex.
| Salesforce Developers

All Apex sharing reason names have the following format:

1 MyReasonName__c

Apex sharing reasons can be referenced programmatically as follows:

1 Schema.CustomObject__Share.rowCause.SharingReason__c

For example, an Apex sharing reason called Recruiter for an object called Job can be referenced as
follows:

1 Schema.Job__Share.rowCause.Recruiter__c

For more information, see Schema Class (atlas.en-


us.apexcode.meta/apexcode/apex_methods_system_schema.htm#apex_methods_system_schema).
To create an Apex sharing reason:
1. From the management settings for the custom object, click New in the Apex Sharing Reasons related
list.
2. Enter a label for the Apex sharing reason. The label displays in the Reason column when viewing the
sharing for a record in the user interface. The label is also enabled for translation through the
Translation Workbench.
3. Enter a name for the Apex sharing reason. The name is used when referencing the reason in the API
and Apex. This name can contain only underscores and alphanumeric characters, and must be unique
in your org. It must begin with a letter, not include spaces, not end with an underscore, and not
contain two consecutive underscores.
4. Click Save.

Apex sharing reasons and Apex managed sharing recalculation are only available for
custom objects.

Apex Managed Sharing Example


For this example, suppose that you are building a recruiting application and have an object called Job.
You want to validate that the recruiter and hiring manager listed on the job have access to the record. The
following trigger grants the recruiter and hiring manager access when the job record is created. This
example requires a custom object called Job, with two lookup fields associated with User records called
Hiring_Manager and Recruiter. Also, the Job custom object should have two sharing reasons added called
Hiring_Manager and Recruiter.

01 trigger JobApexSharing on Job__c (after insert) {


02
03 if(trigger.isInsert){
04 // Create a new list of sharing objects for Job
05 List<Job__Share> jobShrs = new List<Job__Share>();
06
07 // Declare variables for recruiting and hiring manager sharing
08 Job__Share recruiterShr;
09 Job__Share hmShr;
10
11 for(Job__c job : trigger.new){
12 // Instantiate the sharing objects
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 5/8
g j
13
4/24/2019 recruiterShr
Sharing = new Using
a Record Job__Share();
Apex | Apex Developer Guide | Salesforce Developers
14 hmShr = new Job__Share();
15
16 // Set the ID of record being shared
17 recruiterShr.ParentId = job.Id;
18 hmShr.ParentId = job.Id;
19
20 // Set the ID of user or group being granted access
21 recruiterShr.UserOrGroupId = job.Recruiter__c;
22 hmShr.UserOrGroupId = job.Hiring_Manager__c;
23
24 // Set the access level
25 recruiterShr.AccessLevel = 'edit';
26 hmShr.AccessLevel = 'read';
27
28 // Set the Apex sharing reason for hiring manager and recruiter
29 recruiterShr.RowCause = Schema.Job__Share.RowCause.Recruiter__c;
30 hmShr.RowCause = Schema.Job__Share.RowCause.Hiring_Manager__c;
31
32 // Add objects to list for insert
33 jobShrs.add(recruiterShr);
34 jobShrs.add(hmShr);
35 }
36
37 // Insert sharing records and capture save result
38 // The false parameter allows for partial processing if multiple records a
39 // into the operation
40 Database.SaveResult[] lsr = Database.insert(jobShrs,false);
41
42 // Create counter
43 Integer i=0;
44
45 // Process the save results
46 for(Database.SaveResult sr : lsr){
47 if(!sr.isSuccess()){
48 // Get the first save result error
49 Database.Error err = sr.getErrors()[0];
50
51 // Check if the error is related to a trivial access level
52 // Access levels equal or more permissive than the object's defaul
53 // access level are not allowed.
54 // These sharing records are not required and thus an insert excep
55 // acceptable.
56 if(!(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXC
57 && err.getMessage().contains('Acce
58 // Throw an error when the error is not related to trivial acc
59 trigger.newMap.get(jobShrs[i].ParentId).
60 addError(
61 'Unable to grant sharing access due to following exception:
62 + err.getMessage());
63 }
64 }
65 i++;
66 }
67 }
68
69 }

Under certain circumstances, inserting a share row results in an update of an existing share row. Consider
these examples:
A manual share access level is set to Read and you insert a new one set to Write. The original share
rows are updated to Write, indicating the higher level of access.
Users can access an account because they can access its child records (contact, case, opportunity, and
so on). If an account sharing rule is created, the sharing rule row cause (which is a higher access level)
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm
6/8
replaces
4/24/2019 the parent implicit share
Sharingrow cause,
a Record Usingindicating the higher
Apex | Apex Developer Guide |level of access.
Salesforce Developers

The object’s organization-wide default access level must not be set to the most
permissive access level. For custom objects, this level is Public Read/Write. For more
information, see Understanding Sharing (atlas.en-
us.apexcode.meta/apexcode/apex_bulk_sharing_understanding.htm).

Creating Apex Managed Sharing for Customer Community Plus users


Customer Community Plus users are previously known as Customer Portal users. Share objects, such as
AccountShare and ContactShare, aren’t available to these users. If you must use share objects as a
Customer Community Plus user, consider using a trigger, which operates with the without sharing
keyword by default. Otherwise, use an inner class with the same keyword to enable the DML operation to
run successfully. A separate utility class can also be used to enable this access.
Granting visibility via manual/apex shares written to the share objects is supported but the objects
themselves aren't available to Customer Community Plus users. However, other users can add shares that
grant access to Customer Community Plus users.

 Previous Next 
(/docs/atla (/docs/atla
s.en- s.en-
us.apexcod us.apexcod
e.meta/ape e.meta/ape
xcode/apex xcode/apex
_bulk_shari _bulk_shari
ng_underst ng_recalc.h
anding.htm tm)
)

Get started

Salesforce Platform (/platform)

Lightning Platform (/gettingstarted)

Heroku (https://devcenter.heroku.com/start)

MuleSoft Quick Start Guide (https://developer.mulesoft.com/tutorials-and-how-tos)

Salesforce Dev Centers

Lightning Developer Center (/devcenter/lightning)

Mobile Developer Center (/devcenter/mobile)

Heroku Dev Center (http://devcenter.heroku.com/)

Desk.com </developers> (http://dev.desk.com/)

Pardot Developer Site (http://developer.pardot.com/)

MuleSoft Developer Site (http://developer.mulesoft.com/)

Developer resources

Mobile Services (/mobile)


https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 7/8
4/24/2019 Sharing a Record Using Apex | Apex Developer Guide | Salesforce Developers
Lightning Platform Docs (/docs/?service=Force.com&sort=title)

Lightning Platform Downloads (/page/Tools)

Heroku Downloads (http://toolbelt.heroku.com/)

Learn Salesforce with Trailhead (/trailhead?utm_campaign=trailhead&utm_source=website&utm_medium=dsc_footer)

Community
Developer Forums (/forums)

Salesforce Developer Events (/calendar)

Webinars (/content/type/Webinar)

Learn more
Salesforce AppExchange (/appexchange)

Salesforce Administrators (//admin.salesforce.com)

Salesforce.com Help Portal (//help.salesforce.com/)

© Copyright 2000-2018 salesforce.com, inc. All rights reserved. Various trademarks held by their respective owners.
Salesforce.com, inc. The Landmark @ One Market, Suite 300, San Francisco, CA 94105, United States

Privacy Statement (//www.salesforce.com/company/privacy.jsp)

Security Statement (//www.salesforce.com/company/security.jsp)


Terms of Use (/files/tos/Developerforce_TOU_20101119.pdf)

Feedback
About Us (http://www.salesforce.com/company/)

Language: English

(https://www.facebook.com/salesforcedevs) (https://twitter.com/#!/salesforcedevs)

(https://plus.google.com/118327959233932983591)

(https://www.linkedin.com/groups/Developer-Force-Forcecom-Community-3774731)

(https://www.youtube.com/user/DeveloperForce)

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_bulk_sharing_creating_with_apex.htm 8/8

You might also like