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

Stay organized with collections Save and categorize content based on your preferences.

每個 Google 雲端硬碟檔案、資料夾和共用雲端硬碟都有相關聯的權限資源。每個資源都會識別特定 type (使用者、群組、網域、任何人) 和 role 的權限,例如「加註者」或「讀取者」。舉例來說,某個檔案可能擁有授予特定使用者 (type=user) 唯讀存取權 (role=reader) 的權限,而其他權限則授予特定群組成員 (type=group) 為檔案新增註解的權限 (role=commenter)。

如需角色清單和各角色允許的操作完整清單,請參閱角色

共用雲端硬碟資料的適用情境

共用情況分為以下 5 種:

  1. 如要共用「我的雲端硬碟」中的檔案,使用者必須具備「寫入者」或更高的角色。

    • 如果檔案的 writersCanShare 布林值已設為 False,使用者就必須具備「擁有者」角色。

    • 具備「寫入者」角色的使用者俱有臨時的日期與時間限制,無法共用檔案。

    詳情請參閱新增到期日一文。

  2. 如要共用「我的雲端硬碟」中的資料夾,使用者必須具備「寫入者」或更高層級的角色。

    • 如果檔案的 writersCanShare 布林值已設為 False,則使用者必須具備「owner」權限較多的角色。

    • 「我的雲端硬碟」資料夾不得使用「寫入者」角色的臨時存取權 (設有到期日和時間)。

  3. 如要在共用雲端硬碟中共用檔案,使用者必須具備「寫入者」或更高層級的角色。

    • writersCanShare 設定不適用於共用雲端硬碟中的項目。 系統會將其視為一律設為 True

    • 共用雲端硬碟不允許暫時存取 (設有到期日和時間)。

  4. 如要共用共用雲端硬碟中的資料夾,使用者必須具有「發起人」角色。

  5. 如要管理共用雲端硬碟成員,使用者必須具備「發起人」角色。只有使用者和群組可以成為共用雲端硬碟成員。

權限傳播

資料夾的權限清單會向下傳播,而所有子項檔案和資料夾都會繼承父項的權限。每當權限或階層發生變更時,系統會透過所有巢狀資料夾遞迴。例如,如果檔案位於資料夾內,而該資料夾隨後移動到其他資料夾中,新資料夾的權限就會套用到該檔案。如果新資料夾為檔案使用者授予新角色 (例如「寫入者」),就會覆寫舊角色。

反之,如果檔案沿用了資料夾的「寫入者」角色,然後移到另一個提供「讀取者」角色的資料夾,則該檔案會繼承「讀取者」角色。

您無法從共用雲端硬碟的檔案或資料夾中移除繼承的權限。 因此,您必須在沿用權限的直接或間接父項上調整這些權限。沿用的權限可以從「我的雲端硬碟」或「與我共用的項目」底下 移除。

相反地,您可以在「我的雲端硬碟」中的檔案或資料夾覆寫沿用的權限。所以如果檔案繼承「我的雲端硬碟」資料夾的「寫入者」角色,您可以在該檔案中設定「讀取者」角色,以降低其權限層級。

功能

「權限」資源最終無法確定目前使用者針對檔案或資料夾執行的動作。而 Files 資源則包含一系列布林值 capabilities 欄位的集合,用來表示某個檔案或資料夾是否可執行特定動作。Google Drive API 會根據目前與此檔案或資料夾相關聯的使用者權限資源,設定這些欄位。

舉例來說,Alex 登入您的應用程式並嘗試分享檔案時,系統會根據檔案的權限檢查 Alex 的角色。如果角色允許使用者共用檔案,與該檔案相關的 capabilities (例如 canShare) 就會填入與角色相關的內容。如果小莉想要共用檔案,應用程式會檢查 capabilities 以確保 canShare 已設為 true

建立權限

建立權限需要下列 2 個欄位:

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

  • rolerole 欄位可識別 type 可執行的操作。舉例來說,具備 type=userrole=reader 的權限可授予使用者唯讀檔案或資料夾的權限。或者,具備 type=domainrole=commenter 的權限可讓網域中的所有人在檔案中新增註解。如需角色清單和各角色允許的操作完整清單,請參閱角色

建立權限為 type=usertype=group 的權限時,您還必須提供 emailAddress 以將特定使用者或群組連結至該權限。

建立權限時,必須一併提供 type=domain 權限,以便將特定網域連結至該權限。domain

