5

I need a way to find a list of All permissionable Objects for an organization, both Standard Object and Custom Objects.

I would except to get this information from DescribeSObjectResult but it has no method isPermissionable like DescribeFieldResult does.

I tried to find all available objects by querying EntityDefinition but it doesn't have IsPermissionable or something like that. Even if I used IsCustomizable I am not sure if this is equivalent to Is permissionable and even though there list a limit of records which can be queried from EntityDefinition table which is 200 and not convenient.

I am trying to find a way to determine if an object can be specified in ObjectPermission SobjectType field.

For example, if I execute Schema.globalDescribe that method would return me ApexEmailNotification object, AccountShare and AccountFeed for which I can't set ObjectPermissions.

For example, when I try to execute the following code

insert new ObjectPermissions(
    SobjectType = 'ApexEmailNotification',
    ParentId = '0PS1t000002MTOcGAO',
    PermissionsCreate = True
);

Line: 1, Column: 1 System.DmlException: Insert failed. First exception on row 0; first error: INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST, Sobject Type Name: bad value for restricted picklist field: ApexEmailNotification: [SobjectType]

enter image description here

I am trying to find a way to distinguish if an SObjectType or EntityDefinition is permissionable or not and generate a list of permissionable SObjects.

3
  • note you could simplify by assuming any std object ending in Share or Feed is not permissionable;
    – cropredy
    Commented Mar 27, 2019 at 22:51
  • @cropredy Good point but ApexEmailNotification doesn't end in Share or Feed
    – Patlatus
    Commented Mar 28, 2019 at 8:29
  • I think my point was that you could make your routine below faster by ignoring certain standard objects based on naming pattern
    – cropredy
    Commented Mar 28, 2019 at 14:18

1 Answer 1

4

One doesn't simply get a list of permissionable SObjects.

Looks like there is no simple way to find that. However, the error wording suggest that SobjectType field on ObjectPermissions object is a picklist which is even restricted, so it should be possible to retrieve its picklist options.

Let's define some helper methods to retrieve picklist options first.

/**
 * @description Retrieves Picklist Entries for specified field
 * @param obj object type
 * @param field picklist field
 * @return Picklist Entries
 */
public static Schema.PicklistEntry[] getPicklistValues( Schema.SObjectType obj, SObjectField field ) {
    return obj.getDescribe().fields.getMap().get(String.valueOf(field)).getDescribe().getPicklistValues();
}
/**
 * @description Retrieves list of picklist values
 * @param obj SObject type
 * @param field SObject field
 * @return List of picklist values
 */
public static List<String> getPicklistValuesList( Schema.SObjectType obj, SObjectField field ) {
    List<String> results = new List<String>();
    for (PicklistEntry entry: getPicklistValues(obj, field) ) {
        results.add(entry.getValue());
    }
    return results;
}

Next, let's try to get a list of Picklist Options for SobjectType field on ObjectPermissions. It is also tricky because to get ObjectPermission sobject token we need to use workaround since its field token blocks access to object token because Apex is case insensitive

System.debug(LoggingLevel.ERROR, '@@@ v: ' + getPicklistValues(
    Schema.sObjectType.ObjectPermissions.getSobjectType(),
    ObjectPermissions.SobjectType
) );

Here we go. enter image description here enter image description here However, this picklist has empty labels. So, to retrieve the labels, we still need to call Schema.describeSObjects passing objects found by the previous method.

There is another obstacle here, picklist options may include many objects which do not even exist on our instance and we will get exception for such objects.

