web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Microsoft Dynamics CRM (Archived)

EnableRule is not working properly on ribbon

(0) ShareShare
ReportReport
Posted on by

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

I have the same question (0)
  • Community Member Profile Picture
    on at

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

  • Suggested answer
    gdas Profile Picture
    50,091 Moderator on at

    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
    on at

    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
    a33ik Profile Picture
    84,331 Most Valuable Professional on at

    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.

  • gdas Profile Picture
    50,091 Moderator on at

    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);

  • Community Member Profile Picture
    on at

    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?

  • Community Member Profile Picture
    on at

    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.

  • Verified answer
    Community Member Profile Picture
    on at

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

  • Suggested answer
    LaszloPenzes Profile Picture
    on at

    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.

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

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Congratulations to our 2025 Community Spotlights

Thanks to all of our 2025 Community Spotlight stars!

Leaderboard > 🔒一 Microsoft Dynamics CRM (Archived)

#1
JS-09031509-0 Profile Picture

JS-09031509-0 3

#2
AS-17030037-0 Profile Picture

AS-17030037-0 2

#2
Mark Eckert Profile Picture

Mark Eckert 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans