Hide Fields or Tabs by Role with Javascript

By Carlton Colter - Last updated: Wednesday, September 30, 2009 - Save & Share - 13 Comments

Here are a set of methods to assist in hiding tabs or sections based on role, it is a modified version of Jimmy Wang’s version.

First, we need a set of functions to facilitate our our process. We need to get the roles of the current user, GetCurrentUserRoles. Then we need to see if the user has the role, UserHasRole. Finally we can hide the fields (HideFieldByRole) or tabs (HideTabByRole).

GetCurrentUserRoles
The first thing we need to do is get a list of roles according to the current user. There are a couple of different ways to do this. You could use the RemoteCommand to get the current user and then their roles, a blog post by Zahara Hirani on Hide Show Fields in CRM 4 based on security role outlines this. However, I do not want to make multiple request for the same information. I want to get the roles for the current user in one line. Below shows the GetCurrentUserRoles that implements a RetrieveMultiple query to get the names of the roles that a user has in one request.

function GetCurrentUserRoles()
{
  var xml = "" +
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
    "<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\">" +
    GenerateAuthenticationHeader() +
    " <soap:Body>" +
    " <RetrieveMultiple xmlns=\"" +
    "http://schemas.microsoft.com/crm/2007/WebServices\">" +
    " <query xmlns:q1=\"" +
    "http://schemas.microsoft.com/crm/2006/Query" +
    "\" xsi:type=\"q1:QueryExpression\">" +
    " <q1:EntityName>role</q1:EntityName>" +
    " <q1:ColumnSet xsi:type=\"q1:ColumnSet\">" +
    " <q1:Attributes>" +
    " <q1:Attribute>name</q1:Attribute>" +
    " </q1:Attributes>" +
    " </q1:ColumnSet>" +
    " <q1:Distinct>false</q1:Distinct>" +
    " <q1:LinkEntities>" +
    " <q1:LinkEntity>" +
    " <q1:LinkFromAttributeName>roleid</q1:LinkFromAttributeName>" +
    " <q1:LinkFromEntityName>role</q1:LinkFromEntityName>" +
    " <q1:LinkToEntityName>systemuserroles</q1:LinkToEntityName>" +
    " <q1:LinkToAttributeName>roleid</q1:LinkToAttributeName>" +
    " <q1:JoinOperator>Inner</q1:JoinOperator>" +
    " <q1:LinkEntities>" +
    " <q1:LinkEntity>" +
    " <q1:LinkFromAttributeName>systemuserid</q1:LinkFromAttributeName>" +
    " <q1:LinkFromEntityName>systemuserroles</q1:LinkFromEntityName>" +
    " <q1:LinkToEntityName>systemuser</q1:LinkToEntityName>" +
    " <q1:LinkToAttributeName>systemuserid</q1:LinkToAttributeName>" +
    " <q1:JoinOperator>Inner</q1:JoinOperator>" +
    " <q1:LinkCriteria>" +
    " <q1:FilterOperator>And</q1:FilterOperator>" +
    " <q1:Conditions>" +
    " <q1:Condition>" +
    " <q1:AttributeName>systemuserid</q1:AttributeName>" +
    " <q1:Operator>EqualUserId</q1:Operator>" +
    " </q1:Condition>" +
    " </q1:Conditions>" +
    " </q1:LinkCriteria>" +
    " </q1:LinkEntity>" +
    " </q1:LinkEntities>" +
    " </q1:LinkEntity>" +
    " </q1:LinkEntities>" +
    " </query>" +
    " </RetrieveMultiple>" +
    " </soap:Body>" +
    "</soap:Envelope>" +
    "";  

  var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");  

  xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
  xmlHttpRequest.setRequestHeader("SOAPAction",
    " http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
  xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
  xmlHttpRequest.send(xml);  

  var resultXml = xmlHttpRequest.responseXML;
  return(resultXml);
}

The next method is a simple method for searching the XML result from GetCurrentUserRoles. By passing it the roles you are looking for and the roles the user has, it will determine if there is a match. The roles it is passed is separated by a pipe (|).

function UserHasRole(roleNames, rolesXML)
{
  // split roleNames on pipe
  var matchon = roleNames.split('|');

  if(rolesXML != null)
  {
    //select the node text
    var roles = rolesXML.selectNodes("//BusinessEntity/q1:name");
    if(roles != null)
    {
      for( i = 0; i < roles.length; i++)
      {
        for (j = 0; j < matchon.length; j++)
	{
	  // If there is a match, return true, found
	  if (roles[i].text == matchon[j]) return true;
        }
      }
    }
  }
  //otherwise return false
  return false;
}

Finally, we can now implement helper methods to allow the hiding of a tab or a field if a user DOES NOT have a specific role.

function HideTabByRole(role, roles, tabnumber)
// Tab number starts on 0
{
  var tab = document.getElementById('tab'+tabnumber+'Tab');
  var usrRole = UserHasRole(role, roles);
  if(!usrRole)
  {
    tab.style.display = "none";
  }
}

function HideFieldByRole(role, roles, field,cfield,dfield)
{
  var usrRole = UserHasRole(role, roles);
  if(!usrRole)
  {
    field.style.visibility = 'hidden';
    field.style.position = 'absolute';
    cfield.style.visibility = 'hidden';
    cfield.style.position = 'absolute';
    dfield.visibility = 'hidden';
    dfield.style.position = 'absolute';
  }
}

To implement this process, all you have to do is put every piece of code in this article inside your onload with the following customized for your situation.

var UserRoles = GetCurrentUserRoles();

HideTabByRole('Account Managers|SystemAdministrators', UserRoles, 3);

HideFieldByRole('Account Managers', UserRoles,
                crmForm.all.parentcustomerid,
                crmForm.all.parentcustomerid_c,
                crmForm.all.parentcustomerid_d);

If you have any questions of problems implementing this in your environment, please let me know, and I’ll do my best to help you get it working

Posted in Scripts • Tags: , , , , , , , , , Top Of Page

13 Responses to “Hide Fields or Tabs by Role with Javascript”

Pingback from Get Current User’s Business Unit for Hiding Fields | MSCRM Blogger
Time September 30, 2009 at 9:04 am

[...] Hide Fields or Tabs by Role with Javascript [...]

Comment from sheri
Time October 9, 2009 at 11:02 am

Hello,

Thanks for the code – this is working well for me for the fields, but not for the tabs, and I can’t see why. Code is exact as yours, my customizations are:

HideTabByRole(‘Engineer|SystemAdministrator’, UserRoles, tab2Tab);

HideFieldByRole(‘M2M Engineer|System Administrator’, UserRoles,
crmForm.all.m_rmanumber,
crmForm.all.m_rmanumber_c,
crmForm.all.m_rmanumber_d);

Field is hidden to all except Engineer/Admin, but tab is hidden for everyone. I can’t figure out what I am missing?

Cheers,
s.

Comment from sheri
Time October 9, 2009 at 11:04 am

Sorry, to clarify, the roles are actually the same in the code, though they look different in my post.

Comment from Carlton Colter
Time October 10, 2009 at 8:50 am

I will look into that and see why. I know in my CRM lab, the tabs have specific identifiers like tab1Tab, etc.
If you have the IEDeveloper toolbar I believe you can find an item by selecting it and get the id. Either way, I will look into it further, double-check my code, and post a way to identify the tab so that you can get this working.

Comment from Carlton Colter
Time October 10, 2009 at 12:45 pm

Ok… I checked it again and they go from tab0Tab and up. The first tab is tab0Tab and the next tab is tab1Tab and so on.

You will need to do something like:

var tab0Tab = document.getElementById(‘tab0Tab’);

before using it with the old script, or you can copy the new script above, since I updated the page.

Comment from Martin
Time November 3, 2009 at 5:07 am

Hello,

can you tell me exactly where I have to customize the code if I want to hide fields and can I delete the code of the funktion hideTabbyRole?

My fields are

crmForm.all.field1,
crmForm.all.field2,

and the allowed Role is called “special”.

And another question:
Are there differences between the different languages?
The MS CRM System I use is a german one.

Regards

Martin

Comment from Carlton Colter
Time November 3, 2009 at 7:57 am

To implement this you would need to copy the following functions:

Then to implement you would use the following:


var myRoles = GetCurrentUserRoles();

HideFieldByRole('special', myRoles, crmForm.all.field1, crmForm.all.field1_c, crmForm.all.field1_d);
HideFieldByRole('special', myRoles, crmForm.all.field2, crmForm.all.field2_c, crmForm.all.field2_d);

Comment from Carlton Colter
Time November 3, 2009 at 8:00 am

I don’t believe there is a difference in the CRM languages for something like this. While I have not written code on other systems, people in the Netherlands and Thailand have used some of the code I have written and they haven’t alerted me to any problems with the language.

Comment from Martin
Time November 3, 2009 at 9:41 am

Thank you
this code works well now.

My problem was that I only wrote the following:

HideFieldByRole(’special’, myRoles, crmForm.all.field1)
It’s very nice that customizing of this script is not as hard as others.

regards

Comment from René
Time August 9, 2010 at 8:50 am

Hello,

I am trying to implement this code but I am getting no result. If I pste the first code in, no problem, then User has role – the code will be aborded. Do I have to change anything in the code USERHASROLE?
I am new at this, so I hope that you can and will help me.

Thanks,
René

Comment from Marco
Time August 9, 2010 at 6:34 pm

I need to see which user has privileges over an iFrame, is it possible with something related to this approach?

Comment from Carlton Colter
Time August 11, 2010 at 11:54 am

GetCurrentUserRoles and UserHasRole can work within an iFrame, it uses the webservice to query CRM.

Comment from Carlton Colter
Time August 11, 2010 at 11:57 am

René, Are you getting an error somewhere? The UserHasRole returns true if the user has the role, so if you are trying to hide something if they are not a system administrator then you need to reverse it using the not operator (!).

Write a comment