Take ownership of other users Drive-files using Google Apps Script

放肆的年华 提交于 2019-12-02 02:59:32

问题


Intro

I'm tasked with creating a shared Google Drive folder-structure for my company. I want everything in (or parts of) it to be owned by the same user. To do this, I want to use Google Apps Script to force ownership of all files/folder within a folder, for a list of folders.

Problem 

I cant get the ownership-transfer to work.

Thoughts

Google Apps Admins can force ownership from user X to user Y. But that wont do since I only want files places in the shared folder to have ownership transferred.

Previously it could be done by Apps Script, with a third party function called transferOwnership.

In the current implementation of Apps Script I get "Access Denied". If the setOwner-function only can be used by the file owner, it is useless to me, but if the error is from something else, I'd like to know what.

I am full admin and I rather use the "real" function-library then a third party.


回答1:


See & star Issue 2756: Server error for illegal ACL change

Summary: Only the owner of a file can change ownership. Admin accounts don't own user's files, so they have no special privileges in this respect.

As noted in @HenriqueAbreu's comment, a possible work-around utilizing the Drive API (not Google Apps Script) to impersonate domain users is described in this answer, unfortunately without implementation details.




回答2:


You could go for a webapp running with the user credential and trigger sinergy. I'll give you the solution I've implemented in my company. The system below transfer the property every time the trigger run, I’ve chosen to run it once per day at 1 o’clock in the morning. Of course you can change the implementation so that the triggering can occur on whatever situation you prefer, calling it from another script for example.

Let's say that you have a specific user (i.e. the domain super administrator) responsible for holding the property of all the company Folders and Files, and finally let's say that the company root folder is COMPANY.

===============================================

First create an helper GAS Proxy Check if File e Folder is in COMPANY data like this (MUST be published as: running as the super admninstrator, permission to run for any user in the domain):

function doGet(e){
  var id=e.parameter.id;
  var type=e.parameter.type;
  var result="";
  
  if (type=="file"){
    result=isFileInCompanyDataTree(DriveApp.getFileById(id)).toString();
  }
  else if (type=="folder"){
    result=isFolderInCompanyDataTree(DriveApp.getFolderById(id)).toString();
  }
  else
    result="unknow type";
    
  return ContentService.createTextOutput(result);
}


/**
* RECURSIVELY Check if a given folder is in the Company Data Tree
*
* @param {folder} folder for which to check if it is in Company Data Tree
* @return {boolean} true if folder is in Company Data Tree, false otherwise,
*/
function isFolderInCompanyDataTree(folder){
  var isInCompanyData=false;
  var folderId=folder.getId();
  
  if (folderId=="PUT_THE_COMPANY_FOLDER_ID_HERE") return true;
  
  var parents=folder.getParents();
  while (parents.hasNext()) if (isInCompanyData=isFolderInCompanyDataTree(parents.next())) break;
  return isInCompanyData;
}

/**
* RECURSIVELY Check if a given file is in the Company Data Tree
*
* @param {file} file for which to check if is in Company Data Tree
* @return {boolean} true if file is in Company Data Tree, false otherwise,
*/
function isFileInCompanyDataTree(file){
  var isInCompanyData=false;
  var fileParents=file.getParents();
  
  while (fileParents.hasNext()) if (isInCompanyData=isFolderInCompanyDataTree(fileParents.next())) break;
  return isInCompanyData;
}

==============================================

Second create the webapp like this (MUST be published as: running as the user logged in, permission to run for any user in the domain)

function doGet(){
  var result="";
  var triggerId;
  
  // Transfer property
  give2AdminstratorFileAndFolderProperty();
  
  var flagAct=PropertiesService.getUserProperties().getProperty("trasfPropActive");

  if (flagAct=="true"){
    // system active, disable trigger
    triggerId=PropertiesService.getUserProperties().getProperty("triggerId");
    if (triggerId){
      var allTriggers = ScriptApp.getProjectTriggers();
      for (var i = 0; i < allTriggers.length; i++) {
        if (allTriggers[i].getUniqueId() == triggerId) {
          ScriptApp.deleteTrigger(allTriggers[i]);
          break;
        }
      }
    }
    PropertiesService.getUserProperties().deleteProperty("trasfPropActive");
    PropertiesService.getUserProperties().deleteProperty("triggerId");
    GmailApp.sendEmail("yourusername@yourdomain.com", "Automatic property transfer DISABLED for "+Session.getEffectiveUser().getEmail(),"DISABLED ");
    result=ContentService.createTextOutput("Thank you. Automatic property transfer DISABLED");  
  }
  // system NOT ACTIVE, enable trigger
  else{
    triggerId= ScriptApp.newTrigger("give2AdminstratorFileAndFolderProperty").timeBased().everyDays(1).atHour(1).create().getUniqueId();
    PropertiesService.getUserProperties().setProperty("trasfPropActive",true);
    PropertiesService.getUserProperties().setProperty("triggerId",triggerId);
    GmailApp.sendEmail("yourusername@yourdomain.com", " Automatic property transfer ENABLED for "+Session.getEffectiveUser().getEmail(),"ENABLED");
    result=ContentService.createTextOutput("THANK YOU. Automatic property transfer ENABLED");
  }
  
  return result;
}

