a
    !f                     @   s
  d Z ddlZddlZddlZddlZddlZddlZddlmZ ddlm	Z	 ddlm
Z
 ddlmZ ddlmZ ddlZddlZddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ zddlmZ W n ey   dZY n0 eeZdZdZedu rdZdZ dZ!dZ"dZ#dZ$n$ejZej Z ej!Z!ej%Z"ej&Z#ej$Z$dd Z'G dd dej(Z)dd Z*dd Z+G dd dej,Z-G dd dej.Z/G dd dej.Z0G dd dej1Z2G dd  d ej(Z3d!d" Z4d#d$ Z5G d%d& d&e6Z7G d'd( d(e7Z8e9d)d,d*d+Z:dS )-zgUtilities for Google App Engine

Utilities for making it easier to use OAuth 2.0 on Google App Engine.
    N)app_identity)memcache)users)db)login_required)_helpers)client)clientsecrets)	transport)xsrfutil)_appengine_ndbzoauth2client#nsxsrf_secret_keyc                 C   s   t j| ddddS )zEscape text to make it safe to display.

    Args:
        s: string, The text to escape.

    Returns:
        The escaped text as a string.
       )quote'z&#39;)cgiescapereplace)s r   _/var/www/html/python-backend/venv/lib/python3.9/site-packages/oauth2client/contrib/appengine.py
_safe_htmlF   s    	r   c                   @   s   e Zd ZdZe ZdS )SiteXsrfSecretKeyzStorage for the sites XSRF secret key.

    There will only be one instance stored of this model, the one used for the
    site.
    N)__name__
__module____qualname____doc__r   ZStringPropertysecretr   r   r   r   r   R   s   r   c                   C   s   t ddS )z!Returns a random XSRF secret key.   hex)osurandomencoder   r   r   r   _generate_new_xsrf_secret_key[   s    r#   c                  C   sR   t jttd} | sJtjdd}|js4t |_|  |j} t j	t| td t
| S )zReturn the secret key for use for XSRF protection.

    If the Site entity does not have a secret key, this method will also create
    one and persist it.

    Returns:
        The secret key.
    )	namespacesite)key_name)r   getXSRF_MEMCACHE_IDOAUTH2CLIENT_NAMESPACEr   get_or_insertr   r#   putaddstr)r   modelr   r   r   r   `   s    	c                       sn   e Zd ZdZed fddZedd Zdd Z	e
d	d
 Zdd Zdd Zdd Ze
dd Z  ZS )AppAssertionCredentialsa  Credentials object for App Engine Assertion Grants

    This object will allow an App Engine application to identify itself to
    Google and other OAuth 2.0 servers that can verify assertions. It can be
    used for the purpose of accessing data stored under an account assigned to
    the App Engine application itself.

    This credential does not require a flow to instantiate because it
    represents a two legged flow, and therefore has all of the required
    information to generate and refresh its own access tokens.
       c                    s:   t || _|| _|dd| _d| _tt| 	d dS )a  Constructor for AppAssertionCredentials

        Args:
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            **kwargs: optional keyword args, including:
            service_account_id: service account id of the application. If None
                                or unspecified, the default service account for
                                the app is used.
        service_account_idN)
r   scopes_to_stringscope_kwargsr'   r1   _service_account_emailsuperr/   __init__)selfr3   kwargs	__class__r   r   r7      s
    z AppAssertionCredentials.__init__c                 C   s   t |}t|d S )Nr3   )jsonloadsr/   )clsZ	json_datadatar   r   r   	from_json   s    
z!AppAssertionCredentials.from_jsonc              
   C   sb   z"| j  }tj|| jd\}}W n4 tjyV } ztt|W Y d}~n
d}~0 0 || _	dS )aW  Refreshes the access token.

        Since the underlying App Engine app_identity implementation does its
        own caching we can skip all the storage hoops and just to a refresh
        using the API.

        Args:
            http: unused HTTP object

        Raises:
            AccessTokenRefreshError: When the refresh fails.
        )r1   N)
