Приобретайте файлы других пользователей с помощью скрипта Google Apps.

Intro

Мне поручено создать общую структуру папок Google Drive для моей компании. Я хочу, чтобы все в нем (или его части) принадлежало одному и тому же пользователю. Для этого я хочу использовать Google Apps Script для принудительного владения всеми файлами / папками в папке, для списка папок.

Problem 

Я не могу получить право собственности на передачу на работу.

Thoughts

Администраторы Служб Google могут навязывать права владения от пользователя X к пользователю Y. Но этого не произойдет, поскольку я хочу, чтобы права собственности передавались только для файлов, находящихся в общей папке.

Ранее это можно было сделать с помощью Apps Script с помощью сторонней функции с именем TransferOwnership.

В текущей реализации скрипта приложения я получаю "Отказано в доступе". Если владелец файла может использовать только функцию setOwner, это бесполезно для меня, но если ошибка связана с чем-то другим, я хотел бы знать, что именно.

Я полный администратор и скорее использую "настоящую" библиотеку функций, чем стороннюю.

2 ответа

Решение

Смотрите & star Issue 2756: Ошибка сервера для недопустимого изменения ACL

Сводка: только владелец файла может изменить владельца. Учетные записи администраторов не имеют собственных файлов пользователя, поэтому у них нет особых привилегий в этом отношении.

Как отмечается в комментарии @HenriqueAbreu, в этом ответе описывается возможный обходной путь с использованием Drive API (не Google Apps Script) для олицетворения пользователей домена, к сожалению, без подробностей реализации.

Вы могли бы пойти на веб-приложение, работающее с учетными данными пользователя и вызвать синергию. Я дам вам решение, которое я внедрил в своей компании. Приведенная ниже система передает свойство каждый раз, когда запускается триггер, я решил запускать его один раз в день в 1 час ночи. Конечно, вы можете изменить реализацию так, чтобы запуск происходил в любой ситуации, которую вы предпочитаете, например, вызывая ее из другого скрипта.

Допустим, у вас есть определенный пользователь (то есть администратор домена), отвечающий за владение свойством всех папок и файлов компании, и, наконец, допустим, что корневой папкой компании является COMPANY.

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

Сначала создайте вспомогательный прокси- сервер GAS. Проверьте, находится ли папка File e в данных КОМПАНИИ, например, так (ДОЛЖНО быть опубликовано как: запуск в качестве суперадминистратора, разрешение на запуск для любого пользователя в домене):

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;
}

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

Во-вторых, создайте веб-приложение следующим образом (ДОЛЖНО быть опубликовано как: запущено, когда пользователь вошел в систему, разрешение на запуск для любого пользователя в домене)

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");
}

Раздайте URL-адрес второго сценария пользователям домена с просьбой разрешить запрашиваемое разрешение.... или поиграйте с реализацией по вашему желанию... Наслаждайтесь

Другие вопросы по тегам