2

1- I am using fflib for my managed package.

2- By default CRUD/FLS are enabled for all domain/selector flows (Using Base class)

3- In a specific method which is used by site guest users, I want to bypass CRUD/FLS check.

4- "Configuration.disableTriggerCRUDSecurity();" is not working in a domain specific method.

5- I know same is possible in Selector layer (See Accepted Answer) . I want same thing in domain layer.

How to By pass CRUD/FLS from Domain layer in any specific Flow?

Sample Code which should work but it is not working

public inherited sharing abstract class BaseDomain extends fflib_SObjectDomain {
    public BaseDomain(List<SObject> records) {
        super(records);
        Configuration.enforceTriggerCRUDSecurity();
    }
}

public inherited sharing class ABCs extends BaseDomain implements IABCs{

    public ABCs(List<ABC__c> abcs) {
        super(abcs);
    }
    ..........................
    public list<Boolean> incrementViewCount(fflib_ISObjectUnitOfWork uow){
        Configuration.disableTriggerCRUDSecurity();
        //Business Logic
        for(SObject urlObj:Records){
            ABC__c abc = (ABC__c)urlObj;
            Double viewCount = 0;
            if(abc.TotalView__c != null){
                dataDumpViewCount = abc.TotalView__c;
            }
            abc.TotalView__c = dataDumpViewCount +1;
            uow.registerDirty(abc);
        }
    }
}

public with sharing class ABCServiceImpl implements IABCServiceService{

    public void createViewCountByGuestUser(list<ID> abcIds){
        
        new ElevatedViewStatus().saveViewStatus(abcIds);
    }

    private without sharing class ElevatedViewStatus{
        public ViewStatusBO  saveViewStatus(list<ID> abcIds){
            fflib_ISObjectUnitOfWork uow = Application.UnitOfWork.newInstance();
            .........................
            IABCs abcsDomain = (IABCs) Application.Domain.newInstance(abcIds);
            abcsDomain.incrementViewCount(uow);
            ........................
        }
    }
}
7
  • 1
    So, to bypass CRUD/FLS for specific flows, the Domain layer needs contextual information - such as running user. If the Domain layer is acting as your trigger handler, then it is not supposed to care about how invoked only info about the running user and running user's permissions would vary by invocation unless you set a field on the object from the flow and then clear it in the onBeforeInsert/Update domain handlers. Use edit to provide some more info
    – cropredy
    Jan 18, 2022 at 19:02
  • Added one sample code which should work for me but not working. Custom Object is created by Standard Salesforce users but I like to track how many times this data is shown to Site Guest Users. And according to this count I want to update one field from Site Guest user. Jan 19, 2022 at 6:34
  • so if you look in fflib_SObjectDomain, you'll see that Configuration.EnforcingTriggerCRUDSecurity applies only to handleAfterInsert/Update/Delete/Undelete. Your domain method incrementViewCount is not associated with trigger events. fflib is a red herring here - you need to think about why a Flow executed by a guest user can't update the custom object
    – cropredy
    Jan 19, 2022 at 6:41
  • actually, above comment is wrong since you are registerDirty ABC__c and when committed, will execute the domain onAfterUpdate and bypass the isUpdateable check. Is your flow defined to run in System Context rather than the default User Context?
    – cropredy
    Jan 19, 2022 at 16:43
  • My flow is defined to run in the user context. This code is executed by Site guest user. Jan 20, 2022 at 5:10

1 Answer 1

3

I have find one workaround for my requirement.

My flow is

  1. Create a static variable isSupportCRUD with default value true in Base domain class.
  2. Create a new method disableTriggerCRUDSecurity() in the BaseDomain which changes isSupportCRUD value from true to false.
  3. Now change constructor code of Domain Class(ABCs) to disable CRUD according to the value of isSupportCRUD in which you like to disable CRUD security check at runtime.
  4. Remove the Configuration.disableTriggerCRUDSecurity() from Domain method (From my question code)
  5. Call Domain.disableTriggerCRUDSecurity() method before instancing Domain class

Sample Code

public inherited sharing abstract class BaseDomain extends fflib_SObjectDomain {
public static Boolean isSupportCRUD = true;
public BaseDomain(List<SObject> records) {
    super(records);
    Configuration.enforceTriggerCRUDSecurity();
}
public static void disableTriggerCRUDSecurity(){
    isSupportCRUD = false;
 }
}

public inherited sharing class ABCs extends BaseDomain implements IABCs{
public ABCs(List<ABC__c> abcs) {
    super(abcs);
    if(!isSupportCRUD){
       Configuration.disableTriggerCRUDSecurity();
    }
}

..........................
public list<Boolean> incrementViewCount(fflib_ISObjectUnitOfWork uow){
    //Business Logic
    for(SObject urlObj:Records){
        ABC__c abc = (ABC__c)urlObj;
        Double viewCount = 0;
        if(abc.TotalView__c != null){
            dataDumpViewCount = abc.TotalView__c;
        }
        abc.TotalView__c = dataDumpViewCount +1;
        uow.registerDirty(abc);
    }
  }
}

public with sharing class ABCServiceImpl implements IABCService{
public void createViewCountByGuestUser(list<ID> abcIds){
    new ElevatedViewStatus().saveViewStatus(abcIds);
}

private without sharing class ElevatedViewStatus{
    public ViewStatusBO  saveViewStatus(list<ID> abcIds){
        fflib_ISObjectUnitOfWork uow = Application.UnitOfWork.newInstance();
        .........................
        ABCs.disableTriggerCRUDSecurity();
        IABCs abcsDomain = (IABCs) Application.Domain.newInstance(abcIds);
        abcsDomain.incrementViewCount(uow);
        ........................
    }
 }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .