From 604f9a53993da57107dad15e599f8c7526532a2a Mon Sep 17 00:00:00 2001 From: Wim Velzeboer Date: Thu, 22 Feb 2024 20:15:45 +0000 Subject: [PATCH 1/3] Add WITH SYSTEM_MODE to fflib_AppBindingsSelector class This should avoid the requirement of adding read permission to the custom medata object. Particular for external users --- .../classes/fflib_AppBindingsSelector.cls | 83 +++++++++---------- 1 file changed, 38 insertions(+), 45 deletions(-) diff --git a/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls b/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls index 60d9ba5..af72ff4 100644 --- a/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls +++ b/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls @@ -1,5 +1,5 @@ /** - * File Name: fflib_AppBindingsSelector + * File Name: fflib_AppBindingsSelector * @description Selector for fflib_AppBinding__mdt records * * @author architect ir. Wilhelmus G.J. Velzeboer @@ -28,41 +28,35 @@ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -public virtual without sharing class fflib_AppBindingsSelector extends fflib_SObjectSelector -{ - // Used for mocking - @TestVisible - private static System.Type SELECTOR_IMPL_TYPE = fflib_AppBindingsSelector.class; +public virtual without sharing class fflib_AppBindingsSelector extends fflib_SObjectSelector { + // Used for mocking + @TestVisible + private static System.Type SELECTOR_IMPL_TYPE = fflib_AppBindingsSelector.class; - public List getSObjectFieldList() - { - return new List - { - fflib_AppBinding__mdt.Id, - fflib_AppBinding__mdt.BindingObject__c, - fflib_AppBinding__mdt.BindingObjectAlternate__c, - fflib_AppBinding__mdt.BindingSequence__c, - fflib_AppBinding__mdt.DeveloperName, - fflib_AppBinding__mdt.NamespacePrefix, - fflib_AppBinding__mdt.ImplementationType__c, - fflib_AppBinding__mdt.InterfaceType__c, - fflib_AppBinding__mdt.Type__c - }; - } + public List getSObjectFieldList() { + return new List{ + fflib_AppBinding__mdt.Id, + fflib_AppBinding__mdt.BindingObject__c, + fflib_AppBinding__mdt.BindingObjectAlternate__c, + fflib_AppBinding__mdt.BindingSequence__c, + fflib_AppBinding__mdt.DeveloperName, + fflib_AppBinding__mdt.NamespacePrefix, + fflib_AppBinding__mdt.ImplementationType__c, + fflib_AppBinding__mdt.InterfaceType__c, + fflib_AppBinding__mdt.Type__c + }; + } - public static fflib_AppBindingsSelector newInstance() - { - return (fflib_AppBindingsSelector) SELECTOR_IMPL_TYPE.newInstance(); - } + public static fflib_AppBindingsSelector newInstance() { + return (fflib_AppBindingsSelector) SELECTOR_IMPL_TYPE.newInstance(); + } - public Schema.SObjectType getSObjectType() - { - return fflib_AppBinding__mdt.SObjectType; - } + public Schema.SObjectType getSObjectType() { + return fflib_AppBinding__mdt.SObjectType; + } - public virtual List selectAll() - { - /** + public virtual List selectAll() { + /** Todo - Waiting to uncomment the following section until fflib-apex-common fixes the getFieldPath issue Currently failing on the BindingObject__r field, @@ -79,17 +73,16 @@ public virtual without sharing class fflib_AppBindingsSelector extends fflib_SOb .toSOQL()); */ - return (List) Database.query( - String.format( - 'SELECT {0} FROM {1}', - new List - { - getFieldListString() - + ', BindingObject__r.QualifiedApiName' - + ', ApplicationPackage__r.DeveloperName', - getSObjectType().getDescribe().getName() - } - ) - ); - } + return (List) Database.query( + String.format( + 'SELECT {0} FROM {1} WITH SYSTEM_MODE', + new List{ + getFieldListString() + + ', BindingObject__r.QualifiedApiName' + + ', ApplicationPackage__r.DeveloperName', + getSObjectType().getDescribe().getName() + } + ) + ); + } } From fd49c0b66d0d787d587ca4e9ec32b6bff33cf1ab Mon Sep 17 00:00:00 2001 From: Wim Velzeboer Date: Mon, 26 Feb 2024 13:57:26 +0000 Subject: [PATCH 2/3] Add WITH SYSTEM_MODE to fflib_AppBindingsSelector class This should avoid the requirement of adding read permission to the custom medata object. Particular for external users --- .../application/dynamic/classes/fflib_AppBindingsSelector.cls | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls b/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls index af72ff4..26d557c 100644 --- a/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls +++ b/sfdx-source/apex-extensions/main/application/dynamic/classes/fflib_AppBindingsSelector.cls @@ -48,7 +48,8 @@ public virtual without sharing class fflib_AppBindingsSelector extends fflib_SOb } public static fflib_AppBindingsSelector newInstance() { - return (fflib_AppBindingsSelector) SELECTOR_IMPL_TYPE.newInstance(); + return (fflib_AppBindingsSelector) ((fflib_AppBindingsSelector) SELECTOR_IMPL_TYPE.newInstance()) + .setDataAccess(fflib_SObjectSelector.DataAccess.SYSTEM_MODE); } public Schema.SObjectType getSObjectType() { From 3ac1dfac88e576332a05c4fd2c6393fbbd875207 Mon Sep 17 00:00:00 2001 From: Wim Velzeboer Date: Fri, 1 Mar 2024 18:45:51 +0000 Subject: [PATCH 3/3] Add bypass to TriggerHandler --- .../classes/fflib_TriggerHandler.cls | 38 +++++++++++++--- .../fflib_TriggerHandlerTest.cls | 45 ++++++++++++++++++- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/sfdx-source/apex-extensions/main/triggerHandler/classes/fflib_TriggerHandler.cls b/sfdx-source/apex-extensions/main/triggerHandler/classes/fflib_TriggerHandler.cls index e3a6a7c..6090851 100644 --- a/sfdx-source/apex-extensions/main/triggerHandler/classes/fflib_TriggerHandler.cls +++ b/sfdx-source/apex-extensions/main/triggerHandler/classes/fflib_TriggerHandler.cls @@ -32,6 +32,22 @@ public virtual with sharing class fflib_TriggerHandler { public static final System.Type DEFAUT_TRIGGERCONTEXT_TYPE = fflib_TriggerContext.class; + /** + * Retains the trigger tracking configuration used for each domain + **/ + private static Map triggerEventByClass; + + /** + * Retain instance of Trigger Action classes implementing stateful + */ + @TestVisible + private static Map triggerActionStateByClass; + + static + { + triggerEventByClass = new Map(); + } + @TestVisible protected System.Type triggerContextType { @@ -48,12 +64,6 @@ public virtual with sharing class fflib_TriggerHandler protected fflib_ITriggerContext triggerContext; - /** - * Retain instance of Trigger Action classes implementing stateful - */ - @TestVisible - private static Map triggerActionStateByClass; - /** * Provides access to the trigger action configurations and allowing it to be mocked in unit-tests */ @@ -70,6 +80,16 @@ public virtual with sharing class fflib_TriggerHandler execute(ctx); } + public static fflib_SObjectDomain.TriggerEvent getTriggerEvent(Type triggerActionClass) + { + if(!triggerEventByClass.containsKey(triggerActionClass)) + { + triggerEventByClass.put(triggerActionClass, new fflib_SObjectDomain.TriggerEvent()); + } + + return triggerEventByClass.get(triggerActionClass); + } + /** * Tells the trigger handler in which trigger context it is running * @@ -109,7 +129,11 @@ public virtual with sharing class fflib_TriggerHandler { if (isValidExecutionContext(ctx, triggerActionConfig) == false || - isValidSObjectType(triggerActionConfig, ctx) == false) continue; + isValidSObjectType(triggerActionConfig, ctx) == false + || + !getTriggerEvent(triggerActionConfig.getImplementationType()) + .isEnabled(ctx.isBefore(), ctx.isAfter(), ctx.isInsert(), ctx.isUpdate(), ctx.isDelete(), ctx.isUndelete())) + continue; fflib_ITriggerAction triggerAction = getTriggerActionInstance(triggerActionConfig); diff --git a/sfdx-source/apex-extensions/tests/classes/triggerHandler/fflib_TriggerHandlerTest.cls b/sfdx-source/apex-extensions/tests/classes/triggerHandler/fflib_TriggerHandlerTest.cls index 0be6b87..053a8db 100644 --- a/sfdx-source/apex-extensions/tests/classes/triggerHandler/fflib_TriggerHandlerTest.cls +++ b/sfdx-source/apex-extensions/tests/classes/triggerHandler/fflib_TriggerHandlerTest.cls @@ -256,7 +256,6 @@ private class fflib_TriggerHandlerTest private static void itShouldUseTheStatefulTriggerActionClass() { fflib_LogEntry__c record = new fflib_LogEntry__c(LogLevel__c = 'INFO', Message__c = 'Unit Test'); - List records = new List {record}; fflib_ApexMocks mocks = new fflib_ApexMocks(); fflib_ITriggerAction triggerActionMock = (fflib_ITriggerAction) mocks.mock(fflib_ITriggerAction.class); @@ -296,6 +295,42 @@ private class fflib_TriggerHandlerTest ((fflib_ITriggerAction) mocks.verify(triggerActionMock)).doWork(); } + @IsTest + private static void itShouldNotExecuteBeforeDelete() + { + fflib_LogEntry__c record = new fflib_LogEntry__c(LogLevel__c = 'INFO', Message__c = 'Unit Test'); + + fflib_TriggerHandler.triggerActionStateByClass = + new Map{ MyTriggerBypassedAction.class => new MyTriggerBypassedAction() }; + + fflib_TriggerAction__mdt triggerAction = new fflib_TriggerAction__mdt( + ObjectType__c = null, + ObjectTypeAlternate__c = Schema.fflib_LogEntry__c.SObjectType.getDescribe().getName(), + BeforeDelete__c = true, + ImplementationType__c = 'fflib_TriggerHandlerTest.MyTriggerBypassedAction', + ExecutionContext__c = 'Realtime', + Stateful__c = true + ); + + fflib_TriggerHandler triggerHandler = new fflib_TriggerHandler(); + String ctxClassName = triggerHandler.triggerContextType.getName() + '.Constructor'; + fflib_TriggerContext ctx = + (fflib_TriggerContext) + ((fflib_IDomainConstructor) Type.forName(ctxClassName).newInstance()) + .construct(new List {record}); + ctx.triggerOperation = System.TriggerOperation.BEFORE_DELETE; + + // WHEN a record is inserted + System.Test.startTest(); + triggerHandler.addTriggerActionConfig(triggerAction); + + // Setting bypass & run trigger + fflib_TriggerHandler.getTriggerEvent(MyTriggerBypassedAction.class).disableAll(); + triggerHandler.setTriggerContext(ctx).run(); + + System.Test.stopTest(); + } + public class MyTriggerAction extends fflib_TriggerAction // Todo - rename handler to action { public override void onBeforeInsert() @@ -305,4 +340,12 @@ private class fflib_TriggerHandlerTest List records = triggerContext.getRecords(); } } + + public class MyTriggerBypassedAction extends fflib_TriggerAction + { + public override void onBeforeDelete() + { + System.Assert.fail('It should not have reach this point'); + } + } } \ No newline at end of file