ACL calling Script Include is erroring in scoped application

Sue Frost
Giga Guru

I am making a copy of a global application into a scoped application. I've reached the ACLs.

This ACL seems to be returning the correct value but is not allowing the change to be saved and is throwing a log error.

 

ACL:

find_real_file.png

ACL Script:

answer = getAnswer();

gs.info("checkValidAssign Point 99 - answer - " + answer);

function getAnswer(){

	var curUser = gs.getUserID();
	var myUserObject = gs.getUser();
	if(myUserObject.hasRole('Case - Take Ownership - All')){
		return true;
	}
//	var func = new x_enig_commcase.CommercialCaseUtils();
	var func = new global.caseManagementUtils();
	var assign = func.getValidAssign();
	
	gs.info("checkValidAssign Point 1 - assign - " + assign);
	
	if(assign && !current.assigned_to.nil()){
		
		gs.info("checkValidAssign - Point 2");
		return true;
	}
	
	gs.info("checkValidAssign - Point 3.1 - current.sys_id = " + current.sys_id);

	var assignGroup = current.assignment_group;
	
	gs.info("checkValidAssign - Point 3.2 - assignGroup = " + assignGroup);
	
//	if(myUserObject.isMemberOf(assignGroup)){
	if(myUserObject.isMemberOf(current.assignment_group)){
		
		gs.info("checkValidAssign - Point 4");
		
		if(myUserObject.hasRole('Case - Take Ownership - My Groups')){
		
			gs.info("checkValidAssign - Point 3");
			
			return true;
		}
	}
	return false;
	
	
}

 

Log entries:

find_real_file.png

I suspect the last log entry is pointing to the issue:

org.mozilla.javascript.EcmaError: Cannot read property "assigned_to" from null
   Caused by error in Access Control: 'x_enig_commcase_ci_case.state' at line 14

     11: 	}
     12: //	var func = new x_enig_commcase.CommercialCaseUtils();
     13: 	var func = new global.caseManagementUtils();
==>  14: 	var assign = func.getValidAssign();
     15: 	
     16: 	gs.info("checkValidAssign Point 1 - assign - " + assign);
     17: 	

The script include IS being called and seems to be returning the correct answer (I validated with log statements - Point 99 shows the final answer).

 

Script Include:

find_real_file.png

Function:

getValidAssign : function(){
		
//gs.info("getValidAssign - current.assigned_to = " + current.assigned_to);
		
if(getMyAssignments().toString().indexOf(current.assigned_to) > -1){
			
	//gs.info("getValidAssign - into if");
	return true;
}
	return false;
},

 

I'm at a loss as to why the user can't change the state field. There are no other useful log entries. It looks like other ACLs that reference the "getValidAssign" function are also failing.

Can anyone tell me WHY this isn't working?  Thank you!!

 

1 ACCEPTED SOLUTION

is function getMyAssignments() supposed to get all groups the user is a member of?

The OOTB code to do this doesn't work in scoped apps. Even if you call it in a global SI, you need to convert the JavaArray it returns into a JavaScript array. So, may as well just use this function instead. It is best to minimize dependencies to global code in scoped apps as much as possible.

You can use this function that replicates this code:

// original code credit to user Tim2222
// https://community.servicenow.com/community?id=community_question&sys_id=308eac4cdbcb5304b2102926ca9619fd&view_source=searchResult
function getMyGroups() {
	var groups = [];
	var grmember = new GlideRecord('sys_user_grmember');
	grmember.addQuery('user', gs.getUserID());
	grmember.addQuery('group.active', true);
	grmember.query();
	while(grmember.next()){
		groups.push(grmember.getValue('group'));
	}
	// add all parent groups (this is global.getMyGroups behaviour)
	var children = groups;
	while(children.length > 0) {
		var grp = new GlideAggregate('sys_user_group');
		grp.addQuery('active', true);
		grp.addQuery('sys_id', 'IN', children.join(','));
		grp.addEncodedQuery('parentISNOTEMPTY');
		grp.groupBy('parent');
		grp.query();
		children = [];
		while(grp.next()) {
			var parent_id = grp.getValue('parent');
			if (groups.indexOf(parent_id) == -1) {
				groups.push(parent_id);
				children.push(parent_id);
			}
		}
	}
	return groups;
}

