Ë
    +Ñ¦h{+  ã                   óÆ   — 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    úY/var/www/timesheet/venv/lib/python3.12/site-packages/flask_dance/consumer/storage/sqla.pyÚ__tablename__z OAuthConsumerMixin.__tablename__#   s   € à˜cŸl™l×0Ñ0Ó2Ð3Ð4Ð4ó    T)Úprimary_keyé2   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—^‘^×,Ñ,Ô-Ø�7Š7Ø�L‰L˜3˜tŸw™w˜i˜Ô)Ø�=Š=Ø�L‰L˜: d§m¡m _°AÐ6Ô7Ø�}‰}˜SŸX™X e›_Ó-Ð-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Ù‘f˜R“j¨5Ô1€HÙ˜¨(¯/©/ÀEÔJ€JÙÐ)�;×)Ñ)¨$Ó/¸%Ô@€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Ò!H°WÀDÐ5HˆDÕà!.ˆDÔØ"Ò8Ô&8ˆŒØÒ)œi›kˆ�
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$   øè ø€ ò àô ˜s D§N¡N×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�   ø€ Ü�W˜dŸl™l¨I×,<Ñ,<×,@Ñ,@ÀÓ,KÐLÓMˆÙÜó à  $§)¡)¨Y×-=Ñ-=×-AÑ-AÀ&Ó-IÐJôó ˆAô ˜!˜T 1Ó%ˆ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ˆÜ�W˜dŸl™l¨I×,<Ñ,<×,@Ñ,@ÀÓ,KÐLÓMˆÜó 
à˜dŸi™i¨×)9Ñ)9×)=Ñ)=¸fÓ)EÐFô
ó 
ˆð
 ×Ò¡a±ÜÐPÓQÐQô �4—:‘:˜yÔ)©cØ—O‘O¨C�OÓ0‰Eä�T—Z‘Z Ô(©QØ—O‘O¨�OÓ+‰Eä�T—Z‘Z Ô+Ø—O‘O¨D�OÓ1ˆEð	Ø—I‘I“K×%Ñ%ˆ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‰  ø€ Ü�W˜dŸl™l¨I×,<Ñ,<×,@Ñ,@ÀÓ,KÐLÓMˆÜó 
à˜dŸi™i¨×)9Ñ)9×)=Ñ)=¸fÓ)EÐFô
ó 
ˆð
 ×Ò¡a±ÜÐPÓQÐQð Ÿ™×+Ñ+¨D¯J©JÓ7×AÑAØ—^‘^ð Bó 
ˆô ˜dŸj™j¨)Ó4ˆÙ™3Ø+×5Ñ5¸cÐ5ÓBˆNä˜4Ÿ:™: vÓ.ˆÙ™Ø+×5Ñ5¸1Ð5Ó=ˆNà×ÑÔà'Ÿn™n°uÑ=ˆÙ™3Ø #ˆF�9ÑÙ™ØˆF�6‰NØ�‰×Ñ˜˜Ÿ™Ñ- 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ˆÜ�W˜dŸl™l¨I×,<Ñ,<×,@Ñ,@ÀÓ,KÐLÓMˆÜó 
à˜dŸi™i¨×)9Ñ)9×)=Ñ)=¸fÓ)EÐFô
ó 
ˆð
 ×Ò¡a±ÜÐSÓTÐTô �4—:‘:˜yÔ)©cØ—O‘O¨C�OÓ0‰Eä�T—Z‘Z Ô(©QØ—O‘O¨�OÓ+‰Eä�T—Z‘Z Ô+Ø—O‘O¨D�OÓ1ˆEà�‰ŒØ�‰×ÑÔà�
‰
×ÑØ×Ñ¨)¸$ÈÐÓ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 