Privileges by Entity (CRM 2015)

Sometimes, you need to programmatically check a certain privilege on an entity, for business purposes. If you played with user roles, you noticed that all the user roles defined on the main business unit are inherited on the child business units and cannot be altered at child business unit level. The approach below handles this scenario as well and works on both CRM 2013 and CRM 2015. All you have to input is the entity name and the user id.

SQL approach:

DECLARE @EntityName nvarchar(100)
DECLARE @UserId uniqueidentifier

SET @UserId = ''
SET @EntityName = ''

SELECT REPLACE(REPLACE(P.Name,'prv',''),@EntityName,'') as Privilege FROM systemuser SU 
INNER JOIN systemuserroles SUR ON(SU.systemuserid = SUR.systemuserid AND SU.systemuserid = @UserId)
INNER JOIN role R ON(R.roleid = SUR.roleid)
INNER JOIN role PR ON(R.parentrootroleid = PR.roleid)
INNER JOIN roleprivileges RP ON(RP.roleid = PR.roleid)
INNER JOIN privilege P ON(P.privilegeid = RP.privilegeid and P.Name LIKE '%' + @EntityName)

C# approach:

protected OrganizationServiceProxy GetServiceProxy()
{
	if (Proxy == null)
	{
		CrmConnection crmConnection = new CrmConnection("XrmConnectionString");
		Proxy = new OrganizationServiceProxy(crmConnection.ServiceUri, null, crmConnection.ClientCredentials, null);

		if (CallerId != Guid.Empty)
			Proxy.CallerId = CallerId;
	}

	return Proxy;
}

/// 
/// Gets User Privileges for a certain entity
/// 
/// Entity Name
/// System User Id	
public List GetUserPrivilegesByEntity(string entityName, Nullable userId = null)
{
	List privileges = new List();

	if (!userId.HasValue)
		userId = CallerId;

	if (userId != Guid.Empty && !string.IsNullOrEmpty(entityName))
	{
		using (var ctx = GetServiceProxy())
		{
			#region Impersonate Admin (OPTIONAL)
			EntityReference losAdmin = GetAdminUser(ctx); // create a method to retrieve a systemuser with System Administrator role, to avoid lack of privileges for reading the roles and privileges

			if (losAdmin != null)
				ctx.CallerId = losAdmin.Id;
			#endregion

			#region Check Roles
			QueryExpression rolesQuery = new QueryExpression("role");
			rolesQuery.ColumnSet = new ColumnSet(true);
			LinkEntity rolesLink1 = new LinkEntity("role", "systemuserroles", "roleid", "roleid", JoinOperator.Inner);
			LinkEntity rolesLink2 = new LinkEntity("systemuserroles", "systemuser", "systemuserid", "systemuserid", JoinOperator.Inner);

			ConditionExpression userCondition = new ConditionExpression("systemuserid", ConditionOperator.Equal, userId);
			rolesLink2.LinkCriteria.AddCondition(userCondition);

			FilterExpression rolesFilter = new FilterExpression(LogicalOperator.And);
			rolesQuery.Criteria = rolesFilter;

			rolesLink1.LinkEntities.Add(rolesLink2);
			rolesQuery.LinkEntities.Add(rolesLink1);

			EntityCollection retrievedRoles = ctx.RetrieveMultiple(rolesQuery);

			if (retrievedRoles != null && retrievedRoles.Entities != null && retrievedRoles.Entities.Count > 0)
			{
				foreach (Entity role in retrievedRoles.Entities)
				{
					if (role.Attributes.ContainsKey("parentrootroleid") && role["parentrootroleid"] != null && role["parentrootroleid"] is EntityReference)
					{
						Guid rootRoleId = ((EntityReference)role["parentrootroleid"]).Id;

						#region Check Privileges
						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);

						ConditionExpression rootRoleCondition = new ConditionExpression("parentrootroleid", ConditionOperator.Equal, rootRoleId);
						ConditionExpression privilegeCondition = new ConditionExpression("name", ConditionOperator.EndsWith, entityName); // {prvCreateEntityName}

						FilterExpression privilegeFilter = new FilterExpression(LogicalOperator.And);
						privilegeFilter.Conditions.Add(privilegeCondition);
						privilegeQuery.Criteria = privilegeFilter;

						privilegeLink2.LinkCriteria.AddCondition(rootRoleCondition);

						privilegeLink1.LinkEntities.Add(privilegeLink2);
						privilegeQuery.LinkEntities.Add(privilegeLink1);

						EntityCollection retrievedPrivileges = ctx.RetrieveMultiple(privilegeQuery);

						if (retrievedPrivileges != null && retrievedPrivileges.Entities != null && retrievedPrivileges.Entities.Count > 0)
						{
							List addPrivileges = retrievedPrivileges.Entities.ToList().Where(e => e.Attributes.ContainsKey("name") && e["name"] != null).Select(e => e["name"].ToString().Replace(entityName, "").Replace("prv", "")).Distinct().ToList();

							privileges = privileges.Union(addPrivileges).ToList();
						}
						#endregion
					}
				}
			} 
			#endregion
		}
	}

	return privileges;
}

Based on the C# version, feel free to expand the logic for JavaScript as well 🙂 Happy coding!

Leave a comment

Your email address will not be published. Required fields are marked *