ファイル、フォルダ、ドライブを共有する

すべての Google ドライブのファイル、フォルダ、共有ドライブには、permissions リソースが関連付けられています。各リソースは、特定の typeusergroupdomainanyone)と roleownerorganizerfileOrganizerwritercommenterreader)の権限を識別します。たとえば、ファイルには、特定のユーザー(type=user)に読み取り専用アクセス権(role=reader)を付与する権限と、特定のグループ(type=group)のメンバーにファイルにコメントを追加する権限(role=commenter)を付与する権限がある場合があります。

ロールと、各ロールで許可されるオペレーションの完全なリストについては、ロールと権限をご覧ください。

権限の伝播

権限は、親フォルダからすべての子アイテムに下方向に伝播されます。

  • デフォルトで継承: すべての子ファイルとフォルダは、親フォルダから権限を自動的に継承します。
  • 子アイテムで削減できない: 子アイテムで継承された権限を削除または削減することはできません。変更は元の親に対して行うか、フォルダでアクセス制限の設定を使用する必要があります。
  • 子で拡張可能: 子アイテムは、より制限の緩いロールを付与できます。たとえば、ユーザーが role=reader を持っているフォルダ内のファイルに role=writer を付与できます。
  • 移動時に再評価: アイテムを新しい親フォルダに移動すると、新しい親の権限がアイテムとその子に再評価されて適用されます。

ファイルリンクとアクセス制御

ファイルやフォルダを特定のユーザーやグループと共有する場合、アイテムにアクセスするための URL は変更されず、ユーザーごとに一意のリンクが生成されることもありません。代わりに、アイテムには fileId に基づく単一の定数リンクがあります。

ドライブは、アイテムの ACL を評価してアクセスを制御します。ユーザーがリンクを開こうとすると、ドライブは認証されたユーザーの ID を ACL と照合します。権限が取り消されるか、有効期限が切れると、ユーザーは ACL から削除されます。ユーザーがリンクに再度アクセスしようとすると、ドライブはアクセスを拒否します。

ファイルの機能について

permissions リソースは、誰がアクセスできるか(ACL)を定義しますが、現在のユーザーがアプリの UI で特定のアクションを実行できるかどうかを直接示すものではありません。

代わりに、files リソースには、ユーザーの役割とアイテムの設定に基づいて Google Drive API が動的に計算するブール値の capabilities フィールド(canCommentcanSharecanDelete など)のコレクションが含まれています。

ファイル機能を取得する

アプリの UI をレンダリングするときは、権限を直接解析するのではなく、files.capabilities を確認します。

  • fields=capabilities を使用して files.get メソッドを呼び出します。詳細については、特定のフィールドを返すをご覧ください。
  • 返されたブール値フラグを使用して、インターフェースで対応するアクションを有効または無効にします。たとえば、canCommentfalse の場合はコメントを無効にします。

ドライブのリソースを共有するシナリオ

次の表に、さまざまなロケーションとアイテムタイプ間でドライブ リソースを共有するために必要なロールと条件を示します。

ロケーション 項目 必要なロール 主な制約
マイドライブ ファイルまたはフォルダ owner または writer writersCanShare=false の場合は owner が必要です。
フォルダの有効期限付きのアクセス権を設定するには reader が必要です(有効期限を設定するをご覧ください)。
共有ドライブ ファイル organizerfileOrganizerwriterのいずれか writersCanShare は常に true として扱われます。
共有ドライブ フォルダ organizer sharingFoldersRequiresOrganizerPermissionfalse の場合、fileOrganizer も共有できます。
共有ドライブ メンバーシップ organizer user または group にのみ適用されます(ドメインには適用されません)。

権限を管理

次の表に、permissions リソースで使用可能なメソッドの概要を示します。

メソッド API エンドポイント 主なパラメータ リファレンス
作成 POST https://www.googleapis.com/drive/v3/files/{fileId}/permissions roletypeemailAddress、またはdomain permissions.create
取得 GET https://www.googleapis.com/drive/v3/files/{fileId}/permissions/{permissionId} fields permissions.get
リスト GET https://www.googleapis.com/drive/v3/files/{fileId}/permissions pageSizesupportsAllDrivespageToken permissions.list
更新 PATCH https://www.googleapis.com/drive/v3/files/{fileId}/permissions/{permissionId} roleallowFileDiscovery permissions.update
削除 DELETE https://www.googleapis.com/drive/v3/files/{fileId}/permissions/{permissionId} supportsAllDrives permissions.delete

権限を作成する

