
    D6i{+                         d dl m Z  d dlmZmZmZmZ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mZmZ 	 d dlmZ  G d
 d      Z G d de      ZddZy	# e$ r d	ZY #w xY w)    )datetime)JSONColumnDateTimeIntegerString)declared_attr)MutableDict)NoResultFound)BaseStorage)	FakeCachefirst)AnonymousUserMixinNc                       e Zd ZdZed        Z eed      Z e e	d      d      Z
 eeej                  d      Z e ej                   e      d      Zd	 Zy
)OAuthConsumerMixina%  
    A :ref:`SQLAlchemy declarative mixin <sqlalchemy:declarative_mixins>` with
    some suggested columns for a model to store OAuth tokens:

    ``id``
        an integer primary key
    ``provider``
        a short name to indicate which OAuth provider issued
        this token
    ``created_at``
        an automatically generated datetime that indicates when
        the OAuth provider issued this token
    ``token``
        a :class:`JSON <sqlalchemy.types.JSON>` field to store
        the actual token received from the OAuth provider
    c                 <    d| j                   j                          S )Nflask_dance_)__name__lower)clss    d/home/azureuser/techstart-app/venv/lib/python3.12/site-packages/flask_dance/consumer/storage/sqla.py__tablename__z OAuthConsumerMixin.__tablename__#   s    cll002344    T)primary_key2   F)nullable)defaultr   c                 :   g }|j                  | j                  j                         | j                  r|j                  d| j                          | j                  r|j                  d| j                   d       dj                  dj                  |            S )Nzid=z
provider=""z<{}> )append	__class__r   idproviderformatjoin)selfpartss     r   __repr__zOAuthConsumerMixin.__repr__,   sq    T^^,,-77LL3twwi)==LL:dmm_A67}}SXXe_--r   N)r   
__module____qualname____doc__r	   r   r   r   r#   r   r$   r   r   utcnow
created_atr
   
as_mutabler   tokenr)    r   r   r   r      sj    " 5 5 
T	*BfRj51H(//EJJ);))$/%@E.r   r   c                   B    e Zd ZdZ	 	 	 	 	 ddZd	dZd	dZd	dZd	dZy)
SQLAlchemyStoragez
    Stores and retrieves OAuth tokens using a relational database through
    the `SQLAlchemy`_ ORM.

    .. _SQLAlchemy: http://www.sqlalchemy.org/
    Nc                     || _         || _        || _        || _        ||duxs |du| _        n|| _        |xs t
        | _        |xs
 t               | _        y)a
  
        Args:
            model: The SQLAlchemy model class that represents the OAuth token
                table in the database. At a minimum, it must have a
                ``provider`` column and a ``token`` column. If tokens are to be
                associated with individual users in the application, it must
                also have a ``user`` relationship to your User model.
                It is recommended, though not required, that your model class
                inherit from
                :class:`~flask_dance.consumer.storage.sqla.OAuthConsumerMixin`.
            session:
                The :class:`SQLAlchemy session <sqlalchemy.orm.session.Session>`
                for the database. If you're using `Flask-SQLAlchemy`_, this is
                ``db.session``.
            user:
                If you want OAuth tokens to be associated with individual users
                in your application, this is a reference to the user that you
                want to use for the current request. It can be an actual User
                object, a function that returns a User object, or a proxy to the
                User object. If you're using `Flask-Login`_, this is
                :attr:`~flask.ext.login.current_user`.
            user_id:
                If you want to pass an identifier for a user instead of an actual
                User object, use this argument instead. Sometimes it can save
                a database query or two. If both ``user`` and ``user_id`` are
                provided, ``user_id`` will take precendence.
            user_required:
                If set to ``True``, an exception will be raised if you try to
                set or retrieve an OAuth token without an associated user.
                If set to ``False``, OAuth tokens can be set with or without
                an associated user. The default is auto-detection: it will
                be ``True`` if you pass a ``user`` or ``user_id`` parameter,
                ``False`` otherwise.
            anon_user:
                If anonymous users are represented by a class in your application,
                provide that class here. If you are using `Flask-Login`_,
                anonymous users are represented by the
                :class:`flask_login.AnonymousUserMixin` class, but you don't have
                to provide that -- Flask-Dance treats it as the default.
            cache:
                An instance of `Flask-Caching`_. Providing a caching system is
                highly recommended, but not required.

        .. _Flask-SQLAlchemy: http://pythonhosted.org/Flask-SQLAlchemy/
        .. _Flask-Login: https://flask-login.readthedocs.io/
        .. _Flask-Caching: https://flask-caching.readthedocs.io/en/latest/
        N)	modelsessionuseruser_iduser_requiredr   	anon_userr   cache)r'   r5   r6   r7   r8   r9   r:   r;   s           r   __init__zSQLAlchemyStorage.__init__>   sa    r 
	 !%T!1!HWD5HD!.D"8&8)ik