r3   splitr   Zget_access_tokenr1   Errorr   AccessTokenRefreshErrorr-   Zaccess_token)r8   httpscopestoken_er   r   r   _refresh   s    
$z AppAssertionCredentials._refreshc                 C   s   t dd S )Nz3Cannot serialize credentials for Google App Engine.)NotImplementedErrorr8   r   r   r   serialization_data   s    z*AppAssertionCredentials.serialization_datac                 C   s   | j  S N)r3   rK   r   r   r   create_scoped_required   s    z.AppAssertionCredentials.create_scoped_requiredc                 C   s   t |fi | jS rM   )r/   r4   )r8   rE   r   r   r   create_scoped   s    z%AppAssertionCredentials.create_scopedc                 C   s
   t |S )aU  Cryptographically sign a blob (of bytes).

        Implements abstract method
        :meth:`oauth2client.client.AssertionCredentials.sign_blob`.

        Args:
            blob: bytes, Message to be signed.

        Returns:
            tuple, A pair of the private key ID used to sign the blob and
            the signed contents.
        )r   	sign_blob)r8   Zblobr   r   r   rP      s    z!AppAssertionCredentials.sign_blobc                 C   s   | j du rt | _ | j S )zGet the email for the current service account.

        Returns:
            string, The email associated with the Google App Engine
            service account.
        N)r5   r   Zget_service_account_namerK   r   r   r   service_account_email   s    
z-AppAssertionCredentials.service_account_email)r   r   r   r   r   
positionalr7   classmethodr@   rI   propertyrL   rN   rO   rP   rQ   __classcell__r   r   r:   r   r/   w   s   

r/   c                       sB   e Zd ZdZejZ fddZdd Z fddZ	dd	 Z
  ZS )
FlowPropertyzApp Engine datastore Property for Flow.

    Utility property that allows easy storage and retrieval of an
    oauth2client.Flow
    c                    s    t t| |}tt|S rM   )r6   rV   get_value_for_datastorer   Blobpickledumps)r8   model_instanceflowr:   r   r   rW      s    
z$FlowProperty.get_value_for_datastorec                 C   s   |d u rd S t |S rM   )rY   r=   r8   valuer   r   r   make_value_from_datastore   s    z&FlowProperty.make_value_from_datastorec                    s8   |d ur(t |tjs(td| j|tt| 	|S )NzDProperty {0} must be convertible to a FlowThreeLegged instance ({1}))

isinstancer   Flowr   BadValueErrorformatnamer6   rV   validater]   r:   r   r   re      s    zFlowProperty.validatec                 C   s   | S rM   r   r]   r   r   r   empty   s    zFlowProperty.empty)r   r   r   r   r   ra   	data_typerW   r_   re   rf   rU   r   r   r:   r   rV      s   rV   c                       s:   e Zd ZdZejZ fddZdd Z fddZ	  Z
S )CredentialsPropertyzApp Engine datastore Property for Credentials.

    Utility property that allows easy storage and retrieval of
    oauth2client.Credentials
    c                    sF   t dtt|  tt| |}|d u r4d}n| }t	|S )Nzget: Got type  )
