Microsoft Dynamics 365: Combining HTML & JavaScript to restrict entity access

Welcome everyone, hope you like this post and find this information somehow helpful.

In this post we are going to talk about integrating an HTML page in Dynamics 365 CRM as a web resource and combining it with a JavaScript web resource. The business scenario in this case is about modifying an entity page based on condition through JavaScript and displaying a full screen HTML page which shows a custom message to the user. This can apply in different cases depending on the purpose or the business goal that you are trying to achieve, such as putting an entity in beta stage for initial release, modifying entity access based on team membership, etc. Let us take the second case for this task and use the script to check if the current logged-in user is part of a specific/target team, then give access to an entity page or else show a custom message through the HTML page.

I am going to break down the creation process of both web resources in the steps below:

  1. Open Visual Studio Code and create a new HTML file.
  2. Copy and paste the code below then save file:
<!DOCTYPE html>

<html>

<head>

    <title>

    </title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>

        body {

            background-color: #ffffff;

            background-repeat: no-repeat;

            background-position: center;

            background-attachment: fixed;

            text-align: center;

            margin-top: 25%;

        }

        h1 {

            font-family: "Segoe UI", Arial, sans-serif;

            color: #000000;

            background-color: #ffffff;

        }

        p {

            font-family: "Segoe UI", Arial, sans-serif;

            font-size: 16px;

            font-style: normal;

            font-weight: normal;

            color: #000000;

            background-color: #ffffff;

        }

    </style>

</head>

<body>

    <!-- you can edit this part here to show whatever message you would like to on the page -->

    <p><h1>Contacts Beta</h1></p>

    <p>This entity is currently under development and seems you are not part of the team at the moment.</p>

    <p>If you are interested, please reach out to your FISOFT Consulting representative.</p>

</body>

</html>

 This HTML code shows a custom message which is included in the body section and is positioned in the center/middle of the screen.

3. Create a new JavaScript file then copy and paste the code below and save file:

function onLoad() {

    var myTeamId = null;

    var myTeamName = null;

    //the user is not part of the team by default until it is checked

    let isPartOfTeam = false;

    var guid = "[A-z0-9]{8}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{12}";

    var serverUrl = Xrm.Page.context.getClientUrl();

    var userId = Xrm.Page.context.getUserId();

    userId = userId.match(guid);

    userId = userId.input;

    //retrieve teamIds of the teams current user belongs to

    var userTeamsQuery = "TeamMembershipSet?$select=TeamId&$filter=SystemUserId eq guid'" + userId + "'";

    var userTeams = makeRequest(userTeamsQuery);

    var teamQuery = null;

    var teams = null;

    if (userTeams !== null) {

        for (var i = 0; i < userTeams.length; i++) {

            userTeams[i] = userTeams[i].TeamId;

            var teamId = "{" + userTeams[i] + "}";

            //retrieve name and teamIds of the teams via given teamId that we already have above

            teamQuery = "TeamSet?$select=Name, TeamId&$filter=TeamId eq guid'" + teamId + "'";

            teams = makeRequest(teamQuery);

            myTeamId = teamId;

            if (teams !== null && teams.length > 0) {

                myTeamName = teams[0].Name;

                //valuating the isPartOfTeam variable as true if user is part of target team

                if (myTeamName == "Team 1") {

                    isPartOfTeam = true;

                    break;
                }
            }
        }
        //condition to check if user is not part of target team and opening the HTML web resource page

        if (isPartOfTeam == false) {

            var pageParameters = {

                pageType: "webresource", //the HTML page is a web resource type in this case

                webresourceName: "fisoft_htmlPage", //logical name of the HTML web resource you would like to open

            };
            var navigationOptions = {
                target: 1, //value 1 to open the targeted web resource in fullscreen
            };

            //Xrm method that executes the web resource by taking as parameters the variables assigned above

            Xrm.Navigation.navigateTo(pageParameters, navigationOptions);
        }
    }
}

function getRequestObject() {

    if (window.XMLHttpRequest) {

        return new window.XMLHttpRequest;
    } else {
        try {
            return new ActiveXObject("MSXML2.XMLHTTP.3.0");
        } catch (ex) {
            return null;
        }
    }
}
function makeRequest(query) {

    var serverUrl = Xrm.Page.context.getClientUrl();

    var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";

    oDataEndpointUrl += query;

    var service = getRequestObject();

    if (service != null) {

        service.open("GET", oDataEndpointUrl, false);

        service.setRequestHeader("X-Requested-With", "XMLHttpRequest");

        service.setRequestHeader("Accept", "application/json, text/javascript, */*");

        service.send(null);

        var retrieved = JSON.parse(service.responseText).d;

        var results = new Array();

        for (var i = 0; i < retrieved.results.length; i++) {

            results.push(retrieved.results[i]);
        }
        return results;
    }
    return null;
}

