Any way to get Child Relationships without being bound by user permissions?

Question

User object-level permissions limit the results of DescribeSObjectResult.getChildRelationships(). Are there any workarounds?

I have submitted an Idea about this (https://success.salesforce.com/ideaView?id=0873A000000CZLzQAO).

(Note: This seems very closely related to the “Fixed” Known Issue In API version 44, DescribeSObjectResult.getChildRelationships() checks Read Access to the child entity and parent relationship field)

Actual goal

I would like to dynamically generate a query on Case, and several child objects. E.g.: SELECT Id, (SELECT Id, CaseId FROM WorkOrders) FROM Case WHERE ... I would like to pass in the child SObjectTypes (WorkOrder.getSObjectType()) without worrying about the exact fields and the names of the relationship. Apex provides exactly one path to get the names of child relationships, and it all starts with SObjectType.Case.getChildRelationships().

However, it looks like this is user-permissions dependent, even in a trigger context, which makes it worthless for my goal.

Description

In Spring ’19 (and maybe before — I have no idea), running getChildRelationships() will not return a relationship if the executing user does not have allowRead permissions on the child SObject.

(I describe this by example, below.)

I believe this is a bug because the documentation says (emphasis mine):

Apex classes and triggers run in system mode. Classes and triggers have no restrictions on dynamically looking up any sObject that is available in the org. You can generate a map of all the sObjects for your org regardless of the current user’s permission, unless you are executing anonymous Apex.

Sample Code

Below is a simple method that finds the relationship between a parentSObjectType and a childSObjectType. It assumes that there is only one relationship between the two and will throw an error otherwise.

public without sharing class SObjectUtils {
  public static ChildRelationship getRelationshipForSObjectType(SObjectType parentSObjType, SObjectType childSObjType) {
    ChildRelationship value;
    for (ChildRelationship rel : parentSObjType.getDescribe().getChildRelationships()) {
      if (childSObjType == rel.getChildSObject()) {
        if (value != null) {
          throw new RelationshipException('Cannot deduce relationship name from ' + parentSObjType + 
                                          '. There is more than one related object of type ' + childSObjType);
        }
        value = rel;
      }
    }
    return value;
  }
}

Elsewhere in a test, I run:

@isTest
private static class TEST_SObjectUtils {

  static User getUserWithoutWorkOrderPermissions() {
    // return a user without workorder object permissions
  }

  static User getUserWithWorkOrderPermissions() {
    // return a user with workorder object permissions
  }

  @isTest
  static void worksForUserWithWorkOrderPermissions() {
    ChildRelationship rel;
    System.runAs(getUserWithWorkOrderPermissions()) {
      Test.startTest();

        rel = SObjectUtils.getRelationshipForSObjectType(
          Case.getSObjectType(), 
          WorkOrder.getSObjectType()
        );

      Test.stopTest();
    }
    System.assertEquals('WorkOrders', rel.getRelationshipName());
  }


  @isTest
  static void worksForUserWithoutWorkOrderPermissions() {
    ChildRelationship rel;
    System.runAs(getUserWithoutWorkOrderPermissions()) {
      Test.startTest();

        rel = SObjectUtils.getRelationshipForSObjectType(
          Case.getSObjectType(), 
          WorkOrder.getSObjectType()
        );

      Test.stopTest();
    }
    System.assertNotEquals(null, rel); // this fails!!
  }
}

Answer

The error here was described in this Known Issue introduce in Winter ’19:

In API version 44, DescribeSObjectResult.getChildRelationships() checks Read Access to the child entity and parent relationship field.

The bug is marked Fixed in Spring ’19 patch 8.0. My SObjectUtils class was running in v44.0. When I upgrade the API version, the issue was not resolved.

I believe that the field-level security issues described in the above ticket may be fixed, but this bug has to do with object-level security.

Attribution
Source : Link , Question Author : Charles Koppelman , Answer Author : Charles Koppelman

Leave a Comment