CRM Blog

Hide/Show fields in CRM 4.0 based on Security Role

by Zahara Hirani 05.08.08
There is a great blog by Ronald Lemmen regarding hiding and showing fields based on Security Roles for CRM 3.0 (http://ronaldlemmen.blogspot.com/2006/05/finally-there-show-and-hide-fields.html). Unfortunately, that code does not work for CRM 4.0 as the SystemUser web service is no longer available (or at least I couldn’t find it). So after much digging and fusing some of Ronald’s code, here is what I found.

In CRM 4.0, the “WhoAmI” method can be called using the CRM Service Execute method.
We first create an xmlhttp object and using the “Post” method specifies the request to be handled synchronously.
We then create the request object and using the xmlhttp send method retrieves the response.
The response can be accessed using xmlhttp.responseXML and can be loaded into an XML DOM object (xmlDoc).
The response xml returned contains the system user id and the business unit id associated to the system user.
Once we get the user id, we can use the UserManager web service and use the GetUserRoles method to retrieve all the security roles that exists in CRM.
All the roles that the system user is a part of will have a ‘checked=true’ value.
We then check if the current user has the role we are validating against and based on the result hide/show the certain fields.

Below is the code that would need to be placed in the entity’s OnLoad Event. In our case, I am trying to hide the section with the Estimated Revenue field on an opportunity for all CSR role users:

                  //Based on the role of the user logged in, hide the revenue tab on the opportunity
                  if(currentUserHasRole('Customer Service Representative'))
                  {
                        crmForm.all.estimatedrevenue.parentElement.parentElement.parentElement.style.display='none';
                  }
            }
            catch(e)
            
            {
                  
alert("There was an error with this field\'s customized event\u002e\n\nField\u003a crmForm\n\nEvent\u003a onload\n\nError\u003a " + e.description);
            }
      }
}

function getUserId()
{
      try
      {
            var xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
            xmlhttp.open("POST", "../../mscrmservices/2007/crmservice.asmx", false);
            xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
            xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/Execute");
            var soapBody = "<soap:Body>"+ "<Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>"+ "<Request xsi:type='WhoAmIRequest' />"+ "</Execute></soap:Body>";
            var soapXml = "<soap:Envelope " + "xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' "+ "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "+ "xmlns:xsd='http://www.w3.org/2001/XMLSchema'>";
            soapXml += GenerateAuthenticationHeader();
            soapXml += soapBody;
            soapXml += "</soap:Envelope>";
            xmlhttp.send(soapXml);
            xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async=false;
            xmlDoc.loadXML(xmlhttp.responseXML.xml);
            var userid = xmlDoc.getElementsByTagName("UserId")[0].childNodes[0].nodeValue;
            return userid;
      }
      catch(e)
      {
            return null;
      }
}


function getUserRoles(userId)
{
      try
      {
            var command = new RemoteCommand("UserManager", "GetUserRoles");
            command.SetParameter("userIds", "<guid>" + userId + "</guid>");
            var oResult = command.Execute();
            if (oResult.Success)
            {
                  return oResult.ReturnValue;
            }
      }
      catch(e)
      {
      return null;
      }
}

function userHasRole(userId, roleName)
{
      var hasRole = false;
      result = getUserRoles(userId);
      if (result != null)
      {
            var oXml = new ActiveXObject("Microsoft.XMLDOM");
            oXml.resolveExternals = false;
            oXml.async = false;
            oXml.loadXML(result);
            roleNode = oXml.selectSingleNode("/roles/role[name='" + roleName + "']");
            if (roleNode != null)
            {
                  if (roleNode.selectSingleNode("roleid[@checked='true']") != null)
                  {
                        hasRole = true;
                  }
            }
      }
      return hasRole;
}

function currentUserHasRole(roleName)
{
      userId = getUserId();
      return userHasRole(userId, roleName);
}