如何建立權限:

  1. 使用 permissions.create 方法搭配相關聯的檔案或資料夾使用 fileId
  2. 在要求主體中,識別 typerole
  3. 如果為 type=usertype=group,請提供 emailAddress。如果為 type=domain,請提供 domain

擷取檔案、資料夾或共用雲端硬碟的所有權限

使用 permissions.list 方法擷取檔案、資料夾或共用雲端硬碟的所有權限。

驗證使用者權限

應用程式開啟檔案時,應檢查檔案的功能,並呈現使用者介面以反映目前使用者的權限。例如,如果使用者的檔案沒有 canComment 功能,則應在使用者介面中停用留言功能。

如要確認功能,請呼叫 files.get,並將 fileIdfields 參數設為 capabilities 欄位。

如需使用 fields 參數傳回欄位的詳細資訊,請參閱傳回檔案的特定欄位

決定共用雲端硬碟檔案和資料夾的角色來源

如要變更檔案或資料夾的角色,必須知道角色的來源。 在共用雲端硬碟中,角色的依據可以是共用雲端硬碟成員身分、資料夾角色,或檔案角色。

如要判斷共用雲端硬碟的角色或該雲端硬碟內的項目來源,請呼叫 permissions.get,並將 fileIdpermissionIdfields 參數設為 permissionDetails 欄位。如要尋找 permissionId,請使用 permissions.list 搭配 fileId

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

變更權限

如要變更檔案或資料夾的權限,您可以變更已指派的角色:

  1. 呼叫 permissions.update 並具有權限變更 permissionId,以及相關檔案、資料夾或共用雲端硬碟的 fileId。如要尋找 permissionId,請使用 permissions.list 搭配 fileId

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

即使使用者或群組已經是成員,您也可以對共用雲端硬碟中的個別檔案或資料夾授予權限。舉例來說,小莉已將 commenter 角色視為共用雲端硬碟的成員。不過,您的應用程式可將共用檔案的 writer 角色授予小莉。在此情況下,新角色比透過成員授予的角色更為寬鬆,新權限也成為檔案或資料夾的有效角色

撤銷檔案或資料夾的存取權

如要撤銷檔案或資料夾的存取權,請使用 fileIdpermissionId 呼叫 delete 以刪除權限。

刪除「我的雲端硬碟」中的項目時,可以刪除沿用的權限。 刪除沿用的權限將會撤銷該項目和子項目的存取權 (如果有的話)。

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

delete 作業也可用來刪除直接套用至共用雲端硬碟檔案或資料夾的權限。

將檔案擁有權轉移給同一機構中的其他 Google Workspace 帳戶

您可以將「我的雲端硬碟」中現有的檔案擁有權從 Google Workspace 帳戶轉移到同一個機構中的其他帳戶。擁有共用雲端硬碟的機構會擁有其中檔案。因此,共用雲端硬碟中的檔案和資料夾不支援擁有權轉移。共用雲端硬碟的管理者可以將共用雲端硬碟中的項目移至自己的「我的雲端硬碟」,將擁有權轉移給他們。

如要轉移「我的雲端硬碟」中的檔案擁有權,請執行下列任一操作:

  • 建立檔案存取權限,授予特定使用者 (type=user) 擁有者存取權 (role=owner)。

  • 使用 owner 角色更新現有檔案的權限,並將擁有權轉移給指定使用者 (transferOwnership=true)。

將檔案擁有權從某個消費者帳戶轉移至另一個個人帳戶

檔案的擁有權可以在一個個人帳戶之間轉移至另一個個人帳戶。不過,在潛在的新擁有者明確同意轉移作業之前,雲端硬碟不會將 2 個個人帳戶的檔案的擁有權轉移給他人。如要將檔案擁有權從某個消費者帳戶轉移至另一個個人帳戶:

  1. 目前的擁有者必須建立或更新潛在新擁有者的檔案權限,以啟動擁有權轉移程序。權限必須包含以下設定:role=writertype=userpendingOwner=true。如果新擁有者為潛在擁有者建立權限,系統會傳送電子郵件給潛在新擁有者,通知他們要求有人授予檔案擁有權。

  2. 新擁有者會建立或更新檔案權限,以接受擁有權轉移要求。權限必須包含以下設定:role=ownertransferOwnership=true。如果新擁有者建立新權限,系統會傳送電子郵件給原擁有者,說明擁有權已轉移。

檔案轉移後,前一位擁有者的角色會降級為 writer

透過批次要求變更多項權限

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

以下是透過用戶端程式庫執行批次權限修改的範例。

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
from __future__ import print_function

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