Using the Google Apps Script Directory API, how to get groups within a group

I am working on a script that gets all the goups in my domain and lists all the users in those groups.

I rewrote this script because it is GroupsManager

deprecated, so my old script will stop working soon.

Everything works well (although this API is rather slow ...), but the problem is that some groups have not only users, but other groups as well ... some of them only have subgroups (and do not have users (way speak!)

I can't find a way to catch this situation, the list method returns users, it completely ignores the groups inside.

So my question is:

Is there a way to get groups within a group ? Am I missing something?

Below and for information is the code I use to list all members in groups in a spreadsheet, 1 sheet / group so that I can manipulate this data faster and easier later. I used the background color flags as a track keeper to handle a (relatively) small batch operation and a timer trigger that makes it run until it's done. (yes, we have a lot of groups in our group ;-)

function listGroupMembers() {
  var start = new Date().getTime();
  var ss = SpreadsheetApp.openById('1k-o4IVKEhW2zkk_________f2rH4UUt3OAC8I0ZoM');// set your SS ID (runs with timer trigger > needs to open by ID
  var pageToken, page;
  var count=0;
  var groupList = [];
  do {
    page = AdminDirectory.Groups.list({
      domain: 'xxxxx.be',
      maxResults: 100,
      pageToken: pageToken
    });
    var gr = page.groups;
    if (gr) {
      for (var i = 0; i < gr.length; i++) {
        var group = gr[i];
        count++;
        //Logger.log(group);
        groupList.push([group.email,count])
      }
    } else {
      Logger.log('No group found.');
    }
    pageToken = page.nextPageToken;
  } 
  while (pageToken);
  try{
    var GroupAddress = ss.getSheetByName('GroupAddress');// if GroupAddress Sheet already exist, open it
    Logger.log('Use existing sheet "'+GroupAddress.getName()+'"');
  }catch(err){
    Logger.log('create sheet "GroupAddress"');
    ss.deleteSheet(ss.getSheets()[0]);
    var GroupAddress = ss.insertSheet('GroupAddress',0); //else create it as first sheet 
  }
  GroupAddress.getDataRange().clearContent();
  ss.getSheetByName('GroupAddress').getRange(1,1,groupList.length,groupList[0].length).setValues(groupList);

  var groupNames = ss.getSheetByName("GroupAddress").getDataRange().getValues();
  var groupDone = ss.getSheetByName("GroupAddress").getDataRange().getBackgrounds();
  var progress;
  for(var n in groupNames){
    if(groupDone[n][0] != 'white' || (new Date().getTime()-start)/60 > 5000){ // limit to 5 seconds + 1 group
      continue;
    }
    try{
      var outputSheet = ss.insertSheet(groupNames[n][0],Number(n)+1)
      }catch(err){
        var outputSheet = ss.getSheetByName(groupNames[n][0]);
      }
    var group = GroupsApp.getGroupByEmail(groupNames[n][0]);
    //Logger.log('groupNames[n][0] = '+groupNames[n][0]);
    try{
      var users = group.getUsers();
      var output = [];
      for (var i in users){ 
        var user = AdminDirectory.Users.get(users[i].getEmail());
        output.push([Number(i)+1,user.name.fullName, user.primaryEmail,user.aliases!=null?user.aliases:'',new Date(user.creationTime),user.isAdmin,new Date(user.lastLoginTime)]);
      }
      ss.getSheetByName("GroupAddress").getRange(Number(n)+1,1).setBackground('#fff2cc');
      SpreadsheetApp.flush();
      if(output.length>0){
        output.push(['durée :',parseInt((new Date().getTime()-start)/60),'millisecondes','','','','']);
        outputSheet.getRange(1,1,output.length,output[0].length).setValues(output);
      }
    }catch(err){
      continue}
  }
  groupDone = ss.getSheetByName("GroupAddress").getDataRange().getBackgrounds();
  for(progress = groupDone.length-1;progress>=0;progress--){
    if(groupDone[progress][0]!='white'){break};
  }
  Logger.log(n+'='+progress+'?');
  if(n==progress){
    MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'All jobs done in GroupList','All tasks completed on '+new Date().toLocaleString());
    var trig = ScriptApp.getProjectTriggers();
    for(var t in trig){
      try{
      ScriptApp.deleteTrigger(trig[t]);
      }catch(e){}
    }
  }else{
    ScriptApp.newTrigger('listGroupMembers').timeBased().after(3000).create();// wait 3 secs and continue
  }
}

      


EDIT

Thanks to Göran's answer, I have a version that includes all members of all groups, including subgroups.