ファイル、フォルダ、共有ドライブを共有するには、fileId を使用して permissions リソースの create メソッドを呼び出します。権限を作成すると、新しい ACL エントリがアイテムに追加され、割り当てられた permissionId が返されます。

リクエスト本文で、次のフィールドを指定します。

  • role: 付与するアクセスレベル(readercommenterwriter など)。完全なリストについては、ロールと権限をご覧ください。
  • type: 付与対象者のスコープ(usergroupdomain、または anyone)。
  • 受領者の識別子type に基づいて必須):
    • emailAddress: typeuser または group の場合は必須です。
    • domain: typedomain の場合は必須。

次のコードサンプルは、権限の作成方法を示しています。レスポンスは、割り当てられた permissionId を含む permissions リソースのインスタンスを返します。

リクエスト

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

レスポンス

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

対象グループと共有する

対象グループとは、ユーザーにアイテムの共有先として推奨できるグループ(部署やチームなど)のことです。アイテムの共有先を組織全体ではなく、一部の相手に絞るよう促すことができます。対象グループを使用すると、データのセキュリティとプライバシーを強化し、ユーザーが適切に共有しやすくなります。

対象グループと共有するには、type=domain を設定し、domain<TARGET_AUDIENCE_ID>.audience.googledomains.com に設定します。Google 管理コンソールで対象グループを見つける方法や作成する方法について詳しくは、対象グループについてをご覧ください。

ユーザーがターゲット オーディエンスとどのようにやり取りするかを確認するには、リンク共有のユーザー エクスペリエンスをご覧ください。

権限を取得する

権限を取得するには、fileIdpermissionId のパスパラメータを使用して、permissions リソースの get メソッドを呼び出します。権限 ID がわからない場合は、まずすべての権限を一覧表示します。

リストの権限

ファイル、フォルダ、共有ドライブの権限を一覧表示するには、必要な fileId パスパラメータを指定して、permissions リソースの list メソッドを呼び出します。

次のオプションのクエリ パラメータを含めて、レスポンスをページ設定またはフィルタできます。

  • pageSize(省略可): ページごとに返す権限の最大数。共有ドライブ内のファイルに設定されていない場合、最大で 100 件の結果が返されます。共有ドライブにないファイルに対して設定されていない場合は、リスト全体が返されます。

  • pageToken(省略可): 後続のページを取得するための、前回のリスト呼び出しのページトークン。

  • supportsAllDrives(省略可): リクエスト元のアプリがマイドライブと共有ドライブの両方をサポートしているかどうか。

  • useDomainAdminAccess(省略可): ドメイン管理者としてリクエストを発行するには、true に設定します。fileId パラメータが共有ドライブを参照し、リクエスト元が共有ドライブが属するドメインの管理者である場合、リクエスト元にアクセス権が付与されます。詳しくは、ドメイン管理者として共有ドライブを管理するをご覧ください。

  • includePermissionsForView(省略可): レスポンスに含める追加の表示権限。published のみがサポートされています。

  • fields(省略可): レスポンスで返す特定のフィールド。デフォルトでは、listidtypekindrole のみを返します。追加のフィールド(permissionDetails など)を返すには、このパラメータを使用して指定します。詳細については、特定のフィールドを返すをご覧ください。

ロールソースを特定する

ファイルまたはフォルダのロールを変更するには、ロールのソースを知っておく必要があります。共有ドライブの場合、ロールのソースは、共有ドライブのメンバーシップ、フォルダのロール、ファイルのロールに基づくことができます。

共有ドライブまたはそのドライブ内のアイテムのロールソースを特定するには、fileIdpermissionId のパスパラメータ、permissionDetails フィールドに設定された fields パラメータを使用して、permissions リソースの get メソッドを呼び出します。

permissionId を見つけるには、fileId パスパラメータを使用して permissions リソースの list メソッドを使用します。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
    }
  ]
}

権限を更新する

ファイルまたはフォルダの権限を更新するには、割り当てられたロールを変更します。ロールのソースの検索の詳細については、ロールのソースを特定するをご覧ください。

  1. permissions リソースで update メソッドを呼び出し、fileId パス パラメータを関連付けられたファイル、フォルダ、共有ドライブに設定し、permissionId パス パラメータを変更する権限に設定します。permissionId を見つけるには、fileId パスパラメータを指定して permissions リソースの list メソッドを使用します。

  2. リクエストで、新しい role を指定します。

ユーザーまたはグループがすでにメンバーである場合でも、共有ドライブ内の個々のファイルまたはフォルダに対する権限を付与できます。たとえば、アレックスは共有ドライブのメンバーシップの一部として role=commenter を持っています。ただし、アプリは共有ドライブ内のファイルに対する Alex の role=writer を付与できます。この場合、新しいロールはメンバーシップを通じて付与されたロールよりも権限が大きいため、新しい権限がファイルまたはフォルダの有効なロールになります。

