2

I am wondering if there's a way to use Google Apps Script to share a Google Doc or Google Sheet, but programmatically disable the copy/download feature for viewers/commentors on the document? When share a Google Doc or Sheet normally, you can go to the settings icon and deselect those options:

enter image description here

But can I do that through Google Apps Script?

As a follow-up to that, is there any way to disable these options for editors too? I'd love to be able to share a document with someone, make them an editor, but prevent them from sharing it with anyone else. Thank you.

TheMaster
  • 45,448
  • 6
  • 62
  • 85
Lle.4
  • 516
  • 4
  • 17
  • Related: https://stackoverflow.com/a/61098656 – TheMaster Aug 31 '20 at 04:13
  • @TheMaster The method of `setShareableByEditors` is for "Editors can change permissions and share" in your comment. Do you know the method for controlling "Viewers and commenters can see the option to download, print, and copy" in Drive service? – Tanaike Aug 31 '20 at 04:58
  • 1
    @Tanaike No. That's why I added "Related" and not a duplicate or something. I searched apps script documentation and couldn't find any. – TheMaster Aug 31 '20 at 05:12
  • 1
    @TheMaster Thank you. When there is such method, I thought that the script will become simpler. In the current stage, it seems that Drive API v2 also cannot control it. So I proposed to use Drive API v3. By this, the fetch is required to be used. – Tanaike Aug 31 '20 at 05:14

2 Answers2

3

In this case, how about using Drive API? I think that you can set them using Drive API. In this answer, the method of "Files: update" of Drive API v3 is used.

Sample script:

Before you use this script, please enable Drive API at Advanced Google services.

function myFunction() {
  const fileId = "###";  // Please set the file ID.

  const url = "https://www.googleapis.com/drive/v3/files/" + fileId;
  const res = UrlFetchApp.fetch(url, {
    method: "patch",
    headers: {authorization: "Bearer " + ScriptApp.getOAuthToken()},
    contentType: "application/json",
    payload: JSON.stringify({viewersCanCopyContent: false, writersCanShare: false}),
  });
  console.log(res.getContentText())
  
  // DriveApp.createFile(blob)  // This comment line is used for automatically detecting the scope of "https://www.googleapis.com/auth/drive"
}

Note:

  • writersCanShare is for "Editors can change permissions and share"

  • viewersCanCopyContent is for "Viewers and commenters can see the option to download, print, and copy"

    • When I saw the official document, viewersCanCopyContent says Warning: This item is deprecated. Deprecated - use copyRequiresWriterPermission instead.. But when copyRequiresWriterPermission is used, this check couldn't controle. So, in this answer, I used viewersCanCopyContent.
    • For the future update, {viewersCanCopyContent: false, copyRequiresWriterPermission: false, writersCanShare: false} might be suitable instead of {viewersCanCopyContent: false, writersCanShare: false}.
  • Above sample, both checks are unchecked.

    • When copyRequiresWriterPermission can be used, I think that Drive API v2 might be able to use it as follows. But when I tested it now, it seems that "Viewers and commenters can see the option to download, print, and copy" cannot be controled.

        Drive.Files.patch({copyRequiresWriterPermission:false,writersCanShare:false}, fileId);
      
  • For example, when viewersCanCopyContent: true, writersCanShare: true are used, both checks are checked.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • 1
    Thanks so much for the help on this issue. Just to clarify, there's no way to control copying/downloading for editors, correct? Really appreciate the help. – Lle.4 Aug 31 '20 at 18:53
  • @Lle.4 About your additional question, there are `capabilities.canCopy` and `capabilities.canDownload` for controlling the copy and download. But in the current stage, it seems that these values cannot be changed by the API. For example, how about requesting it as the future request to Google issue tracker? https://developers.google.com/issue-tracker I deeply apologize that I cannot resolve your additional question soon. By the way, about your 1st question, can I ask you about whether it was resolved? – Tanaike Aug 31 '20 at 22:59
0

Posting an alternate solution to this for anyone who needs it.

var count = 0;

// Recursively removes download permissions from all files in supplied path
// Includes files in subdirectories
function main() {
  removeDownloadPermissions("Assets");
}


// Returns the folder Id of the first folder to match the folder name
function getFolderId(folderName) {
  var folderIterator = DriveApp.getFoldersByName(folderName);
  var folder = folderIterator.next();

  return folder.getId();
}

// Returns the folder Id of the first folder to match the folder name
function getFolder(folderName) {
  var folderIterator = DriveApp.getFoldersByName(folderName);
  var folder = folderIterator.next();

  return folder;
}

// removes the download permissions on all items in a folder hierarchy
function removeDownloadPermissions(folderName) {
  var folder = getFolder(folderName);
  var files = folder.getFiles();
  
  // Set permissions on each file in the root folder
  while (files.hasNext()) {
    var file = files.next();

    // Remove download permission
    Drive.Files.patch({copyRequiresWriterPermission:true}, file.getId());
    count++;

    console.log("Operation " + count.toString() + " download permission removed from file: " + file.getName());
  }

  // ** Begin recursion into subdirectories as needed
  var childFolders = folder.getFolders();

  while (childFolders.hasNext()) {
    var childFolder = childFolders.next();
    removeDownloadPermissions(childFolder.getName());
  }
  // ** End recursion

}
Marcus
  • 166
  • 6