I'm working on a script that gets all goups in my domain and lists all users in these groups.
I rewrote this script because GroupsManager
is deprecated so my old script will stop working soon.
All is working well (although this API is quite slow...) but the issue I have is that some groups have not only users but include also other groups... some of them have only subgroups (and no users (way of speaking !)
I can't find any way to catch that situation, the list method return users, it ignores completely groups inside.
So my question is :
Is there a way to get the groups inside a group ? Am I missing something obvious ?
Below and for info is the code I use to list all members in groups in a spreadsheet, 1 sheet / group so that I can manipulate these data faster and easier later on. I used background color flags as a track keeper to handle a (relatively) small batch operation and a timer trigger that make it work until it's done. (yes, we have a lot of groups in our domain ;-)
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 gets all members of all groups including subgroups.
I changed (very) slightly his code to fit my requirements and I also needed to limit the number of cells in each sheet to what I needed because the total (1000*26 cells/sheet) was exceeding the 200000 cells limit (I have more than 100 sheets).
Full code below for anybody who would be interested (including menu 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();
}