¿Cómo usar DEFERRED.DEFER con OAUTH2 en Google App Engine?
-
21-12-2019 - |
Pregunta
Tengo decorador:
http = httplib2.Http()
service = discovery.build('gmail', 'v1', http=http)
# Creating decorator for OAuth2 account.
decorator = appengine.oauth2decorator_from_clientsecrets(
CLIENT_SECRETS,
scope='https://www.googleapis.com/auth/gmail.readonly',
message=MISSING_CLIENT_SECRETS_MESSAGE)
y clase que lo usan:
class CSVGeneratorHandler(webapp2.RedirectHandler):
@decorator.oauth_required
def get(self):
http = decorator.http()
first_messages = service.users().messages().list(userId='me').execute(http=http)
template = JINJA_ENVIRONMENT.get_template('templates/success.html')
self.response.write(template.render({}))
que funciona muy bien.
Pero cuando intento mover la solicitud de API service.users (). Mensajes (). Lista (UserID= 'yo'). Ejecutar (http= http) a la tarea (con diferidos.diferir (get_mails)) Tengo un error: "Iniciar sesión requerido".
Entiendo que la función Get_mails debe recibir contexto o credenciales del programa principal.Pero no entiendo cómo hacer eso.
¿Puede alguien ayudarme?
Solución
Después de unas pocas horas encontré la respuesta.
En primer lugar, necesita guardar las credenciales en algún lugar.Porque nosotros, gae, tenemos un tipo de campo especial para ello:
from oauth2client.appengine import StorageByKeyName
from google.appengine.ext import db
class CredentialsModel(db.Model):
credentials = CredentialsProperty()
El siguiente paso es configurar autenticación sin decorador y solo después de esa tarea de enviar a la cola:
user = users.get_current_user()
flow = flow_from_clientsecrets(os.path.join(os.path.dirname(os.path.realpath(__file__)), CLIENT_SECRETS),
scope='https://www.googleapis.com/auth/gmail.readonly',
redirect_uri='http://127.0.0.1:8080/success')
auth_uri = str(flow.step1_get_authorize_url())
code = self.request.get('code')
if not code:
return self.redirect(auth_uri)
credentials = flow.step2_exchange(code)
storage = StorageByKeyName(CredentialsModel, user.user_id(), 'credentials')
storage.put(credentials)
deferred.defer(get_mails, user.user_id())
¡No se olvide de obtener credenciales en la función diferida!
def get_mails(user_id):
storage = StorageByKeyName(CredentialsModel, user_id, 'credentials')
credentials = storage.get()
http = httplib2.Http()
http = credentials.authorize(http)
all_messages = []
service = discovery.build('gmail', 'v1', http=http)
first_messages = service.users().messages().list(userId='me').execute()