26 Jul’17

Dynamics 365, EnterpriseCRM 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.

Written by

Someswara Siripuram

CRM Team Leader

Leave a Reply

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

Time limit is exhausted. Please reload the CAPTCHA.

Want to streamline your business processes?

  • This field is for validation purposes and should be left unchanged.

Recent Articles

  • Design Views in App Designer – D365

    11 April’ 2018

    Introduction: Create and edit public or system views by using the app designer Description: Dynamics 365 sales app des...

    Read more
  • Call Management in D365 Field Service

    10 April’ 2018

    Introduction: This blog provides a solution to requirement of Client for Call Management in D365 Field Service. Scenari...

    Read more
  • Fetch Hierarchical data for Product Category in Dynamics 365 Operations

    10 April’ 2018

    Introduction: In this blog article, we will see how we can fetch hierarchical data using X++. How to fetch? We will ta...

    Read more
  • PowerBI April 2018 Update: Combo Chart Line Formatting

    10 April’ 2018

    Introduction: PowerBI introduced the feature to format line styles and legends for line charts a while ago. However, th...

    Read more
  • Power BI April 2018 Update: Q&A Explorer

    10 April’ 2018

    Introduction: In this blog we will explore some of the new features added to Power BI. Power BI has upgraded its Q&...

    Read more