I
f you’ve taken a look at the ‘My Groups Work’ module (or maybe a particular security rule or report) you may have noticed that the condition or filter for that record makes a function call to return a list of values to compare against the value in the given field. In the case of the ‘My Groups Work’ module under the ‘Service Desk’ application there is a function called ‘getMyGroups’ that is used to identify task records where the assignment group value is one of the groups for which the current user is a member.
The ‘getMyGroups’ function simply returns an array of group sys_id values for the groups that a user belongs to. I saw a forum posting recently that pointed out (correctly) that the ‘getMyGroups’ function only returns group membership, but doesn’t return groups where the user is listed as the manager. The function also doesn’t attempt to return child groups of the groups where a person is a manager or group member. So, if I am the Director of Operations and I want to see a list of all tasks for the Operations group (which I am a manager of) as well as the sub-groups of that group, I would have to be added specifically to each sub-group to have all of the groups that I am interested in tracking be displayed in the list.
With some help from John Andersen, I’ve created the ‘Advanced getMyGroups’ function. This function is designed to give users a better way to display group membership information. It is used in the same way that you would use the ‘getMyGroups’ function, but also includes an optional parameter that allows you to return groups managed by an individual and/or sub-groups of a given group where I am a member or manager. The ‘maxDepth’ parameter returns the values as shown below…
- No maxDepth returns groups where user is a group member (Same as current ‘getMyGroups’ function)
- maxDepth of 0 returns groups where user is a group member or a manager
- maxDepth greater than 0 returns groups where user is a group member or a manager PLUS all child groups up to ‘maxDepth’ levels deep
The most common usage of this function is probably in a filter on a module or a report. So, if I were creating a module to show all tickets where I am a member of the group OR where I am the group manager, PLUS all of the sub-groups up to 5 levels deep I could use the following in my filter…
‘javascript:getMyGroupsAdvanced(5)’

In order to use the function, you need to set up a new business rule on the ‘Global’ table. The business rule must also be marked as ‘Client callable’ so that you can call the function from filter/condition builders. The settings for the business rule are shown here…
Name: getMyGroupsAdvanced
Table: Global
Client callable: True
Script:
//No maxDepth returns groups where user is a group member (Same as 'getMyGroups' function)
//maxDepth of 0 returns groups where user is a group member or a manager
//maxDepth greater than 0 returns groups where user is a group member or a manager PLUS all child groups up to 'maxDepth' levels deep
var maxDepth;
var x;
var groupArr = new Array();
var finalArr = new Array();
function getMyGroupsAdvanced(inputDepth){
//Set maxDepth to the given depth
maxDepth = inputDepth;
//Get the sys_id of the current user
var uID = gs.getUserID();
//Get all active groups where user is a member
var grmember = new GlideRecord('sys_user_grmember');
grmember.addQuery('user', uID);
grmember.addQuery('group.active', true);
grmember.query();
while(grmember.next()){
//Push the group sys_id values into the group array
groupArr.push(grmember.group.toString());
}
//If a maxDepth value is given then include groups where user is a manager
if(maxDepth >= 0){
//Get all active groups where user is a manager
var grman = new GlideRecord('sys_user_group');
grman.addQuery('manager', uID);
grman.addQuery('active', true);
grman.query();
while(grman.next()){
//Push the group sys_id values into the group array
groupArr.push(grman.sys_id.toString());
}
}
//Remove any duplicates from group string
groupArr = checkDuplicates(groupArr);
//If maxDepth > 0 then check for child groups
if(maxDepth > 0){
//Iterate through all of the groups and return all children for each group
for(x in groupArr){
//Only process if group sys_id is not already in the returned array
if(finalArr.length == 0 || finalArr.join().indexOf(groupArr[x]) == -1){
finalArr.push(groupArr[x]);
}
recursChildGroups(groupArr[x], 0);
}
}
//If we didn't check for child groups then just return the group array
else{
finalArr = groupArr;
}
//Return the array of group IDs
return finalArr;
}
function recursChildGroups(group, depth){
//Increase the current depth
depth++;
//If we have gone more than the allowed depth then abort for the given group
if(depth > maxDepth){
//('Possible recursive group loop with group ' + group);
return null;
}
//Make sure that we have a valid group ID
if(group){
if(group.toString().length == 0){
return null;
}
//Query for the active child groups of this group
var rec = new GlideRecord('sys_user_group');
rec.addQuery('parent', group);
rec.addQuery('active', true);
rec.query();
while(rec.next()){
//If the group has already been added then do not add again
if(finalArr.join().indexOf(rec.sys_id.toString()) > -1){
continue;
}
//Add the group to the final array
finalArr.push(rec.sys_id.toString());
//Find the child groups of this group
recursChildGroups(rec.sys_id.toString(),depth);
}
}
return null;
}
function checkDuplicates(a){
//Check all values in the incoming array and eliminate any duplicates
var r = new Array();
o:for(var i = 0, n = a.length; i < n; i++){
for(var x = 0, y = r.length; x < y; x++){
if(r[x]==a[i]){
continue o;
}
}
r[r.length] = a[i];
}
return r;
}
Comments
Posted On
May 04, 2010Posted By
Bill CollinsHow do I make this work?
javascript:getMyGroupsAdvanced(5).GetGroupFilter(‘database,network’)
Posted On
May 04, 2010Posted By
Mark StangerI don’t think that you do. As far as I’ve seen, the ‘GetGroupFilter’ function is used for reference qualifiers but wouldn’t be applied in this way for a module or report filter.
Posted On
May 04, 2010Posted By
Xavier BrumioulGreat script!
thank you for all your work!
Posted On
May 10, 2010Posted By
garrett.griffinThanks for this, greatly appreciated! Perfect timing too, I started looking for a way to do exactly this on the same day you posted it.
Posted On
Jun 14, 2010Posted By
Tim HExcellent, thank you very much, Mark! Works great!
Posted On
Jul 22, 2010Posted By
Marc GI’ve also noticed that getMyGroups returns groups from above, i.e. parents of any groups you are a member of.
I am a member of Problem, which has a parent of SLM
when running getMyGroups I also get tickets assigned to SLM, I’m only interested in Problem group tickets.
Oddly, the filter also displays the parent group as though I’m only filtering on that.
Tasks-ASSIGNMENTGROUPIS SLM
Weird!
Posted On
Feb 06, 2012Posted By
AndrewThis is great, thanks for this. Kind of weird there is no option in ServiceNow to do this automatically.
Any ideas on how we would get this code to work in the report section. i.e. if we give users the ability to create reports for their groups, out of the box they can create reports for their groups and any of the associated parent groups of the child groups they belong to. We need this to be the other way around, i.e. if you are a member of a parent group and you click on the visible to: Group button you should see that parent group and also the parent s children??
Posted On
Feb 06, 2012Posted By
Mark StangerThe report page is back-end XML so there’s no way to directly manipulate the behavior of that page. You might be able to use a UI script to manipulate the functions there but that would be a pretty significant hack that would probably end up breaking during an upgrade. It’s probably best to request this as an enhancement with ServiceNow support.