Делитесь файлами, папками и дисками

Каждый файл, папка и общий диск Google Drive имеют связанные с ними ресурсы permissions . Каждый ресурс определяет разрешение для определенного type ( user , group , domain , anyone ) и role ( owner , organizer , организатор fileOrganizer , writer , commenter , reader ). Например, файл может иметь разрешение, предоставляющее определенному пользователю ( type=user ) доступ только для чтения ( role=reader ), в то время как другое разрешение предоставляет членам определенной группы ( type=group ) возможность добавлять комментарии к файлу ( role=commenter ).

Полный список ролей и разрешенных для каждой из них операций см. в разделе «Роли и разрешения» .

Как распространяются разрешения

Права доступа распространяются от родительских папок ко всем дочерним элементам:

  • Наследуется по умолчанию : все дочерние файлы и папки автоматически наследуют права доступа от родительской папки.
  • Нельзя уменьшить права доступа для дочерних элементов : Вы не можете удалить или уменьшить унаследованные права доступа для дочернего элемента. Изменения должны быть внесены в родительский элемент, либо папка должна использовать настройки ограниченного доступа .
  • Может быть расширено для дочерних элементов : дочерний элемент может предоставлять более разрешительную роль, например, предоставлять role=writer файлу внутри папки, где у пользователя есть role=reader .
  • Переоценка при перемещении : При перемещении элемента в новую родительскую папку переоцениваются и применяются разрешения новой родительской папки к этому элементу и его дочерним элементам.

Файловые ссылки и контроль доступа

Когда вы предоставляете доступ к файлу или папке определенному пользователю или группе, URL-адрес для доступа к элементу не меняется, и для каждого пользователя не генерируется уникальная ссылка. Вместо этого элемент имеет одну постоянную ссылку, основанную на его fileId .

Drive контролирует доступ, оценивая список контроля доступа (ACL) элемента. Когда пользователь пытается открыть ссылку, Drive проверяет его подлинность по списку ACL. Если разрешение отозвано или истекает срок его действия, пользователь удаляется из списка ACL. Если пользователь попытается перейти по ссылке снова, Drive откажет в доступе.

Понимание возможностей файлов

Ресурс permissions определяет, кто имеет доступ (ACL), но не указывает напрямую, может ли текущий пользователь выполнять определенное действие в пользовательском интерфейсе вашего приложения.

Вместо этого ресурс files содержит набор логических полей capabilities (таких как canComment , canShare или canDelete ), которые API Google Drive вычисляет динамически на основе роли пользователя и настроек элемента.

Получить возможности файла

При отрисовке пользовательского интерфейса вашего приложения проверяйте files.capabilities , а не анализируйте разрешения напрямую:

  • Вызовите метод files.get с fields=capabilities . Для получения дополнительной информации см. раздел «Возвращение определенных полей» .
  • Используйте возвращаемые логические флаги для включения или отключения соответствующих действий в вашем интерфейсе. Например, отключите комментирование, если canComment имеет false .

Сценарии совместного использования ресурсов Диска

В таблице ниже показаны необходимые роли и условия для совместного использования ресурсов Диска в разных местах и ​​для разных типов элементов:

Расположение Элемент Требуемые роли Ключевые ограничения
Моя поездка Файл или папка owner или writer Требуется указать owner , если writersCanShare=false .
Для ограничения доступа к папкам требуется reader (см. раздел «Установка даты истечения срока действия »).
Общий диск Файл organizer , fileOrganizer или writer writersCanShare всегда рассматривается как true .
Общий диск Папка organizer fileOrganizer также может предоставлять доступ, если sharingFoldersRequiresOrganizerPermission имеет false .
Общий диск Членство organizer Применяется только к user или group (не к доменам).

Управление правами доступа

В следующей таблице приведено краткое описание методов, доступных для ресурса permissions :

Метод конечная точка API Ключевые параметры Ссылка
Создавать POST https://www.googleapis.com/drive/v3/files/{fileId}/permissions role , type , emailAddress или 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 pageSize , supportsAllDrives , pageToken permissions.list
Обновлять PATCH https://www.googleapis.com/drive/v3/files/{fileId}/permissions/{permissionId} role , allowFileDiscovery permissions.update
Удалить DELETE https://www.googleapis.com/drive/v3/files/{fileId}/permissions/{permissionId} supportsAllDrives permissions.delete

Создайте разрешение

Чтобы предоставить общий доступ к файлу, папке или общему диску, вызовите метод create ресурса permissions , указав fileId . Создание разрешения добавляет новую запись ACL к элементу и возвращает присвоенный permissionId .

В теле запроса укажите следующие поля:

  • role : Уровень доступа, который необходимо предоставить (например, reader , commenter или writer ). Полный список см. в разделе «Роли и разрешения» .
  • type : Область действия разрешения для получателя ( user , group , domain или anyone ).
  • Идентификатор получателя гранта (обязательно в зависимости от type ):
    • emailAddress : Обязательно, если typeuser или group .
    • domain : Обязательно, если typedomain .

Приведённый ниже пример кода демонстрирует, как создать разрешение. В ответ возвращается экземпляр ресурса permissions , включая присвоенный permissionId ).

Запрос

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 см. в разделе «О целевых аудиториях» .

