3

Assuming I've 2 users in my org: [User A] & [User B]

Assuming I've a Managed Package CustomObject: [abc__XYZ__c]

IMPORTANT:

  • [User A] - has been assigned a License of this Managed Package.
  • [User B] - DO NOT have a User License to this Managed Package.

Consider these 3 Visualforce Pages & respective Apex Classes:

  1. Test1
  2. Test2 / Test2Controller
  3. Test3 / Test3Controller

Code for the Pages/Classes is as follows:

Test1 VF Page:

<apex:page standardController="abc__XYZ__c">
    <apex:pageBlock>
        <apex:pageBlockSection columns="1">
            <apex:outputField value="{!abc__XYZ__c.Name}" />
            <apex:outputField value="{!abc__XYZ__c.abc__TotalAmount__c}" />
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

Test2 VF Page:

<apex:page controller="Test2Controller">
    <apex:pageBlock>
        <apex:pageBlockSection columns="1">
            <apex:outputText value="{!mysObjVar['Name']}" />
        <apex:outputText value="{!mysObjVar['abc__TotalAmount__c']}" />
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

Test2Controller APEX Class:

public with sharing class Test2Controller {
    public abc__XYZ__c mysObjVar { get;set; }
    
    public Test2Controller() {
        mysObjVar = new abc__XYZ__c();
        abc__XYZ__c[] b = [select Id, name, abc__totalamount__c from abc__XYZ__c where id =: ApexPages.currentPage().getParameters().get('id')];
        if (b.size() > 0)
            mysObjVar = b[0];
    }
}

Test3 VF Page:

<apex:page controller="Test3Controller">
    <apex:pageBlock>
        <apex:pageBlockSection columns="1" title="via sObject">
            <apex:outputText value="{!mysObjVar['Name']}" />
            <apex:outputText value="{!mysObjVar['abc__TotalAmount__c']}" />
        </apex:pageBlockSection>
        <apex:pageBlockSection columns="1" title="via Custom">
            Name: <apex:outputText value="{!sName}" />
            Total: <apex:outputText value="{!sTotal}" />
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>

Test3Controller APEX Class:

public with sharing class Test3Controller {
    public sObject mysObjVar { get;set; } 
    public string sName { get;set; }
    public decimal sTotal { get;set; }
            
    public Test3Controller() {
        Schema.DescribeSObjectResult dr = Schema.getGlobalDescribe().get('abc__XYZ__c').getDescribe();
        if( dr.isAccessible() && !dr.isDeprecatedAndHidden() && dr.isQueryable() )
        {
            mysObjVar = Schema.getGlobalDescribe().get('abc__XYZ__c').newSObject();
            string recordid = ApexPages.currentPage().getParameters().get('id');
            sObject[] b = database.query('select Id, name, abc__TotalAmount__c from abc__XYZ__c where id =: recordid');
            if (b.size() > 0) {
                mysObjVar = b[0];
                sName = (string) b[0].get('Name');
                sTotal = (decimal) b[0].get('abc__TotalAmount__c');
            }
        }
    }
}

Now:

  • If I access, via [User A]: Test1, Test2, and Test3 VF pages in browser with a valid Record Id, I get ALL these 3 VF pages show me Values for the fields I have shown.

  • If I access, via [User B]:

    • Test1 VF page show "Insufficient Privileges" error.
    • Test2 VF page show me Empty Page.
    • Test3 VF Page show me Empty Section when access via sObject[fieldName] BUT show me Actual Values in field in a section when I use String Property to fetch the field values (image attached)

enter image description here

And so my question, how can a User who does not have a License to the Package be able to Fetch Data, and be able to display it to user via a Custom Property, but not via an sObject instance variable or direct object instance variable?

To me it seems like a big Bug in platform! Ideally I don't think it should every allow reading of Data to any User who does not have access to the Managed Package via Licenses and Describe() Calls should respect that, shouldn't they?

2 Answers 2

1

To test whether a user has access to a managed package, there is a method

UserInfo.isCurrentUserLicensed( String namespace )

All of your examples above are consistent with the lack of enforcement of pretty much any permissions on CRUD/FLS at the Apex/SOQL level. This is an ongoing thorny topic that's been covered unhappily in many threads on the Dev Forums, the Partner Community, etc. Take a read if you have time:

https://developer.salesforce.com/forums/ForumsMain?id=906F00000009JFXIA2

Your Test1 page uses a standard controller so it enforces CRUD/FLS .. but the other two Apex controllers (Test2Controller and Test3Controller) are running in system context and bypass CRUD/FLS.

Your example in Test3 page shows the hacky behavior of using a field reference to an SObject versus a String that was assigned in Apex.

This doc pretty much covers it:

https://developer.salesforce.com/page/Testing_CRUD_and_FLS_Enforcement

2
  • Not so sure if I am able to stress on the fact that data is being allowed to access via code. The code that I posted points to the fact that it is not My developed package that can access data but in fact anyone who develops something in the org can put in a module and platform did not threw error as such to restrict data access. May be I'm seeing it backwards :-)
    – VarunC
    Commented Feb 6, 2015 at 14:00
  • I think I understand what you're concerned with: an unlicensed user of your managed package is able to access the data within your packages objects if they use Apex to do so. And I'm saying: yes, that's the way it works and you could go make a big fuss to Premiere Support and your TAM or TE and they'd tell you that this is the way it is (on purpose) even though it's unbelievable. There are ideas out there on the Idea Exchange about Apex enforcement of CRUD/FLS "automatically" but so far, no hints of this changing any time soon
    – daveespo
    Commented Feb 6, 2015 at 21:23
0

UPDATE: This answer is incorrect, as both users have CRUD permissions at the profile level to the object.

It gets a bit confusing because the platform tries to do CRUD/FLS checks for you (whenever it can). It can do these checks at the apex level (when you use a standard controller) or at the visual force layer (when its clear which field is being referenced).

5
  • I totally agree @Robert. But my confusion gets deep when I see that Describe Call is actually allowing accessibility. Please check back, I've edited the code to include the modified code for Describe call check in Test3Controller class.
    – VarunC
    Commented Feb 5, 2015 at 10:49
  • I'm sorry -- on first reading I missed that you were checking is accessible. Can you check which profile your second user is using and verify that the profile does not grant access to the object? Commented Feb 5, 2015 at 11:30
  • Well that is true actually, the profile has permissions to the object. But the thing is, I kind of not able to get align with the fact that with same set or permissions access, I can access the data with slight change of Coding Methodology.
    – VarunC
    Commented Feb 5, 2015 at 12:12
  • And both users have permission to access the VF Page and Controller classes? In that case this is purely about the license enforcement code and not the underlying perms. Commented Feb 5, 2015 at 13:30
  • yes, both users have permissions to page and class.
    – VarunC
    Commented Feb 5, 2015 at 13:58

You must log in to answer this question.

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