google-apps-scriptgoogle-drive-api

Google Apps Script - removeEditor/Viewer of single user from all files


I would like to remove a single user's editor/viewer access for all files in my Google Drive. When I tried this, I get the error "No such user". When I logged getEditor, the only results were "[DriveUser]". Greatly appreciate any thoughts on how to solve this. Thank you.

function RemoveEditors(){ 

  const EDITOR = "mickey@mouse.com";

  var files = DriveApp.getFiles();
  while (files.hasNext()) {
    var file = files.next();
    file.removeEditor(EDITOR);
    }
}

Solution

  • In your script, how about the following modification?

    Pattern 1:

    In this pattern, your script is simply modified.

    function RemoveEditors() {
      const EDITOR = "mickey@mouse.com";
      var files = DriveApp.getFiles();
      while (files.hasNext()) {
        var file = files.next();
        var editor = file.getEditors().find(e => e.getEmail() == EDITOR);
        if (editor) {
          file.removeEditor(EDITOR);
        }
      }
    }
    

    Pattern 2:

    I thought that in the above modification, all files are required to be retrieved. In that case, the process cost might be high. So, in order to reduce the process cost of the script, in this pattern, the files with the editor of EDITOR are searched using the search query. And, the editor is removed.

    function RemoveEditors() {
      const EDITOR = "mickey@mouse.com";
      var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false`);
      while (files.hasNext()) {
        var file = files.next();
        file.removeEditor(EDITOR);
      }
    }
    

    Pattern 3:

    In this pattern, Drive API is used. By this, I thought that when the number of files is large, the process cost might be reduced a little. When you use this script, please enable Drive API at Advanced Google services. And also, please install a Google Apps Script library of BatchRequest. Ref

    function RemoveEditors() {
      const EDITOR = "mickey@mouse.com";
    
      const q = `'${EDITOR}' in writers and trashed=false`;
      let requests = [];
      let pageToken = "";
      do {
        const obj = Drive.Files.list({ q, fields: "nextPageToken,items(permissions(emailAddress,id,role),id)", maxResults: 1000, pageToken });
        if (obj.items.length > 0) {
          requests = [...requests, ...obj.items.flatMap(({ permissions, id }) => {
            const user = permissions.find(({ emailAddress, role }) => role == "writer" && emailAddress == EDITOR);
            if (user) {
              return {
                method: "DELETE",
                endpoint: `https://www.googleapis.com/drive/v3/files/${id}/permissions/${user.id}`,
              };
            }
            return [];
          })];
        }
        pageToken = obj.nextPageToken;
      } while (pageToken);
      if (requests.length == 0) return;
      var result = BatchRequest.EDo({ batchPath: "batch/drive/v3", requests });
    }
    

    References:

    Added:

    For example, when the above pattern 2 is used and an error at file.removeEditor(EDITOR) is avoided, how about the following sample script?

    Sample 1:

    function RemoveEditors() {
      const EDITOR = "mickey@mouse.com";
      var yourEmail = "###your email address###"; // Please set your email address.
    
      var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false and '${yourEmail}' in owners`);
      while (files.hasNext()) {
        var file = files.next();
        file.removeEditor(EDITOR);
      }
    }
    

    Sample 2:

    function RemoveEditors() {
      const EDITOR = "mickey@mouse.com";
      var files = DriveApp.searchFiles(`'${EDITOR}' in writers and trashed=false`);
      while (files.hasNext()) {
        var file = files.next();
        try {
          file.removeEditor(EDITOR);
        } catch(e) {
          console.log(`Error message: ${e.message}, Error file: ${file.getId()}`);
        }
      }
    }