Sharing access to partner community users based on record owner

Im trying to write what feels like it should be a simple Apex sharing rule but not having much luck.

Basically I want partner users to be able to see all “customers” (custom object) owned by customer community users within the same account. The communities sharing set settings allow me to automatically share customers with other customer community users but not partner community users. So i’m trying to setup a apex trigger to create sharing rules for all the partner community users within the same account.

When I edit a customer i’m getting this error:

Apex trigger shareCustomer caused an unexpected exception, contact your administrator: shareCustomer: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []: Trigger.shareCustomer: line 22, column 1

line 22 being the insert statement

and here is my code!

trigger shareCustomer on Customer__c (after insert, after update) {

    List<Customer__Share> customerShares  = new List<Customer__Share>();
    Customer__Share customerShare;

    for(Customer__c customer :{
        list<User> users = [ Select Id from User where accountId = :customer.Organization_Id__c and profileId = '00eG0000000ycc8IAA' and isActive = true];

        for (User u: users) {

                customerShare = new Customer__Share();
                customerShare.ParentId = customer.Id;
                customerShare.UserOrGroupId = u.Id;
                customerShare.AccessLevel = 'edit';
                customerShare.RowCause = Schema.Customer__Share.RowCause.Organization__c;


    Database.SaveResult[] lsr = Database.insert(customerShares);


here is a simple diagram of the relationships im trying to get through:

enter image description here

UPDATE: Some of the responders seem to be getting confused because the data in question is “customers” what i’ve done is try and write a reusable class that could share any data, with any partner accounts roles.. but STILL not working, getting the same error as above.

public static void shareWithAccount(Id parentId, Id accountId) {

        List<Customer__Share> customerShares  = new List<Customer__Share>();
        Customer__Share customerShare;

        list<UserRole> roles = [ SELECT Name, Id FROM UserRole where PortalAccountId  = :accountId];

        string roleID;
        for (UserRole role: roles) {

           try {
            Group g = [select Id from group where RelatedId = :role.Id and type='Role' limit 1]; 

            customerShare = new Customer__Share();
            customerShare.ParentId = parentId;
            customerShare.UserOrGroupId = g.Id;
            customerShare.AccessLevel = 'edit';
            customerShare.RowCause = Schema.Customer__Share.RowCause.Organization__c;

           } catch (exception e) {



        if (!customerShares.isEmpty())
            Database.SaveResult[] customerSharesResult = Database.insert(customerShares);



Update 03-11-16

Two important revisions to communities have occurred since I wrote this answer that should be considered. First is that User Sharing and visibility restrictions on the User Object in an Org are now in place (SU 15 as I recall). This impacts SF Users visibility to other users both inside an Org and within an Org’s Customer Community.

The 2nd one is the introduction of Customer Community Plus licenses. These licenses DO NOT have the same sharing model as regular Customer Communities. That sharing is vastly different. However, Customer Community Plus licenses support Managed Apex Sharing which is often the only way in which records can be shared. Sharing groups are not available as they are with regular Customer Communities. Please keep this in mind when reading this answer.


I just found this: “You can share a standard or custom object with users or groups. Apex sharing is not available for Customer Community users.” on the following page I think that’s the definitive answer regarding Apex Sharing with Community Users. You’ll need to either change owners or set up a sharing group.


I’d gotten that the customer wasn’t a contact, but that the Portal User was. You still need to get the Owner of the Portal to set up your sharing if you’re going to do it by User. Remember: Portal Users do not have a Role. You’re not going to be able to do any kind of role based sharing unless you do it as a child of the Owner.

Your idea of transferring ownership to the system admin has a lot of merit, especially if the Portal User doesn’t need to retain ownership and only needs to be able to view the record. That would likely be the simplest solution to your problem.


I’ve edited my post to included some of my comments below and try to clarify them rather than create a long back and forth thread.

Fist, depending on your actual schema, I believe the above query should retrieve the Owner’s ID and UserRoleId, not the Portal User’s RoleId provided the contact__c object is the same as the contact object.

Since both Owners who have SF Licenses and Portal Users that have Communities licenses are all Users, in theory, you could get them all in one query. You can also do them as two separate queries. How best to do them depends on what info you need and whether one depends on the other. Its also a matter of what method you’re most comfortable with.

The Owner(a SF User) owns the Contact and the Account associated with the Contact, but not the Communities User. To be clear, a Communities User cannot own another Contact nor an Account simply because they don’t have anything other than read access to those objects for their own information (both contact and account)!

However any kind of User can be retrieved via a query on User. Additionally, a User’s Contact info can be retrieved by a query on User (contact =, contact.Name =, etc.).

You say below that the Owner of the contact for the Portal User is also a Portal User, the question I’d have is what license that Portal User has? It can’t be a Communities License.

If this helps, here’s how Communities Users are created using Apex:

Account> a = new Account(Name = Acme ); 
/* OwnerID will either be specified or will be ID of User who performs this operation.*/
insert a;

Contact c = new Contact(FirstName = John, LastName = Doe, Account = a[0].Id (ID of Ajax Acct), email =, Phone = 800-555-1212, MailingStreet = .....); 
/* you know the drill for the rest of the data required. */
/* Again, the OwnerID is for the User who performs the operation unless an OwnerID is specified */
insert c;

User u =new User(ContactID = c[0].Id (John Doe's contact.Id), Alias = 'PrtlUsr1', Email= c[0].Email, FirstName= c[0].FirstName, LastName= c[0].LastName, userName=c[0].Email, ProfileID = CommunitiesLicenceID for your org);
/* Again, the OwnerID is for the User who performs the operation unless an OwnerID is specified */
Insert u;

In my experience, it requires a SF User license to create a Portal User.

The owner of the customer is a portal user tho, i guess thats what im
not understanding. Are you saying is should be getting the portal user
-> Contact -> and that owner? how does that help when what im trying to share is the “customer” I think people are getting confused because
they are called “customers” but they are just a custom object.

This could very well be the “disconnect” that’s been occurring. Since there is no “role hierarchy”, yes, you need to be retrieving the Portal User Contact and the Owner of the Portal User Contact in order to share anything that belongs to the Portal User. Why? Because the only other person that can see everything the Portal User "owns" is the Owner of the Portal User Contact -> (Portal)!

The only other way that immediately comes to mind that might help you accomplish what you desire would be to utilize your trigger to add these Users to a Sharing Group of some kind; something you might also want to consider as an alternative.

I hope this provides the clarification you needed in order to help you move forward with your trigger.

BTW, when you do your test class, I recommend you utilize “Run As” when you create your Account, Contact and Portal User. That will automatically create the Portal User with the Run As User as it’s Owner.

Original Answer

Communities Users have an Owner. They do not have a Role, all they have is a User Profile. Essentially, they quasi inherit their Role from their Owner. Their Owner can see any of the records they create. So, if you want to share something a Communities User “owns”, you’re going to need to do that through their Owner.

trigger shareCustomer on Customer__c (after insert, after update) {

   List<Customer__Share> customerShares  = new List<Customer__Share>();
   Customer__Share customerShare;

I agree with Greenstork, you need the User Role Id from related Owners (Users) in the trigger set. Now the question is:

Are your customers logging in as Communities Users or as Customers (Contacts)?

If as Users, then your query may need to reflect that. Your query currently shows as Customer__c, which is a Custom Object. Is there a relationship between Customer__c and either Contacts or Communities Users?

List<Customer__c> enhancedCustomerList = [SELECT id, Owner.UserRoleId, OwnerID FROM Customer__c WHERE id IN];

If there is, you may want to utilize that relationship in your trigger. That’s for you to decide. I primarily say that because it may simplify things for you because of Ownership when it comes to Communities Users.

The rest of your trigger would look pretty much the same as what Greenstork has shown depending on the relationships you use between contact, account, Portal User, and Portal User.OwnerID. The sharing is going to occur based on the Owner of contact/customer__c/Portal User.

Source : Link , Question Author : Keith Mancuso , Answer Author : crmprogdev

Leave a Comment