Обновление скрипта Python с oauth2client до google-auth - PullRequest
0 голосов
/ 14 декабря 2018

Я бы хотел обновить следующий код с oauth2client до google-auth .Да, этот код работает и является копией вставки из демоверсии Google на их сайте.

from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools

# If modifying these scopes, delete the file token.json.
SCOPES = 'https://www.googleapis.com/auth/presentations.readonly'

# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'

def main():
    """Shows basic usage of the Slides API.
    Prints the number of slides and elments in a sample presentation.
    """
    # The file token.json stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    # delete the file to for authentication and authorization again
    store = file.Storage('token.json')
    creds = store.get()

    if not creds or creds.invalid:
        # credentials.json is issued by Google for the application
        flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
        creds = tools.run_flow(flow, store)

    service = build('slides', 'v1', http=creds.authorize(Http()))

    # Call the Slides API
    presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
    slides = presentation.get('slides')

    print('The presentation contains {} slides:'.format(len(slides)))
    for i, slide in enumerate(slides):
        print('- Slide #{} contains {} elements.'.format(
            i + 1, len(slide.get('pageElements'))))


if __name__ == '__main__':
    main()

Я смог обновить большую его часть (я думаю), но не смог найти эквивалент для tools.run_flowиспользуя google-auth .Ниже моя обновленная версия, и в ней есть все (я думаю), кроме механизма для выполнения tools.run_flow.Как tools.run_flow выполняется с помощью google-auth ?

from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
PRESENTATION_ID = '<some id>'

credentials = service_account.Credentials.from_service_account_file(
    "the-json-file.json",
    scopes=SCOPES
)    

service = build('slides', 'v1', credentials=credentials)
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')

print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
    print('- Slide #{} contains {} elements.'.format(
        i + 1, len(slide.get('pageElements'))))

Когда я запускаю приведенный выше код с использованием подхода google-auth , я получаю следующий результат:

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/<some id>?alt=json returned "The caller does not have permission">

В дополнительном контексте я пытаюсь создать сценарий Python, который обращается к Google Slides для выполнения некоторой обработки содержимого слайдов.Я только читаю, а не пишу в Google Slides.Приведенный выше код является моей попыткой обработать часть аутентификации и авторизации доступа к контенту Google Slides для моей учетной записи GSuite (я являюсь администратором GSuite моей организации).Первый пример с использованием более старого oauth2client прекрасно работает, но поскольку oauth2client устарел и рекомендуется google-auth , я хотел бы сделать это "правильным" способомс использованием самой последней библиотеки.

ОБНОВЛЕНИЕ

Я решил часть своей проблемы с помощью следующего кода:

from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build

from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow

import os
import json


def get_credentials():

    CLIENT_SECRET_FILE = '<some file>'
    SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']

    credentials_path = '<some path>/token.json'

    if os.path.exists(credentials_path):
        # expect these to be valid. may expire at some point, but should be refreshed by google api client...
        return Credentials.from_authorized_user_file(credentials_path, scopes=SCOPES)
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            CLIENT_SECRET_FILE,
            scopes=SCOPES,
            redirect_uri='urn:ietf:wg:oauth:2.0:oob')

        auth_url, _ = flow.authorization_url(prompt='consent')

        print('Please go to this URL and finish the authentication flow: {}'.format(auth_url))
        code = input('Enter the authorization code: ')

        flow.fetch_token(code=code)
        credentials = flow.credentials

        credentials_as_dict = {
            'token': credentials.token,
            'refresh_token': credentials.refresh_token,
            'id_token': credentials.id_token,
            'token_uri': credentials.token_uri,
            'client_id': credentials.client_id,
            'client_secret': credentials.client_secret
        }

        with open(credentials_path, 'w') as file:
            file.write(json.dumps(credentials_as_dict))

        return credentials

# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'

service = build('slides', 'v1', credentials=get_credentials())
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')

print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
    print('- Slide #{} contains {} elements.'.format(
        i + 1, len(slide.get('pageElements'))))

Моя проблема сейчас вызываетвеб-браузер, чтобы открыть автоматически.Я могу скопировать и вставить ссылку и получить код вручную, и все это работает.В идеале мне бы хотелось, чтобы автоматически открывался веб-браузер и захватывался токен, как это было в старой библиотеке.

решено

Обновите код раздела впредыдущий пример кода к этому:

    flow = InstalledAppFlow.from_client_secrets_file(
        CLIENT_SECRET_FILE,
        scopes=SCOPES,
        redirect_uri='urn:ietf:wg:oauth:2.0:oob')

    credentials = flow.run_local_server()

    credentials_as_dict = {
        'token': credentials.token,
        'refresh_token': credentials.refresh_token,
        'id_token': credentials.id_token,
        'token_uri': credentials.token_uri,
        'client_id': credentials.client_id,
        'client_secret': credentials.client_secret
    }

Веб-браузер открывается автоматически и фиксирует значение токена.Все хорошо.

...