【问题标题】:Transfer ownership of a file to another user in Google Apps Script在 Google Apps 脚本中将文件的所有权转让给其他用户
【发布时间】:2012-05-29 09:32:02
【问题描述】:

我创建了一个小的上传 UI,我将其包含在 Google 协作平台页面中。它让用户上传一个文档。由于脚本已发布,它在我的帐户下运行,并且上传的文件上传到我的谷歌驱动器。我可以从应用程序脚本中将上传文件的人添加为编辑器,但我想做的是让他们成为文件的所有者。 (从应用程序脚本中,您可以对文件执行 .getOwner() ......但不是 .setOwner() .....有人知道解决方法吗?

【问题讨论】:

    标签: google-apps-script google-drive-api


    【解决方案1】:

    很遗憾,Apps 脚本不支持更改文件的所有者。 Issue 74 是添加此功能的功能请求,如果您在问题上加注星标,您将表示您对该功能的支持并收到更新通知。

    -----已编辑------

    现在有一个方便的方法叫做 setOwner,可以在这里找到:https://developers.google.com/apps-script/reference/drive/file#setOwner(User)

    还有可能传递新所有者的电子邮件地址而不是 User 对象,这在某些情况下更加方便: https://developers.google.com/apps-script/reference/drive/file#setOwner(String)

    【讨论】:

    • 我已将自己添加到列表中...同时上面的代码是一个很好的解决方法!
    • 似乎只有文件的所有者可以使用setOwner() 更改文件的所有权 - 请参阅:stackoverflow.com/a/26531182/1063287
    • 根据this official help article,文件所有权的转移仅适用于Google Docs、Sheets、Slides和Forms,不适用于上传的文件。
    【解决方案2】:

    2016 年 9 月 12 日更新:

    此代码使用已授予Google Apps Domain-Wide Delegation of Authority 的服务帐户。这使您可以更改域中任何用户拥有的任何文件的所有者。此代码使用 Eric Koleda 的 Google apps-script-oauth2 库。

    var PRIVATE_KEY  = PropertiesService.getScriptProperties().getProperty('PRIVATE_KEY'); 
    var CLIENT_EMAIL = PropertiesService.getScriptProperties().getProperty('CLIENT_EMAIL');
    
    /**
    * Transfers ownership of a file or folder to another account on the domain.
    *
    * @param  {String} fileId The id of the file or folder
    * @param  {String} ownerEmail  The email address of the new owner.
    */
    function transferOwnership(fileId, ownerEmail) {
      var file = DriveApp.getFileById(fileId);
      var currentOwnerEmail = file.getOwner().getEmail(); //the user that we need to impersonate
    
      var service = getService(currentOwnerEmail);
      if (service.hasAccess()) {
        var url = 'https://www.googleapis.com/drive/v2/files/' + fileId + '/permissions'; 
        var payload = {value: ownerEmail,
                       type: 'user',
                       role: 'owner'};
        var options = {method: "post",
                       contentType: "application/json",
                       headers : {
                         Authorization: 'Bearer ' + service.getAccessToken()
                       },
                       payload: JSON.stringify(payload)//,
                       ,muteHttpExceptions: true
                      };        
        //debugger;
        //throw 'test my errors';
    
        var response = UrlFetchApp.fetch(url, options);
        if (response.getResponseCode() === 200 || 
            (response.getResponseCode() === 400 && response.getContentText().indexOf('were successfully shared'))
        ) {
          return response.getContentText();
        }
        if (response.getResponseCode() === 401 && response.getContentText().indexOf('Invalid Credentials')) {
          throw 'Unable to transfer ownership from owner ' + currentOwnerEmail + ' ... ' +
            'Please make sure the file\'s owner has a Google Apps license (and not a Google Apps Vault - Former Employee license) and try again.';
        }
        throw response.getContentText(); 
      } else {
        throw service.getLastError();
      }
    }
    
    /**
     * Reset the authorization state, so that it can be re-tested.
     */
    function reset() {
      var service = getService();
      service.reset();
    }
    
    /**
     * Configures the service.
     */
    function getService(userEmail) {
      return OAuth2.createService('GoogleDrive:' + userEmail)
          // Set the endpoint URL.
          .setTokenUrl('https://accounts.google.com/o/oauth2/token')
    
          // Set the private key and issuer.
          .setPrivateKey(PRIVATE_KEY)
          .setIssuer(CLIENT_EMAIL)
    
          // Set the name of the user to impersonate. This will only work for
          // Google Apps for Work/EDU accounts whose admin has setup domain-wide
          // delegation:
          // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
          .setSubject(userEmail)
    
          // Set the property store where authorized tokens should be persisted.
          .setPropertyStore(PropertiesService.getScriptProperties())
    
          // Set the scope. This must match one of the scopes configured during the
          // setup of domain-wide delegation.
          .setScope('https://www.googleapis.com/auth/drive');
    }
    

    旧答案(现在已过时,因为文档列表 API 已弃用):

    您可以在 Google Apps 脚本中通过使用原始 atom xml 协议访问文档列表 API 来实现此目的。您需要成为域的超级管理员。这是一个适合我的示例:

    /**
    * Change Owner of a file or folder 
    * Run this as admin and authorise first in the script editor.
    */ 
    function changeOwner(newOwnerEmail, fileOrFolderId){
      var file = DocsList.getFileById(fileOrFolderId);
      var oldOwnerEmail = file.getOwner().getEmail();
      if (oldOwnerEmail === newOwnerEmail) {
        return;
      }
      file.removeEditor(newOwnerEmail);
      var base = 'https://docs.google.com/feeds/';
      var fetchArgs = googleOAuth_('docs', base);
      fetchArgs.method = 'POST';
      var rawXml = "<entry xmlns='http://www.w3.org/2005/Atom' xmlns:gAcl='http://schemas.google.com/acl/2007'>"
          +"<category scheme='http://schemas.google.com/g/2005#kind' "
          +"term='http://schemas.google.com/acl/2007#accessRule'/>"
          +"<gAcl:role value='owner'/>"
          +"<gAcl:scope type='user' value='"+newOwnerEmail+"'/>"
          +"</entry>";
      fetchArgs.payload = rawXml;
      fetchArgs.contentType = 'application/atom+xml';
      var url = base + encodeURIComponent(oldOwnerEmail) + '/private/full/'+fileOrFolderId+'/acl?v=3&alt=json';
      var content = UrlFetchApp.fetch(url, fetchArgs).getContentText(); 
    }
    
    //Google oAuth
    function googleOAuth_(name,scope) {
      var oAuthConfig = UrlFetchApp.addOAuthService(name);
      oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
      oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
      oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
      oAuthConfig.setConsumerKey("anonymous");
      oAuthConfig.setConsumerSecret("anonymous");
      return {oAuthServiceName:name, oAuthUseToken:"always"};
    }
    

    【讨论】:

    • 非常好的彼得!虽然这段代码很棒,但如果我不是管理员,它并没有解决更简单的需要转移我自己的文件的所有权。但我不得不承认,这种用法可能不太常见 :) 顺便说一句,如果您不在 Google Apps for Business 帐户上,即使通过此 API 也无法转移文件的所有权。我刚刚测试过了。 Google 员工 Vic Fryzel 不久前表示他们将取消此限制,但它对我仍然有效:groups.google.com/d/msg/google-documents-list-api/v67Pa8tS0EM/…
    • 我很确定您可以更改“url”变量,以便它允许应用程序用户转移所有权,但是是的,消费者帐户拥有的文件存在限制(但不是 edu/gov ) 看来:support.google.com/drive/bin/…
    • 非常感谢这段代码......我会尝试实现它......因为这真的可以解决我现在的用例(我是一个商业用户并且拥有超级管理员权限......所以谢谢!!!!(但是谷歌......真的只是实现一个 setOwner 函数......如果你不是文件的所有者,或者不是有权更改所有者的超级用户,让它抛出一个异常一个文件....将使我们的生活更轻松!!!!
    • 非常感谢...这段代码确实适用于我的情况,非常感谢!!! (但严肃的谷歌......添加changeOwner功能,漂亮,漂亮请:-)
    【解决方案3】:

    试试这个! (至少它对我有用)

    var newFolder = DriveApp.createFolder(folderName).addEditor(ownerEmail).setOwner(ownerEmail).addEditor(group.getEmail()).removeEditor(Session.getActiveUser().getEmail());     
    

    上面创建了一个文件夹并添加了一个新编辑器,将新编辑器设置为所有者,将另一个组添加到编辑器中,最后从编辑器中删除刚刚创建文件夹的用户。

    【讨论】:

    • 问题是关于上传文件的所有权转移。目前无法完成。
    【解决方案4】:

    我想出了一个解决方法——不确定它是否正是你们所寻找的。只需授予您要切换所有权的帐户的访问权限即可。访问文档/表单/等。从该帐户中提取,然后制作该文件的副本。您现在是所有者。您必须重新邀请其他人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多