共用檔案、資料夾和雲端硬碟

每個 Google 雲端硬碟檔案、資料夾和共用雲端硬碟都有相關聯的permissions資源。每個資源都會識別特定 type (usergroupdomainanyone) 和 role (ownerorganizerfileOrganizerwritercommenterreader) 的權限。舉例來說,某個檔案可能具有一項權限,可授予特定使用者 (type=user) 唯讀存取權 (role=reader),而另一項權限則可授予特定群組 (type=group) 的成員在檔案中新增留言的權限 (role=commenter)。

如需角色完整清單和各角色允許執行的作業,請參閱「角色和權限」。

權限的運作方式

資料夾的權限清單會向下傳播。所有子檔案和資料夾都會沿用上層資料夾的權限。每當權限或階層發生變更,系統就會以遞迴方式將變更傳播至所有巢狀資料夾。舉例來說,如果檔案位於某個資料夾中,而該資料夾隨後移至另一個資料夾內,則新資料夾的權限會傳播至該檔案。如果新資料夾授予檔案使用者新角色 (例如「編輯者」),系統會覆寫舊角色。

相反地,如果檔案從資料夾繼承 role=writer,並移至提供「讀者」角色的另一個資料夾,檔案現在就會繼承 role=reader

無法從共用雲端硬碟中的檔案或資料夾移除沿用的權限。 而是必須在直接或間接父項中調整權限。您可以從「我的雲端硬碟」或「與我共用」中的項目移除沿用權限。

反之,您可以在「我的雲端硬碟」中的檔案或資料夾上覆寫沿用權限。因此,如果檔案從「我的雲端硬碟」資料夾繼承 role=writer,您可以對檔案設定 role=reader,降低其權限層級。

瞭解檔案功能

permissions 資源最終不會決定目前使用者對檔案或資料夾執行動作的能力。而是包含一組布林值 capabilities 欄位,用來指出是否可對檔案或資料夾執行動作。filesGoogle Drive API 會根據與檔案或資料夾相關聯的目前使用者權限資源,設定這些欄位。

舉例來說,當 Alex 登入您的應用程式並嘗試共用檔案時,系統會檢查 Alex 的角色是否具備該檔案的權限。如果角色允許使用者共用檔案,系統會根據角色填入檔案的相關 capabilities,例如 canShare。如果 Alex 想分享檔案,應用程式會檢查 capabilities,確保 canShare 設為 true

如要查看如何擷取 capabilities 檔案的範例,請參閱「取得檔案功能」。

取得檔案功能

應用程式開啟檔案時,應檢查檔案功能並顯示 UI,反映目前使用者的權限。舉例來說,如果使用者沒有檔案的 canComment 功能,UI 應停用加註功能。

如要檢查功能,請使用 fileId 路徑參數和設為 capabilities 欄位的 fields 參數,對 files 資源呼叫 get() 方法。如要進一步瞭解如何使用 fields 參數傳回欄位,請參閱「傳回特定欄位」。

以下程式碼範例說明如何驗證使用者權限。回應會傳回使用者對檔案擁有的功能清單。每項功能都對應至使用者可執行的細部動作。部分欄位只會填入共用雲端硬碟中的項目。

要求

GET https://www.googleapis.com/drive/v3/files/FILE_ID?fields=capabilities

回應

{
  "capabilities": {
    "canAcceptOwnership": false,
    "canAddChildren": false,
    "canAddMyDriveParent": false,
    "canChangeCopyRequiresWriterPermission": true,
    "canChangeItemDownloadRestriction": true,
    "canChangeSecurityUpdateEnabled": false,
    "canChangeViewersCanCopyContent": true,
    "canComment": true,
    "canCopy": true,
    "canDelete": true,
    "canDisableInheritedPermissions": false,
    "canDownload": true,
    "canEdit": true,
    "canEnableInheritedPermissions": true,
    "canListChildren": false,
    "canModifyContent": true,
    "canModifyContentRestriction": true,
    "canModifyEditorContentRestriction": true,
    "canModifyOwnerContentRestriction": true,
    "canModifyLabels": true,
    "canMoveChildrenWithinDrive": false,
    "canMoveItemIntoTeamDrive": true,
    "canMoveItemOutOfDrive": true,
    "canMoveItemWithinDrive": true,
    "canReadLabels": true,
    "canReadRevisions": true,
    "canRemoveChildren": false,
    "canRemoveContentRestriction": false,
    "canRemoveMyDriveParent": true,
    "canRename": true,
    "canShare": true,
    "canTrash": true,
    "canUntrash": true
  }
}