loggerinfor-   typer6   rh   rW   to_jsonr   rX   )r8   r[   credr:   r   r   rW     s    
z+CredentialsProperty.get_value_for_datastorec                 C   s^   t dtt|  |d u r"d S t|dkr2d S ztj|}W n tyX   d }Y n0 |S )Nzmake: Got type r   )	rj   rk   r-   rl   lenr   Credentialsnew_from_json
ValueError)r8   r^   credentialsr   r   r   r_     s    
z-CredentialsProperty.make_value_from_datastorec                    sR   t t| |}tdtt|  |d urNt|tj	sNt
d| j||S )Nzvalidate: Got type z@Property {0} must be convertible to a Credentials instance ({1}))r6   rh   re   rj   rk   r-   rl   r`   r   rp   r   rb   rc   rd   r]   r:   r   r   re     s    zCredentialsProperty.validate)r   r   r   r   r   rp   rg   rW   r_   re   rU   r   r   r:   r   rh      s
   rh   c                       s   e Zd ZdZedd fdd	Zdd Zdd	 Zd
d Z	e
jdddd Ze
jdddd Ze
jdddd Z  ZS )StorageByKeyNamea  Store and retrieve a credential to and from the App Engine datastore.

    This Storage helper presumes the Credentials have been stored as a
    CredentialsProperty or CredentialsNDBProperty on a datastore model class,
    and that entities are stored by key_name.
       Nc                    sJ   t t|   |du r.|du r&td| }|| _|| _|| _|| _dS )a  Constructor for Storage.

        Args:
            model: db.Model or ndb.Model, model class
            key_name: string, key name for the entity that has the credentials
            property_name: string, name of the property that is a
                           CredentialsProperty or CredentialsNDBProperty.
            cache: memcache, a write-through cache to put in front of the
                   datastore. If the model you are using is an NDB model, using
                   a cache will be redundant since the model uses an instance
                   cache and memcache for you.
            user: users.User object, optional. Can be used to grab user ID as a
                  key_name if no key name is specified.
        Nz1StorageByKeyName called with no key name or user.)	r6   rt   r7   rr   user_id_model	_key_name_property_name_cache)r8   r.   r&   Zproperty_namecacheuserr:   r   r   r7   0  s    zStorageByKeyName.__init__c                 C   sJ   t | jtr6tdur$t| jtr$dS t| jtjr6dS td| jdS )zDetermine whether the model of the instance is an NDB model.

        Returns:
            Boolean indicating whether or not the model is an NDB or DB model.
        NTFz(Model class not an NDB or DB model: {0}.)	r`   rw   rl   
_NDB_MODEL
issubclassr   Model	TypeErrorrc   rK   r   r   r   _is_ndbM  s    	
zStorageByKeyName._is_ndbc                 C   s(   |   r| j| jS | j| jS dS )a  Retrieve entity from datastore.

        Uses a different model method for db or ndb models.

        Returns:
            Instance of the model corresponding to the current storage object
            and stored using the key name of the storage object.
        N)r   rw   Z	get_by_idrx   Zget_by_key_namerK   r   r   r   _get_entity_  s    	zStorageByKeyName._get_entityc                 C   s@   |   rt| j| j  n tj| j | j}t| dS )zDelete entity from datastore.

        Attempts to delete using the key_name stored on the object, whether or
        not the given key is in the datastore.
        N)	r   _NDB_KEYrw   rx   deleter   Key	from_pathkind)r8   Z
entity_keyr   r   r   _delete_entitym  s    zStorageByKeyName._delete_entityT)Zallow_existingc                 C   s   d}| j r(| j | j}|r(tj|}|du rf|  }|durft|| j}| j rf| j 	| j|
  |r~t|dr~||  |S )zcRetrieve Credential from datastore.

        Returns:
            oauth2client.Credentials
        N	set_store)rz   r'   rx   r   rp   rq   r   getattrry   setrm   hasattrr   )r8   rs   r<   entityr   r   r   
locked_gety  s    
zStorageByKeyName.locked_getc                 C   sB   | j | j}t|| j| |  | jr>| j| j|  dS )z}Write a Credentials to the datastore.

        Args:
            credentials: Credentials, the credentials to store.
        N)	rw   r*   rx   setattrry   r+   rz   r   rm   )r8   rs   r   r   r   r   
