He wanted to avoid the use of the RetrievePrincipalAccessRequest because it requires to provide an existing record id in order to perform the request. I agree with this, in addition the result of a RetrievePrincipalAccessRequest doesn't guarantee that the user has the privilege, but only that the user can access to that specific record (for example when the record is only shared to the user).
A good aspect of the privileges is that they respect a naming convention, so the Read privilege for the Account entity is called prvReadAccount, the Write privilege prvWriteAccount, etc etc. This naming convention is valid also for custom entity, so if we have an entity called new_SMS and we want to know if the user can create a new_SMS record, we will check for the prvCreatenew_SMS privilege.
The easy way it to check first that the privilege is inside the CRM and after to compare its Id with the values returned by a RetrieveUserPrivilegesRequest:
bool userHasPrivilege = false; ConditionExpression privilegeCondition = new ConditionExpression("name", ConditionOperator.Equal, "prvCreatenew_SMS"); // name of the privilege FilterExpression privilegeFilter = new FilterExpression(LogicalOperator.And); privilegeFilter.Conditions.Add(privilegeCondition); QueryExpression privilegeQuery = new QueryExpression { EntityName = "privilege", ColumnSet = new ColumnSet(true), Criteria = privilegeFilter }; EntityCollection retrievedPrivileges = service.RetrieveMultiple(privilegeQuery); if (retrievedPrivileges.Entities.Count == 1) { RetrieveUserPrivilegesRequest request = new RetrieveUserPrivilegesRequest(); request.UserId = userId; // Id of the User RetrieveUserPrivilegesResponse response = (RetrieveUserPrivilegesResponse)service.Execute(request); foreach (RolePrivilege rolePrivilege in response.RolePrivileges) { if (rolePrivilege.PrivilegeId == retrievedPrivileges.Entities[0].Id) { userHasPrivilege = true; break; } } }The hard way it to build a single MEGA query to perform the same check (4 LinkEntity!):
bool userHasPrivilege = false; QueryExpression privilegeQuery = new QueryExpression("privilege"); privilegeQuery.ColumnSet = new ColumnSet(true); LinkEntity privilegeLink1 = new LinkEntity("privilege", "roleprivileges", "privilegeid", "privilegeid", JoinOperator.Inner); LinkEntity privilegeLink2 = new LinkEntity("roleprivileges", "role", "roleid", "roleid", JoinOperator.Inner); LinkEntity privilegeLink3 = new LinkEntity("role", "systemuserroles", "roleid", "roleid", JoinOperator.Inner); LinkEntity privilegeLink4 = new LinkEntity("systemuserroles", "systemuser", "systemuserid", "systemuserid", JoinOperator.Inner); ConditionExpression userCondition = new ConditionExpression("systemuserid", ConditionOperator.Equal, userId); // // Id of the User ConditionExpression privilegeCondition = new ConditionExpression("name", ConditionOperator.Equal, "prvCreatenew_SMS"); // name of the privilege privilegeLink4.LinkCriteria.AddCondition(userCondition); FilterExpression privilegeFilter = new FilterExpression(LogicalOperator.And); privilegeFilter.Conditions.Add(privilegeCondition); privilegeQuery.Criteria = privilegeFilter; privilegeLink3.LinkEntities.Add(privilegeLink4); privilegeLink2.LinkEntities.Add(privilegeLink3); privilegeLink1.LinkEntities.Add(privilegeLink2); privilegeQuery.LinkEntities.Add(privilegeLink1); EntityCollection retrievedPrivileges = service.RetrieveMultiple(privilegeQuery); if (retrievedPrivileges.Entities.Count > 0) { userHasPrivilege = true; }
Precisely what i was looking for. Thank you very much. Wonderful post.
ReplyDeleteExactly what I was looking for. Thanks Guido
ReplyDeleteBy the way, Mega query works faster )
ReplyDelete