2

Similar to this question, I cannot create a CustomObject__Share record as a Community User (Customer Community License).

Taking the advice provided there, I have created a Share__c object that serves as a dispatch object. The code looks like this:

trigger MyTrigger on CustomObject__c (after insert) { List<Share__c> shares = new List<Share__c>(); for (CustomObject__c each: Trigger.New) { shares.add(new Share__c(RecordId__c = each.Id)); } insert shares; }

on the Share__c object I have

trigger Share on Share__c (after insert) { Set<String> recordIds = new Set<String>(); for (Share__c each : Trigger.New) { recordIds.add(each.RecordId__c); } System.enqueueJob(new ShareCustomObjects(recordIds)); }

and the Queueable

public without sharing class ShareCustomObjects implements Queueable {
    Set<String> recordIds;
    public ShareCustomObjects(Set<String> theRecordIds) {
        recordIds = theRecordIds; 
    }

    public void execute(QueueableContext context) {
        Map<String, CustomObject> filterMap = new Map<String, CustomObject>();
        for (CustomObject each : [SELECT Id, CustomField__c FROM CustomObject WHERE Id = :recordIds]) {
            filterMap.put(each.CustomField__c, each);
        }
        List<CustomObject__Share> inserts = new List<CustomObject__Share>();
        CustomObject__Share share;
        // get the config based on the ShareConfigObject__c
        for (ShareConfigObject each : [SELECT Id, User__c, Account__c FROM ShareConfigObject__c WHERE Account__c = :filterMap.keyset()]) {
            share = new CustomObject__Share(
                ParentId = filterMap.get(String.valueOf(each.Account__c).left(15)).Id,
                UserOrGroupId = each.User__c,
                AccessLevel = 'Edit',
                RowCause = Schema.CustomObject__Share.RowCause.My_Share_Rule
            );
            inserts.add(share);
        }
        insert inserts;
    }
}

The Users being shared with are Community Plus Users, which are supported by Apex Sharing. I am using Queueables which should be executing in System context. If a System Admin creates a CustomObject__c the CustomObject__Share object is created. However, Customer Community Users are getting the error System.DmlException: Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: [] when I look through their Debug Logs and no CustomObject__Share objects are being created.

Any clues as to what could be wrong?

  • I am sure you must have it, but reconfirming. Do you have appropriate access provided to the community user’s profile for your ‘Share__c’ object? – Jayant Das May 9 '18 at 0:42
  • @JayantDas, yes I do. – Jake Richter May 9 '18 at 10:35
  • Also, it's failing on the line that inserts the CustomObject__Share records. – Jake Richter May 9 '18 at 10:44
2

Since you've referenced an answer that I wrote, I would recommend you do several things to help you resolve your issues. First, it appears that you're writing your Shares__c objects as a record that contains an Id which I assume is the record you want to share?

It seems to me there's additional information that's missing in your Share__c object record, plus I'd recommend you write the Id as a string instead of an Id. In fact, I'd recommend you write all the information you're going to pass to the object as a comma separated string so you can easily split it when it reaches your queueable class.

In that manner you can also append the string with an error message as you develop your app. You can remove Shares__c records on success (you don't want them to accumulate as unneeded records in your object) or add error messages/flags to your string on failure. On failure, you can send an email to an admin for follow-up or decide to do a "retry" once or twice before doing the email (esp if the error is caused by a record lock).

In addition to the record (an Account?) you want to share, you'll also need the Id of the Customer Community user that you want to share the record with. Based on what you've posted, if you added debug statements to your code, we'd know whether the Community Plus User (you don't give us any info about your ShareConfigObject) information is being returned by your query.

ParentId = filterMap.get(String.valueOf(each.Account__c).left(15)).Id,

Is there a reason you're using 15 character Id's for your ParentId's? It seems that you want to share the actual Account recordId, not the ParentId record and all it's related records as it appears to me that your code is trying to do.

Your code seems to be trying to share the CustomObject__c and not the Account. This pattern only uses the CustomObject__c as a "temporary holder" of information while you "queue them up" for asynchronous creation of the new shares on the Account records with your Community Plus Users.

Schematically, things should look something like the image below:

ApexManagedSharingFromCommunityPlus

2

The problem was that the records were owned by users with a Customer Community License. Once a record is owned by such a license, it cannot be shared except through sharing sets.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.