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 sam
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
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.