Does “with sharing” only apply to 1st entry point of code?

I was watching an old Dev 501 video today (#4 Classes & Objects) in which the instructor said profile based sharing rules were only checked at the entry point where apex code begins it’s execution. He said profile based sharing of any classes called beyond the entry point wasn’t checked by SF to determine whether it should run.

The video is quite old and may no longer apply. SF was at API 15 at the time this was recorded. When I looked at the docs, it was unclear to me on whether sharing is checked following initial entry. Is the video correct or is sharing checked again and respected with each call that follows to another class?

Edit

Before posting this, some of the articles I looked at included Without Sharing: Best practices when bypassing Apex sharing rules and object security by Dan Appleman in which he says “CRUD and FLS security is largely part of the user interface infrastructure. Sharing is largely implemented in the database query system.” He then goes on to discuss what he refers to as “A Matter of Intent”.

One of the questions that had occurred to me was the situation where at the entry point, “without sharing” was specified, a query returned the data to be operated on and a subsequent class to process the data “with sharing” was called. Because of FLS, the user who initiated the transaction might have read only access to some of the fields, yet the 2nd class called might operate on the fields, then perform DML to commit them.

If sharing rules are propagated from the initial User who initiated the transaction, the DML would presumably fail. If they’re not propagated, the DML would succeed. I’d like to understand which would be the case and whether it’s because of the class’s sharing being propagated in the one situation or the user’s sharing in the other possible outcome.

Appleman’s article didn’t discuss propagation of Role based sharing as additional classes are called from the entry point or subsequent classes. It wasn’t clear to me whether the calling class’s sharing model would be what was respected by subsequent classes, the the User’s sharing model who initiated the execution of Apex code or neither of them.

In a single class execution, the answer is clear, but its less obvious in other situations, especially when SOQL or DML isn’t involved. For example, if the above mentioned user doesn’t have FLS permissions to edit a particular field in Opportunity named myOppField__c, I wouldn’t expect an Apex Class “with sharing” to prevent code from allowing opp.myOppField__c[i] = opp2[i+1].myOppField__c; from running.

Instead, what I’d hope to be able to expect, would be a problem when an attempt was made to commit the database changes via DML when the revised data was returned to a calling class defined “with sharing” from the subsequent class which had been defined “without sharing” that made the changes to the read only field (for that User).

You could say, that this suggests to me that permissions and security involve more than just DML and SOQL queries, but coding to take those permissions into account as well. I hope this helps clarify the nature of my question. I greatly appreciate the answers I’ve received thus far.

Answer

The “with sharing” and “without sharing” keywords deal with if sharing is enforced within the confines of that class. This affects DML statements and queries that are performed within the bounds of that class.

See my answer on this question for an explaination of how “with sharing” and “without sharing” affect queries and DML operations.

It does indeed apply every time you come into or out of a class. The current class’ execution context is affected by “with sharing” or “without sharing.”

Only the entry point determines if the user can run through the entire logic. For example, if a user has access to a Visualforce page, they do not need to have access to the page’s extensions/controller classes. This may be what the instructor was attempting to explain when they stated that only the first entry point determines if access is granted to an execution context.


Edit:

First, FLS is never applied to Apex Code. You must manually choose to enforce FLS. This is true regardless of the current sharing mode. Conversely, universally required/unique indexes/etc are always enforced in Apex Code, regardless of the sharing model.

However, in regards to queries and DML, it is entirely possible to query records in a “without sharing” context, and pass those records to a “with sharing” context, in which case, the DML will fail if the user does not have read or edit access on the record in question. The difference is how sharing is enforced in the various contexts. For example, here’s a trivial case:

// Without sharing util class
public without sharing class accountUtil {
    public static Account[] getAccounts() {
        return [SELECT Name, OwnerId, Industry FROM Account];
    }
}

// With sharing controller
public with sharing class accountEdit {
    public account[] accounts { get; set; }
    public accountEdit() {
        accounts = accountUtil.getAccounts();
    }
    public void save() {
        try {
            update accounts;
        } catch(Exception e) {
            ApexPages.addMessages(e);
        }
    }
}

<!-- trivial mass edit page -->
<apex:page controller="accountEdit">
    <apex:form>
        <apex:pageBlock>
            <apex:pageMessages />
            <apex:pageBlockButtons>
                <apex:commandButton action="{!save}" value="Save"/>
            </apex:pageBlockButtons>
            <apex:pageBlockTable value="{!accounts}" var="account">
                <apex:column>
                    <apex:inputField value="{!account.name}" />
                </apex:column>
                <apex:column>
                    <apex:inputField value="{!account.Industry}" />
                </apex:column>
            </apex:pageBlockTable>
        </apex:pageBlock>
    </apex:form>
</apex:page>

Given this code, an administrator would be able to edit every account in the system. However, if you turn sharing to private or read-only on accounts, and then log in as a normal user, they’ll get “Insufficient privileges” error when this DML attempts to operate. Sharing is enforced at the moment the DML occurs, if done so in a “with sharing” context. You can try it out in a dev org to see what I’m demonstrating.

However, this only applies at the record level. Field level security is always compromised when using code, so if you intend to prevent an edit on a field, you need to check the field’s access before you write to it. You can always see a user’s field permissions using describes, even in a “without sharing” context (the context doesn’t affect the describes a user would receive).

Attribution
Source : Link , Question Author : crmprogdev , Answer Author : Community

Leave a Comment