services/gservice.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from apiclient import discovery
import logging
from oauth2client import client
import httplib2
from datetime import datetime, timedelta
import tools
from constants import SECURE_BASE
from settings.secrets import GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
from oauth2client.client import GoogleCredentials
class GoogleServiceFetcher(object):
def __init__(self, user, api='fitness', version='v3',
scopes=None, credential_type='user'):
self.user = user
self.service = None
self.api = api
self.version = version
self.credentials = None
self.http_auth = None
self.credential_type = credential_type
if credential_type == 'user':
self.get_user_credentials_object()
else:
self.get_application_credentials_object()
self.scopes = scopes if scopes else []
def build_service(self):
ok = False
logging.debug("Building %s service for %s (%s)" % (self.credential_type, self.api, self.version))
kwargs = {}
if self.credential_type == 'user':
if not self.http_auth:
self.get_http_auth()
kwargs['http'] = self.http_auth
ok = bool(self.http_auth)
else:
kwargs['credentials'] = self.credentials
ok = bool(self.credentials)
self.service = discovery.build(self.api, self.version, **kwargs)
if not ok:
logging.warning("Failed to build service for %s (%s) - Credential failure?" % (self.api, self.version))
return ok
def set_google_credentials(self, credentials_object):
logging.debug(credentials_object.to_json())
self.user.set_integration_prop('google_credentials', credentials_object.to_json())
self.user.put()
def get_google_credentials(self):
return self.user.get_integration_prop('google_credentials', {})
def get_auth_flow(self, scope):
base = 'http://localhost:8080' if tools.on_dev_server() else SECURE_BASE
flow = client.OAuth2WebServerFlow(client_id=GOOGLE_CLIENT_ID,
client_secret=GOOGLE_CLIENT_SECRET,
scope=scope,
access_type='offline',
prompt='consent',
redirect_uri=base + "/api/auth/google/oauth2callback")
flow.params['include_granted_scopes'] = 'true'
# flow.params['access_type'] = 'offline'
return flow
def get_user_credentials_object(self):
if not self.credentials:
cr_json = self.get_google_credentials()
if cr_json:
# Note JSON is stored as escaped string, not dict
cr = client.Credentials.new_from_json(cr_json)
expires_in = cr.token_expiry - datetime.utcnow()
logging.debug("expires_in: %s" % expires_in)
if expires_in < timedelta(minutes=15):
try:
cr.refresh(httplib2.Http())
except client.HttpAccessTokenRefreshError, e:
logging.error("HttpAccessTokenRefreshError: %s" % e)
cr = None
else:
self.set_google_credentials(cr)
self.credentials = cr
return cr
def get_application_credentials_object(self):
if not self.credentials:
self.credentials = GoogleCredentials.get_application_default()
def get_auth_uri(self, state=None):
flow = self.get_auth_flow(scope=' '.join(self.scopes))
auth_uri = flow.step1_get_authorize_url(state=state)
return auth_uri
def get_http_auth(self):
self.get_user_credentials_object()
if self.credentials:
self.http_auth = self.credentials.authorize(httplib2.Http())
def check_available_scopes(self):
scopes = self.credentials.retrieve_scopes(httplib2.Http())
missing_scopes = []
if self.scopes:
for scope in self.scopes:
if scope not in scopes:
missing_scopes.append(scope)
if missing_scopes:
logging.debug("Missing scopes: %s" % missing_scopes)
return missing_scopes