0

I want to add permission people who can access my site using spreadsheet. From More>Sharing & Permission > Add people I can do that manually but I'm thinking if its possible I place email address whom to share on a spreadsheet and Google site automatically allow access to them.

Is that possible? Any appscript/way to do that? If so where is the documentation/way to do that? Did some Google search but couldn't find such data.

Update [Site must be "Private" to work removeViewer] Following code can successfully add & delete new viewers. But it can't update users when new row (email address) is added. It gives following error: "Service error: SitesApp: AclEntry already exists added"

// These globals should be customized for your site   
    var domain = '';  // Leave blank for consumer account

    /**
     * Adds a custom menu to the active spreadsheet, containing a single menu item
     */

    function onOpen() {
      var sheet = SpreadsheetApp.getActiveSpreadsheet();
      var entries = [{
        name : "Update Viewers",
        functionName : "updateSiteViewersUI"
      }];
      sheet.addMenu("Site Utilities", entries);
    };


/**
 * Spreadsheet UI wrapper for updateSiteViewers()
 */
function updateSiteViewersUI() {
  var result = updateSiteViewers();
  Browser.msgBox('Site Viewers updated', 
                 'Added: '+result.added+'\\nRemoved:'+result.removed,
                 Browser.Buttons.OK)
}

/**
 * Reads email addresses from Column A, skipping a header line, and uses
 * them to update Viewer permissions on the Google Site.
 */
function updateSiteViewers() {  
  var sheet = SpreadsheetApp.getActiveSheet();
  var rows = sheet.getDataRange();
  var values = rows.getValues();

  // Get user list from sheet
  var sheetUsers = [];
  for (var i = 1; i < values.length; i++) {
    var row = values[i];
    sheetUsers.push(row[0]); // build array of users
  }

  // uniqueFrom 
  Array.prototype.uniqueFrom = function() {
  if (!arguments.length)
    return [];
  var a1 = this.slice(0); // Start with a copy

  for (var n=0; n < arguments.length; n++) {
    var a2 = arguments[n];
    if (!(a2 instanceof Array))
      throw new TypeError( 'argument ['+n+'] must be Array' );

    for(var i=0; i<a2.length; i++) {
      var index = a1.indexOf(a2[i]);
      if (index > -1) {
        a1.splice(index, 1);
      } 
    }
  }
  return a1;
}
  // Get user list from consumer site
  var site = SitesApp.getSiteByUrl("https://sites.google.com/site/xyz/");
 Logger.log(site.getName());   
  var siteViewers = site.getViewers();

  /**
 * Returns a non-destructive Array of elements that are not found in
 * any of the parameter arrays.
 *
 * @param {...Array} var_args   Arrays to compare.
 */

  // Compare lists to find out what work we need to do
  var viewersToAdd = sheetUsers.uniqueFrom(siteViewers);
  var viewersToRemove = siteViewers.uniqueFrom(sheetUsers);

  // Update the Viewers list
  // Note - We could just add everyone, since the API ignores duplicates,
  // but then we wouldn't know how many changes there were.
  site.addViewers(viewersToAdd);

  for (var j=0; j < viewersToRemove.length; j++) {
    site.removeViewer(viewersToRemove[j]);
  }

  return {added:viewersToAdd.length, removed:viewersToRemove.length};
};
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
Zils
  • 403
  • 2
  • 4
  • 19

2 Answers2

2

Edit: Code updated to address two issues. See "Issues" section added at end of answer.
I haven't seen any examples that do what you're describing, but it should be straight-forward to implement. There is documentation for the classes and methods involved.

Look at the methods for Class Site, here. You will be especially interested in the methods dealing with viewer and editor permissions on sites:

  • Site.getViewers()
  • Site.getEditors()
  • Site.addViewer()
  • Site.addEditor()
  • Site.removeViewer()
  • Site.removeEditor()

This example relies on the Array.uniqueFrom() method from Javascript algorithm to find elements in array that are not in another array. It expects your spreadsheet to have a header in cell A1, with column A containing email addresses that you want to grant Viewer permissions to.

// These globals should be customized for your site
var domain = 'yourdomain.com';  // Leave blank for consumer account
var sitename = 'your_site';

/**
 * Adds a custom menu to the active spreadsheet, containing a single menu item
 */
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Update Viewers",
    functionName : "updateSiteViewersUI"
  }];
  sheet.addMenu("Site Utilities", entries);
};

