简体   繁体   English

如何使用 Google Drive API 通过服务帐户访问域中的共享文件?

[英]How to get access to shared files in a domain with a service account using the Google Drive API?

I have been trying to access some simple information on Google Shared Drive files from a Python 3.7 script:我一直在尝试从 Python 3.7 脚本访问有关 Google Shared Drive 文件的一些简单信息:

The last time a Google Sheets file on a shared drive was modified.上次修改共享驱动器上的 Google 表格文件的时间。

I have created a service account in the GCP Drive API menu and it can access/edit/etc Google Sheets without any problem the via the Sheets API.我在 GCP Drive API 菜单中创建了一个服务帐户,它可以通过 Sheets API 毫无问题地访问/编辑/等 Google Sheets。

However, when I use the same service account for the Drive API, it does not return any info on files outside its own folder (which contains only one file: "Getting Started").但是,当我为 Drive API 使用相同的服务帐户时,它不会返回有关其自己文件夹(仅包含一个文件:“入门”)之外的文件的任何信息。 The account has access to all Cloud APIs, has Domain-wide Delegation with all scopes related to Drive API included in the API control menu in GSuite.该帐户可以访问所有 Cloud API,具有域范围的委派,其中包含与 GSuite 的 API 控制菜单中包含的 Drive API 相关的所有范围。

The email address of the service account has been properly added to all folders in the shared drive.服务帐户的电子邮件地址已正确添加到共享驱动器中的所有文件夹。

Any idea?任何的想法? Basically all I need is to know when is the last time a sheet was modified by any given user.基本上我只需要知道任何给定用户最后一次修改工作表是什么时候。

secret_cred_file = ...
SCOPES = ['https://www.googleapis.com/auth/drive']
credentials = service_account.Credentials.from_service_account_file(secret_cred_file, scopes=SCOPES)
service = discovery.build('drive', 'v3', credentials=credentials)
results = service.files().list(pageSize=10, fields="nextPageToken, files(id, name,modifiedTime)").execute()
items = results.get('files', [])

PS: I have seen this: Getting files from shared folder but it does not help PS:我见过这个: 从共享文件夹中获取文件但它没有帮助

You need to impersonate your users.您需要模拟您的用户。

It is not possible to make an API call to get all the files in your domain in one go.不可能通过调用 API 一次性获取域中的所有文件。

In the Service Accounts article it says:服务帐户文章中,它说:

Service accounts are not members of your Google Workspace domain, unlike user accounts.与用户帐户不同,服务帐户不是您的 Google Workspace 域的成员。 For example, if you share assets with all members in your Google Workspace domain, they will not be shared with service accounts...This doesn't apply when using domain-wide delegation, because API calls are authorized as the impersonated user, not the service account itself.例如,如果您与 Google Workspace 网域中的所有成员共享资产,它们将不会与服务帐号共享...这在使用域范围委派时不适用,因为 API 调用被授权为模拟用户,而不是服务帐户本身。

So unfortunately you can't just share a file with a service account.所以很遗憾,您不能只与服务帐户共享文件。 To get all the files in your domain you would need to:要获取域中的所有文件,您需要:

  1. Impersonate an admin account and get a list of all the users.模拟管理员帐户并获取所有用户的列表。
  2. Impersonate each user and make Drive API request for each.模拟每个用户并为每个用户发出 Drive API 请求。

Here is a good quick start for the Python Library , specifically this section这是Python 库的一个很好的快速入门,特别是本节

Remember to set permissions in both the GCP console and the Admin console though it seems like you have done this correctly.请记住在 GCP 控制台和管理控制台中设置权限,尽管您似乎已正确完成此操作。

Example script示例脚本

from google.oauth2 import service_account
from googleapiclient.discovery import build

def main():

    SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly',
        'https://www.googleapis.com/auth/admin.directory.user.readonly']
    SERVICE_ACCOUNT_FILE = 'credentials.json'

    credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

    # Admin SDK to get users
    admin_delegated_credentials = credentials.with_subject('[ADMIN_EMAIL]')
    admin_service = build(
        'admin',
        'directory_v1',
        credentials=admin_delegated_credentials
        )

    admin_results = admin_service.users().list(customer='my_customer', maxResults=10,
                                orderBy='email').execute()
    users = admin_results.get('users', [])

    if not users:
        print('No users in the domain.')
    else:
        for user in users:
            print(u'{0} ({1})'.format(user['primaryEmail'],
                user['name']['fullName']))

            # Drive to get files for each user
            delegated_credentials = credentials.with_subject(user['primaryEmail'])

            drive_service = build(
                'drive',
                'v3',
                credentials=delegated_credentials
                )
            drive_results = drive_service.files().list(
                pageSize=10,
                fields="nextPageToken, files(id, name,modifiedTime)"
                ).execute()
            items = drive_results.get('files', [])

            if not items:
                print('No files found.')
            else:
                print('Files:')
                for item in items:
                    print(u'{0} ({1})'.format(item['name'],
                        item['id']))

if __name__ == '__main__':
    main()

Explanation解释

This script has two scopes:这个脚本有两个作用域:

  • 'https://www.googleapis.com/auth/drive.metadata.readonly' 'https://www.googleapis.com/auth/drive.metadata.readonly'
  • 'https://www.googleapis.com/auth/admin.directory.user.readonly' 'https://www.googleapis.com/auth/admin.directory.user.readonly'

