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

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

如需各角色和每個角色允許的作業的完整清單,請參閱角色與權限

共用雲端硬碟資源的情境

共用情境共有五種:

  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。只有使用者和群組可以成為共用雲端硬碟的成員。

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

與機密專案的使用者合作時,您可能會希望在一段時間後,限制他們對雲端硬碟中的特定檔案存取權。您可以針對「我的雲端硬碟」中的檔案,設定到期日來限製或移除該檔案的存取權。

如何設定到期日:

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

  • 只能在使用者和群組權限上進行設定。
  • 時間必須設在未來。
  • 時間不得超過未來一年。

如要進一步瞭解到期日,請參閱下列文章:

權限傳播

資料夾的權限清單會向下傳播,且所有子項檔案和資料夾都會繼承父項的權限。每當權限或階層發生變更時,系統就會以遞迴方式在所有巢狀資料夾中執行傳播作業。舉例來說,如果檔案存在於資料夾中,而該資料夾隨後移到另一個資料夾,則新資料夾的權限會套用至該檔案。如果新資料夾授予檔案使用者的新角色 (例如「寫入者」),則會覆寫舊角色。

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

無法從共用雲端硬碟的檔案或資料夾中移除沿用的權限。 相反地,您必須根據繼承的直接或間接父項來調整這些權限。您可以移除「我的雲端硬碟」或「與我共用」下方項目沿用的權限。

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

能力

權限資源最終不會決定目前使用者是否能對檔案或資料夾執行動作。相反地,檔案資源會包含一組布林值 capabilities 欄位,用於表示動作是否可以在檔案或資料夾上執行。Google Drive API 會根據目前的使用者對檔案或資料夾關聯的權限資源設定這些欄位。

舉例來說,當 Alex 登入應用程式並嘗試共用檔案時,系統會檢查 Alex 的角色是否有該檔案的權限。如果角色允許使用者共用檔案,檔案的相關 capabilities (例如 canShare) 會填入與角色相關的資料。如果 Alex 想共用檔案,應用程式會檢查 capabilities,確認 canShare 已設為 true

如需擷取檔案 capabilities 的範例,請參閱「驗證使用者權限」。

建立權限

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

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

  • rolerole 欄位會識別 type 可執行的作業。舉例來說,如果具備 type=userrole=reader 的權限,就會授予特定使用者檔案或資料夾的唯讀存取權。或者,具備 type=domainrole=commenter 的權限可讓網域中的所有使用者對檔案加上註解。如需各個角色和角色允許操作的完整清單,請參閱角色與權限

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

在建立 type=domain 的權限時,您還必須提供 domain,將特定網域連結至該權限。

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

  1. 搭配相關檔案或資料夾的 fileId,使用 permissions.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"
    }
  ]
}

驗證使用者權限

應用程式開啟時,應檢查檔案的功能並轉譯 UI,以反映目前使用者的權限。舉例來說,如果使用者的檔案上沒有 canComment 功能,則應該在 UI 中停用註解功能。

如要進一步瞭解 capabilities,請參閱上方的「功能」一節。

如要檢查功能,請使用 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,
    "canChangeSecurityUpdateEnabled": false,
    "canComment": true,
    "canCopy": true,
    "canDelete": true,
    "canDownload": true,
    "canEdit": true,
    "canListChildren": false,
    "canModifyContent": true,
    "canModifyContentRestriction": true,
    "canModifyLabels": true,
    "canMoveChildrenWithinDrive": false,
    "canMoveItemOutOfDrive": true,
    "canMoveItemWithinDrive": true,
    "canReadLabels": true,
    "canReadRevisions": true,
    "canRemoveChildren": false,
    "canRemoveMyDriveParent": true,
    "canRename": true,
    "canShare": true,
    "canTrash": true,
    "canUntrash": true
  }
}

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

如要變更檔案或資料夾的角色,您必須知道角色的來源。 如為共用雲端硬碟,角色來源可根據共用雲端硬碟的成員、資料夾的角色或檔案角色而定。

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

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

顯示範例

以下程式碼範例說明如何判斷角色來源。回應會傳回 Permission 資源的 permissionDetailsinheritedFrom 欄位會提供繼承權限的項目 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
    }
  ]
}

變更權限

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

  1. 使用變更權限的 permissionId 呼叫 permissions.update,並針對關聯檔案、資料夾或共用雲端硬碟呼叫 fileId。如要尋找 permissionId,請將 permissions.listfileId 搭配使用。

  2. 在要求中識別新的 role

即使使用者或群組已經是成員,您仍可針對共用雲端硬碟中的個別檔案或資料夾授予權限。舉例來說,Alex 擁有 role=commenter 做為共用雲端硬碟成員。不過,您的應用程式可以為共用雲端硬碟中的檔案授予 Alex role=writer,在這種情況下,由於新角色的權限比成員資格賦予的角色更寬鬆,因此新權限將成為該檔案或資料夾的「有效角色」

顯示範例

以下程式碼範例說明如何將檔案或資料夾的權限從加註者變更為寫入者。回應會傳回 Permission 資源的執行個體。

要求

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 呼叫 delete,以刪除權限。

對於「我的雲端硬碟」中的項目,您可以刪除繼承的權限。刪除繼承的權限會撤銷該項目和子項項目的存取權 (如果有的話)。

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

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

顯示範例

下列程式碼範例說明如何透過刪除 permissionId 撤銷存取權。如果成功,回應主體會是空白的。如要確認權限已移除,請搭配 fileId 使用 permissions.list

要求

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

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

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

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

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

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

在個人帳戶之間轉移檔案擁有權

您可以在一個個人帳戶之間轉移檔案擁有權。不過,除非潛在的新擁有者明確同意轉移,否則雲端硬碟不會在兩個個人帳戶之間轉移檔案擁有權。如要將檔案擁有權從某個個人帳戶轉移到另一個個人帳戶:

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