locked_put  s
    zStorageByKeyName.locked_putc                 C   s    | j r| j | j |   dS )z!Delete Credential from datastore.N)rz   r   rx   r   rK   r   r   r   locked_delete  s    zStorageByKeyName.locked_delete)NN)r   r   r   r   r   rR   r7   r   r   r   r   Znon_transactionalr   r   r   rU   r   r   r:   r   rt   (  s   




rt   c                   @   s   e Zd ZdZe ZdS )CredentialsModelz`Storage for OAuth 2.0 Credentials

    Storage of the model is keyed by the user.user_id().
    N)r   r   r   r   rh   rs   r   r   r   r   r     s   r   c                 C   s.   | j j}tjt | t|d}|d | S )a  Composes the value for the 'state' parameter.

    Packs the current request URI and an XSRF token into an opaque string that
    can be passed to the authentication server via the 'state' parameter.

    Args:
        request_handler: webapp.RequestHandler, The request.
        user: google.appengine.api.users.User, The current user.

    Returns:
        The state value as a string.
    Z	action_id:)requesturlr   Zgenerate_tokenr   rv   r-   )request_handlerr|   urirF   r   r   r   _build_state_value  s
    r   c                 C   s4   |  dd\}}tjt || |dr,|S dS dS )aJ  Parse the value of the 'state' parameter.

    Parses the value and validates the XSRF token in the state parameter.

    Args:
        state: string, The value of the state parameter.
        user: google.appengine.api.users.User, The current user.

    Returns:
        The redirect URI, or None if XSRF token is not valid.
    r   r   r   N)rsplitr   Zvalidate_tokenr   rv   )stater|   r   rF   r   r   r   _parse_state_value  s    r   c                   @   s   e Zd ZdZdd Zdd ZeeeZdd Zdd	 Z	ee	eZ
ed
ejejejddddeedf
ddZdd Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zd d! Zd"d# ZdS )$OAuth2Decoratora`  Utility for making OAuth 2.0 easier.

    Instantiate and then use with oauth_required or oauth_aware
    as decorators on webapp.RequestHandler methods.

    ::

        decorator = OAuth2Decorator(
            client_id='837...ent.com',
            client_secret='Qh...wwI',
            scope='https://www.googleapis.com/auth/plus')

        class MainHandler(webapp.RequestHandler):
            @decorator.oauth_required
            def get(self):
                http = decorator.http()
                # http is authorized with the user's Credentials and can be
                # used in API calls

    c                 C   s   || j _d S rM   )_tlsrs   )r8   rs   r   r   r   set_credentials  s    zOAuth2Decorator.set_credentialsc                 C   s   t | jddS )zA thread local Credentials object.

        Returns:
            A client.Credentials object, or None if credentials hasn't been set
            in this thread yet, which may happen when calling has_credentials
            inside oauth_aware.
        rs   Nr   r   rK   r   r   r   get_credentials  s    zOAuth2Decorator.get_credentialsc                 C   s   || j _d S rM   )r   r\   )r8   r\   r   r   r   set_flow  s    zOAuth2Decorator.set_flowc                 C   s   t | jddS )zA thread local Flow object.

        Returns:
            A credentials.Flow object, or None if the flow hasn't been set in
            this thread yet, which happens in _create_flow() since Flows are
            created lazily.
        r\   Nr   rK   r   r   r   get_flow  s    zOAuth2Decorator.get_flowru   Nz/oauth2callbackrs   c                 K   sz   t  | _d| _d| _|| _|| _t|| _	|| _
|| _|| _|| _|| _|| _d| _|	| _|
| _|| _|| _|| _dS )a  Constructor for OAuth2Decorator

        Args:
            client_id: string, client identifier.
            client_secret: string client secret.
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            auth_uri: string, URI for authorization endpoint. For convenience
                      defaults to Google's endpoints but any OAuth 2.0 provider
                      can be used.
            token_uri: string, URI for token endpoint. For convenience defaults
                       to Google's endpoints but any OAuth 2.0 provider can be
                       used.
            revoke_uri: string, URI for revoke endpoint. For convenience
                        defaults to Google's endpoints but any OAuth 2.0
                        provider can be used.
            user_agent: string, User agent of your application, default to
                        None.
            message: Message to display if there are problems with the
                     OAuth 2.0 configuration. The message may contain HTML and
                     will be presented on the web interface for any method that
                     uses the decorator.
            callback_path: string, The absolute path to use as the callback
                           URI. Note that this must match up with the URI given
                           when registering the application in the APIs
                           Console.
            token_response_param: string. If provided, the full JSON response
                                  to the access token request will be encoded
                                  and included in this query parameter in the
                                  callback URI. This is useful with providers
                                  (e.g. wordpress.com) that include extra
                                  fields that the client may want.
            _storage_class: "Protected" keyword argument not typically provided
                            to this constructor. A storage class to aid in
                            storing a Credentials object for a user in the
                            datastore. Defaults to StorageByKeyName.
            _credentials_class: "Protected" keyword argument not typically
                                provided to this constructor. A db or ndb Model
                                class to hold credentials. Defaults to
                                CredentialsModel.
            _credentials_property_name: "Protected" keyword argument not
                                        typically provided to this constructor.
                                        A string indicating the name of the
                                        field on the _credentials_class where a
                                        Credentials object will be stored.
                                        Defaults to 'credentials'.
            **kwargs: dict, Keyword arguments are passed along as kwargs to
                      the OAuth2WebServerFlow constructor.
        NF)	threadinglocalr   r\   rs   
_client_id_client_secretr   r2   _scope	_auth_uri
_token_uri_revoke_uri_user_agentr4   _message	_in_error_callback_path_token_response_param_storage_class_credentials_class_credentials_property_name)r8   	client_idclient_secretr3   auth_uri	token_uri
revoke_uri
user_agentmessagecallback_pathZtoken_response_paramr   r   r   r9   r   r   r   r7   
  s$    >
zOAuth2Decorator.__init__c                 C   s4   |j jd |j jt| j |j jd d S )Nz<html><body>z</body></html>)responseoutwriter   r   )r8   r   r   r   r   _display_error_message[  s    z&OAuth2Decorator._display_error_messagec                    s    fdd}|S )a,  Decorator that starts the OAuth 2.0 dance.

        Starts the OAuth dance for the logged in user if they haven't already
        granted access for this application.

        Args:
            method: callable, to be decorated method of a webapp.RequestHandler
                    instance.
        c                    s   j r|  d S t }|s8| t| jj d S |  t	| |j
jd< jjd j|d _ s|  S zPz | g|R i |}W n* tjy   |   Y W d _S 0 W d _nd _0 |S Nr   r|   )r   r   r   get_current_userredirectcreate_login_urlr   r   _create_flowr   r\   paramsr   r   r   r'   rs   has_credentialsauthorize_urlr   rC   r   argsr9   r|   respmethodr8   r   r   check_oauthk  s6    

