Skip to main content

Notifications

Announcements

No record found.

Microsoft Dynamics CRM (Archived)

EnableRule is not working properly on ribbon

Posted on by Microsoft Employee

Hi,

We have a ribbon where we load a JS function to check whether the logged user has any of the allowed roles to "see" the "Qualify" button on a lead; theoretically, because is not working.

For what I was able to see, the Javascript function is not reactive and the "Qualify" button loads before the function ends. Therefore the function does not hide the button.

This is the function:

function CheckSecurityRoles() {
	// Definicion de variables
	// Se leen los argumentos pasados como roles permitidos
	var allowedRoles = arguments;
	// Se lee el ID de los roles del usuario ingresado
	var loggedUserRoles = Xrm.Page.context.userSettings.securityRoles;
	
	// Se accede a la API de Xrm para obtener todos los roles del sistema
	Xrm.WebApi.retrieveMultipleRecords("roles", "?$select=name,roleid").then( 
		function success(result) {
			// Definicion de variables
			var userHasAccess = false;
			
			// Se verifican los roles devueltos y los roles permitidos
			if(result.entities.length > 0 && allowedRoles.length > 0) {
				// Definicion de variables
				var totalRoles = result.entities;
				var existingRoles = compareRolesNames(allowedRoles, totalRoles);
				
				// Se verifican los roles existentes devueltos
				if(existingRoles.length > 0) {
					userHasAccess = compareRolesID(loggedUserRoles, existingRoles);					
				} // end-if
			} // end-if
			console.log("CheckSecurityRoles() devolvió (OK): " + userHasAccess);
		// Devuelve el acceso
		return userHasAccess;
	}, // end-function
	// En caso de error en la ejecución de la API
	function (error) {
		console.log("CheckSecurityRoles() devolvió (ERROR): " + error.message);
		return false;
	});
}

function compareRolesNames(firstRoles, secondRoles) {
	// Declaración de variables
	var resultingRoles = new Array();

	// Se itera el array de roles pasados como primer argumento
	for(var firstRolesIndex = 0; firstRolesIndex < firstRoles.length; firstRolesIndex++) {
		// Se itera el array de roles pasados como segundo argumento
		for(var secondRolesIndex = 0; secondRolesIndex < secondRoles.length; secondRolesIndex++) {
			if(firstRoles[firstRolesIndex].toLowerCase() === secondRoles[secondRolesIndex].name.toLowerCase()) {
				// Se agrega al array de roles resultantes las coincidencias entre los roles del primero y segundo parámetro
				resultingRoles.push(secondRoles[secondRolesIndex]);
			} // end-if
		} // end-for
	} // end-for
	
	// Devolución de roles comparados
	return resultingRoles;
}

function compareRolesID(firstRoles, secondRoles) {
	// Declaración de variables
	var result = false;
	
	// Se iteran los roles del array pasado como primer parámetro
	for(var firstRolesIndex = 0; firstRolesIndex < firstRoles.length; firstRolesIndex++) {
		// Se iteran los roles del array pasado como segundo parámetro
		for(var secondRolesIndex = 0; secondRolesIndex < secondRoles.length; secondRolesIndex++) {
			// Se comparan los roles de cada array
			if(firstRoles[firstRolesIndex] === secondRoles[secondRolesIndex].roleid) {
				// Se otorga el acceso
				result = true;
			} //end-if
		} //end-for
	} // end-for
	
	// Se devuelve el acceso
	return result;
}


I was reading that Xrm class hasn't an asynchronous property.

Note: I realized the function works since I debugged the entire function with `console.log(userHasAccess)`, any suggestions to make the function reactive or make it work?

Thanks in advance.

