无法将文件所有权从服务帐户转移到 google 云端硬盘用户

Unable to transfer ownership of file from service account to google drive user

尝试转让所有权时出现以下错误:

"domain": "global",
"reason": "invalidSharingRequest",
"message": "Bad Request. User message: \"You can't change the owner of this item.\""

这是我的代码:

use Google_Client; 
use Google_Service_Drive;
use Google_Service_Drive_DriveFile;
use Google_Service_Drive_Permission;

public function uploadDocument() {

 $FOLDER_ID = 'my_folder_ID_string';

 $client = new Google_Client();
 $client->setAuthConfig(base_path('service_account_credentials.json'));
 $client->setScopes(array('https://www.googleapis.com/auth/drive'));

 $service = new Google_Service_Drive($client);

 $fileMetadata = new Google_Service_Drive_DriveFile(array(
                                                     'name' => 'Test.pdf',
                                                     'parents' => [$FOLDER_ID]
                                                    ));

 $content = file_get_contents(public_path('tmp/Test.pdf'));

 $file = $service->files->create($fileMetadata, array(
                                                    'data' => $content,
                                                    'mimeType' => 'application/pdf',
                                                    'uploadType' => 'multipart',
                                                    'fields' => 'id'
                                                     ));

  // Transfer Ownership
  $newPermission = new Google_Service_Drive_Permission();
  $newPermission->setRole('owner');
  $newPermission->setType('user');
  $newPermission->setEmailAddress('email@gmail.com');
  $optParams = array('transferOwnership' => 'true');

  $service->permissions->create($file->id, $newPermission, $optParams);

}

文件夹已成功上传到共享文件夹中的Google驱动器(所有者为'email@gmail.com',服务帐户为'editor'),但上传文件的所有者为服务帐户和编辑是 'email@gmail.com'.

您不能更改位于共享驱动器上的文件的所有者

根据documentation

Files within a shared drive are owned by the shared drive, not individual users.

因此,无需“取消”服务帐户的所有权。

您可以为用户提供任何其他 role,例如organizer 这将允许用户将文件移出共享驱动器,从而成为文件的所有者。\

更新

如果文件是由服务帐户上传到用户云端硬盘上的共享文件夹而不是共享云端硬盘,则情况有所不同。

具体来说:

  • 对于 GSuite 用户,域外的所有权转移是不允许的,这将导致错误 Ownership can only be transferred to another user in the same organization as the current owner..
  • 服务帐户不被视为域用户,因此受到相同的限制。
  • 对于消费者用户,允许将所有权从服务帐户转移到用户,但有限制: 只有 Google mimeType 的文档可以更改所有者。
  • 由于上述将所有权从服务帐户转移到用户的限制,最好使用 impersonation.
  • 来避免此问题
  • 模拟是指服务帐户代表用户(例如您)行事,当他将文件上传到您的云端硬盘时,相当于您自己上传文件 - 不需要转让所有权,没有明确的必须与服务帐户共享文件夹。
  • 要set-up模仿你需要
    • 在您的 GCP 控制台中为特定服务帐户启用 domain-wide 委托。

    • 通过继续 Security > API Controls > Domain wide delegation.

      在您的管理控制台中授权服务帐户所需的所有范围
    • 修改您的代码,添加行

      $client->setSubject($EmailOfUserToImpersonate);

  • 请注意,不幸的是 domain-wide 委派只能用于域 - 即 GSuite 帐户。
  • 对于消费者 (gmail) 帐户,无法将 non-Google mimeType 的所有权从服务帐户转移给用户。
  • 作为解决方法,用户可以复制服务帐户上传的文件 - 随后服务帐户可以删除原始文件。