Я администратор GSuite с почти 300 пользователями, и я ухожу от GSuite. Мне нужно загрузить все наши пользовательские файлы, которые они создали/загрузили.
Я начинаю с малого с написания сценария Python, который покажет мне пользовательские файлы в списке, и похоже, что я застрял в подавляющих проблемах с авторизацией.
https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/admin.datatransfer,https://www.googleapis.com/auth/admin.directory.user, https://www.googleapis.com/auth/admin.directory.group
Так хорошо в соответствии с документацией (https://developers.google.com/admin-sdk/directory/v1/guides/delegation)
Я создаю объект ресурса из ServiceAccountCredentials и создаю объект, основанный на имени/версии API "drive" и "v3" соответственно, и пытаюсь получить список файлов в соответствии с быстрым стартом Google (https://developers.google.com/drive/api/v3/quickstart/python):
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
SERVICE_ACCOUNT_EMAIL = "[email protected]"
SERVICE_ACCOUNT_PKCS12 = "./service_key.json"
def create_directory_service(user_email):
credentials = ServiceAccountCredentials.from_json_keyfile_name(SERVICE_ACCOUNT_PKCS12, scopes=['https://www.googleapis.com/auth/drive'])
credentials = credentials.create_delegated(user_email)
return build('drive', 'v3', credentials=credentials)
resource = create_directory_service('[email protected]')
results = resource.files().list(
pageSize=10, fields="nextPageToken, files(id, name)"
).execute()
items = results.get('files', [])
print(items)
Это выглядит совершенно правильно, но я получаю сообщение об ошибке:
Подключен к отладчику pydev (сборка 181.5087.37)
Traceback (последний последний вызов): Файл "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py", строка 1664, в главном() файле "/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py ", строка 1658, в главных глобалах = debugger.run(setup ['file'], None, None, is_module) Файл"/Applications/PyCharm.app/Contents/helpers/pydev/pydevd.py ", строка 1068, в run pydev_imports.execfile (файл, globals, locals) # выполнить скрипт Файл "/Applications/PyCharm.app/Contents/helpers/pydev/_pydev_imps/_pydev_execfile.py", строка 18, в execfile exec (компиляция ([ CN10] "\n", файл, 'exec'), glob, loc) Файл "/Users/probe/Projects/drive_getter/src/dconnect.py", строка 16, в pageSize = 10, fields = "nextPageToken, файлы (id, name) "Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/_helpers.py ", строка 130, в positional_wrapper return wrapped (* args, ** kwargs ) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http.py", строка 835, в методе execute = str (self.method), body = self.body, headers = self.headers) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/googleapiclient/http. py ", строка 162, в _retry_request resp, content = http.request(uri, method, * args, ** kwargs) Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/transport.py ", строка 159, в new_request credentials._refresh (orig_request_method) Файл"/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py ", строка 749, в _refresh self._do_refresh_request (http) Файл "/Users/probe/Projects/drive_getter/drive_getter/lib/python3.6/site-packages/oauth2client/client.py", строка 819, в _do_refresh_request повысит HttpAccessTokenRefreshError (error_msg, status = resp.status) oauth2client.client.HttpAccessTokenRefreshError: unauthorized_client: клиент неавторизован для получения токенов доступа с использованием этого метода.
Любая идея, что было сделано неправильно в этом процессе? Опять же: моя цель состоит в том, чтобы перечислить и загрузить все пользовательские файлы со всех пользователей GSuite, поэтому я думал о том, чтобы зацикливать мои электронные письма пользователей и применять одну и ту же логику для всех, пока не получаю все загруженные файлы.
Спасибо за сотрудничество!
Решение было простым.
Прежде всего, для того, что я мог найти, библиотека google.oauth2 поддерживает функции делегирования домена только в том случае, если вы используете ключ P12 и строите объект на основе этих учетных данных.
Во-вторых, обратите внимание на имя файла p12, который вы загружаете, я переименовал ключевое имя файла на что-то более короткое и не обратил внимания на то, что Google включает в себя открытый отпечаток пальца в самом имени файла.
Таким образом, решение состоит в том, что все шаги, описанные в моем сообщении вопроса, создают учетную запись службы с ключом p12, делегируют доменное доменное имя и рабочий код будет выглядеть так:
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
SERVICE_ACCOUNT_EMAIL = "[email protected]"
PK12_FILE = "./private-key-original-filename.p12"
PK12_PASSWORD = "notasecret"
SCOPES = ['https://www.googleapis.com/auth/drive']
def create_directory_service(user_email):
credentials = ServiceAccountCredentials.from_p12_keyfile(
SERVICE_ACCOUNT_EMAIL,
PK12_FILE,
PK12_PASSWORD,
scopes=SCOPES
)
credentials = credentials.create_delegated(user_email)
return build('drive', 'v3', credentials=credentials)
bryan = create_directory_service('[email protected]')
results = bryan.files().list(
pageSize=10, fields="nextPageToken, files(id, name, mimeType, parents)"
).execute()
items = results.get('files', [])
print(items)
Бонус: если вы когда-либо захотите загрузить файлы из GDrive и сохранить структуру папок (Google не сообщает вам, является ли хеш файл файловой системой или нет), используйте mimeType извлеченный и родительский ID для создания стека родителей (папок), создайте их автоматически, зацикливая свой список, а затем поместите файлы в их соответствующий родительский идентификатор.
Клиент неавторизован для получения токенов доступа, используя этот метод.
В консоли Google Develoepr есть несколько разных типов клиентов.
Код, используемый для аутентификации с этими разными типами, по понятным причинам отличается.
Код, который вы используете, представляется правильным кодом для python с учетной записью службы. Хотя from_json_keyfile_name
принимает файл p12, а не файл.json.
Там для клиента должен быть в corect. Вернитесь в консоль разработчика Google, создайте клиент учетной записи службы и загрузите правильный.json файл.
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/sqlservice.admin']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
Я рекомендую использовать файл.json по файлу p12, я подозреваю, что Google не будет использовать их в какой-то момент в будущем.
from oauth2client.service_account import ServiceAccountCredentials
него есть метод credentials.create_delegated, который позволяет мне загружать файлы определенного пользователя, но этот объект не поддерживает учетные данные учетной записи службы в JSON, но когда я использую ваш импорт, я могу загрузить учетную запись службы учетные данные в JSON, но нет метода create_delegated. :)