*This post is locked for comments

  • Suggested answer
    LaszloPenzes Profile Picture
    LaszloPenzes on at
    RE: EnableRule is not working properly on ribbon

    I know this is an old thread and the problem might have been solved in the meantime.

    Just in case anyone finds it, the proper solution is to init the button it in two rounds:

    • First run the async query and return false.
    • When the query succeeded, store the result in a global variable and call context.ui.refreshRibbon(). When the ribbon is being refreshed, return the value stored in the global variable.
  • Verified answer
    Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: EnableRule is not working properly on ribbon

    It worked when we changed to a synchronic script (xhr.open( METHOD, URL, SYNC=false )

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: EnableRule is not working properly on ribbon

    Just in case, I found this. It may be useful. 

    When loading the page:

    I am able to see the Response tab:

    I don't see the returned data type as JSON.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: EnableRule is not working properly on ribbon

    Hi Goutam,

    I've tried everything and is still not working. This is my script:

    function checkSecurityRoles() {
    	var access = false,
    		allowed = arguments,
    		logged = Xrm.Page.context.userSettings.securityRoles;
    		
    	if(allowed.length < 1 || logged.length < 1) {
    		return access;
    	}
    	
    	var clientUrl = Xrm.Page.context.getClientUrl();
    	var xhr = new XMLHttpRequest();
    	xhr.open( "GET", encodeURI(clientUrl + "/api/data/v9.0/roles?$select=name,roleid"), false);
    	xhr.setRequestHeader("Accept", "application/json");
        xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
        xhr.setRequestHeader("OData-MaxVersion", "4.0");
        xhr.setRequestHeader("OData-Version", "4.0");
    	xhr.onreadystatechange = function() {
    		if(this.readyState == 4) {
    			xhr.onreadystatechange = null;
    			if(this.status == 200) {
    				var jsonResponse = JSON.parse(this.response);
    				var all = jsonResponse.value.map( function(item) {
    					return { roleid: item.roleid, name: item.name }
    				});
    				var existing = new Array();
    				
    				allowed.forEach( function(arole) {
    					var match = all.find( function(role) {
    						return role.name.toLowerCase() === arole.toLowerCase();
    					});
    					existing.push(match);
    				});
    				
    				if(existing.length < 1) {
    					return access;
    				}
    				
    				var matches = new Array();
    				existing.forEach( function(erole) {
    					var match = logged.find( function(lrole) {
    						return erole.roleid === lrole;
    					});
    					matches.push(match);
    				});
    				
    				if(matches.length > 0) {
    					access = true;
    				}
    				
    			} else {
    				var error = JSON.parse(this.response);
    				console.log('API respondio Error: ' + error.message);
    			}
    		}
    	};
    	xhr.send();
    	
    	return access;
    }


    I am not sure how to proceed in order to make this work. If I just write "console.log('something here');" inside the function it works okay, but if I write the previous code, it doesn't.

    Just for testing purposes I ran the previous code without the function specifying some roles manually emulating arguments and it seems to work great. But, in the function the CRM ignores completely this function.

    How should I proceed?

  • gdas Profile Picture
    gdas 50,085 on at
    RE: EnableRule is not working properly on ribbon

    Hi Martin,

    You can also do synchronous  Web API  call using XMLHttpRequest. Using synchronous call function  will wait to complete execution until  get the final result true/false.

    download the CRMRestBuilder and prepare your query and make sure you are doing false in below line

     var req = new XMLHttpRequest();

    req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v9.0/" + Query, false);

  • Suggested answer
    a33ik Profile Picture
    a33ik 84,323 Most Valuable Professional on at
    RE: EnableRule is not working properly on ribbon

    Hello,

    Xrm.WebApi calls are done in async manner so userHasAccess returned earlier then it is changed in callback. To resolve it you will have to do calls in sync way using old-style approach that we used before Xrm.Webapi was introduced.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: EnableRule is not working properly on ribbon

    Goutam, thanks for answering, but it does not work.

    I think this is because userHasAccess is being returned before the AJAX call ends.

  • Suggested answer
    gdas Profile Picture
    gdas 50,085 on at
    RE: EnableRule is not working properly on ribbon

    Hi Martin ,

    Try with this - 

    function CheckSecurityRoles() {
        var userHasAccess = false;
        // Definicion de variables
        // Se leen los argumentos pasados como roles permitidos
        var allowedRoles = arguments;
        // Se lee el ID de los roles del usuario ingresado
        var loggedUserRoles = Xrm.Page.context.userSettings.securityRoles;
    	
        // Se accede a la API de Xrm para obtener todos los roles del sistema
        Xrm.WebApi.retrieveMultipleRecords("roles", "?$select=name,roleid").then( 
    		function success(result) {
    		    // Definicion de variables
    		     userHasAccess = false;
    			
    		    // Se verifican los roles devueltos y los roles permitidos
    		    if(result.entities.length > 0 && allowedRoles.length > 0) {
    		        // Definicion de variables
    		        var totalRoles = result.entities;
    		        var existingRoles = compareRolesNames(allowedRoles, totalRoles);
    				
    		        // Se verifican los roles existentes devueltos
    		        if(existingRoles.length > 0) {
    		            userHasAccess = compareRolesID(loggedUserRoles, existingRoles);					
    		        } // end-if
    		    } // end-if
    		    console.log("CheckSecurityRoles() devolvió (OK): " + userHasAccess);
    		    // Devuelve el acceso
    		   
    		}, // end-function
    	// En caso de error en la ejecución de la API
    	function (error) {
    	    console.log("CheckSecurityRoles() devolvió (ERROR): " + error.message);
    	   // return false;
    	});
        return userHasAccess;
    }


    You need to do synchronous call using web api if its does not work and set the value under success and return the true or false at the end.

  • Community Member Profile Picture
    Community Member Microsoft Employee on at
    RE: EnableRule is not working properly on ribbon

    I read Javascript reactive programming does not use loops. I'll try to use a "each" to iterate the data.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,269 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,198 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans
Liquid error: parsing "/blogs/post/?postid=%27nvOpzp;%20AND%201=1%20OR%20(%3C%27%22%3EiKO))," - Too many )'s.