共用雲端硬碟資源的情境

分享情境分為以下五種:

  1. 如要共用「我的雲端硬碟」中的檔案,使用者必須具備 role=writerrole=owner

    • 如果檔案的 writersCanShare 布林值設為 false,使用者必須具備 role=owner

    • 如果使用者具有 role=writer,且臨時存取權受限於到期日期和時間,就無法共用檔案。詳情請參閱「設定到期日,限制檔案存取權」一文。

  2. 如要共用「我的雲端硬碟」中的資料夾,使用者必須擁有 role=writerrole=owner

    • 如果檔案的 writersCanShare 布林值設為 false,使用者必須具備權限較高的 role=owner

    • 在設有 role=writer 的「我的雲端硬碟」資料夾中,不允許設定臨時存取權 (受存取權到期日和時間限制)。詳情請參閱「設定檔案存取期限」。

  3. 如要分享共用雲端硬碟中的檔案,使用者必須擁有 role=writerrole=fileOrganizerrole=organizer 權限。

    • writersCanShare 設定不適用於共用雲端硬碟中的項目。 系統會將其視為一律設為 true
  4. 如要共用共用雲端硬碟中的資料夾,使用者必須具備 role=organizer

    • 如果共用雲端硬碟的sharingFoldersRequiresOrganizerPermission限制設為 false,具備role=fileOrganizer權限的使用者就能共用該共用雲端硬碟中的資料夾。
  5. 使用者必須具備role=organizer,才能管理共用雲端硬碟成員。只有使用者和群組可以成為共用雲端硬碟的成員。

建立權限

建立權限時,必須提供下列兩個欄位:

  • typetype 可識別權限範圍 (usergroupdomainanyone)。type=user 權限適用於特定使用者,type=domain 權限則適用於特定網域中的所有使用者。

  • rolerole 欄位會識別 type 可執行的作業。舉例來說,具有 type=userrole=reader 的權限可授予特定使用者檔案或資料夾的唯讀存取權。或者,具有 type=domainrole=commenter 權限 的網域使用者都能為檔案加註。如需角色完整清單,以及各角色允許執行的作業,請參閱「角色和權限」。

建立 type=usertype=group 權限時,您也必須提供 emailAddress,將特定使用者或群組與權限建立關聯。

建立 type=domain 權限時,您也必須提供 domain,將特定網域與權限建立關聯。

如要建立權限,請按照下列步驟操作:

  1. 搭配相關聯檔案或資料夾的 fileId 路徑參數,使用 create() 方法。
  2. 在要求主體中,指定 typerole
  3. 如果是 type=usertype=group,請提供 emailAddress。如果 type=domain,請提供 domain

以下程式碼範例說明如何建立權限。回應會傳回 Permission 資源的執行個體,包括指派的 permissionId

要求

POST https://www.googleapis.com/drive/v3/files/FILE_ID/permissions
{
  "requests": [
    {
        "type": "user",
        "role": "commenter",
        "emailAddress": "alex@altostrat.com"
    }
  ]
}

回應

{
    "kind": "drive#permission",
    "id": "PERMISSION_ID",
    "type": "user",
    "role": "commenter"
}

使用目標對象

目標對象是一種使用者群組 (例如部門或團隊),您可以建議使用者將這類群組做為共用對象。您可以鼓勵使用者與特定或部分目標對象 (而非整個機構) 共用項目。目標對象可協助您提升資料安全性和隱私,並讓使用者更輕鬆地共用項目。詳情請參閱「關於目標對象」。

如要使用目標對象,請按照下列步驟操作:

  1. 在 Google 管理控制台中,依序前往「選單」 >「目錄」 >「目標對象」

    前往「目標對象」

    您必須使用具備超級管理員權限的帳戶登入,才能執行這項工作。

  2. 在「目標對象」清單中,按一下目標對象名稱。如要建立目標對象,請參閱「建立目標對象

  3. 從目標對象網址複製專屬 ID:https://admin.google.com/ac/targetaudiences/ID

  4. 使用 type=domain 建立權限,並將 domain 欄位設為 ID.audience.googledomains.com

如要瞭解使用者與目標對象的互動情形,請參閱連結分享的使用者體驗

列出所有權限

permissions 資源上使用 list() 方法,即可擷取檔案、資料夾或共用雲端硬碟的所有權限。

下列程式碼範例說明如何取得所有權限。回應會傳回權限清單。

要求

GET https://www.googleapis.com/drive/v3/files/FILE_ID/permissions

回應

{
  "kind": "drive#permissionList",
  "permissions": [
    {
      "id": "PERMISSION_ID",
      "type": "user",
      "kind": "drive#permission",
      "role": "commenter"
    }
  ]
}

更新權限

如要更新檔案或資料夾的權限,可以變更指派的角色。如要進一步瞭解如何找出角色來源,請參閱「判斷角色來源」。

  1. permissions 資源上呼叫 update() 方法,並將 permissionId 路徑參數設為要變更的權限,以及將 fileId 路徑參數設為相關聯的檔案、資料夾或共用雲端硬碟。如要尋找 permissionId,請在 permissions 資源上使用 list() 方法,並搭配 fileId 路徑參數。

  2. 在要求中,找出新的 role

即使使用者或群組已是成員,您還是可以授予共用雲端硬碟中個別檔案或資料夾的權限。舉例來說,Alex 是共用雲端硬碟的成員,role=commenter不過,您的應用程式可以授予 Alex role=writer 共用雲端硬碟中檔案的存取權。在本例中,由於新角色比透過成員資格授予的角色權限更寬鬆,因此新權限會成為檔案或資料夾的有效角色

下列程式碼範例顯示如何將檔案或資料夾的權限從「註解者」變更為「編輯者」。回應會傳回 permissions 資源的例項。

要求

PATCH https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID
{
  "requests": [
    {
        "role": "writer"
    }
  ]
}

回應

{
  "kind": "drive#permission",
  "id": "PERMISSION_ID",
  "type": "user",
  "role": "writer"
}

判斷角色來源

如要變更檔案或資料夾的角色,您必須知道角色的來源。如果是共用雲端硬碟,角色的來源可能是共用雲端硬碟的成員資格、資料夾的角色或檔案的角色。

如要判斷共用雲端硬碟或該硬碟中項目的角色來源,請使用 fileIdpermissionId 路徑參數,以及設為 permissionDetails 欄位的 fields 參數,在 permissions 資源上呼叫 get() 方法。

如要找出 permissionId,請使用 permissions 資源的 list() 方法,並搭配 fileId 路徑參數。如要在 list 要求中擷取 permissionDetails 欄位,請將 fields 參數設為 permissions/permissionDetails

這個欄位會列舉使用者、群組或網域的所有沿用和直接檔案權限。

下列程式碼範例說明如何判斷角色來源。回應會傳回 permissions 資源的 permissionDetails。「inheritedFrom」欄位提供沿用權限的項目 ID。

要求

GET https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID?fields=permissionDetails&supportsAllDrives=true

回應

{
  "permissionDetails": [
    {
      "permissionType": "member",
      "role": "commenter",
      "inheritedFrom": "INHERITED_FROM_ID",
      "inherited": true
    },
    {
      "permissionType": "file",
      "role": "writer",
      "inherited": false
    }
  ]
}

使用批次要求更新多項權限

強烈建議使用批次要求修改多項權限。

以下範例說明如何使用用戶端程式庫,以批次方式修改權限。

Java

drive/snippets/drive_v3/src/main/java/ShareFile.java
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.Permission;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/* Class to demonstrate use-case of modify permissions. */
public class ShareFile {

  /**
   * Batch permission modification.
   * realFileId file Id.
   * realUser User Id.
   * realDomain Domain of the user ID.
   *
   * @return list of modified permissions if successful, {@code null} otherwise.
   * @throws IOException if service account credentials file not found.
   */
  public static List<String> shareFile(String realFileId, String realUser, String realDomain)
      throws IOException {
        /* Load pre-authorized user credentials from the environment.
         TODO(developer) - See https://developers.google.com/identity for
         guides on implementing OAuth2 for your application.application*/
    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList(DriveScopes.DRIVE_FILE));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

    // Build a new authorized API client service.
    Drive service = new Drive.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Drive samples")
        .build();

    final List<String> ids = new ArrayList<String>();


    JsonBatchCallback<Permission> callback = new JsonBatchCallback<Permission>() {
      @Override
      public void onFailure(GoogleJsonError e,
                            HttpHeaders responseHeaders)
          throws IOException {
        // Handle error
        System.err.println(e.getMessage());
      }

      @Override
      public void onSuccess(Permission permission,
                            HttpHeaders responseHeaders)
          throws IOException {
        System.out.println("Permission ID: " + permission.getId());

        ids.add(permission.getId());

      }
    };
    BatchRequest batch = service.batch();
    Permission userPermission = new Permission()
        .setType("user")
        .setRole("writer");