The project initialized in the GCP Cloud console has also been granted these scopes from within the Admin console > Security > API Controls > Domain wide delegation > Add new在 GCP Cloud 控制台中初始化的项目也已从管理控制台 > 安全 > API 控制 > 域范围委派 > 添加新的

The first thing the script does is build the credentials using from_service_account_file :脚本所做的第一件事是使用from_service_account_file构建凭据:

credentials = service_account.Credentials.from_service_account_file(
        SERVICE_ACCOUNT_FILE, scopes=SCOPES)

Then it builds the delegated credentials, that is, the user to be impersonated:然后它构建委托凭据,即要模拟的用户:

admin_delegated_credentials = credentials.with_subject('[ADMIN_EMAIL]')

From there it can build the service as normal.从那里它可以正常构建服务。 It gets a list of the users, loops through the users and lists their files.它获取用户列表,遍历用户并列出他们的文件。 You could adapt this to your needs.您可以根据自己的需要进行调整。

References参考

I was able to list shared drive files without impersonating a user by adding some parameters to the list method as stated on google documentation :我能够通过向google 文档中所述的 list 方法添加一些参数来列出共享驱动器文件,而无需冒充用户:

Implement shared drive support实施共享驱动器支持

Shared drives follow different organization, sharing, and ownership models from My Drive.共享云端硬盘遵循与“我的云端硬盘”不同的组织、共享和所有权模式。 If your app is going to create and manage files on shared drives, you must implement shared drive support in your app.如果您的应用要在共享驱动器上创建和管理文件,您必须在应用中实现共享驱动器支持。 To begin, you need to include the supportsAllDrives=true query parameter in your requests when your app performs these operations:首先,当您的应用程序执行这些操作时,您需要在请求中包含supportsAllDrives=true查询参数:

files.get, files.list, files.create, files.update, files.copy, files.delete, changes.list, changes.getStartPageToken, permissions.list, permissions.get, permissions.create, permissions.update, permissions.delete files.get、files.list、files.create、files.update、files.copy、files.delete、changes.list、changes.getStartPageToken、permissions.list、permissions.get、permissions.create、permissions.update、权限。删除

Search for content on a shared drive搜索共享云端硬盘上的内容

Use the files.list method to search for shared drives.使用 files.list 方法搜索共享驱动器。 This section covers shared drive-specific fields in the files.list method.本节介绍 files.list 方法中的共享驱动器特定字段。 To search for shared drive, refer to Search for files and folders.要搜索共享驱动器,请参阅搜索文件和文件夹。

The files.list method contains the following shared drive-specific fields and query modes: files.list 方法包含以下共享驱动器特定字段和查询模式:

driveId — ID of shared drive to search. driveId — 要搜索的共享驱动器的 ID。

includeItemsFromAllDrives — Whether shared drive items should be included in results. includeItemsFromAllDrives — 共享驱动器项目是否应包含在结果中。 If not present or set to false, then shared drive items are not returned.如果不存在或设置为 false,则不会返回共享驱动器项目。

corpora — Bodies of items (files/documents) to which the query applies. corpora — 查询适用的项目(文件/文档)的主体 Supported bodies are user, domain, drive, and allDrives.支持的主体是用户、域、驱动器和所有驱动器。 Prefer user or drive to allDrives for efficiency.为了效率,用户或驱动器优先于所有驱动器。

supportsAllDrives — Whether the requesting application supports both My Drives and shared drives. supportAllDrives — 请求应用程序是否同时支持我的驱动器和共享驱动器。 If false, then shared drive items are not included in the response.如果为 false,则响应中不包含共享驱动器项目。

Example例子

service.files().list(includeItemsFromAllDrives=True, supportsAllDrives=True, pageSize=10, fields="nextPageToken, files(id, name,modifiedTime)").execute()

It is nice to remember that the folder or files needs to be shared with the service account.很高兴记住文件夹或文件需要与服务帐户共享。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用共享设备和服务帐户获取文件夹和文件 Google Drive API - Get folder and files Google Drive API with Shared Device and Service Account 如何使用服务帐户将共享谷歌驱动器中的文件移至垃圾箱 - How to move a file in a shared google drive to trash using a service account Google API 服务帐户。 即使使用域范围的委派访问,也只能看到服务帐户驱动器 - Google API Service Account. Can only see service accounts drive even with Domain Wide Delegation Access Google Drive API 使用 python 中的服务帐户未显示与我共享的文件夹 - Google Drive API using Service Account in python not showing up folders that are shared to me Google云端硬盘api和服务帐户 - Google drive api and service account 使用服务帐户从谷歌日历 API 将共享日历插入我的列表时,访问角色出现问题 - Trouble with access role when inserting shared calendar to my list from google calendar API using service account 使用服务帐户密钥的 Google Drive Python API 授权 - Google Drive Python API authorization using service account key 如何在Google的python API和驱动器上使用服务帐户? - How to use a service account with Google's python api and drive? 使用服务帐户模拟 Google Drive 获取刷新令牌 - Get refresh token using service account impersonation Google Drive 如何使用驱动器 API 和 Python 中的服务帐户将电子表格中的所有工作表导出为 CSV 文件? - How to export all sheets in a Spreadsheet as CSV files using the Drive API with a Service Account in Python?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM