Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
* Recursively gets all groups that a given user/group is a member
* of, either directly or indirectly, in a GWS domain.
* -OR-
* checks whether user/group is a member of provided group,
* both tasks support external users to the domain.
* Uses the AdminDirectory advanced service, and should be invoked by domain Admins!
* Article:
* Pablo Felip (@pfelipm)
* @param {string} userGroupEmail Email of user or group
* @param {string} [group] Group to check membership in (optional, if provided, behaviour & returned result are different)
* @return {Array|Boolean} Sorted array of group email addresses, empty if no memberships found or TRUE/FALSE
function checkMembership(userGroupEmail, groupEmail) {
* Helper function to retrieve groups that a given user or group is a direct-member of
* @param {string} email Email of user or group
* @return {Array] Array of group email addresses
const getDirectGroups = (email) => {
let token, groups = [];
try {
do {
response = AdminDirectory.Groups.list({ userKey: email, maxResults: 200, pageToken: token });
if (response.groups) groups = [...groups, =>];
token = response.token
} while (token);
} catch (e) {
// Exception if not a member of any group, we'll return the default empty array!
return groups;
};`[START] Finding group memberships for: "${userGroupEmail}"`);
const t1 = new Date().getTime();
* IIFE that performs a recursive membership search
* @param {Array} groups Array of groups to check
* @return {Array} Array of group email addresses, can contain duplicates
let allGroups = (seekGroups = (groups) => {
if (groups.length == 0) {
// Base case, we have no problem to solve here!'Empty array of groups to inspect, nothing to do.');
return [];
} else if (groups.length == 1) {
// [A] general case → complexity reduction [depth]`Finding memberships for: ${groups[0]}...`);
return [groups[0], ...seekGroups(getDirectGroups(groups[0]))];
} else if (groups.length > 1) {
// [B] general case → complexity reduction [width]`Splitting problem → ${groups.length} groups left, ["${groups[0]}",].`);
return [...seekGroups([groups.shift()]), ...seekGroups(groups)];
// Remove (possible) duplicates & sort list of group emails
allGroups = allGroups.filter((group, index, groups) => groups.indexOf(group) == index).sort();
const t2 = new Date().getTime();
if (!groupEmail) {
// Return array of groups that provided user/group is a member of`[END] "${userGroupEmail}" is a member of ${allGroups.length} groups (${t2 - t1} ms).`, '\n', allGroups);
return allGroups;
} else {
// Return membership to provided group (TRUE/FALSE)
const isMember = allGroups.some(group => group == groupEmail);`[END] "${userGroupEmail}" ${isMember ? 'is a' : 'is not a'} member of "${groupEmail}" (${t2 - t1} ms)`);
return isMember;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment