You need to sign in to do that
Don't have an account?
Alex Packard 5
UserRecordAccess Values Incorrect
If you do a SOQL query for a single UserRecordAccess record, you get the correct values. But if you query for multiple UserRecordAccess records in a single query, the values returned are often incorrect (for instance the HasAllAccess value may be true when it should be false).
This problem makes it impossible for us to reliably communicate object permissions to our users.
This is nearly identical to the following issues that was marked as fixed back in the Winter 15 release: https://success.salesforce.com/issues_view?id=a1p30000000T4iiAAC
Below is a test class I wrote that reproduces the issue. In this test class I use the Macro sobject, but the problem applies to other objects as well. I first noticed it on a custom object.
This problem makes it impossible for us to reliably communicate object permissions to our users.
This is nearly identical to the following issues that was marked as fixed back in the Winter 15 release: https://success.salesforce.com/issues_view?id=a1p30000000T4iiAAC
Below is a test class I wrote that reproduces the issue. In this test class I use the Macro sobject, but the problem applies to other objects as well. I first noticed it on a custom object.
@isTest public without sharing class UserRecordAccessTest { private static testMethod void test(){ //Create the users that will own the records final User[] users = createStandardUsers(2); final User u1 = users[0]; final User u2 = users[1]; //Create the records, each owned by a different user final SObject o1 = createRecord(u1.Id); final SObject o2 = createRecord(u2.Id); insert new SObject[]{o1, o2}; system.runAs(u1){ //Query for each UserRecordAccess entry individually final UserRecordAccess access1 = queryForSingleUserRecordAccess(u1.Id, o1.Id); final UserRecordAccess access2 = queryForSingleUserRecordAccess(u1.Id, o2.Id); //Query for both UserRecordAccess entries at the same time final UserRecordAccess[] accessList = queryForUserRecordAccesses(u1.Id, new Set<Id>{o1.Id, o2.Id}); //The UserRecordAccess entries should have the same values, regardless of how they were queried compareUserRecordAccesses(access1, accessList[0]);//This fails because the HasAllAccess value is false for the entry queried individually, but is true for the entry queried in a list compareUserRecordAccesses(access2, accessList[1]); } } private static UserRecordAccess queryForSingleUserRecordAccess(final Id userId, final Id recordId){ return [ SELECT RecordId, HasReadAccess, HasEditAccess, HasDeleteAccess, HasTransferAccess, HasAllAccess FROM UserRecordAccess WHERE UserId = :userId AND RecordId = :recordId ]; } private static UserRecordAccess[] queryForUserRecordAccesses(final Id userId, final Set<Id> recordIds){ return [ SELECT RecordId, HasReadAccess, HasEditAccess, HasDeleteAccess, HasTransferAccess, HasAllAccess FROM UserRecordAccess WHERE UserId = :userId AND RecordId IN :recordIds ORDER BY RecordId ]; } private static void compareUserRecordAccesses(final UserRecordAccess expected, final UserRecordAccess actual){ system.assertEquals(expected.RecordId, actual.RecordId); system.assertEquals(expected.HasReadAccess, actual.HasReadAccess); system.assertEquals(expected.HasEditAccess, actual.HasEditAccess); system.assertEquals(expected.HasDeleteAccess, actual.HasDeleteAccess); system.assertEquals(expected.HasTransferAccess, actual.HasTransferAccess); system.assertEquals(expected.HasAllAccess, actual.HasAllAccess); } private static User[] createStandardUsers(final Integer count){ final Profile standardUser = [SELECT Id FROM Profile WHERE Name = 'Standard User']; final User[] users = new User[]{}; for(Integer i = 0; i < count; i++){ users.add(new User( UserName = 'test' + i + '@userrecordaccesstest.com', LastName = 'Smith', Email = 'test@user.com', Alias = 'test', CommunityNickname = 'test' + i, TimeZoneSidKey = 'America/Indiana/Indianapolis', LocaleSidKey = 'en_US', EmailEncodingKey = 'UTF-8', LanguageLocaleKey = 'en_US', ProfileId = standardUser.Id )); } insert users; return users; } private static SObject createRecord(final Id ownerId){ return new Macro(Name = 'Macro' + ownerId, OwnerId = ownerId); } }
I believe I have demonstrated that there is a bug in your system, one that it negatively impacting our ability to deliver a reliable product to our customers, what can I do to get this problem fixed (or at least acknowledged)?
This is a pretty dissapointing result, as it means that you can only look at accurate UserRecordAccess values for one record at a time.
If anybody ever finds this post and has the same problem, please vote for this idea I created and maybe one day they will fix it: https://partners.salesforce.com/ideaView?id=0873A000000lKROQA2