I have a visual force page and its controller as follows:

<apex:page controller="OpportunityBusinessService" tabStyle="Opportunity">

        <apex:pageBlock mode="edit">

            <apex:repeat value="{!Opportunities}" var="OpportunityItem">
                <apex:pageBlockSection title="Opportunity Record">
                    <apex:inputField value="{!OpportunityItem.name}" />
                    <apex:inputField value="{!OpportunityItem.Amount}" />
                    <apex:inputField value="{!OpportunityItem.StageName}" />

            <apex:pageBlockButtons location="bottom">
                <apex:commandButton value="Save" action="{!save}" />


public inherited sharing class OpportunityBusinessService {
    public List<Opportunity> Opportunities {get; set;}

    public OpportunityBusinessService() {
        Opportunities = [Select Id, Name, Amount, StageName from Opportunity];

    public PageReference save() {
        try {
            for (Opportunity opportunityItem: Opportunities){
                opportunityItem.Amount = 200;

            update Opportunities;
        } catch(Exception e) {
            System.debug('Error occured during update '+e.getMessage());
        return null;

The opportunity object in my org has the OWD as private. A user's profile does only permit to readonly. When login in as this user, I can only read opportunities that this user owns. When I execute the save button on this page as the same user, the action is executed successfully.

My understanding is that an apex class with 'inherited sharing' or 'with sharing' keyword, I understand that this user sharing settings are applied; therefore, I expected an error when trying to update the opportunities object.

Can you help me out figure out why?

1 Answer 1


It's important to distinguish between record-level visibility (OWDs and sharing) and the CRUD and FLS permissions on the user's Profile. The one does not enforce the other.

The behavior you describe appears to be as designed. Your controller is correctly operating as with sharing because it is used as a Visualforce controller. It can see those Opportunity records which the OWD Private permits, that is, those owned by the user in this circumstance.

The user's ability to run update operations on these Opportunities is because Apex runs in system mode, where FLS and CRUD are not enforced. If you want FLS and CRUD to be enforced against your Apex controller, you must manually check, for example, isUpdateable() against each sObject type you modify. This Trailhead module covers this area.


You must log in to answer this question.

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