locked
CRM 2011 Hide Form Tab/Section based on Security Role RRS feed

  • Question

  • I have an annoying little jscript issue that I can't figure out, and I'm hoping someone can help with. I've exhausted my searches on the web for a solution.

    I am trying to hide a tab/section of a form based on a user's security role.  The function works when the "true" stream is hit, however, fails on the "false/null" stream. I suspect it is a mishandling of nulls or "undefined" but I simply cannot get this function to take the alternate path.

    Code is posted below. I added some alerts and checks to see if I ever hit the "false/null/undefined" stream, but I never do. I am clearly mishandling this scenario in some way.

    When the user has the "System Administrator" role, I can successful hide/show the tab/section.

    However, when the user does not have the "System Administrator" role, I get the following jscript error:

    Microsoft Dynamics CRM Error Report Contents

    <CrmScriptErrorReport>
      <ReportVersion>1.0</ReportVersion>
      <ScriptErrorDetails>
       <Message>'Xrm.Page.ui.navigation.items.get(...)' is null or not an object</Message>
       <Line>4</Line>
       <URL>/%7B634769324600000000%7D/WebResources/new_hidenavigationtab</URL>
       <PageURL>/userdefined/edit.aspx?etc=2&id=%7b25B8D298-CF14-E111-950C-005056BC2CB4%7d&pagemode=iframe&preloadcache=1341347069786</PageURL>
       <Function>hideTabSection()</Function>
       <CallStack>
        <Function>hideTabSection()</Function>
        <Function>crmForm_window_onload_handler(eventObj,eventArgs)</Function>
        <Function>anonymousanonymous(){crmForm_window_onload_handler(Xrm.Page.ui)}</Function>
       </CallStack>
      </ScriptErrorDetails>
      <ClientInformation>
       <BrowserUserAgent>Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; Tablet PC 2.0; MS-RTC EA 2; Microsoft Outlook 14.0.6117)</BrowserUserAgent>
       <BrowserLanguage>en-us</BrowserLanguage>
       <SystemLanguage>en-us</SystemLanguage>
       <UserLanguage>en-us</UserLanguage>
       <ScreenResolution>1440x900</ScreenResolution>
       <ClientName>Outlook Laptop - Online</ClientName>
       <ClientTime>2012-07-03T16:24:43</ClientTime>
      </ClientInformation>
      <ServerInformation>
        <OrgLanguage>1033</OrgLanguage>
        <OrgCulture>1033</OrgCulture>
        <UserLanguage>1033</UserLanguage>
        <UserCulture>1033</UserCulture>
        <OrgID>{6D8EAC07-6B14-E111-B3C7-005056BC2CB4}</OrgID>
        <UserID>{6D34DE99-0F15-E111-950C-005056BC2CB4}</UserID>
        <CRMVersion>5.0.9690.2243</CRMVersion>
      </ServerInformation>
    </CrmScriptErrorReport>

     

    function HidePeerReviewerSection() {
            if (UserHasRole("System Administrator") == true) {
            Xrm.Page.ui.tabs.get("nav_Preferences").sections.get("nav_PeerReviewer").setVisible(true);
        } else {
                 if ((UserHasRole("System Administrator") == false) || (UserHasRole("System Administrator") == null) || (UserHasRole("System Administrator") == "undefined")) {
    alert(UserHasRole("System Administrator"));
    alert("You really suck");
            Xrm.Page.ui.tabs.get("nav_Preferences").sections.get("nav_PeerReviewer").setVisible(false);
        }
    }
    }
    function UserHasRole(roleName) {
        var serverUrl = Xrm.Page.context.getServerUrl();
        var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";
        var org = Xrm.Page.context.getOrgUniqueName()
        var oDataEndpointUrl = "/" + org + "/XRMServices/2011/OrganizationData.svc/";
        oDataEndpointUrl += "RoleSet?$top=1&$filter=Name eq '" + roleName + "'";
        var service = GetRequestObject();
        if (service != null) {
            service.open("GET", oDataEndpointUrl, false);
            service.setRequestHeader("X-Requested-Width", "XMLHttpRequest");
            service.setRequestHeader("Accept", "application/json, text/javascript, */*");
            service.send(null);
            var requestResults = eval('(' + service.responseText + ')').d;
            if (requestResults != null && requestResults.results.length == 1) {
                var role = requestResults.results[0];
                var id = role.RoleId;
                var currentUserRoles = Xrm.Page.context.getUserRoles();
                for (var i = 0; i < currentUserRoles.length; i++) {
                    var userRole = currentUserRoles[i];
                    if (GuidsAreEqual(userRole, id)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    function GetRequestObject() {
        if (window.XMLHttpRequest) {
            return new window.XMLHttpRequest;
        } else {
            try {
                return new ActiveXObject("MSXML2.XMLHTTP.3.0");
            } catch (ex) {
                return null;
            }
        }
    }
    function GuidsAreEqual(guid1, guid2) {
        var isEqual = false;
        if (guid1 == null || guid2 == null) {
            isEqual = false;
        } else {
            isEqual = guid1.replace(/[{}]/g, "").toLowerCase() == guid2.replace(/[{}]/g, "").toLowerCase();
        }
        return isEqual;
    }

    Tuesday, July 3, 2012 8:25 PM

Answers

  • HI Dave,

                    I wonder if, since you are in CRM 2011, it would be easier for you to create another form without the tab/section you want to hide and assign only the role you want to that form and get rid of all the JavaScript codes.


    Regards,
    Damian Sinay

    • Marked as answer by Dave Maslen Wednesday, July 4, 2012 4:34 AM
    Wednesday, July 4, 2012 2:34 AM
  • Hey guys,

    It is kind of a catch 22 in my opinion.

    On the one hand, with multiple forms, you eliminate the need to write javascript to hide tabs/section. You might eliminate some "unsupported" customizations via this route too. However, then you are  left with what I think is a significant maintenance issue. If the user community suddenly decides to change form layouts (a common occurence in a lot of companies), you need to a) make sure all form layouts get changed, and b) you need to make sure the fields/navigation on each form is the same. Not a huge issue if you have 2 forms, but what if you have 10-20? Personally, I don't like maintaining this kind of structure. It is subject to inconsistencies. To me, it is the equivalent of allowing users to generate their own reports in Excel, vs. using an SSRS structured reporting model/cube. Too much margin for error. 

    On the other hand, for some developers javascript is cumbersome. However, in my opinion, I'd rather write a function once, and if it needs changing, you only have to worry about changing it in one place. The webresource structure in CRM 2011 is designed with this maintenance model in mind. You need only maintain one script per function, and that can be shared across any form within the application.

    It comes down to personal preference, and this is mine.

    That being said, clearly I was tired today. The jcript I posted isn't even the one that is erroring out. It seems my script to hide left hand navigation items is actually the one crapping out, not the tab/section hide script as suggested above.

    The problem was actually with security roles, and field level security. I was missing some read permissions for items I was trying to hide, and field level security was enabled on the boolean field I was checking. I had to give the appropriate teams read access on that field.

    I've marked both as the solution as I think both are valid solutions to the problem posted. It all comes down to your personal preference, and I'm sure we could debate the pros and cons of each until the cows come home.

    Thanks for the help!

    Dave



    • Marked as answer by Dave Maslen Wednesday, July 4, 2012 4:34 AM
    • Edited by Dave Maslen Wednesday, July 4, 2012 4:37 AM
    Wednesday, July 4, 2012 4:34 AM

All replies

  • HI Dave,

                    I wonder if, since you are in CRM 2011, it would be easier for you to create another form without the tab/section you want to hide and assign only the role you want to that form and get rid of all the JavaScript codes.


    Regards,
    Damian Sinay

    • Marked as answer by Dave Maslen Wednesday, July 4, 2012 4:34 AM
    Wednesday, July 4, 2012 2:34 AM
  • I agree with Dave, CRM 2011 allows you to create multiple forms for the same entity. These forms can be have role bases access. Hence it can be configured that a user with role A can only access form A. This should solve your problem and with less amount of efforts.

    -Devashish
    http://thecrmworld.wordpress.com
    http://ebizartisans.com


    Wednesday, July 4, 2012 4:02 AM
  • Hey guys,

    It is kind of a catch 22 in my opinion.

    On the one hand, with multiple forms, you eliminate the need to write javascript to hide tabs/section. You might eliminate some "unsupported" customizations via this route too. However, then you are  left with what I think is a significant maintenance issue. If the user community suddenly decides to change form layouts (a common occurence in a lot of companies), you need to a) make sure all form layouts get changed, and b) you need to make sure the fields/navigation on each form is the same. Not a huge issue if you have 2 forms, but what if you have 10-20? Personally, I don't like maintaining this kind of structure. It is subject to inconsistencies. To me, it is the equivalent of allowing users to generate their own reports in Excel, vs. using an SSRS structured reporting model/cube. Too much margin for error. 

    On the other hand, for some developers javascript is cumbersome. However, in my opinion, I'd rather write a function once, and if it needs changing, you only have to worry about changing it in one place. The webresource structure in CRM 2011 is designed with this maintenance model in mind. You need only maintain one script per function, and that can be shared across any form within the application.

    It comes down to personal preference, and this is mine.

    That being said, clearly I was tired today. The jcript I posted isn't even the one that is erroring out. It seems my script to hide left hand navigation items is actually the one crapping out, not the tab/section hide script as suggested above.

    The problem was actually with security roles, and field level security. I was missing some read permissions for items I was trying to hide, and field level security was enabled on the boolean field I was checking. I had to give the appropriate teams read access on that field.

    I've marked both as the solution as I think both are valid solutions to the problem posted. It all comes down to your personal preference, and I'm sure we could debate the pros and cons of each until the cows come home.

    Thanks for the help!

    Dave



    • Marked as answer by Dave Maslen Wednesday, July 4, 2012 4:34 AM
    • Edited by Dave Maslen Wednesday, July 4, 2012 4:37 AM
    Wednesday, July 4, 2012 4:34 AM