For my developer edition instance, such unavailable objects are AccountBrand, AccountRelationship, ActionCadence, ActionCadenceStep, ActionCadenceStepTracker, ActionCadenceTracker, ActionPlan, ActionPlanTemplate, ActiveScratchOrg, AddOnDefinition, Address, AggregationRow, AiImageDetectedObject, AiImageObject, AiImageTrainingObject, AppIntelQueryRequest, CardPaymentMethod, CareBarrier, CareBarrierDeterminant, CareBarrierType, CareDeterminant, CareDeterminantType, CareDiagnosis, CareInterventionType, CarePreauth, CarePreauthItem, CareProgram, CareProgramCampaign, CareProgramEnrollee, CareProgramTeamMember, CareRequest, CareRequestDrug, CareRequestItem, Certification, CertificationDef, CertificationSectionDef, CertificationStep, CertificationStepDef, ChannelProgram, ChannelProgramLevel, ChannelProgramMember, Claim, CloudServiceProvider, CloudServiceProviderApi, ConsumptionSchedule, ContactPointAddress, ContactPointConsent, ContactPointEmail, ContactPointPhone, ContactPointTypeConsent, ContractLineItem, CoverageBenefit, CoverageBenefitItem, CoverageType, CustomerAssetAuto, CustomerAssetHome, DataSharingCustomerLocal, DataUseLegalBasis, DataUsePurpose, EditionDefinition, EngagementProgram, EngagementProgramNode, EngagementProgramVersion, Entitlement, EntitlementContact, EnvironmentHubInvitation, EnvironmentHubMember, FtestAccountChild, FtestChild, FtestConcrete, FtestConcrete2, FtestConcrete3, FtestConcrete4, FtestConcrete5, FtestConcrete6, FtestConcrete7, FtestConcrete8, FtestConcreteNoDefault, FtestConcreteNoDefault2, FtestConcreteNoDefault3, FtestConcreteNoSup, FtestConcreteNoSup2, FtestConcreteNoSup3, FtestError, FtestErrorChild, FtestGrandChild, FtestHiddenName, FtestMain, FtestOffCoreRecord, FtestPerson, FtestVirtualMain, Goal, GoalLink, HealthCareDiagnosis, HealthCareProcedure, IdeaTheme, IdentityDocument, IncludedLicenseDefinition, Individual, InStoreLocation, InsurancePolicy, InsurancePolicyAsset, InsurancePolicyBeneficiary, InsurancePolicyCoverageLimit, InsurancePolicyMember, InsuranceProfile, KeyPerformanceIndicator, LicensingError, LicensingRequest, LiveAgentSession, LiveChatTranscript, LiveChatVisitor, Location, MaintenancePlan, ManagementAddOnLicense, ManagementEditionLicense, ManagementPlatformLicense, ManagementUserLicense, MemberPlan, MessagingEndUser, MessagingSession, Metric, MetricDataLink, MyCustomObject, NamespaceRegistry, OperatingHours, OrderDeliveryGroup, OrderDeliveryGroupLine, OrderDeliveryMethod, OrderItemSummary, OrderPriceAdjustDistrLine, OrderSummary, OrgSnapshot, PartnerFundAllocation, PartnerFundClaim, PartnerFundRequest, PartnerMarketingBudget, PaymentAuthorization, PaymentGroup, PersonEducation, PersonEmployment, PersonLifeEvent, PersonList, PlanBenefit, PlanBenefitItem, PlatformLicenseDefinition, Producer, ProductCoverage, ProductItem, ProductRequest, ProductTransfer, ProfileSkill, ProfileSkillEndorsement, ProfileSkillUser, PurchaserPlan, PurchaserPlanAssn, Question, Quote, RegisteredMobileDevice, RetailLocationGroup, RetailStore, RetailStoreKpi, RetailStoreVisitTemplate, RetailVisitKpi, RetailVisitTemplate, RetailVisitTemplateWorkTask, RetailVisitWorkTask, RetailWorkTask, RetailWorkTaskKpi, ReturnOrder, SalesAgreement, Scorecard, ScorecardAssociation, ScorecardMetric, ScratchOrgInfo, ServiceAppointment, ServiceContract, ServiceCrew, ServiceResource, ServiceTerritory, SettingUsageDefinition, SettingUsageMap, ShapeRepresentation, Shipment, SignupRequest, SocialPost, Survey, SurveyInvitation, SurveyResponse, SurveySubject, Tenant, TenantParameterMap, TimeSheet, TrialEnvironmentSignup, UsageEntitlement, UsageFactor, UserLicenseDefinition, Visit, WebStore, WorkCapacityLimit, WorkCoaching, WorkFeedback, WorkFeedbackQuestion, WorkFeedbackQuestionSet, WorkFeedbackRequest, WorkFeedbackTemplate, WorkGoal, WorkGoalCollaborator, WorkGoalLink, WorkOrder, WorkPerformanceCycle, WorkReward, WorkRewardFund, WorkRewardFundType, WorkType, WorkTypeGroup, WorkUpgradeAction, WorkUpgradeCustomer, WorkUpgradeUser.

So we need a way to filter them out.

The only option I currently have found it to catch an exception there and hope we don't exceed Describe call limit for an organization.

List<Map<String, String>> results = new List<Map<String, String>>();
    for ( String o: getPicklistValuesList(
        Schema.sObjectType.ObjectPermissions.getSobjectType(),
        ObjectPermissions.SobjectType
    ) ) {
        try{
            for (DescribeSObjectResult describeResult: Schema.describeSObjects(
                new List<String>{o}
            ) ) {
                results.add(new Map<String, String>{'label'=>describeResult.getLabel(), 'value'=>describeResult.getName()});
            } 
        } catch (Exception e) {
            //failed.add(o);
        }
    }
    /*for (DescribeSObjectResult describeResult: Schema.describeSObjects(
        getPicklistValuesList(
            Schema.sObjectType.ObjectPermissions.getSobjectType(),
            ObjectPermissions.SobjectType
        )
    ) ) {
        results.add(new Map<String, String>{'label'=>describeResult.getLabel(), 'value'=>describeResult.getName()});
    }*/
    return results;

Phil W suggested to use Global Describe instead of catching an error, so I refactored my method into following form:

    List<Map<String, String>> results = new List<Map<String, String>>();

    Map<String, SObjectType> globalDescribe = Schema.getGlobalDescribe();

    for ( String o: getPicklistValuesList(
        Schema.sObjectType.ObjectPermissions.getSobjectType(),
        ObjectPermissions.SobjectType
    ) ) {
        if ( globalDescribe.containsKey(o)) {
            DescribeSObjectResult result = globalDescribe.get(o).getDescribe();
            results.add(new Map<String, String>{'label'=>result.getLabel(), 'value'=>result.getName()});
        }
    }
    return results;
3
  • Could you not use the (expensive to call, but one-shot) Schema.getGlobalDescribe() to provide a map where the key is the object type name, and find out if the picklist entry exists in that map instead of relying on Schema.describeSObjects and exception handling?
    – Phil W
    Commented Mar 27, 2019 at 20:32
  • @PhilW This is a good interesting idea, I should try that
    – Patlatus
    Commented Mar 27, 2019 at 20:33
  • @PhilW yes, two versions return the same results for my organization.
    – Patlatus
    Commented Mar 27, 2019 at 20:44

You must log in to answer this question.

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