z3OAuth2Decorator.oauth_required.<locals>.check_oauthr   )r8   r   r   r   r   r   oauth_required`  s     zOAuth2Decorator.oauth_requiredc                 C   sP   | j du rL|j| j}tj| j| j| jf|| j	| j
| j| jd| j| _ dS )aU  Create the Flow object.

        The Flow is calculated lazily since we don't know where this app is
        running until it receives a request, at which point redirect_uri can be
        calculated and then the Flow object can be constructed.

        Args:
            request_handler: webapp.RequestHandler, the request handler.
        N)redirect_urir   r   r   r   )r\   r   Zrelative_urlr   r   ZOAuth2WebServerFlowr   r   r   r   r   r   r   r4   )r8   r   r   r   r   r   r     s    

zOAuth2Decorator._create_flowc                    s    fdd}|S )a!  Decorator that sets up for OAuth 2.0 dance, but doesn't do it.

        Does all the setup for the OAuth dance, but doesn't initiate it.
        This decorator is useful if you want to create a page that knows
        whether or not the user has granted access to this application.
        From within a method decorated with @oauth_aware the has_credentials()
        and authorize_url() methods can be called.

        Args:
            method: callable, to be decorated method of a webapp.RequestHandler
                    instance.
        c                    s   j r|  d S t }|s8| t| jj d S |  t	| |j
jd< jjd j|d _z  | g|R i |}W d _nd _0 |S r   )r   r   r   r   r   r   r   r   r   r   r\   r   r   r   r   r'   rs   r   r   r   r   setup_oauth  s*    

z0OAuth2Decorator.oauth_aware.<locals>.setup_oauthr   )r8   r   r   r   r   r   oauth_aware  s    zOAuth2Decorator.oauth_awarec                 C   s   | j duo| j j S )zTrue if for the logged in user there are valid access Credentials.

        Must only be called from with a webapp.RequestHandler subclassed method
        that had been decorated with either @oauth_required or @oauth_aware.
        N)rs   invalidrK   r   r   r   r     s    zOAuth2Decorator.has_credentialsc                 C   s   | j  }t|S )zReturns the URL to start the OAuth dance.

        Must only be called from with a webapp.RequestHandler subclassed method
        that had been decorated with either @oauth_required or @oauth_aware.
        )r\   Zstep1_get_authorize_urlr-   )r8   r   r   r   r   r     s    
zOAuth2Decorator.authorize_urlc                 O   s   | j tj|i |S )a  Returns an authorized http instance.

        Must only be called from within an @oauth_required decorated method, or
        from within an @oauth_aware decorated method where has_credentials()
        returns True.

        Args:
            *args: Positional arguments passed to httplib2.Http constructor.
            **kwargs: Positional arguments passed to httplib2.Http constructor.
        )rs   Z	authorizer
   Zget_http_object)r8   r   r9   r   r   r   rD     s    zOAuth2Decorator.httpc                 C   s   | j S )a.  The absolute path where the callback will occur.

        Note this is the absolute path, not the absolute URI, that will be
        calculated by the decorator at runtime. See callback_handler() for how
        this should be used.

        Returns:
            The callback path as a string.
        )r   rK   r   r   r   r     s    zOAuth2Decorator.callback_pathc                    s   |  G  fdddt j}|S )a  RequestHandler for the OAuth 2.0 redirect callback.

        Usage::

            app = webapp.WSGIApplication([
                ('/index', MyIndexHandler),
                ...,
                (decorator.callback_path, decorator.callback_handler())
            ])

        Returns:
            A webapp.RequestHandler that handles the redirect back from the
            server during the OAuth 2.0 dance.
        c                       s    e Zd ZdZe fddZdS )z7OAuth2Decorator.callback_handler.<locals>.OAuth2Handlerz4Handler for the redirect_uri of the OAuth 2.0 dance.c                    s   | j d}|r8| j d|}| jjdt| nt } 	|   j
| j j} j jd  j|d| tt| j d|}|d u r| jjd d S  jr|jrt|j}t| j|}| | d S )NerrorZerror_descriptionz%The authorization request failed: {0}r   r   z The authorization request failed)r   r'   r   r   r   rc   r   r   r   r   r\   Zstep2_exchanger   r   r   r   r+   r   r-   r   Ztoken_responser<   rZ   r   Z_add_query_parameterr   )r8   r   Zerrormsgr|   rs   r   Z	resp_json	decoratorr   r   r'   	  sJ    
z;OAuth2Decorator.callback_handler.<locals>.OAuth2Handler.getN)r   r   r   r   r   r'   r   r   r   r   OAuth2Handler  s   r   )webappZRequestHandler)r8   r   r   r   r   callback_handler  s    $z OAuth2Decorator.callback_handlerc                 C   s   t | j|  fgS )aM  WSGI application for handling the OAuth 2.0 redirect callback.

        If you need finer grained control use `callback_handler` which returns
        just the webapp.RequestHandler.

        Returns:
            A webapp.WSGIApplication that handles the redirect back from the
            server during the OAuth 2.0 dance.
        )r   ZWSGIApplicationr   r   rK   r   r   r   callback_application,  s    
z$OAuth2Decorator.callback_application)r   r   r   r   r   r   rT   rs   r   r   r\   r   rR   oauth2clientZGOOGLE_AUTH_URIZGOOGLE_TOKEN_URIZGOOGLE_REVOKE_URIrt   r   r7   r   r   r   r   r   r   rD   r   r   r   r   r   r   r   r     s<   



P-)	
7r   c                       s,   e Zd ZdZedd fdd	Z  ZS ) OAuth2DecoratorFromClientSecretsa~  An OAuth2Decorator that builds from a clientsecrets file.

    Uses a clientsecrets file as the source for all the information when
    constructing an OAuth2Decorator.

    ::

        decorator = OAuth2DecoratorFromClientSecrets(
            os.path.join(os.path.dirname(__file__), 'client_secrets.json')
            scope='https://www.googleapis.com/auth/plus')

        class MainHandler(webapp.RequestHandler):
            @decorator.oauth_required
            def get(self):
                http = decorator.http()
                # http is authorized with the user's Credentials and can be
                # used in API calls

       Nc           
         s   t j||d\}}|t jt jfvr,t dt|}||d |d |d |d}	|	durh|	|d< tt	| j
|d |d	 |fi | |dur|| _nd
| _dS )a#  Constructor

        Args:
            filename: string, File name of client secrets.
            scope: string or iterable of strings, scope(s) of the credentials
                   being requested.
            message: string, A friendly string to display to the user if the
                     clientsecrets file is missing or invalid. The message may
                     contain HTML and will be presented on the web interface
                     for any method that uses the decorator.
            cache: An optional cache service client that implements get() and
                   set()
            methods. See clientsecrets.loadfile() for details.
            **kwargs: dict, Keyword arguments are passed along as kwargs to
                      the OAuth2WebServerFlow constructor.
        )r{   z4OAuth2Decorator doesn't support this OAuth 2.0 flow.r   r   )r   r   r   r   Nr   r   z0Please configure your application for OAuth 2.0.)r	   ZloadfileZTYPE_WEBZTYPE_INSTALLEDZInvalidClientSecretsErrordictupdater'   r6   r   r7   r   )
r8   filenamer3   r   r{   r9   Zclient_typeZclient_infoZconstructor_kwargsr   r:   r   r   r7   P  s6    


z)OAuth2DecoratorFromClientSecrets.__init__)NN)r   r   r   r   r   rR   r7   rU   r   r   r:   r   r   ;  s   r   r0   c                 C   s   t | |||dS )a  Creates an OAuth2Decorator populated from a clientsecrets file.

    Args:
        filename: string, File name of client secrets.
        scope: string or list of strings, scope(s) of the credentials being
               requested.
        message: string, A friendly string to display to the user if the
                 clientsecrets file is missing or invalid. The message may
                 contain HTML and will be presented on the web interface for
                 any method that uses the decorator.
        cache: An optional cache service client that implements get() and set()
               methods. See clientsecrets.loadfile() for details.

    Returns: An OAuth2Decorator
    )r   r{   )r   )r   r3   r   r{   r   r   r   "oauth2decorator_from_clientsecrets{  s    r   )NN);r   r   r<   loggingr    rY   r   Zgoogle.appengine.apir   r   r   Zgoogle.appengine.extr   Z google.appengine.ext.webapp.utilr   Zwebapp2r   r   r   r   r	   r
   Zoauth2client.contribr   r   ImportError	getLoggerr   rj   r)   r(   ZCredentialsNDBModelZCredentialsNDBPropertyZFlowNDBPropertyr   r}   ZSiteXsrfSecretKeyNDBZNDB_KEYZ	NDB_MODELr   r   r   r#   r   ZAssertionCredentialsr/   PropertyrV   rh   ZStoragert   r   r   r   objectr   r   rR   r   r   r   r   r   <module>   sp   


	d!,  g@ 