I may need to make many @RestResource Apex classes run either with sharing or without sharing where that option is selected at runtime.
But this approach (that I am using at present):
/**
* Allow code to run "with sharing" or "without sharing" based on configuration.
*/
public inherited sharing class Sharing {
public interface Executable {
Object execute(Object[] args);
}
// With
private with sharing class WithSharing {
public Object execute(Executable executable, Object[] args) {
return executable.execute(args);
}
}
// Without
private without sharing class WithoutSharing {
public Object execute(Executable executable, Object[] args) {
return executable.execute(args);
}
}
//
// Execute the code with or without sharing based on this documentation...
//
// Both inner classes and outer classes can be declared as with sharing.
// The sharing setting applies to all code contained in the class,
// including initialization code, constructors, and methods.
// Inner classes do not inherit the sharing setting from their container class.
//
public static Object apply(Executable executable, Object[] args) {
// TODO from config
Boolean withSharing = false;
if (withSharing) return new WithSharing().execute(executable, args);
else return new WithoutSharing().execute(executable, args);
}
// No-args
public static Object apply(Executable executable) {
return apply(executable, new Object[] {});
}
}
is quite ugly to add to the many classes (that have static entry points) e.g.:
@RestResource(urlMapping='...')
global inherited sharing class MyRest {
@HttpPost
global static Result post() {
return (Result) Sharing.apply(new Executable());
}
private inherited sharing class Executable implements Sharing.Executable {
public Object execute() {
return postWithSharingApplied();
}
}
// The content of the original post method
private static Result postWithSharingApplied() {
...
}
...
}
Is there a cleaner way to do this?
PS
A follow-up question is Inherited sharing question in nested inner classes.
PPS
A key point is that the class containing the business logic MyRest above must not be declared as with sharing or without sharing so is best declared as inherited sharing. (I originally didn't realize this.) This makes each business logic method also have inherited sharing.
The key sentences from the documentation about this are:
The sharing setting of the class where the method is defined is applied, not of the class where the method is called
and:
A class declared as inherited sharing runs as without sharing only when explicitly called from an already established without sharing context.
String action, Map<String, Object> argsisn't too appropriate here). – Keith C Jan 21 '20 at 08:34