4

I'm trying to do some checks that insert a custom sObject share to determine if that sObject is set to 'Public Read Only', see this question: Determine org. wide security on an object

However, because I have to trap an DML exception about arbitrary 'sharing rules', I've been checking other users sharing records on these custom sobjects: because the current user always has 'ALL' access to their own records of that sobject.

However, if no other users have a record of the sobject in question than I need to create a temporary one in their name (create, update owner id, test-insert share, look for exception).

Except I need to know if I can determine which users in the particular org have a license to the product (so I can use their user Id) - and if not, do non-licensed users have access to the API to create sObject's that are part of my package, so that I can choose a user at random and create a temporary object for their user id!?

Example code:

public boolean determineIfProjectIsPublicReadOnly(){
        Schema.SObjectType targetType = Schema.getGlobalDescribe().get('Project__share');
        sObject testProjectTaskShare = targetType.newSObject();
    List<Project__c> projects = [SELECT Id,OwnerId FROM Project__c WHERE OwnerId != :UserInfo.GetUserId() LIMIT 1];

    if(projects.size() == 0){
        return true;            
    }
    else{
        testProjectTaskShare.put('AccessLevel','Read');
        testProjectTaskShare.put('UserOrGroupId',UserInfo.getUserId());
        testProjectTaskShare.put('ParentId',projects[0].Id);

        Database.SaveResult sr = Database.insert(testProjectTaskShare, false);
        if(sr.isSuccess()){
            // Public Read Only for Project_Task__c
            return false;
        }
        else{
            Database.Error err = sr.getErrors()[0];
            system.debug(err.getMessage());
            if(err.getStatusCode() == StatusCode.FIELD_INTEGRITY_EXCEPTION  &&  err.getMessage().contains('AccessLevel')){
                return true;
            }
                 //this error is thrown attempting to insert share record where one already exists for the current user 
            else if(err.getStatusCode() == StatusCode.FIELD_FILTER_VALIDATION_EXCEPTION){
                return false;
            }
            else{
                return false;
            }
        }
    }
1

With all the issues you raised your best bet here might be going outside of apex and getting this via the metadata REST api. The CustomObject.SharingModel property has exactly what you need.

The only thing to consider is whether this callout needs to run whenever your page loads to make sure the metadata your app has is up to date or if you can get away with running it on a scheduled basis and clean up any "sharing hierarchies" that the user made that no longer make sense.

| improve this answer | |
  • thanks grigriforce -- unfortunately we're a native app and I can't call out to any outside services – jordan.baucke Sep 24 '12 at 21:23
  • You can't even callout to the metadata api? I didn't realize native apps couldn't even use the sf apis. – Greg Grinberg Sep 24 '12 at 22:05
  • No web-service callouts - we'd have to use a proxy server to access the metadata api from within APEX – jordan.baucke Oct 2 '12 at 17:25
-2

Short answer: You can determine if the current user has access to a given namespace (your package): http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_userinfo.htm

To check for accessibility, describe the sObject and check isAccessible, updateable, writeable, etc. You generally don't need to know if no other users have access - only if the running user has access. After all, a properly-set security model gives access where needed without crating duplicate records of an object.

That being said, I'm not sure that from your question you're necessarily developing a package in the best possible way. We don't refer to "instances" of sObjects, generally; the word is "record." I'm sure you've gone through the documentation thoroughly, but perhaps looking at the ISV part of the developerforce website will help.

Sorry to be harsh; I just think there are ways to architect your app so you can avoid this issue and not have to solve it.

| improve this answer | |
  • 2
    David, I am developing a UI that allows users to create a dynamic hierarchy of manual sharing records based on an explicit set of rules related to how two objects are related. The short-coming is not one of my own understanding of the security model. It's a shortcoming in Salesforce providing an adequate API to discover the properties of the security model that is currently enabled. I'm well aware of the ability to check a user's individual access to a record or record type, that is not the goal: The goal is to determine if an sObject is 'Public Read Only' in the absence of other users. – jordan.baucke Sep 9 '12 at 22:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.