I modified my code a bit to fit my requirements and I also needed to limit the number of cells in each sheet to whatever I needed, because the total (1000 * 26 cells / sheets) exceeded the 200,000 cell limit (I have more 100 sheets).

Full code below for anyone interested (including menus and a few utilities):

function onOpen() {
  var menu = SpreadsheetApp.getUi().createMenu("Utilitaires INSAS")
  .addItem("reset colors", "resetColors")
  .addItem("create groupUser lists", "listGroupMembers")
  .addItem("delete all sheets", "delsheets");
  menu.addToUi();
}

function listGroupMembers() {
  var start = new Date().getTime();
  var ss = SpreadsheetApp.openById('1k-o4IVKEhW2zkkEu0gAvb92rQf2rH4UUt3OAC8I0ZoM');// set your SS ID (runs with timer trigger > needs to open by ID
  var pageToken, page;
  var count=0;
  var groupList = [];
  do {
    page = AdminDirectory.Groups.list({
      domain: 'insas.be',
      maxResults: 100,
      pageToken: pageToken
    });
    var gr = page.groups;
    if (gr) {
      for (var i = 0; i < gr.length; i++) {
        var group = gr[i];
        count++;
        //Logger.log(group);
        groupList.push([group.email,count])
      }
    } else {
      Logger.log('No group found.');
    }
    pageToken = page.nextPageToken;
  } 
  while (pageToken);
  try{
    var GroupAddress = ss.getSheetByName('GroupAddress');// if GroupAddress Sheet already exist, open it
    Logger.log('Use existing sheet "'+GroupAddress.getName()+'"');
  }catch(err){
    Logger.log('create sheet "GroupAddress"');
    ss.deleteSheet(ss.getSheets()[0]);
    var GroupAddress = ss.insertSheet('GroupAddress',0); //else create it as first sheet 
  }
  GroupAddress.getDataRange().clearContent();
  ss.getSheetByName('GroupAddress').getRange(1,1,groupList.length,groupList[0].length).setValues(groupList);

  var groupNames = ss.getSheetByName("GroupAddress").getDataRange().getValues();
  var groupDone = ss.getSheetByName("GroupAddress").getDataRange().getBackgrounds();
  var progress;
  for(var n in groupNames){
    if(groupDone[n][0] != 'white' || (new Date().getTime()-start)/60 > 5000){ // limit to 5 seconds + 1 group
      continue;
    }
    Logger.log('groupNames[n][0] = '+groupNames[n][0]);
    try{
      var outputSheet = ss.getSheetByName(groupNames[n][0]);
      Logger.log('sheet '+outputSheet.getName()+' created');
      }catch(err){
        var outputSheet = ss.insertSheet(groupNames[n][0],ss.getSheets().length+1);
      }
    try{
      var users = getUsersInGroup(groupNames[n][0]);
      var output = [];
      for (var i in users){ 
        var user = users[i];
//        Logger.log(user);
        output.push([Number(i)+1,user.email,user.role,user.groupName]);
      }
      ss.getSheetByName("GroupAddress").getRange(Number(n)+1,1).setBackground('#fff2cc');
      SpreadsheetApp.flush();
      if(output.length>0){
        output.push(['Ex.T = '+parseInt((new Date().getTime()-start)/60)+' mS','','','']);
        outputSheet.getRange(1,1,output.length,output[0].length).setValues(output);
        outputSheet.deleteRows(output.length+2, outputSheet.getMaxRows()-output.length-4);
        outputSheet.deleteColumns(6, outputSheet.getMaxColumns()-6);
      }
    }catch(err){
      continue}
  }
  groupDone = ss.getSheetByName("GroupAddress").getDataRange().getBackgrounds();
  for(progress = groupDone.length-1;progress>=0;progress--){
    if(groupDone[progress][0]!='white'){break};
  }
  Logger.log(n+'='+progress+'?');
  if(n==progress){
    MailApp.sendEmail(Session.getEffectiveUser().getEmail(),'All jobs done in GroupList','All tasks completed on '+new Date().toLocaleString());
    var trig = ScriptApp.getProjectTriggers();
    for(var t in trig){
      try{
      ScriptApp.deleteTrigger(trig[t]);
      }catch(e){}
    }
  }else{
    ScriptApp.newTrigger('listGroupMembers').timeBased().after(10000).create();// wait 3 secs and continue
  }
}

function resetColors(){
  var ss = SpreadsheetApp.getActive();
  ss.getSheets()[0].getDataRange().setBackground(null);
}

