How to ensure two arrays are of the same type and works with ArrayUtil.diff()?

Ted Norlander
ServiceNow Employee
ServiceNow Employee

Hi Experts!

I'm struggling with ArrayUtil.diff() to produce the expected results.

When testing it using 'manual edited' arrays it works fine but as soon as I try to populate the arrays from different data sources I get into trouble to get the arrays in the desired format...and I don't have skills enough to convert/arrange the arrays properly, that's where I need your help!

 

The use-case behind this is that I need to compare a list of required groups with the current users group memberships.

 

I run this in a display Business Rule to decide whether to decrypt data or not in a script.

 

My current example and the results below:

 

(function executeRule(current, previous /*null when async*/) {

// Check if user should see encrypted data
// User must be member of all groups listed in MultiSecClass!

var arrUtil = new global.ArrayUtil();

//Testing - this works!
//var au = new global.ArrayUtil();
//var a1 = ["c0887618871e4a90d4d731d80cbb3581","e60a7e98871e4a90d4d731d80cbb3527","791aba98871e4a90d4d731d80cbb35a2","cfcbad03d711110050f5edcb9e61038f"];
//var a2 = ["791aba98871e4a90d4d731d80cbb35a2","e60a7e98871e4a90d4d731d80cbb3527","c0887618871e4a90d4d731d80cbb3581"];
//var grpdiff = au.diff(a1, a2);

// Convert users groups to array
var arrmygrps = gs.getUser().getMyGroups().toArray();
gs.addInfoMessage("arrmygrps: " + Object.prototype.toString.call(arrmygrps) + " " + JSON.stringify(arrmygrps));

// Convert current required Security Class groups to array
var mscarr = current.u_multisecclass.split(',');
gs.addInfoMessage("mscarr: " + Object.prototype.toString.call(mscarr) + " " + JSON.stringify(mscarr));

// Check if user have required Security Class groups
var grpdiff = arrUtil.diff(mscarr, arrmygrps);
gs.addInfoMessage("Group Diff: " + grpdiff);

// If user has required Security Class groups, decrypt data into read-only fields
//if (grpdiff<1) {
// var gc = global.GlideCryptoModule.getModule('global.pocsecurityclasses');
// Comment out when working
// gs.addInfoMessage("Decryption script accessed");
// gs.addInfoMessage("Text Field 1: " + gc.decryptData(current.u_text_field_1));

// current.u_calc_field = gc.decryptData(current.u_text_field_1);

//}
})(current, previous);
 

 

TedNorlander_0-1717406943290.png

As you can see the array objects have different formats. I have played around with various methods trying to get them into the same format to make it work.

Sometimes it looks like the same format but then apparently one of the objects isn't an array and the comparison fails.

 

Any ideas on how to solve this is appreciated.

 

Best regards

Ted

1 ACCEPTED SOLUTION

Kieran Anson
Kilo Patron

Hey Ted,

You've come across the joy of a platform that is both Java and Javascript, and depending on the API functions you're using you receive different data payloads.

(function executeRule(current, previous /*null when async*/) {

	var currentUserGroups = global.j2js(gs.getUser().getMyGroups());
	//j2js turns a Java array into a JavaScript one
	var allowedGroups = current.getValue('u_multisecclass').split(',');
	var au = new ArrayUtil();

	var diff = au.diff(allowedGroups, currentUserGroups);
	//etc

	//alternative method
	//Will test each element until it finds one that matches
	//Saves potentially parsing the entire array when we only need
	//one record to match
	var isMember = allowedGroups.some(function(groupName){
		return gs.getUser().isMemberOf(groupName)
	});

})(current, previous);

 

View solution in original post

4 REPLIES 4

Kieran Anson
Kilo Patron

Hey Ted,

You've come across the joy of a platform that is both Java and Javascript, and depending on the API functions you're using you receive different data payloads.

(function executeRule(current, previous /*null when async*/) {

	var currentUserGroups = global.j2js(gs.getUser().getMyGroups());
	//j2js turns a Java array into a JavaScript one
	var allowedGroups = current.getValue('u_multisecclass').split(',');
	var au = new ArrayUtil();

	var diff = au.diff(allowedGroups, currentUserGroups);
	//etc

	//alternative method
	//Will test each element until it finds one that matches
	//Saves potentially parsing the entire array when we only need
	//one record to match
	var isMember = allowedGroups.some(function(groupName){
		return gs.getUser().isMemberOf(groupName)
	});

})(current, previous);

 

I am today old to know of j2js

Ted Norlander
ServiceNow Employee
ServiceNow Employee

Thanks Kieran!

The Java to JavaScript conversion made the trick.

Now I can move on in my life...

 

😉

Ted Norlander
ServiceNow Employee
ServiceNow Employee

Final version of the script (display Business Rule) after corrections according to Kieran's suggestions:

 

 

 

 

(function executeRule(current, previous /*null when async*/) {

	// Check if user should see encrypted data
	// User must be member of all groups listed in MultiSecClass!

	var arrUtil = new global.ArrayUtil();

	// Convert users groups to array
	var arrmygrps = global.j2js(gs.getUser().getMyGroups());
	//gs.addInfoMessage("arrmygrps: " + Object.prototype.toString.call(arrmygrps) + " " + JSON.stringify(arrmygrps));

	// Convert current required Security Class groups to array
	var mscarr = current.u_multisecclass.split(',');
	//gs.addInfoMessage("mscarr: " + Object.prototype.toString.call(mscarr) + " " + JSON.stringify(mscarr));
	
	// Check if user have required Security Class groups 
	var grpdiff = arrUtil.diff(mscarr, arrmygrps);
	//gs.addInfoMessage("Group Diff: " + grpdiff);
	
	// If user has required Security Class groups, decrypt data into read-only fields
	if (grpdiff<1) {
		var gc = global.GlideCryptoModule.getModule('global.pocsecurityclasses');
		// Comment out when working
		//gs.addInfoMessage("Decryption script accessed");
		//gs.addInfoMessage("Text Field 1: " + gc.decryptData(current.u_text_field_1));
		
		current.u_calc_field = gc.decryptData(current.u_text_field_1);
	}
})(current, previous);

 

 

 

This code assesses required groups vs user groups.
My intention is to populate the 'required groups' using other Business Rules so that the whole process becomes dynamic, the current use-case is that if an incident has Affected CIs/Impacted Services with Security Classifications that requires membership in corresponding groups.
The current use-cases requires membership in more then one group hence the array-comparison.
 
This helped me a lot and will be very useful in more contexts then the one described here.