Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
leoherzog committed Mar 6, 2018
0 parents commit f58b7b0
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 0 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
![Google Group Directory Unlister](https://raw.githubusercontent.com/xd1936/googlegroupdirectoryunlister/master/img/screenshot.png)

# Google Group Directory Unlister

### Basics

[Google Groups for Gsuite](https://support.google.com/a/topic/25838) is a product that allows admins to create mailing lists for their domain. It is different than the public-facing [Google Groups](https://groups.google.com/) forums. When an admin makes a new Google Group for their domain, by default, the email address for that group is available in their domain's directory. That means that every user in the domain has the group's email address autocomplete when they type in the "To:" field in Gmail. There is no way to change that setting unless you do it programatically via the [Admin Group Settings API](https://developers.google.com/admin-sdk/groups-settings/v1/reference/groups).

In order to make our Admin's lives easier, I created this script. It simply grabs all of the groups on your domain and lets you toggle whether they are or are not included in the directory.

### Setup

`Note: This project must be initially created by a domain administrator account`

1. Log in as a domain administrator and create a [new Google Apps Script project](https://script.google.com/) in Google Drive.
2. Copy and paste the code from [`code.gs`](https://raw.githubusercontent.com/xd1936/googlegroupdirectoryunlister/master/code.gs) into `code.gs` in the Apps Script project
3. Create a new html file with **File****New****Html file**, name it `index.html`, and copy the code from [`index.html`](https://raw.githubusercontent.com/xd1936/googlegroupdirectoryunlister/master/index.html) into it.
4. Go into **Resources****Advanced Google services...**, and turn on the **Admin Directory API** and **Groups Settings API**. Also follow the *Developer Console* link on this same screen and enable access to the **Admin SDK** and **Groups Settings API** for this project ([more information](https://developers.google.com/apps-script/guides/services/advanced)).
5. Go into the `code.gs` file and change the `domain` variable on line 3 to be your domain.
6. Go into **Publish****Deploy as web app...**. Choose the level of access that you want to have on the panel (Under **Who has access to the app:**), and click **Deploy**.

You're done! Navigate to that web app URL to see your groups and modify each one's setting.

### Updating

When updates are released here on Github, simply copy and paste the newer [`code.gs`](https://raw.githubusercontent.com/xd1936/googlegroupdirectoryunlister/master/code.gs) and [`index.html`](https://raw.githubusercontent.com/xd1936/googlegroupdirectoryunlister/master/index.html) files to your project, and go to **Publish****Deploy as web app...**. Increment the version number (Pick "New" under the **Project Version** dropdown) and click **Deploy**. You should be good to go!

- - -

Feel free to take a look at the source and adapt as you please. I would love to see some pull requests for improvements to the Javascript.

This source is licensed as follows:

[![Creative Commons License](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/)

<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Google Group Directory Unlister</span> is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).

- - -

[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/white_img.png)](https://buymeacoff.ee/leoherzog)
73 changes: 73 additions & 0 deletions code.gs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
//
var domain = "yourdomain.com";
//
//

function doGet() {
return HtmlService.createHtmlOutputFromFile('index.html').setTitle("Google Group Directory Unlister");
}

function test_() {
//var groups = getAllGroups();
//Logger.log(JSON.stringify(groups));

//Logger.log(showGroupInDirectory("[email protected]", false));
//Logger.log(getGroupDirectoryStatus("[email protected]"));
}

// https://developers.google.com/apps-script/advanced/admin-sdk-directory#list_all_groups
function getAllGroups() {
var allGroups = [];
var pageToken, page;
do {
page = AdminDirectory.Groups.list({
"domain": domain,
"pageToken": pageToken
});
var groups = page.groups;
if (groups) {
for (var i in groups) {
allGroups = allGroups.concat(groups[i]);
}
} else {
throw 'No groups found.';
}
pageToken = page.nextPageToken;
} while (pageToken);
return allGroups;
}

function showGroupInDirectory(groupId, showInDirectory) {

var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (!groupId || typeof groupId != "string" || !re.test(groupId.toLowerCase())) {
throw "Please call this function with a Google Group ID";
}
if (showInDirectory == null) {
showInDirectory = "true";
}
showInDirectory = showInDirectory.toString();
if (showInDirectory != "true" && showInDirectory != "false") {
throw "Please call this function with a boolean. Do you want this group to show in the directory or not?";
}

// okay. we now have a valid email address for the group id, and if we do or don't want it to be in the directory.
// get the group object
var group = AdminGroupsSettings.Groups.get(groupId);
// update it's "included in the list" property
group.includeInGlobalAddressList = showInDirectory;
// then patch the group with it's new setting
AdminGroupsSettings.Groups.patch(group, groupId);

return group;

}

function getGroupSettings(groupId) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (!groupId || typeof groupId != "string" || !re.test(groupId.toLowerCase())) {
throw "Please call this function with a Google Group ID";
}
return AdminGroupsSettings.Groups.get(groupId);
}
Binary file added img/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
117 changes: 117 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="//use.fontawesome.com/releases/v5.0.8/js/all.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/bootswatch/4.0.0/materia/bootstrap.min.css" rel="stylesheet" />
<style>body{padding-top:40px}</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-auto mr-auto">
<h1><i class="fas fa-users"></i> Google Group Directory Listings</h1>
</div>
<div class="col-auto">
<button type="button" id="refresh" class="btn btn-primary btn-lg"><i class="fas fa-sync"></i></button>
</div>
</div>
<div id="content" class="row">
</div>
</div>
<script>
$(document).ready(function() {
getGroups();
});

$('#refresh').click(function() {
if (!$('#refresh').hasClass('disabled')) {
getGroups();
}
});

function getGroups() {
$('#refresh').addClass('disabled').html('<i class="fas fa-spin fa-sync"></i>');
google.script.run.withSuccessHandler(updateCards).withFailureHandler(handleError).getAllGroups();
}

function updateCards(groups) {

console.log("Updating all groups...");

var content = "";
for (var i in groups) {
var id = sanitizeForId(groups[i].email);
content += '<div class="col-4">';
content += '<div id="' + id + '" class="card border-light mb-3">';
content += '<div class="card-header">' + groups[i].email + ' <small>(' + groups[i].directMembersCount + ')</small></div>';
content += '<div class="card-body">';
content += '<h4 class="card-title">' + groups[i].name + '</h4>';
content += '<p id="' + id + '-status" class="card-text"><button id="' + id + '-button" type="button" class="btn btn-sm btn-secondary disabled">Loading...</button></p>';
content += '</div>';
content += '</div>';
content += '</div>';
}
$('#content').empty().html(content);

console.log("Updated all groups! Updating statuses for each card...");

for (var i in groups) {
getCardStatus(groups[i].email);
}

$('#refresh').removeClass('disabled').html('<i class="fas fa-sync"></i>');

}

function handleError(error) {
alert(error);
}

function getCardStatus(groupId) {
google.script.run.withSuccessHandler(updateCardStatus).withFailureHandler(handleError).getGroupSettings(groupId);
}

function updateCardStatus(settings) {

console.log("Updating Card for " + settings.email + "...");

var id = sanitizeForId(settings.email);
var card = $('#' + id);
var status = $('#' + id + '-status');

card.removeClass("border-light border-success border-danger border-warning");
if (settings.includeInGlobalAddressList == "true") {
card.addClass("border-success");
status.html('<button id="' + id + '-button" onclick="unlist(\'' + settings.email + '\')" type="button" class="btn btn-sm btn-success"><i class="fas fa-minus"></i> Unlist from Directory</button>');
} else if (settings.includeInGlobalAddressList == "false") {
card.addClass("border-danger");
status.html('<button id="' + id + '-button" onclick="relist(\'' + settings.email + '\')" type="button" class="btn btn-sm btn-danger"><i class="fas fa-plus"></i> Relist to Directory</button>');
} else {
card.addClass("border-warning");
status.html('<button id="' + id + '-button" type="button" class="btn btn-sm btn-warning disabled">Error</button>');
}

}

function unlist(groupId) {
console.log("Unlisting " + groupId + "...");
$("#" + sanitizeForId(groupId) + '-button').addClass("disabled").prop('onclick', null).off('click');
google.script.run.withSuccessHandler(updateCardStatus).withFailureHandler(handleError).showGroupInDirectory(groupId, "false");
}

function relist(groupId) {
console.log("Relisting " + groupId + "...");
$("#" + sanitizeForId(groupId) + '-button').addClass("disabled").prop('onclick', null).off('click');
google.script.run.withSuccessHandler(updateCardStatus).withFailureHandler(handleError).showGroupInDirectory(groupId, "true");
}

function sanitizeForId(email) {
return email.replace(/@|\./g, "");
}
</script>

</body>
</html>

0 comments on commit f58b7b0

Please sign in to comment.