System mode or God mode in Apex – Gotchas

In many of my previous implementations I have used advantage of Apex code running in System mode however never tried how far it can go in terms of capabilties. There is no specific Salesforce documentation which can explain that what is allowed or not allowed in System mode.

In this post, we will go through some scenario and will try to understand what really is possible in Apex System mode and when it can fail.

Before diving more lets discuss how many types of mode do we have in Apex ?

User Mode : As per this Salesforce post, all Profile level permissions, sharing rules and Field level security are enforced in Apex if it runs in User mode. Standard Controller and Anonymous Apex runs in User mode.

System Mode : Same post conforms that custom controller, trigger, Apex class, controller extension works in System mode. Means eventhough user does not have necessary profile level permission, record level permission or field level permission, but still they can perform any operation on it.

Creating test scenario

For testing purpose, I am going to use a user with “Chatter free” license and existing Opportunity record. Consider OWD for opportunity is “private”.

Apex class :

In this class, I am trying to update existing Opportunity

public class  SystemMode_Scenario {
    public static void perform(){
        Opportunity Opp = [SELECT NAME,StageName FROM Opportunity WHERE Id = '006K000000CD1fZIAT'] ;
        Opp.StageName = 'Negotiation/Review' ;
        update Opp;
    }
}

Trigger on Feeditem :

Whenever chatter free user is posting any chatter comment, below trigger should run and execute method in Apex class

trigger updateOpportunityFromChatterComment on FeedItem  (before insert) {
    SystemMode_Scenario.perform();
}

Chatter free user trying to update Standard Opportunity record – God mode in Action

As we know, Chatter free user cannot access any standard or custom objects. so as per documentation there is no way chatter user can access or update existing Opportunity.

However, if you try to add comment in chatter using chatter user, trigger will be able to update existing Opportunity eventhough user does not has CRUD permission at profile level. So, we can say Apex really works in GOD mode.

When Apex does not work in System or God mode – Gode mode failing because of “with sharing” keyword

Example 1 :

Update Apex class with below code, only difference you can spot is addition of “with sharing” keyword.

public with sharing class  SystemMode_Scenario {
    public static void perform(){
        Opportunity Opp = [SELECT NAME,StageName FROM Opportunity WHERE Id = '006K000000CD1fZIAT'] ;
        Opp.StageName = 'Negotiation/Review' ;
        update Opp;
    }
}

If you try to add chatter comment, it will fail saying “List has no rows for assignment” because logged in user does not has access to existing Opportunity and Apex class is defined using keyword “with Sharing” and makes sense.

Salesforce System Mode fail- With Sharing keyword
Salesforce System Mode fail- “With Sharing” keyword

Example 2:

In this example, lets try to create new record for Lead object and therefore update Apex class with below code :

public with sharing class  SystemMode_Scenario {
    public static void perform(){
        Lead l = new Lead(LastName='Zaa',Company='Cognizant');
        insert l;
    }
}

In previous example, we have seen that Apex class failed because of “with sharing” keyword and it makes sense because chatter does not has record level permission.

In this example, we are not trying to access any existing record rather creating a new lead record. “with sharing” keyword only checks if user has access to existing record or not and therfore this code should work if Apex works in God mode.

However, code will still fail with below error saying “Invalid User Type”.

Salesforce God Mode failing
Salesforce God Mode failing

Conclusion:

So saying, Apex runs in God mode not realy true if class is defined using keyword “with sharing”. “with sharing” keyword not only checks record level permission however somehow it enforces profile level permission as well.

My two cents – Should we use System mode or rather I will say abuse God mode ?

So, there is way to get out of licensing cost. Consultants or developers may think that we can buy low cost license and using custom Apex and visualforce, same functionality can be achieved. However, I would not suggest because of below two reasons :

  1. Salesforce documentation clearly segregates capabilities of difference licenses and they can change System mode functionality anytime. In fact, they have already started it by introducing “with sharing” keyword.
  2. You’re violating the Master Service Agreement and/or related agreements. You could be charged for full licenses retroactively, and failure to pay is breach of contract that will result in a lawsuit for damages, plus the loss of data that could result.

I would suggest to go through this article of Abhinav as well, which also explains similar to what I am trying to explain here.

If any information here are not correct or you have different experience, please share in comment. I would try to update this post with your feedback.

Posted

in

,

by


Related Posts

Comments