Чтобы узнать, как пользователи взаимодействуют с целевой аудиторией, см. раздел «Пользовательский опыт при обмене ссылками» .

Получите разрешение

Чтобы получить разрешение, вызовите метод get ресурса permissions с параметрами ` fileId и permissionId пути. Если идентификатор разрешения неизвестен, сначала перечислите все разрешения .

Список разрешений

Чтобы вывести список разрешений для файла, папки или общего диска, вызовите метод list ресурса permissions с обязательным параметром fileId path`.

Для постраничной навигации или фильтрации ответа можно добавить любой из следующих необязательных параметров запроса :

  • pageSize (необязательно): Максимальное количество разрешений, возвращаемых на странице. Если не задано для файлов на общем диске, возвращается не более 100 результатов. Если не задано для файлов, не находящихся на общем диске, возвращается весь список.

  • pageToken (необязательно): Токен страницы из предыдущего вызова списка для получения следующей страницы.

  • supportsAllDrives (необязательно): указывает, поддерживает ли запрашивающее приложение одновременно «Мой диск» и общие диски.

  • useDomainAdminAccess (необязательно): Установите значение true , чтобы отправить запрос от имени администратора домена. Запрашивающему предоставляется доступ, если параметр fileId относится к общему диску, и запрашивающий является администратором домена, к которому принадлежит общий диск. Для получения дополнительной информации см. раздел «Управление общими дисками от имени администраторов домена» .

  • includePermissionsForView (необязательно): Дополнительные разрешения на просмотр, которые будут включены в ответ. Поддерживается только published .

  • fields (необязательно): Конкретные поля, которые следует вернуть в ответе. По умолчанию list возвращает только id , type , kind и role . Чтобы вернуть дополнительные поля (например, permissionDetails ), укажите их с помощью этого параметра. Дополнительную информацию см. в разделе «Возвращение определенных полей» .

Определите источник роли

Чтобы изменить роль файла или папки, необходимо знать источник этой роли. Для общих дисков источником роли может быть членство в общем диске, роль папки или роль файла.

Чтобы определить источник ролей для общего диска или элементов на этом диске, вызовите метод get ресурса permissions с параметрами fileId и permissionId , а параметр ` fields установите равным полю permissionDetails .

Чтобы найти permissionId , используйте метод list ресурса permissions с параметром fileId path. Чтобы получить поле permissionDetails в запросе list , установите параметр fields в значение permissions/permissionDetails .

В этом поле перечислены все унаследованные и прямые права доступа к файлам для пользователя, группы или домена.

Приведенный ниже пример кода показывает, как определить источник роли. В ответ возвращается permissionDetails permissions ресурса. Поле inheritedFrom содержит идентификатор элемента, от которого наследуется разрешение.

Запрос

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. Вызовите метод update ресурса permissions , указав в параметре fileId path` путь к связанному файлу, папке или общему диску, а в параметре permissionId path` — разрешение на изменение. Чтобы найти ` permissionId , используйте метод list ресурса permissions с параметром ` fileId path`.

  2. В запросе укажите новую role .

Вы можете предоставлять разрешения на отдельные файлы или папки на общем диске, даже если пользователь или группа уже являются его членами. Например, у Алекса есть role=commenter в рамках его членства на общем диске. Однако ваше приложение может предоставить Алексу role=writer для файла на общем диске. В этом случае, поскольку новая роль более разрешительная, чем роль, предоставленная в рамках его членства, новое разрешение становится фактической ролью для файла или папки.

Вы можете применять обновления с помощью семантики патчей, то есть вносить частичные изменения в ресурс. Необходимо явно указать поля, которые вы собираетесь изменить, в вашем запросе. Любые поля, не включенные в запрос, сохраняют свои существующие значения. Для получения дополнительной информации см. раздел «Работа с частично измененными ресурсами» .

Помимо изменения ролей, вы также можете изменить доступность элемента, если type разрешения — domain или 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 .

Во избежание конфликтов выполняйте изменения разрешений для одного и того же элемента последовательно или используйте пакетные запросы для изменения нескольких разрешений в одном запросе.

Ниже приведён пример пакетного изменения прав доступа к клиентской библиотеке.

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

}

.СЕТЬ

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

Удалить разрешение

Чтобы отозвать доступ к файлу или папке, вызовите метод delete ресурса permissions , указав в качестве параметров fileId и permissionId path.

Наследованные разрешения нельзя отозвать напрямую для дочерних элементов. Вместо этого обновите или удалите разрешения в родительской папке (или используйте параметр ограниченного доступа ).

Обратите внимание, что удаление доступа пользователя к родительскому элементу отменяет только разрешения, унаследованные от этого родительского элемента. Если пользователю также были предоставлены прямые разрешения на дочерний элемент, этот прямой доступ сохраняется. Чтобы подтвердить удаление разрешения, вызовите функцию list с указанием fileId .

Установите срок действия

Для предоставления временного доступа к файлу или папке установите поле expirationTime ( RFC 3339 дата-время ) при вызове методов create или update .

Срок действия ограничен следующими условиями:

  • Этот параметр можно установить только для прав доступа user и group (не domain или anyone ).
  • Время должно быть в будущем, максимум — в течение одного года.
  • Для папок временный доступ поддерживается только для роли reader .