/**
* For each folder and file is in the Company Data Tree owned by 'me', transfer property to the domain super administrator 
*
* @return {folderList} contains the list of folders for which the property changed
*/
function give2AdminstratorFileAndFolderProperty(){
  if (Session.getEffectiveUser().getEmail()=="yourusername@yourdomain.com") return "Nothing done, your are the super administrator! The goal of this script make sense only for user that are NOT the super administrator.";
  var folderChanged="";
  var fileChanged="";
  folderChanged=transferFolderProperty();
  fileChanged=transferFileProperty();
  return "List of folder: "+folderChanged+".\n\nList of files: "+fileChanged;
}

function check_give2AdminstratorFileAndFolderProperty(){
  var folderChanged="";
  var fileChanged="";
  folderChanged=check_transferFolderProperty();
  fileChanged=check_transferFileProperty();
  Logger.log("\n\nList of folder: "+folderChanged+".\n\nList of files: "+fileChanged);
}
/**
* For each folder is in the Company Data Tree owned by 'me', transfer property to the domain super administrator 
*
* @return {folderList} contains the list of folders for which the property changed
*/
function transferFolderProperty(){
  var folders = DriveApp.searchFolders('"me" in owners');
  var folderList="";
  
  
  while (folders.hasNext()) {
    var folder = folders.next();
    if (isFolderInCompanyDataTree(folder)){
      folder.setOwner("yourusername@yourdomain.com");
      folderList=folder.getName()+", ";
    }
  }
  return folderList.slice(0,-2);
}

function check_transferFolderProperty(){
  var folders = DriveApp.searchFolders('"me" in owners');
  var folderList="";
  
  
  while (folders.hasNext()) {
    var folder = folders.next();
    if (isFolderInCompanyDataTree(folder)){
      folderList=folder.getName()+", ";
    }
  }
  return folderList.slice(0,-2);
}

/**
* For each file is in the Company Data Tree that is owned by 'me', transfer property to the domain super administrator 
*
* @return {fileList} contains the list of files for which the property changed
*/
function transferFileProperty(){
  var files = DriveApp.searchFiles('"me" in owners');
  var fileList=""; 
  while (files.hasNext()) {
    var file = files.next();
    if (isFileInCompanyDataTree(file)){
      file.setOwner("yourusername@yourdomain.com");
      fileList=file.getName()+", ";
    }
  }
  return fileList.slice(0,-2);
}

function check_transferFileProperty(){
  var files = DriveApp.searchFiles('"me" in owners');
  var fileList=""; 
  while (files.hasNext()) {
    var file = files.next();
    if (isFileInCompanyDataTree(file)){
      fileList=file.getName()+", ";
    }
  }
  return fileList.slice(0,-2);
}


/**
* Check if a given folder is in the Company Data Tree
*
* @param {folder} folder for which to check if is in Company Data Tree
* @return {boolean} true if folder is in Company Data Tree, false otherwise,
*/
function isFolderInCompanyDataTree(folder){
  var token = ScriptApp.getOAuthToken();
  
  var response=UrlFetchApp.fetch("PUT_HERE_THE_URL_OF_THE_PROXY_CREATED_AT_STEP_ONE"+"?id="+folder.getId()+"&type=folder", {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  }).getContentText();
  return (response==="true");
}


/**
* Check if a given file is in the Company Data Tree
*
* @param {file} file for which to check if is in Company Data Tree
* @return {boolean} true if file is in Company Data Tree, false otherwise,
*/
function isFileInCompanyDataTree(file){
  var token = ScriptApp.getOAuthToken();
  var response=UrlFetchApp.fetch("PUT_HERE_THE_URL_OF_THE_PROXY_AT_CREATED_AT_STEP_ONE"+"?id="+file.getId()+"&type=file", {
    headers: {
      'Authorization': 'Bearer ' +  token
    }
  }).getContentText();
  return (response==="true");
}

Distribute the URL of the second script to the domain users asking them to allow the permission it'll be asking. ...or play with the implementation as you prefer... Enjoy



来源:https://stackoverflow.com/questions/23783735/take-ownership-of-other-users-drive-files-using-google-apps-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!