function getUsersInGroup(rootGroup) {
  var groupTreeUsers = [];
  var groups = [];
  groups.push(rootGroup);

  while (groups.length > 0) {
    var currentGroup = groups.pop();
    var groupName = AdminDirectory.Groups.get(currentGroup).name;
    var groupMembers = getAllMembers_(currentGroup);

    for (var i in groupMembers) {
      if (groupMembers[i].type == 'USER') {
        var groupMember = groupMembers[i];
        groupMember['groupName'] = currentGroup;
        groupTreeUsers.push(groupMember)
      }
      else if (groupMembers[i].type == 'GROUP') {
        groups.push(groupMembers[i].email)
      }
    }
  }
  Logger.log('There are %s user members in %s (including sub groups)', groupTreeUsers.length, rootGroup);
  return groupTreeUsers;
}

function getAllMembers_(group) {
  var memberPageToken, memberPage;
  var members = [];
  do {
    memberPage = AdminDirectory.Members.list(group, {
      maxResults: 200,
      pageToken: memberPageToken
    });
    var pageMembers = memberPage.members;
    if (pageMembers) {
      for (var j =0; j < pageMembers.length; j++) {
        members.push(pageMembers[j]);
      }
    }
    memberPageToken = memberPage.nextPageToken;
  } while (memberPageToken);
  return members;
}

function delsheets(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var numSheets = ss.getNumSheets();// check how many sheets in the spreadsheet
  for (var pa=numSheets-1;pa>0;pa--){ 
    if(ss.getSheets()[pa].getSheetName()!='GroupAddress'){
      ss.deleteSheet(ss.getSheets()[pa]); // delete sheets begining with the last one
      Utilities.sleep(100);
    }
  }
  SpreadsheetApp.flush();
} 

      

+3


source to share


1 answer


AdminDirectory MembersCollection might be what you are looking for.

Snippet example:

var members = AdminDirectory.Members.list('testgroup@example.com').members;
for (var i = 0; i < members.length; i++) {
  var member = members[i];
  switch (member.type) {
    case 'USER':
      Logger.log('%s is a user', member.email);
      break;
    case 'GROUP':
      Logger.log('%s is a group', member.email);
      break;
    default:
      Logger.log('This will never happen');
  }

      

Some of my clients have groups containing groups, combining groups ... forming a group tree of arbitrary depth. I am using this code to get all members of a user in a group tree like this:

function walkTreeStack() {
  var rootGroup = 'testgroup@example.com';
  var groupTreeUsers = [];
  var groups = [];
  groups.push(rootGroup);

  while (groups.length > 0) {
    var currentGroup = groups.pop();
    var groupName = AdminDirectory.Groups.get(currentGroup).name;
    var groupMembers = getAllMembers_(currentGroup);

    for (var i in groupMembers) {
      if (groupMembers[i].type == 'USER') {
        groupTreeUsers.push([groupName, groupMembers[i].email])
      }
      else if (groupMembers[i].type == 'GROUP') {
        groups.push(groupMembers[i].email)
      }
    }
  }

  Logger.log('There are %s user members in %s (including sub groups)', groupTreeUsers.length, groupName);
}

function getAllMembers_(group) {
  var memberPageToken, memberPage;
  var members = [];
  do {
    memberPage = AdminDirectory.Members.list(group, {
      maxResults: 200,
      pageToken: memberPageToken
    });
    var pageMembers = memberPage.members;
    if (pageMembers) {
      for (var j =0; j < pageMembers.length; j++) {
        members.push(pageMembers[j]);
      }
    }
    memberPageToken = memberPage.nextPageToken;
  } while (memberPageToken);
  return members;
}

      



This is slightly faster if executed recursively, but I suspect the script might crash due to memory constraints if there are a large number of subgroups and users:

function getGroupTreeMembers() {
  var rootGroup = 'testgroup@example.com';
  var groupTreeUsers = [];

  walkTreeRecursive_(rootGroup, groupTreeUsers);

  var groupName = AdminDirectory.Groups.get(rootGroup).name;  
  Logger.log('There are %s user members in %s (including sub groups)', groupTreeUsers.length, groupName);
}

function walkTreeRecursive_(rootGroup, groupTreeUsers) {
  var groupName = AdminDirectory.Groups.get(rootGroup).name;
  var groupMembers = getAllMembers_(rootGroup);
  var groups = [];
  for (var i in groupMembers) {
    if (groupMembers[i].type == 'USER') {
      groupTreeUsers.push([groupName, groupMembers[i].email])
    }
    else if (groupMembers[i].type == 'GROUP') {
      groups.push(groupMembers[i].email)
    }
  }
  for (var i in groups) {
    walkTreeRecursive_(groups[i], groupTreeUsers);
  }
}

      

For more information visit:

https://developers.google.com/admin-sdk/directory/v1/reference/members#resource

+4


source







All Articles