パッチ セマンティクスを使用して更新を適用できます。つまり、リソースに部分的な変更を加えることができます。リクエストで、変更するフィールドを明示的に設定する必要があります。リクエストに含まれていないフィールドは、既存の値が保持されます。詳細については、部分リソースの操作をご覧ください。

ロールの変更に加えて、権限 typedomain または anyone の場合は、アイテムの検出可能性を変更することもできます。共有ファイルを検索可能または非公開にするには、パッチ リクエストに allowFileDiscovery ブール値フィールドを含めます。これを true に設定すると、指定したユーザーに直接リンクが提供されていない場合でも、そのユーザーの検索結果にアイテムが表示されます。この設定を変更するために権限を削除して再作成する必要はありません。

次のコードサンプルは、ファイルまたはフォルダの権限を commenter から writer に変更する方法を示しています。レスポンスは permissions リソースのインスタンスを返します。

リクエスト

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

レスポンス

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

バッチ リクエストで複数の権限を更新する

同じファイル、フォルダ、共有ドライブに対する権限の同時変更はサポートされていません。この制限は、同じ受信者または異なる受信者の権限を変更する場合、リクエストが単一のアプリから送信されるか複数のユーザーから送信されるかに関係なく、すべての変更オペレーション(更新や削除など)に適用されます。

ドライブは、アイテムの権限を単一の ACL として評価して更新します。同時オペレーションは、競合状態を引き起こし、権限の変更をサイレントに上書きしたり、sharingRateLimitExceeded エラーをトリガーしたりする可能性があります。

競合を回避するには、同じアイテムに対する権限の変更を順番に実行するか、バッチ リクエストを使用して、1 つのリクエストで複数の権限を変更します。

次に、クライアント ライブラリを使用して権限の一括変更を行う例を示します。

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
import {GoogleAuth} from 'google-auth-library';
import {google} from 'googleapis';

/**
 * Shares a file with a user and a domain.
 * @param {string} fileId The ID of the file to share.
 * @param {string} targetUserEmail The email address of the user to share with.
 * @param {string} targetDomainName The domain to share with.
 * @return {Promise<Array<string>>} A promise that resolves to an array of permission IDs.
 */
async function shareFile(fileId, targetUserEmail, targetDomainName) {
  // Authenticate with Google and get an authorized client.
  // TODO (developer): Use an appropriate auth mechanism for your app.
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Drive API client (v3).
  const service = google.drive({version: 'v3', auth});

  /** @type {Array<string>} */
  const permissionIds = [];

  // The permissions to create.
  const permissions = [
    {
      type: 'user',
      role: 'writer',
      emailAddress: targetUserEmail, // e.g., 'user@partner.com'
    },
    {
      type: 'domain',
      role: 'writer',
      domain: targetDomainName, // e.g., 'example.com'
    },
  ];

  // Iterate through the permissions and create them one by one.
  for (const permission of permissions) {
    const result = await service.permissions.create({
      requestBody: permission,
      fileId,
      fields: 'id',
    });

    if (result.data.id) {
      permissionIds.push(result.data.id);
      console.log(`Inserted permission id: ${result.data.id}`);
    } else {
      throw new Error('Failed to create permission');
    }
  }
  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;
        }
    }
}

権限を削除する

ファイルまたはフォルダへのアクセスを取り消すには、fileIdpermissionId のパス パラメータを使用して、permissions リソースの delete メソッドを呼び出します。

継承された権限は、子アイテムで直接取り消すことはできません。代わりに親フォルダの権限を更新または削除します(または、アクセス制限の設定を使用します)。

親アイテムからユーザーのアクセス権を削除すると、その親から継承された権限のみが取り消されます。ユーザーに子アイテムに対する直接権限も付与されている場合、その直接アクセスは維持されます。権限が削除されたことを確認するには、fileId を使用して list を呼び出します。

有効期限を設定する

ファイルまたはフォルダへの一時的なアクセス権を付与するには、create メソッドまたは update メソッドを呼び出すときに、expirationTime フィールド(RFC 3339 の日時)を設定します。

有効期限には次の制限があります。

  • user 権限と group 権限でのみ設定できます(domain 権限や anyone 権限では設定できません)。
  • 時間は 1 年以内の未来の日時にする必要があります。
  • フォルダの場合、一時的なアクセス権は reader ロールでのみサポートされます。