GlideUser().getMyGroups() | The Ultimate Scoped App Workaround Guide


ServiceNow Nerd
ServiceNow Developer MVP 2020-2022
ServiceNow Community MVP 2019-2022

View solution in original post

13 REPLIES 13

Can you try one more thing by qualifying a scope. Also refer to

http://sncommander.com/some-common-hurdles-in-scoped-apps-in-servicenow/

 

var myAssigned = global.getMyAssignments().toString();
gs.info("myAssigned = " + myAssigned)
Please mark Correct and click the Thumb up if my answer helps you resolve your issue. Thanks!
Vinod Kumar Kachineni
Community Rising Star 2022

Done.  Here's the result:

 

Evaluator: java.lang.SecurityException: Illegal access to package_private global script getMyApprovals: caller not in scope rhino.global
   Caused by error in script at line 1

==>   1: var myAssigned = global.getMyAssignments().toString();
      2: gs.print("myAssigned = " + myAssigned)

Background message, type:error, message: Illegal access to package_private global script getMyApprovals: caller not in scope rhino.global



I think you should have a new script include say

NewScriptInclude

in the global with a function

getMyAssignments

that returns

getMyAssignments.toString() and is marked as available to all scopes.

Then you should try

var myAssigned = new global.NewScriptInclude.getMyAssignments().toString(); 
gs.print("myAssigned = " + myAssigned)



 

Please mark Correct and click the Thumb up if my answer helps you resolve your issue. Thanks!
Vinod Kumar Kachineni
Community Rising Star 2022

is function getMyAssignments() supposed to get all groups the user is a member of?

The OOTB code to do this doesn't work in scoped apps. Even if you call it in a global SI, you need to convert the JavaArray it returns into a JavaScript array. So, may as well just use this function instead. It is best to minimize dependencies to global code in scoped apps as much as possible.

You can use this function that replicates this code:

// original code credit to user Tim2222
// https://community.servicenow.com/community?id=community_question&sys_id=308eac4cdbcb5304b2102926ca9619fd&view_source=searchResult
function getMyGroups() {
	var groups = [];
	var grmember = new GlideRecord('sys_user_grmember');
	grmember.addQuery('user', gs.getUserID());
	grmember.addQuery('group.active', true);
	grmember.query();
	while(grmember.next()){
		groups.push(grmember.getValue('group'));
	}
	// add all parent groups (this is global.getMyGroups behaviour)
	var children = groups;
	while(children.length > 0) {
		var grp = new GlideAggregate('sys_user_group');
		grp.addQuery('active', true);
		grp.addQuery('sys_id', 'IN', children.join(','));
		grp.addEncodedQuery('parentISNOTEMPTY');
		grp.groupBy('parent');
		grp.query();
		children = [];
		while(grp.next()) {
			var parent_id = grp.getValue('parent');
			if (groups.indexOf(parent_id) == -1) {
				groups.push(parent_id);
				children.push(parent_id);
			}
		}
	}
	return groups;
}

GlideUser().getMyGroups() | The Ultimate Scoped App Workaround Guide


ServiceNow Nerd
ServiceNow Developer MVP 2020-2022
ServiceNow Community MVP 2019-2022

Thanks Paul!

I tried your code and it is working to return the list of group sys_ids that the user belongs to. That is what I need and answers my question.

 

- - - 

Just FYI for other readers - I had other ACL issues so I've actually just starting rebuilding the ACLs in my new application. The original ACLs are from the Dublin release and quite possibly obsolete. This is not a technical issue.