CRM Field Security Profiles Bug

Our clients use FLS extensively. And we faced weird bug when FLS permissions aren't applied properly even though users are members of respective FLS profiles.
Assume that there are two solutions: 'first' and 'second'. Both of them are managed. Not sure if it's really important but they have different publishers. First one contains field 'new_attr1' for entity 'new_entity1'. They key point that it has IsSecured set to zero. Second solution has modifications to the same entity 'new_entity1' and for field 'new_attr1' IsSecured set to one, which means that Filed Security is enabled for it. Also second solution contains configured FLS profiles with read, update and create permissions set to yes. Then solutions 'first' and 'second' get imported into organization in that specific order. Users added to FLS profiles and have access to entities and fields works properly (some of them able to read 'new_attr1' field, some - don't). Now to reproduce a bug we need to import 'first' and 'second' solutions in the same order one or more times (sometimes it doesn't break from the first try). Now users who are still members of FLS profiles with read, update or create permissions for field 'new_attr1' aren't able to read it. They see asterisks there. If we open FLS profiles we see that permissions properly set and users are still their members. What the hell!
First of all CRM security model doesn't use system entities tables and views directly (such as FieldSecurityProfile). Instead it populates service tables with suffix 'Map' on the end. I'm not sure but most probably for performance reasons. In our case we are interesting in table PrincipalAttributeAccessMap. If we check, it will show up that our users are missing there:

SELECT *
FROM [PrincipalAttributeAccessMap]
where AttributeId = '<user-id>'

So far Dynamics CRM support couldn't reproduce and confirm it. But we are able to reproduce and our clients aren't happy that FLS permissions get lost after deployments.
We have found a few workarounds. First, we can go into FLS and remove users, save, add users back, save. And it will work properly. But that manual process doesn't scale well when you have many organizations with several FLS profiles in each. Other solution is to run next query after solutions import on each organization:

use [org_MSCRM]

declare  @principalid uniqueidentifier

declare users_cursor CURSOR 
FOR select su.SystemUserId
from SystemUser su
where su.IsDisabled = 0

open users_cursor

FETCH NEXT FROM users_cursor
into @principalid

WHILE @@FETCH_STATUS = 0
BEGIN
 print @principalid
 exec p_PrincipalAttributeAccessMapReinit @principalid, 8, 0

 FETCH NEXT FROM users_cursor
 into @principalid
END


CLOSE users_cursor;  
DEALLOCATE users_cursor;

Note that it will reinitialize only users access to fields. For teams access you need to change query above slightly.
P.S. As always note that this solutions isn't recommended or supported by MS. Always do backup before running any script on DB.

Show Comments