    userPermission.setEmailAddress(realUser);
    try {
      service.permissions().create(realFileId, userPermission)
          .setFields("id")
          .queue(batch, callback);

      Permission domainPermission = new Permission()
          .setType("domain")
          .setRole("reader");

      domainPermission.setDomain(realDomain);

      service.permissions().create(realFileId, domainPermission)
          .setFields("id")
          .queue(batch, callback);

      batch.execute();

      return ids;
    } catch (GoogleJsonResponseException e) {
      // TODO(developer) - handle error appropriately
      System.err.println("Unable to modify permission: " + e.getDetails());
      throw e;
    }
  }
}

Python

drive/snippets/drive-v3/file_snippet/share_file.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def share_file(real_file_id, real_user, real_domain):
  """Batch permission modification.
  Args:
      real_file_id: file Id
      real_user: User ID
      real_domain: Domain of the user ID
  Prints modified permissions

  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """
  creds, _ = google.auth.default()

  try:
    # create drive api client
    service = build("drive", "v3", credentials=creds)
    ids = []
    file_id = real_file_id

    def callback(request_id, response, exception):
      if exception:
        # Handle error
        print(exception)
      else:
        print(f"Request_Id: {request_id}")
        print(f'Permission Id: {response.get("id")}')
        ids.append(response.get("id"))

    # pylint: disable=maybe-no-member
    batch = service.new_batch_http_request(callback=callback)
    user_permission = {
        "type": "user",
        "role": "writer",
        "emailAddress": "user@example.com",
    }
    batch.add(
        service.permissions().create(
            fileId=file_id,
            body=user_permission,
            fields="id",
        )
    )
    domain_permission = {
        "type": "domain",
        "role": "reader",
        "domain": "example.com",
    }
    domain_permission["domain"] = real_domain
    batch.add(
        service.permissions().create(
            fileId=file_id,
            body=domain_permission,
            fields="id",
        )
    )
    batch.execute()

  except HttpError as error:
    print(f"An error occurred: {error}")
    ids = None

  return ids


if __name__ == "__main__":
  share_file(
      real_file_id="1dUiRSoAQKkM3a4nTPeNQWgiuau1KdQ_l",
      real_user="gduser1@workspacesamples.dev",
      real_domain="workspacesamples.dev",
  )

Node.js

drive/snippets/drive_v3/file_snippets/share_file.js
/**
 * Batch permission modification
 * @param{string} fileId file ID
 * @param{string} targetUserEmail username
 * @param{string} targetDomainName domain
 * @return{list} permission id
 * */
async function shareFile(fileId, targetUserEmail, targetDomainName) {
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const service = google.drive({version: 'v3', auth});
  const permissionIds = [];

  const permissions = [
    {
      type: 'user',
      role: 'writer',
      emailAddress: targetUserEmail, // 'user@partner.com',
    },
    {
      type: 'domain',
      role: 'writer',
      domain: targetDomainName, // 'example.com',
    },
  ];
  // Note: Client library does not currently support HTTP batch
  // requests. When possible, use batched requests when inserting
  // multiple permissions on the same item. For this sample,
  // permissions are inserted serially.
  for (const permission of permissions) {
    try {
      const result = await service.permissions.create({
        resource: permission,
        fileId: fileId,
        fields: 'id',
      });
      permissionIds.push(result.data.id);
      console.log(`Inserted permission id: ${result.data.id}`);
    } catch (err) {
      // TODO(developer): Handle failed permissions
      console.error(err);
    }
  }
  return permissionIds;
}

PHP