16 responses to “System mode or God mode in Apex – Gotchas”

  1. Aaditya Avatar
    Aaditya

    That’s Great article indeed, Jitendra !!!

  2. Aditya Avatar
    Aditya

    Hi, smilar differenence in case of standard controller with extension. It was not allowing to query on the records on which i was not having access.

  3. Ankush Somani Avatar
    Ankush Somani

    Hi, Jitendra,

    I just came to your site today..and almost stick with it like fevi-quick. It has very good content.

      1. santhosh Avatar
        santhosh

        good article, Jitendra,

        I have one doubt here, visualforce page extends to custom controller hence it runs under system mode but customer controller is having “with sharing” enforced. so finally controller executes in which mode ?

        Regards,
        Santhosh

  4. Sudipta Deb Avatar
    Sudipta Deb

    Hi Jitendra –

    In my case, I have tested with below scenarios.

    Account OWD is private. “Sys Admin” Profile is having all access to Account, whereas “Cognizant Employee” profile is having only read access to Account. I have created an account with Sys Admin profile and manually shared with user – Pradipta Deb(Profile – “Cognizant Employee”) as read/write. I have written a custom controller (with sharing) and VF page to support Creation of Account and Updation of Existing Account.

    Now when I am running the VF page with Pradipta Deb, I am able to create the new Account where the Owner is Pradipta Deb. But Pradipta Deb’s profile i.e. “Cognizant Employee” is not allowed to create any new account. Seems like profile level permission is completely ignored here.

    Now when trying to update the existing account (The account created by Sys Admin and Manually Shared), I am able to do that. Seems like it is again ignoring profile level permission (read only) and considering only the manual sharing permission (read/write).

    So my understanding is that “with sharing” doesn’t care when creating the new record, it is not applicable when trying to edit the existing record. Could you please let me know whether my understanding is correct? Thanks in advance.

    Regards,
    Sudipta Deb

    1. Jitendra Zaa Avatar

      “with Sharing” is for record sharing but not for profile permission, that’s why you are seeing this behavior. You need to perform check if want to enforce profile and FLS as per this post – https://developer.salesforce.com/page/Enforcing_CRUD_and_FLS

      1. NARESH CHANDA Avatar
        NARESH CHANDA

        @Jitendra Zaa – Thank you for writing articles that create interest and makes learning fun! Kudos to that. So, you said in your article that ‘With Sharing’ somehow enforces profile level permissions, but Sudipta Deb’s test said that ‘With Sharing’ DOES NOT enforce profile level permissions and you suggested to use alternative ways. I am confused here, as both your conclusions doesn’t culminate the same point. Can you please enlighten the difference?

  5. Anand Vivek Avatar
    Anand Vivek

    Hi,

    As per your explanation though the chatter user did not have access to a particular object, the trigger worked in making changes to the particular object. But the same does not seem to work for Community License who do not have access to the tasks.

    When an action is performed by a Community user I am trying to close a task of a particular type. This does not seem to be possible unless the tasks ISVISIBLEINSELFSERVICE is marked as true. Tried the same by explicity marking a class as without sharing also but did not work. Am I doing something wrong?

  6. Liron C Avatar
    Liron C

    Good post.
    I also do not recommend to abuse the free chatter licenses for any actions that they are not allowed (even if currently SF doesn’t enforce all of privileges).

    If you really must do it, it’s safer to run it in different context. Means, chatter user can write a feeds, and scheduler will run later and do other actions with this feeds with real system admin privileges. I don’t see how SF can easily block such process.

  7. Deepshikha Avatar
    Deepshikha

    Hi Jitendra,

    As per the documentation it well explains use of with and without sharing keyword.
    However, i am still stuck with one confusion.If we donot mention the keywords, it by defaults works in without sharing mode(system mode).
    Then what is that specific thing which would be coming if we use without sharing keyword.
    Please explain.

    Thanks in advance!

    Deepshikha

    1. Jitendra Avatar

      Hi Deepshikha,
      Let’s say classA is written without any keyword. Now, ClassB is written “with sharing” keyword. if ClassB calls ClassA, then ClassA would be running as “With Sharing” keyword because ClassB’s context. If you want to enforce ClassA to run independent of any calling class context, we should declare ClassA using “Without Sharing” keyword. Hope it helps.

  8. Moh Sarfaraj Avatar

    Hi,

    I have tested with all these what I get… let me explain.

    I have created a clone profile of Standard User & that profile have all permissions(Read,write,delete) for Account. But Contact have only Read permission.

    What I want to do, I have developed a Trigger on Account that’s whenever Account is Created It will create related Contact.
    This trigger has a handler class included ‘with sharing’

    then I logging with Standard User profile’s user & create an Account then Contact is automatically Created!

    there is no effect with keyword ‘with sharing or without sharing’

    Someone please come to clear this concept!

    Many Thanks,
    Sarfraz

    1. Jitendra Avatar

      With or Without sharing only respect OWD. It does not check Profile permission.

  9. Suman Sarita Mahapatra Avatar
    Suman Sarita Mahapatra

    HI Jitendra,

    I am doing tooling api calls in apex controller, which is being used by LWC. And for tooling api calls user require access to metadata objects, so I want the apex to run in system mode . So, what should be the approach.

    Thanks
    Suman

  10. Shubham Avatar
    Shubham

    That was a very hepful post

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Jitendra Zaa

Subscribe now to keep reading and get access to the full archive.

Continue Reading