This script consists of onLoad, getRequestObject and makeRequest functions. What it basically does is that retrieves the teams in which the current user is a part of and then based on condition it will execute or not the HTML web resource created in the previous step.

I will get to this in more detail for better understanding by breaking down the onLoad() function of this script:

Variable “isPartOfTeam” is false by default, because it is convenient to keep it that way until it is checked. The variable “userTeamsQuery” stores a query which is executed by makeRequest() function. It filters teams by comparing the system user ID and the current user ID, so it extracts only the teams in which is a member of.

Then there is a for loop which retrieves team IDs and the name of each team that got filtered, then a nested if condition where is stated the name of the target team:

//valuating the isPartOfTeam variable as true if user is part of target team
                if (myTeamName == "Team 1") {
                    isPartOfTeam = true;
                    break;
                }
Team 1 is the target team in this case and we want to allow access to the entity page only to users who are part of this team. Next is the main condition of this web resource’s purpose, because it checks if the current user is part of our targeted team.

The condition I am talking about is:

//condition to check if user is not part of target team and opening the HTML web resource page
        if (isPartOfTeam == false) {

            var pageParameters = {
                pageType: "webresource", //the HTML page is a web resource type in this case
                webresourceName: "fisoft_htmlPage", //logical name of the HTML web resource you would like to open
            };
            var navigationOptions = {
                target: 1, //value 1 to open the targeted web resource in fullscreen
            };
            //Xrm method that executes the web resource by taking as parameters the variables assigned above
            Xrm.Navigation.navigateTo(pageParameters, navigationOptions);
        }
As I mentioned above, the “isPartOfTeam” variable is false by default but it can change after checking the user teams and if the user is part of our target team this variable becomes true. If this variable remains false that means the user is not part of the targeted team, so the HTML web resource is executed by using Xrm.Navigation.navigateTo() function. This function takes two parameters which state the page parameters and navigation options. Page parameters include the variables “pageType” (which in this case has value ‘webresource’, because that is how we would want it to execute like) and “webresourceName” (which carry the same name as the logical name of the uploaded HTML web resource that you would like to open). Navigation options include the variable “target” which is responsible for opening the HTML page in full screen.
Keep in mind: variable “webresourceName” must have the same name as the uploaded HTML file in the solution you are working on.
Now let’s get to the CRM part where we upload the web resources and put them to use.
If you are not familiar with Dynamics 365 CRM solutions or entities yet:
1. First off, you would like to navigate to Settings > Advanced Settings > Solutions > Choose the solution where the entity you will work on is located. Then navigate to New > Web Resource as illustrated below:
2. Create a new web resource as illustrated below:
This is the JavaScript web resource which I have named as ‘fisoft_fullPageHtml’ and that is step 1. Step 2 is the display name of the web resource, step 3 you choose the type of it and in this case it is a script. Step 4 is about clicking on text editor button and pasting the JavaScript code inside. After that step 5 and 6 is about saving the web resource first then publishing it.
3. Repeat the same steps for the HTML web resource, but the difference this time is that the type that you will choose is webpage and after clicking on text editor paste the HTML code into Source tab (just in case you get confused). Remember to name this web resource same as you have named it inside the JavaScript code where you assign it to the “webresourceName” variable. Check the illustration below:
4. After saving and publishing both of the created web resources, navigate to Entities > Select the entity > Forms > Main Form > Form Properties.
The page should look like this:
Then click on Add and search by the logical name of the created JavaScript web resource and then click Add as illustrated below:
Then the page should look like this:
5. Make sure the parameters look like this:
Then click on Add button where the third arrow points at, afterwards you choose the JavaScript resource from the library and then enter the function name, then make sure the Enabled checkbox is checked, just like illustrated below:
6. Save and publish the form:
Now we get to the part where we test the web resources a new team. I have created a team named ‘Team 1’ for this task and have not assigned any user to it just so I can trigger the JavaScript web resource onLoad() function.
If you are not familiar with Dynamics 365 CRM teams yet:
1. Navigate to the Dynamics 365 app page where you can access your entity page:
2. The JavaScript web resource is called on the form of my Contacts entity as I described through the steps previously mentioned, so when I will click on New button to create a record, the HTML page will be prompted by the script, because the user I am currently right now is not part of ‘Team 1’ that I targeted in the script:
The goal is now achieved as I cannot access the entity page and cannot create/edit records, because I am a user who is not part of a specific team. This way we can manipulate access by showing a custom HTML page, integrate HTML and JavaScript web resources in Dynamics 365 CRM, combine HTML and JavaScript web resources together to fulfill a business request/goal.