r   c                 2    t        | j                  |j                  j                  d      g      }|sGt         fd| j                  |j                  j                  d      fD              }t        |d|      }dj                  |j                  |      S )Nr8   c              3   J   K   | ]  }t        |j                          y wN_get_real_userr:   .0refr'   s     r   	<genexpr>z3SQLAlchemyStorage.make_cache_key.<locals>.<genexpr>   s$       sDNN3    #r7   r#   z"flask_dance_token|{name}|{user_id})namer8   )r   r8   configgetr7   getattrr%   rG   )r'   	blueprintr7   r8   uidus   `     r   make_cache_keyz SQLAlchemyStorage.make_cache_key   s    WdllI,<,<,@,@,KLM  $))Y-=-=-A-A&-IJ A !T1%C3:: ; 
 	
r   c                      j                  |||      } j                  j                  |      }|r|S  j                  j	                   j
                        j                  |j                        }t        | j                  |j                  j                  d      g      }t         fd| j                  |j                  j                  d      fD              } j                  r|s|st        d      t         j
                  d      r|r|j                  |      }nSt         j
                  d      r|r|j                  |      }n(t         j
                  d      r|j                  d	      }	 |j                         j                   } j                  j%                  ||       |S # t"        $ r d	}Y +w xY w)
a  When you have a statement in your code that says
        "if <provider>.authorized:" (for example "if google.authorized:"),
        a long string of function calls result in this function being used to
        check the Flask server's cache and database for any records associated
        with the current_user. The `user` and `user_id` parameters are actually
        not set in that case (see base.py:token(), that's what calls this
        function), so the user information is instead loaded from the
        current_user (if that's what you specified when you created the
        blueprint) with blueprint.config.get('user_id').

        :param blueprint:
        :param user:
        :param user_id:
        :return:
        rK   r7   r8   r$   r8   c              3   J   K   | ]  }t        |j                          y wr?   r@   rB   s     r   rE   z(SQLAlchemyStorage.get.<locals>.<genexpr>   $      
 3/
rF   r7   z1Cannot get OAuth token without an associated userr8   r7   N)rN   r;   rI   r6   queryr5   	filter_byrG   r   r8   rH   r7   r9   
ValueErrorhasattroner0   r   set)	r'   rK   r7   r8   	cache_keyr0   rV   rL   rM   s	   `        r   rI   zSQLAlchemyStorage.get   s|   " '')$PW'X	

y)L ""4::.88)..8QWdllI,<,<,@,@,KLM 
dii)9)9)=)=f)EF
 

 aPQQ 4::y)cOOCO0ETZZ(QOOO+ETZZ+OODO1E	IIK%%E
 	

y%(  	E	s   9F1 1F?>F?c                     t        | j                  |j                  j                  d      g      }t         fd| j                  |j                  j                  d      fD              } j
                  r|s|st        d       j                  j                   j                        j                  |j                        }t         j                  d      }|r|r|j                  |      }t         j                  d      }	|	r|r|j                  |      }|j                          |j                  |d}
|r|r||
d<   |	r|r||
d<    j                  j                    j                  d
i |
        j                  j                           j                   j                   j#                  |||	             y )Nr8   c              3   J   K   | ]  }t        |j                          y wr?   r@   rB   s     r   rE   z(SQLAlchemyStorage.set.<locals>.<genexpr>   rS   rF   r7   z1Cannot set OAuth token without an associated userrQ   rT   rU   )r$   r0   rP   r1   )r   r8   rH   rI   r7   r9   rX   r6   rV   r5   rW   rG   rY   deleteaddcommitr;   rN   )r'   rK   r0   r7   r8   rL   rM   existing_queryhas_user_idhas_userkwargss   `          r   r[   zSQLAlchemyStorage.set   s   WdllI,<,<,@,@,KLM 
dii)9)9)=)=f)EF
 

 aPQQ ++DJJ7AA^^ B 
 djj)43+55c5BN4::v.+5515=N'nnu=3 #F9F6N-f-.

)$P	
r   c                 :     j                   j                   j                        j                  |j                        }t        | j                  |j                  j                  d      g      }t         fd| j                  |j                  j                  d      fD              } j                  r|s|st        d      t         j                  d      r|r|j                  |      }nSt         j                  d      r|r|j                  |      }n(t         j                  d      r|j                  d       }|j                           j                   j                           j                  j                   j!                  |||             y )	NrQ   r8   c              3   J   K   | ]  }t        |j                          y wr?   r@   rB   s     r   rE   z+SQLAlchemyStorage.delete.<locals>.<genexpr>   rS   rF   r7   z4Cannot delete OAuth token without an associated userrT   rU   rP   )r6   rV   r5   rW   rG   r   r8   rH   rI   r7   r9   rX   rY   r_   ra   r;   rN   )r'   rK   r7   r8   rV   rL   rM   s   `      r   r_   zSQLAlchemyStorage.delete   sA   ""4::.88)..8QWdllI,<,<,@,@,KLM 
dii)9)9)=)=f)EF
 

 aSTT 4::y)cOOCO0ETZZ(QOOO+ETZZ+OODO1E

)$P	
r   )NNNNN)NN)	r   r*   r+   r,   r<   rN   rI   r[   r_   r1   r   r   r3   r3   6   s5     B*H

3j$
L
r   r3   c                     t        | d      r| j                         } t        |       r |        } |rt        | |      ry| S )a  
    Given a "user" that could be:

    * a real user object
    * a function that returns a real user object
    * a LocalProxy to a real user object (like Flask-Login's ``current_user``)

    This function returns the real user object, regardless of which we have.
    _get_current_objectN)rY   ri   callable
isinstance)r7   r:   s     r   rA   rA     s?     t*+'')~vZi0Kr   r?   )r   
sqlalchemyr   r   r   r   r   sqlalchemy.ext.declarativer	   sqlalchemy.ext.mutabler
   sqlalchemy.orm.excr   flask_dance.consumer.storager   flask_dance.utilsr   r   flask_loginr   ImportErrorr   r3   rA   r1   r   r   <module>rt      s\     > > 4 . , 4 ..
". ".JM
 M
`s  s   A A A 