CRM Tip: Issue with checking Security role GUID of custom security roles

Problem Statement:

We often encounter a scenario where we need to perform some operations based on the fact if the user has a particular security role. We also know that the GUID of a custom security role created by us remains the same, even if is installed in some other environment.

Consider the following scenario:

I want to check if the logged in User has “Custom View Only Role”, I want to hide some fields on the form. Also, the role – “Custom View Only Role” is created by me.

Common Solution:

For the above problem, this is how a developer would proceed:

  1. Get the GUID of the security role, and hardcode it for checking.
  2. Get all the User roles of the logged in user.
  3. Iterate on all the roles and check if any of the roles from the user roles match the GUID of the “Custom View Only Role”.
  4. If any match, then returns true and based on this perform the required operation – in this case, hide some fields.

This is how the code would look:

function CheckUserRole() {
    // GUID of the custom role that you created.
    var CustomViewOnlyRoleId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";

    // Get all the roles of the Logged in User.
    var currentUserRoles = Xrm.Page.context.getUserRoles();

    for (var i = 0; i < currentUserRoles.length; i++) {
        var userRoleId = currentUserRoles[i];
        if (userRoleId.toLowerCase() == CustomViewOnlyRoleId.toLowerCase()) {
            // Return true if the Role matches
            return true;
        }
    }
    return false;
}

 

 

Issues with the above Solution

  1. This will only work if the D365/ CRM Organization has only root Business Unit and no child business units
  2. It will fail if there are any child BUs and the logged in user is in any of the Child BU and also has the “Custom View Only Role”.

In this case, the function will return false, even though the User had the role

Why this happens:

This happens because, in CRM, a copy of all the roles is created for each BU. So the GUID of all the same role within Different BU will be different.

Alternative Solution:

We can check with Role name instead of GUID, and tweak the above code. But checking with Role names is not a good practice since the role names can be changed in the future.

Better Solution

Since the issue is with copy of the same role for different BU, we can solve this by leveraging the “Parent root role id”

There is a field on the Role entity called Parent Root Role. This stores the reference of the Root role on all the copies of each BU role.

So even though the role ids will not be same, the Parent Root Role Id will be same for all the copies. Below is the code to leverage the parent role id and check if the logged in user has the role using the Role GUID.

You can also find this code in My Github

function CheckUserRole() {
    // GUID of the custom role that you created.
    var CustomViewOnlyRoleId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
    var returnValue = false;

    // Get all the roles of the Logged in User.
    var currentUserRoles = Xrm.Page.context.getUserRoles();

    // Get the Parent roles for each, and then compare.
    GetParentRoles(currentUserRoles, function (result) {
        for (var i = 0; i < result.value.length; i++) {
            if (result.value[i]["_parentrootroleid_value"].toLowerCase() == CustomViewOnlyRoleId.toLowerCase())
                returnValue = true;           
        }
    }, function (error) {
        alert(error);
    }
    );

    return returnValue;

}

function GetParentRoles(roles, successCallback, errorCallback) {
    var fetchXml = '';
    fetchXml += '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">';
    fetchXml += '<entity name="role">';
    fetchXml += '   <attribute name="name" />';
    fetchXml += '   <attribute name="businessunitid" />';
    fetchXml += '   <attribute name="roleid" />';
    fetchXml += '   <attribute name="parentrootroleid" />';
    fetchXml += '   <order attribute="name" descending="false" />';
    fetchXml += '   <filter type="or">';
    for (var cnt = 0; cnt < roles.length; cnt++) {
        fetchXml += '       <condition attribute="roleid" operator="eq" value="{' + roles[cnt] + '}" />';
    }
    fetchXml += '   </filter>';
    fetchXml += '</entity>';
    fetchXml += '</fetch > ';

    MK.WebAPI.Retrieve("roles", null, fetchXml, null, successCallback, errorCallback, true, null, null, false);
}

 

In case of queries or feedback, please comment on the post below.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s