/**
 * Spreadsheet UI wrapper for updateSiteViewers()
 */
function updateSiteViewersUI() {
  var result = updateSiteViewers();
  Browser.msgBox('Site Viewers updated', 
                 'Added: '+result.added+'\\nRemoved:'+result.removed,
                 Browser.Buttons.OK)
}

/**
 * Reads email addresses from Column A, skipping a header line, and uses
 * them to update Viewer permissions on the Google Site.
 */
function updateSiteViewers() {  
  var sheet = SpreadsheetApp.getActiveSheet();
  var rows = sheet.getDataRange();
  var values = rows.getValues();
  var sheetUsers = [];

  // Get user list from sheet
  for (var i = 1; i < values.length; i++) {
    var row = values[i];
    sheetUsers.push(row[0]); // build array of users
  }

  // Get user list from site
  var site = (domain === '')
             ? SitesApp.getSite(sitename)           // consumer
             : SitesApp.getSite(domain, sitename ); // hosted apps
  var siteViewers = site.getViewers().join(',').split(',');
  var editors = site.getEditors()
  var owners = site.getOwners()
  var viewersToAdd = sheetUsers.uniqueFrom(siteViewers);
  var viewersToRemove = siteViewers.uniqueFrom(sheetUsers);
  var addErrors = 0; // Counter for exceptions

  // Update the Viewers list
  for (var i=0; i < viewersToAdd.length; i++) {
    try {
      site.addViewer(viewersToAdd[i]);
    }
    catch (e) {
      // May receive Service error: SitesApp: AclEntry already exists
      // If a non-google user is a Viewer, they are not reported
      // by getViewers(). Bummer. We'll ignore just those errors.
      addErrors++; // Count the error
      if (e.message !== "Service error: SitesApp: AclEntry already exists") {
        throw e;
      }
    }
  }

  for (var i=0; i < viewersToRemove.length; i++) {
    site.removeViewer(viewersToRemove[i]);
  }

  return {added:viewersToAdd.length-addErrors, removed:viewersToRemove.length, errors:addErrors};
};

Issues

Two Google Apps Issues have complicated this script. Visit and star them to increase the priority that they get fixed.

  • Issue 3550: Site.getViewers() and Site.getEditors() do not return complete sharing list.

    Because it cannot find out about non-google users, this script will not remove them from the Viewers list.

  • Issue 3551: Site.addViewers() and Site.addEditors() do not ignore existing members

Community
  • 1
  • 1
Mogsdad
  • 44,709
  • 21
  • 151
  • 275
  • Just one word: brilliant and clear . Yes I know, that's two words... +1 :-) – Serge insas Jan 09 '14 at 17:16
  • That is awesome! Only problem, I'm getting error: "The resource you requested could not be located". I need to be clear about " domain " "Site". If my site is: https://sites.google.com/site/XYZ , domain will be sites.google.com ?? with or without http?? I really appreciate your help. +100!! – Zils Jan 09 '14 at 21:38
  • var site = SitesApp.getSiteByUrl("https://sites.google.com/site/XYZ) this method remove that error but creates new one. "Cannot find function uniqueFrom in object xzy@gmail.com" – Zils Jan 09 '14 at 22:09
  • @Mogsdad: I'm getting some errors when solving one creates another. As you're the first person who've gave a brief guideline to make it possible It'll act as reference in future for new comers. Could you please check your script on a consumer level google site practically and make necessary correction accordingly so that it can run hassle free? I appreicate your efforts. – Zils Jan 10 '14 at 08:48
  • @Mogsdad: I've updated my post with the code that can add viewer & Delete existing. But updating users is still getting errors. When new email is added on A3 it gives: "Service error: SitesApp: AclEntry already exists added" is because A2 is already on permission list?? – Zils Jan 10 '14 at 10:28
  • @ Mogsdad: It does not ignor, it actually stop adding. For example it duplicate is on A5, It is adding upto A4 then stop adding although A6, A7, A8 ect are not duplicate. For capitalization, yes its same. – Zils Jan 10 '14 at 11:01
0

Look at google apps sctipt sitesApp and spreadsheetApp. With both you can write a script to do what you want.

Zig Mandel
  • 19,571
  • 5
  • 26
  • 36