function Test()
{
      if(true)
      {
            try
            {
Filed under:

Comments

# PM said on May 30, 2008 04:36 PM:

When I use this code I get the Microsoft general error. Am I supposed to leave some of this code out or replace something?

# PM said on May 30, 2008 05:44 PM:

I got it to work by

changing this:

"localhost/.../crmservice.asmx"

to this:

"/mscrmservices/2007/crmservice.asmx"

My problem now is trying to get the code to only run for a NEW form.

The code is this:

var MyForm = crmForm.FormType;

if (MyForm == 1)

{

}

But, I do not know where to place it within the code.

Any suggestions?

# Zahara Hirani said on June 1, 2008 01:46 PM:

PM,

Did you want the code to only trigger if its a new form? If so, you only want the code to validate on a Create Form Type.

Here is the start piece of your form OnLoad :

var MyForm = crmForm.FormType;

if (MyForm == 1)

{

  //Based on the role of the user logged in, hide the revenue tab on the opportunity

  if(currentUserHasRole('Customer Service Representative'))

  {

     crmForm.all.estimatedrevenue.parentElement.parentElement.parentElement.style.display='none';

  }

}

}

catch(e)            

{....

You can use the rest of the code from the catch.

Hope this help!

Zahara

# Jamie said on June 3, 2008 06:11 PM:

This looks so promising, but I am getting the "Error on page." in IE and it crashes. I am trying to put this code on the Task entity.

I also changed my URL to reflect that of my server:

xmlhttp.open("POST", "crmsvr/.../crmservice.asmx", false);

# Ronny VDS said on June 9, 2008 08:44 AM:

Hiding fields with jscript is not secure.

This way a user can still see the fields by simply printing the form.

You can also use IE Developer to change css styles so to simply show the tab or field again in the page. (or other tools like IE7Pro...)

It is nice to hide some unnecessary fields for the current user but do not use this when it's top secret information.

(Use a custom entity in a iframe instead)

# Shiva said on June 20, 2008 04:36 PM:

Hi Zahara,

I am not much familiar with JavaScript I work in X++ which is simillar to C++ and C#.

What I need to do in CRM 4.0 is I need to hide a custom tab to all the roles except for one role (let's say Role A) if the role "is not equal" to  A then I need to hide the tab .

how do we modify the following line to get that logic.

if(currentUserHasRole('Customer Service Representative')) // not equal to CSR

Also how do we find out the full name of the tab page like the following one

crmForm.all.estimatedrevenue.parentElement.parentElement.parentElement.style.display='none';

summary:

If I wish to hide Tab "T" of form "F" to all the roles except to role "A". what would be the code.

Any help would be greatly appreciated.

Thanks and Regards

# Shiva said on June 23, 2008 12:09 PM:

Hi Zahara,

I found the way to find out the tab ID but when I copied and paste the your code in CRM 4.0  I got some error.

Is that code is good for all forms or just for opportunity.

I need the code for Accounts form.

Any help will be appreciated

Shiva

# SG said on June 24, 2008 10:22 AM:

Hi,

I spent 3 days to make this hiding work in CRM 4.0 but it still did not work. When I add the role check line

(if(currentUserHasRole('Customer Service Representative'))

 {

    crmForm.all.estimatedrevenue.parentElement.parentElement.parentElement.style.display='none';

 }

I get error by the way I have learnt a lot about JavaScript during my last 3  days research.

with best Regards,

SG

# Mark said on December 2, 2008 10:23 AM:

Couldn't get it to work.  

# Danny Varghese said on January 20, 2009 08:40 PM:

Hello,

I was able to get this working, here's what I did:

1.  For the system role in the first condition,I changed it to the role I personally needed to check against.

2.  The biggest issue was in the xmlhttp.open method, after the POST parameter, the url needs to be fully qualified, and not be relative.

The above two fixes should do it!  Good luck!

# Sunil said on April 28, 2009 10:16 AM:

Can we hide views i CRM 4.0 depending upon security roles?

Thanks.

Sunil

# Danny Varghese said on June 4, 2009 10:52 AM:

Hi Sunil,

Yes you can, here's a link to one my colleague at Crowe's site: msdynamicscrm-e.blogspot.com/.../hiding-view-in-crm-40-using-plug-in.html

He hides views using a plugin which you can modify to include security roles.

# jeroen van heel said on June 10, 2009 11:04 AM:

I want this script to work based on business unit not a security role. how can i do that ?

what do i have to change?

# My2Cents said on June 10, 2009 05:20 PM:

Script works great to Hide the fields/tabs as needed.

Danny is correct about the xmlhttp.open method, works best with full URL crmsrv.domain.com/crmservice...

Shiva, If you wish to only show the fields for a certain group enter the Group as Customer Support is in the script but set it to false.

if(currentUserHasRole('Customer Service Representative')== false)

This will not show the fields to any other group.  We use this to hide the Accounting fields so no one can change them easily.  

there might be a way around it, but our sales and CSR people won't look hard enough to find it.

Thanks Zahara,

# Danny Varghese said on June 22, 2009 11:35 PM:

Hi Jeroen,

If you look at the top of the script, we call a method (userhasrole) to see if it returns true.  If it does return true, then hide the section/field.

You'll have to edit that method to retrieve the business unit and not the security role and you should be good!  Good luck!

# Chris said on July 23, 2009 06:30 AM:

Is it possible to achieve the same result using a user's team?

# Hide Fields or Tabs by Role with Javascript | MSCRM Blogger said on September 30, 2009 09:13 AM:

Pingback from  Hide Fields or Tabs by Role with Javascript | MSCRM Blogger

# Danny Varghese said on October 7, 2009 03:16 PM:

Hi Chris,

I don't see why not, you'd just have to retrieve the list of teams, and then compare that to the team the user belongs too.

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Security Check
Please answer the simple math problem below.

(required)