<s> """<STR_LIT>""" <EOL> import cgi <EOL> import json <EOL> import logging <EOL> import os <EOL> import pickle <EOL> import threading <EOL> import httplib2 <EOL> import webapp2 as webapp <EOL> from google . appengine . api import app_identity <EOL> from google . appengine . api import memcache <EOL> from google . appengine . api import users <EOL> from google . appengine . ext import db <EOL> from google . appengine . ext . webapp . util import login_required <EOL> from oauth2client import GOOGLE_AUTH_URI <EOL> from oauth2client import GOOGLE_REVOKE_URI <EOL> from oauth2client import GOOGLE_TOKEN_URI <EOL> from oauth2client import clientsecrets <EOL> from oauth2client import util <EOL> from oauth2client . client import AccessTokenRefreshError <EOL> from oauth2client . client import AssertionCredentials <EOL> from oauth2client . client import Credentials <EOL> from oauth2client . client import Flow <EOL> from oauth2client . client import OAuth2WebServerFlow <EOL> from oauth2client . client import Storage <EOL> from oauth2client . contrib import xsrfutil <EOL> try : <EOL> from google . appengine . ext import ndb <EOL> except ImportError : <EOL> ndb = None <EOL> __author__ = '<STR_LIT>' <EOL> logger = logging . getLogger ( __name__ ) <EOL> OAUTH2CLIENT_NAMESPACE = '<STR_LIT>' <EOL> XSRF_MEMCACHE_ID = '<STR_LIT>' <EOL> def _safe_html ( s ) : <EOL> """<STR_LIT>""" <EOL> return cgi . escape ( s , quote = <NUM_LIT:1> ) . replace ( "<STR_LIT:'>" , '<STR_LIT>' ) <EOL> class InvalidClientSecretsError ( Exception ) : <EOL> """<STR_LIT>""" <EOL> class InvalidXsrfTokenError ( Exception ) : <EOL> """<STR_LIT>""" <EOL> class SiteXsrfSecretKey ( db . Model ) : <EOL> """<STR_LIT>""" <EOL> secret = db . StringProperty ( ) <EOL> if ndb is not None : <EOL> class SiteXsrfSecretKeyNDB ( ndb . Model ) : <EOL> """<STR_LIT>""" <EOL> secret = ndb . StringProperty ( ) <EOL> @ classmethod <EOL> def _get_kind ( cls ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' <EOL> def _generate_new_xsrf_secret_key ( ) : <EOL> """<STR_LIT>""" <EOL> return os . urandom ( <NUM_LIT:16> ) . encode ( "<STR_LIT>" ) <EOL> def xsrf_secret_key ( ) : <EOL> """<STR_LIT>""" <EOL> secret = memcache . get ( XSRF_MEMCACHE_ID , namespace = OAUTH2CLIENT_NAMESPACE ) <EOL> if not secret : <EOL> model = SiteXsrfSecretKey . get_or_insert ( key_name = '<STR_LIT>' ) <EOL> if not model . secret : <EOL> model . secret = _generate_new_xsrf_secret_key ( ) <EOL> model . put ( ) <EOL> secret = model . secret <EOL> memcache . add ( XSRF_MEMCACHE_ID , secret , <EOL> namespace = OAUTH2CLIENT_NAMESPACE ) <EOL> return str ( secret ) <EOL> class AppAssertionCredentials ( AssertionCredentials ) : <EOL> """<STR_LIT>""" <EOL> @ util . positional ( <NUM_LIT:2> ) <EOL> def __init__ ( self , scope , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . scope = util . scopes_to_string ( scope ) <EOL> self . _kwargs = kwargs <EOL> self . service_account_id = kwargs . get ( '<STR_LIT>' , None ) <EOL> super ( AppAssertionCredentials , self ) . __init__ ( None ) <EOL> @ classmethod <EOL> def from_json ( cls , json_data ) : <EOL> data = json . loads ( json_data ) <EOL> return AppAssertionCredentials ( data [ '<STR_LIT>' ] ) <EOL> def _refresh ( self , http_request ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> scopes = self . scope . split ( ) <EOL> ( token , _ ) = app_identity . get_access_token ( <EOL> scopes , service_account_id = self . service_account_id ) <EOL> except app_identity . Error as e : <EOL> raise AccessTokenRefreshError ( str ( e ) ) <EOL> self . access_token = token <EOL> @ property <EOL> def serialization_data ( self ) : <EOL> raise NotImplementedError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> def create_scoped_required ( self ) : <EOL> return not self . scope <EOL> def create_scoped ( self , scopes ) : <EOL> return AppAssertionCredentials ( scopes , ** self . _kwargs ) <EOL> class FlowProperty ( db . Property ) : <EOL> """<STR_LIT>""" <EOL> data_type = Flow <EOL> def get_value_for_datastore ( self , model_instance ) : <EOL> flow = super ( FlowProperty , self ) . get_value_for_datastore ( <EOL> model_instance ) <EOL> return db . Blob ( pickle . dumps ( flow ) ) <EOL> def make_value_from_datastore ( self , value ) : <EOL> if value is None : <EOL> return None <EOL> return pickle . loads ( value ) <EOL> def validate ( self , value ) : <EOL> if value is not None and not isinstance ( value , Flow ) : <EOL> raise db . BadValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' % <EOL> ( self . name , value ) ) <EOL> return super ( FlowProperty , self ) . validate ( value ) <EOL> def empty ( self , value ) : <EOL> return not value <EOL> if ndb is not None : <EOL> class FlowNDBProperty ( ndb . PickleProperty ) : <EOL> """<STR_LIT>""" <EOL> def _validate ( self , value ) : <EOL> """<STR_LIT>""" <EOL> logger . info ( '<STR_LIT>' , type ( value ) ) <EOL> if value is not None and not isinstance ( value , Flow ) : <EOL> raise TypeError ( '<STR_LIT>' <EOL> '<STR_LIT>' % ( self . _name , <EOL> value ) ) <EOL> class CredentialsProperty ( db . Property ) : <EOL> """<STR_LIT>""" <EOL> data_type = Credentials <EOL> def get_value_for_datastore ( self , model_instance ) : <EOL> logger . info ( "<STR_LIT>" + str ( type ( model_instance ) ) ) <EOL> cred = super ( CredentialsProperty , self ) . get_value_for_datastore ( <EOL> model_instance ) <EOL> if cred is None : <EOL> cred = '<STR_LIT>' <EOL> else : <EOL> cred = cred . to_json ( ) <EOL> return db . Blob ( cred ) <EOL> def make_value_from_datastore ( self , value ) : <EOL> logger . info ( "<STR_LIT>" + str ( type ( value ) ) ) <EOL> if value is None : <EOL> return None <EOL> if len ( value ) == <NUM_LIT:0> : <EOL> return None <EOL> try : <EOL> credentials = Credentials . new_from_json ( value ) <EOL> except ValueError : <EOL> credentials = None <EOL> return credentials <EOL> def validate ( self , value ) : <EOL> value = super ( CredentialsProperty , self ) . validate ( value ) <EOL> logger . info ( "<STR_LIT>" + str ( type ( value ) ) ) <EOL> if value is not None and not isinstance ( value , Credentials ) : <EOL> raise db . BadValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' % <EOL> ( self . name , value ) ) <EOL> return value <EOL> if ndb is not None : <EOL> class CredentialsNDBProperty ( ndb . BlobProperty ) : <EOL> """<STR_LIT>""" <EOL> def _validate ( self , value ) : <EOL> """<STR_LIT>""" <EOL> logger . info ( '<STR_LIT>' , type ( value ) ) <EOL> if value is not None and not isinstance ( value , Credentials ) : <EOL> raise TypeError ( '<STR_LIT>' <EOL> '<STR_LIT>' % <EOL> ( self . _name , value ) ) <EOL> def _to_base_type ( self , value ) : <EOL> """<STR_LIT>""" <EOL> if value is None : <EOL> return '<STR_LIT>' <EOL> else : <EOL> return value . to_json ( ) <EOL> def _from_base_type ( self , value ) : <EOL> """<STR_LIT>""" <EOL> if not value : <EOL> return None <EOL> try : <EOL> credentials = Credentials . new_from_json ( value ) <EOL> except ValueError : <EOL> credentials = None <EOL> return credentials <EOL> class StorageByKeyName ( Storage ) : <EOL> """<STR_LIT>""" <EOL> @ util . positional ( <NUM_LIT:4> ) <EOL> def __init__ ( self , model , key_name , property_name , cache = None , user = None ) : <EOL> """<STR_LIT>""" <EOL> super ( StorageByKeyName , self ) . __init__ ( ) <EOL> if key_name is None : <EOL> if user is None : <EOL> raise ValueError ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> key_name = user . user_id ( ) <EOL> self . _model = model <EOL> self . _key_name = key_name <EOL> self . _property_name = property_name <EOL> self . _cache = cache <EOL> def _is_ndb ( self ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( self . _model , type ) : <EOL> if ndb is not None and issubclass ( self . _model , ndb . Model ) : <EOL> return True <EOL> elif issubclass ( self . _model , db . Model ) : <EOL> return False <EOL> raise TypeError ( '<STR_LIT>' % <EOL> ( self . _model , ) ) <EOL> def _get_entity ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _is_ndb ( ) : <EOL> return self . _model . get_by_id ( self . _key_name ) <EOL> else : <EOL> return self . _model . get_by_key_name ( self . _key_name ) <EOL> def _delete_entity ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _is_ndb ( ) : <EOL> ndb . Key ( self . _model , self . _key_name ) . delete ( ) <EOL> else : <EOL> entity_key = db . Key . from_path ( self . _model . kind ( ) , self . _key_name ) <EOL> db . delete ( entity_key ) <EOL> @ db . non_transactional ( allow_existing = True ) <EOL> def locked_get ( self ) : <EOL> """<STR_LIT>""" <EOL> credentials = None <EOL> if self . _cache : <EOL> json = self . _cache . get ( self . _key_name ) <EOL> if json : <EOL> credentials = Credentials . new_from_json ( json ) <EOL> if credentials is None : <EOL> entity = self . _get_entity ( ) <EOL> if entity is not None : <EOL> credentials = getattr ( entity , self . _property_name ) <EOL> if self . _cache : <EOL> self . _cache . set ( self . _key_name , credentials . to_json ( ) ) <EOL> if credentials and hasattr ( credentials , '<STR_LIT>' ) : <EOL> credentials . set_store ( self ) <EOL> return credentials <EOL> @ db . non_transactional ( allow_existing = True ) <EOL> def locked_put ( self , credentials ) : <EOL> """<STR_LIT>""" <EOL> entity = self . _model . get_or_insert ( self . _key_name ) <EOL> setattr ( entity , self . _property_name , credentials ) <EOL> entity . put ( ) <EOL> if self . _cache : <EOL> self . _cache . set ( self . _key_name , credentials . to_json ( ) ) <EOL> @ db . non_transactional ( allow_existing = True ) <EOL> def locked_delete ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _cache : <EOL> self . _cache . delete ( self . _key_name ) <EOL> self . _delete_entity ( ) <EOL> class CredentialsModel ( db . Model ) : <EOL> """<STR_LIT>""" <EOL> credentials = CredentialsProperty ( ) <EOL> if ndb is not None : <EOL> class CredentialsNDBModel ( ndb . Model ) : <EOL> """<STR_LIT>""" <EOL> credentials = CredentialsNDBProperty ( ) <EOL> @ classmethod <EOL> def _get_kind ( cls ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' <EOL> def _build_state_value ( request_handler , user ) : <EOL> """<STR_LIT>""" <EOL> uri = request_handler . request . url <EOL> token = xsrfutil . generate_token ( xsrf_secret_key ( ) , user . user_id ( ) , <EOL> action_id = str ( uri ) ) <EOL> return uri + '<STR_LIT::>' + token <EOL> def _parse_state_value ( state , user ) : <EOL> """<STR_LIT>""" <EOL> uri , token = state . rsplit ( '<STR_LIT::>' , <NUM_LIT:1> ) <EOL> if not xsrfutil . validate_token ( xsrf_secret_key ( ) , token , user . user_id ( ) , <EOL> action_id = uri ) : <EOL> raise InvalidXsrfTokenError ( ) <EOL> return uri <EOL> class OAuth2Decorator ( object ) : <EOL> """<STR_LIT>""" <EOL> def set_credentials ( self , credentials ) : <EOL> self . _tls . credentials = credentials <EOL> def get_credentials ( self ) : <EOL> """<STR_LIT>""" <EOL> return getattr ( self . _tls , '<STR_LIT>' , None ) <EOL> credentials = property ( get_credentials , set_credentials ) <EOL> def set_flow ( self , flow ) : <EOL> self . _tls . flow = flow <EOL> def get_flow ( self ) : <EOL> """<STR_LIT>""" <EOL> return getattr ( self . _tls , '<STR_LIT>' , None ) <EOL> flow = property ( get_flow , set_flow ) <EOL> @ util . positional ( <NUM_LIT:4> ) <EOL> def __init__ ( self , client_id , client_secret , scope , <EOL> auth_uri = GOOGLE_AUTH_URI , <EOL> token_uri = GOOGLE_TOKEN_URI , <EOL> revoke_uri = GOOGLE_REVOKE_URI , <EOL> user_agent = None , <EOL> message = None , <EOL> callback_path = '<STR_LIT>' , <EOL> token_response_param = None , <EOL> _storage_class = StorageByKeyName , <EOL> _credentials_class = CredentialsModel , <EOL> _credentials_property_name = '<STR_LIT>' , <EOL> ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . _tls = threading . local ( ) <EOL> self . flow = None <EOL> self . credentials = None <EOL> self . _client_id = client_id <EOL> self . _client_secret = client_secret <EOL> self . _scope = util . scopes_to_string ( scope ) <EOL> self . _auth_uri = auth_uri <EOL> self . _token_uri = token_uri <EOL> self . _revoke_uri = revoke_uri <EOL> self . _user_agent = user_agent <EOL> self . _kwargs = kwargs <EOL> self . _message = message <EOL> self . _in_error = False <EOL> self . _callback_path = callback_path <EOL> self . _token_response_param = token_response_param <EOL> self . _storage_class = _storage_class <EOL> self . _credentials_class = _credentials_class <EOL> self . _credentials_property_name = _credentials_property_name <EOL> def _display_error_message ( self , request_handler ) : <EOL> request_handler . response . out . write ( '<STR_LIT>' ) <EOL> request_handler . response . out . write ( _safe_html ( self . _message ) ) <EOL> request_handler . response . out . write ( '<STR_LIT>' ) <EOL> def oauth_required ( self , method ) : <EOL> """<STR_LIT>""" <EOL> def check_oauth ( request_handler , * args , ** kwargs ) : <EOL> if self . _in_error : <EOL> self . _display_error_message ( request_handler ) <EOL> return <EOL> user = users . get_current_user ( ) <EOL> if not user : <EOL> request_handler . redirect ( users . create_login_url ( <EOL> request_handler . request . uri ) ) <EOL> return <EOL> self . _create_flow ( request_handler ) <EOL> self . flow . params [ '<STR_LIT:state>' ] = _build_state_value ( <EOL> request_handler , user ) <EOL> self . credentials = self . _storage_class ( <EOL> self . _credentials_class , None , <EOL> self . _credentials_property_name , user = user ) . get ( ) <EOL> if not self . has_credentials ( ) : <EOL> return request_handler . redirect ( self . authorize_url ( ) ) <EOL> try : <EOL> resp = method ( request_handler , * args , ** kwargs ) <EOL> except AccessTokenRefreshError : <EOL> return request_handler . redirect ( self . authorize_url ( ) ) <EOL> finally : <EOL> self . credentials = None <EOL> return resp <EOL> return check_oauth <EOL> def _create_flow ( self , request_handler ) : <EOL> """<STR_LIT>""" <EOL> if self . flow is None : <EOL> redirect_uri = request_handler . request . relative_url ( <EOL> self . _callback_path ) <EOL> self . flow = OAuth2WebServerFlow ( <EOL> self . _client_id , self . _client_secret , self . _scope , <EOL> redirect_uri = redirect_uri , user_agent = self . _user_agent , <EOL> auth_uri = self . _auth_uri , token_uri = self . _token_uri , <EOL> revoke_uri = self . _revoke_uri , ** self . _kwargs ) <EOL> def oauth_aware ( self , method ) : <EOL> """<STR_LIT>""" <EOL> def setup_oauth ( request_handler , * args , ** kwargs ) : <EOL> if self . _in_error : <EOL> self . _display_error_message ( request_handler ) <EOL> return <EOL> user = users . get_current_user ( ) <EOL> if not user : <EOL> request_handler . redirect ( users . create_login_url ( <EOL> request_handler . request . uri ) ) <EOL> return <EOL> self . _create_flow ( request_handler ) <EOL> self . flow . params [ '<STR_LIT:state>' ] = _build_state_value ( request_handler , <EOL> user ) <EOL> self . credentials = self . _storage_class ( <EOL> self . _credentials_class , None , <EOL> self . _credentials_property_name , user = user ) . get ( ) <EOL> try : <EOL> resp = method ( request_handler , * args , ** kwargs ) <EOL> finally : <EOL> self . credentials = None <EOL> return resp <EOL> return setup_oauth <EOL> def has_credentials ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . credentials is not None and not self . credentials . invalid <EOL> def authorize_url ( self ) : <EOL> """<STR_LIT>""" <EOL> url = self . flow . step1_get_authorize_url ( ) <EOL> return str ( url ) <EOL> def http ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> return self . credentials . authorize ( httplib2 . Http ( * args , ** kwargs ) ) <EOL> @ property <EOL> def callback_path ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _callback_path <EOL> def callback_handler ( self ) : <EOL> """<STR_LIT>""" <EOL> decorator = self <EOL> class OAuth2Handler ( webapp . RequestHandler ) : <EOL> """<STR_LIT>""" <EOL> @ login_required <EOL> def get ( self ) : <EOL> error = self . request . get ( '<STR_LIT:error>' ) <EOL> if error : <EOL> errormsg = self . request . get ( '<STR_LIT>' , error ) <EOL> self . response . out . write ( <EOL> '<STR_LIT>' % <EOL> _safe_html ( errormsg ) ) <EOL> else : <EOL> user = users . get_current_user ( ) <EOL> decorator . _create_flow ( self ) <EOL> credentials = decorator . flow . step2_exchange ( <EOL> self . request . params ) <EOL> decorator . _storage_class ( <EOL> decorator . _credentials_class , None , <EOL> decorator . _credentials_property_name , <EOL> user = user ) . put ( credentials ) <EOL> redirect_uri = _parse_state_value ( <EOL> str ( self . request . get ( '<STR_LIT:state>' ) ) , user ) <EOL> if ( decorator . _token_response_param and <EOL> credentials . token_response ) : <EOL> resp_json = json . dumps ( credentials . token_response ) <EOL> redirect_uri = util . _add_query_parameter ( <EOL> redirect_uri , decorator . _token_response_param , <EOL> resp_json ) <EOL> self . redirect ( redirect_uri ) <EOL> return OAuth2Handler <EOL> def callback_application ( self ) : <EOL> """<STR_LIT>""" <EOL> return webapp . WSGIApplication ( [ <EOL> ( self . callback_path , self . callback_handler ( ) ) <EOL> ] ) <EOL> class OAuth2DecoratorFromClientSecrets ( OAuth2Decorator ) : <EOL> """<STR_LIT>""" <EOL> @ util . positional ( <NUM_LIT:3> ) <EOL> def __init__ ( self , filename , scope , message = None , cache = None , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> client_type , client_info = clientsecrets . loadfile ( filename , <EOL> cache = cache ) <EOL> if client_type not in ( clientsecrets . TYPE_WEB , <EOL> clientsecrets . TYPE_INSTALLED ) : <EOL> raise InvalidClientSecretsError ( <EOL> "<STR_LIT>" ) <EOL> constructor_kwargs = dict ( kwargs ) <EOL> constructor_kwargs . update ( { <EOL> '<STR_LIT>' : client_info [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : client_info [ '<STR_LIT>' ] , <EOL> '<STR_LIT:message>' : message , <EOL> } ) <EOL> revoke_uri = client_info . get ( '<STR_LIT>' ) <EOL> if revoke_uri is not None : <EOL> constructor_kwargs [ '<STR_LIT>' ] = revoke_uri <EOL> super ( OAuth2DecoratorFromClientSecrets , self ) . __init__ ( <EOL> client_info [ '<STR_LIT>' ] , client_info [ '<STR_LIT>' ] , <EOL> scope , ** constructor_kwargs ) <EOL> if message is not None : <EOL> self . _message = message <EOL> else : <EOL> self . _message = '<STR_LIT>' <EOL> @ util . positional ( <NUM_LIT:2> ) <EOL> def oauth2decorator_from_clientsecrets ( filename , scope , <EOL> message = None , cache = None ) : <EOL> """<STR_LIT>""" <EOL> return OAuth2DecoratorFromClientSecrets ( filename , scope , <EOL> message = message , cache = cache ) </s>