drive/snippets/drive_v3/src/DriveShareFile.php
<?php
use Google\Client;
use Google\Service\Drive;
function shareFile()
{
    try {
        $client = new Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope(Drive::DRIVE);
        $driveService = new Drive($client);
        $realFileId = readline("Enter File Id: ");
        $realUser = readline("Enter user email address: ");
        $realDomain = readline("Enter domain name: ");
        $ids = array();
            $fileId = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ';
            $fileId = $realFileId;
            $driveService->getClient()->setUseBatch(true);
            try {
                $batch = $driveService->createBatch();

                $userPermission = new Drive\Permission(array(
                    'type' => 'user',
                    'role' => 'writer',
                    'emailAddress' => 'user@example.com'
                ));
                $userPermission['emailAddress'] = $realUser;
                $request = $driveService->permissions->create(
                    $fileId, $userPermission, array('fields' => 'id'));
                $batch->add($request, 'user');
                $domainPermission = new Drive\Permission(array(
                    'type' => 'domain',
                    'role' => 'reader',
                    'domain' => 'example.com'
                ));
                $userPermission['domain'] = $realDomain;
                $request = $driveService->permissions->create(
                    $fileId, $domainPermission, array('fields' => 'id'));
                $batch->add($request, 'domain');
                $results = $batch->execute();

                foreach ($results as $result) {
                    if ($result instanceof Google_Service_Exception) {
                        // Handle error
                        printf($result);
                    } else {
                        printf("Permission ID: %s\n", $result->id);
                        array_push($ids, $result->id);
                    }
                }
            } finally {
                $driveService->getClient()->setUseBatch(false);
            }
            return $ids;
    } catch(Exception $e) {
        echo "Error Message: ".$e;
    }

}

.NET

drive/snippets/drive_v3/DriveV3Snippets/ShareFile.cs
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Requests;
using Google.Apis.Services;

namespace DriveV3Snippets
{
    // Class to demonstrate use-case of Drive modify permissions.
    public class ShareFile
    {
        /// <summary>
        /// Batch permission modification.
        /// </summary>
        /// <param name="realFileId">File id.</param>
        /// <param name="realUser">User id.</param>
        /// <param name="realDomain">Domain id.</param>
        /// <returns>list of modified permissions, null otherwise.</returns>
        public static IList<String> DriveShareFile(string realFileId, string realUser, string realDomain)
        {
            try
            {
                /* Load pre-authorized user credentials from the environment.
                 TODO(developer) - See https://developers.google.com/identity for
                 guides on implementing OAuth2 for your application. */
                GoogleCredential credential = GoogleCredential.GetApplicationDefault()
                    .CreateScoped(DriveService.Scope.Drive);

                // Create Drive API service.
                var service = new DriveService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive API Snippets"
                });

                var ids = new List<String>();
                var batch = new BatchRequest(service);
                BatchRequest.OnResponse<Permission> callback = delegate(
                    Permission permission,
                    RequestError error,
                    int index,
                    HttpResponseMessage message)
                {
                    if (error != null)
                    {
                        // Handle error
                        Console.WriteLine(error.Message);
                    }
                    else
                    {
                        Console.WriteLine("Permission ID: " + permission.Id);
                    }
                };
                Permission userPermission = new Permission()
                {
                    Type = "user",
                    Role = "writer",
                    EmailAddress = realUser
                };

                var request = service.Permissions.Create(userPermission, realFileId);
                request.Fields = "id";
                batch.Queue(request, callback);

                Permission domainPermission = new Permission()
                {
                    Type = "domain",
                    Role = "reader",
                    Domain = realDomain
                };
                request = service.Permissions.Create(domainPermission, realFileId);
                request.Fields = "id";
                batch.Queue(request, callback);
                var task = batch.ExecuteAsync();
                task.Wait();
                return ids;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}

刪除權限

如要撤銷檔案或資料夾的存取權,請在 permissions 資源上呼叫 delete() 方法,並將 fileIdpermissionId 路徑參數設為刪除權限。

如果是「我的雲端硬碟」中的項目,您可以刪除繼承的權限。刪除繼承的權限後,您將無法再存取該項目和子項目 (如有)。

共用雲端硬碟中的項目無法撤銷沿用權限。請改為更新或刪除上層檔案/資料夾的權限。

delete() 方法也可用於刪除直接套用至共用雲端硬碟檔案或資料夾的權限。

下列程式碼範例說明如何刪除 permissionId 來撤銷存取權。如果成功,回應主體會留白。如要確認權限已移除,請在 permissions 資源上使用 list() 方法,並提供 fileId 路徑參數。

要求

DELETE https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID

設定到期日來限制檔案存取權

與他人合作處理機密專案時,您可能會希望在一段時間後,限制他們存取雲端硬碟中的特定檔案。您可以為「我的雲端硬碟」中的檔案設定到期日,藉此限制或移除檔案存取權。

如要設定到期日,請按照下列步驟操作:

expirationTime 欄位會使用 RFC 3339 日期時間表示權限到期時間。到期時間有下列限制:

  • 僅限對使用者和群組權限設定到期時間。
  • 時間必須是未來的時間。
  • 時間不得晚於一年後。

如要進一步瞭解有效期限,請參閱下列文章: