o
    eG                     @   s   d Z ddlZddlmZmZ ddlmZmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZ dd	lmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% dd
l&m'Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z. G dd de/Z0dS )zY
    flask_login.login_manager
    -------------------------
    The LoginManager class.
    N)datetime	timedelta)_request_ctx_stackabortcurrent_appflashredirecthas_app_contextrequestsession   )	text_type)COOKIE_NAMECOOKIE_DURATIONCOOKIE_SECURECOOKIE_HTTPONLYLOGIN_MESSAGELOGIN_MESSAGE_CATEGORYREFRESH_MESSAGEREFRESH_MESSAGE_CATEGORYID_ATTRIBUTEAUTH_HEADER_NAMESESSION_KEYSUSE_SESSION_FOR_NEXT)AnonymousUserMixin)user_loaded_from_cookieuser_loaded_from_headeruser_loaded_from_requestuser_unauthorizeduser_needs_refreshuser_accessedsession_protected)	login_url_create_identifier_user_context_processorencode_cookiedecode_cookiemake_next_paramexpand_login_viewc                   @   s   e Zd ZdZd-ddZd.ddZd.dd	Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zd/ddZ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ejd,d+ ZdS )0LoginManagerzThis object is used to hold the settings used for logging in. Instances
    of :class:`LoginManager` are *not* bound to specific apps, so you can
    create one in the main body of your code and then bind it to your
    app in a factory function.
    NTc                 C   s   t | _d | _i | _t| _t| _d | _t	| _
t| _d| _d | _d | _d | _t| _d | _d | _d | _t| _|d ur?| || d S d S )Nbasic)r   anonymous_user
login_viewblueprint_login_viewsr   login_messager   login_message_categoryrefresh_viewr   needs_refresh_messager   needs_refresh_message_categorysession_protectionlocalize_callbackunauthorized_callbackneeds_refresh_callbackr   id_attribute_user_callback_header_callback_request_callbackr#   _session_identifier_generatorinit_appselfappadd_context_processor rA   F/qpanel/venv/lib/python3.10/site-packages/flask_login/login_manager.py__init__#   s(   zLoginManager.__init__c                 C   s   t dt | || dS )zl
        This method has been deprecated. Please use
        :meth:`LoginManager.init_app` instead.
        z5Warning setup_app is deprecated. Please use init_app.N)warningswarnDeprecationWarningr<   r=   rA   rA   rB   	setup_app_   s   zLoginManager.setup_appc                 C   s(   | |_ || j |r|t dS dS )a  
        Configures an application. This registers an `after_request` call, and
        attaches this `LoginManager` to it as `app.login_manager`.

        :param app: The :class:`flask.Flask` object to configure.
        :type app: :class:`flask.Flask`
        :param add_context_processor: Whether to add a context processor to
            the app that adds a `current_user` variable to the template.
            Defaults to ``True``.
        :type add_context_processor: bool
        N)login_managerafter_request_update_remember_cookiecontext_processorr$   r=   rA   rA   rB   r<   h   s
   zLoginManager.init_appc                 C   s   t t  | jr|  S tj| jv r| jtj }n| j}|s$t	d | j
r@| jdur8t| | j
| jd nt| j
| jd tj}|dtrct|}|  td< t|tjtd< t|}t|S t|tjd}t|S )a  
        This is called when the user is required to log in. If you register a
        callback with :meth:`LoginManager.unauthorized_handler`, then it will
        be called. Otherwise, it will take the following actions:

            - Flash :attr:`LoginManager.login_message` to the user.

            - If the app is using blueprints find the login view for
              the current blueprint using `blueprint_login_views`. If the app
              is not using blueprints or the login view for the current
              blueprint is not specified use the value of `login_view`.

            - Redirect the user to the login view. (The page they were
              attempting to access will be passed in the ``next`` query
              string variable, so you can redirect there if present instead
              of the homepage. Alternatively, it will be added to the session
              as ``next`` if USE_SESSION_FOR_NEXT is set.)

        If :attr:`LoginManager.login_view` is not defined, then it will simply
        raise a HTTP 401 (Unauthorized) error instead.

        This should be returned from a view or before/after_request function,
        otherwise the redirect will have no effect.
          Ncategoryr   _idnextnext_url)r   sendr   _get_current_objectr5   r
   	blueprintr-   r,   r   r.   r4   r   r/   configgetr   r(   r;   r   r'   urlmake_login_urlr   )r>   r,   rV   r"   redirect_urlrA   rA   rB   unauthorizedz   s.   
zLoginManager.unauthorizedc                 C   
   || _ |S )aB  
        This sets the callback for reloading a user from the session. The
        function you set should take a user ID (a ``unicode``) and return a
        user object, or ``None`` if the user does not exist.

        :param callback: The callback for retrieving a user object.
        :type callback: callable
        )r8   r>   callbackrA   rA   rB   user_loader      	zLoginManager.user_loaderc                 C   s   t d || _|S )a  
        This function has been deprecated. Please use
        :meth:`LoginManager.request_loader` instead.

        This sets the callback for loading a user from a header value.
        The function you set should take an authentication token and
        return a user object, or `None` if the user does not exist.

        :param callback: The callback for retrieving a user object.
        :type callback: callable
        zRLoginManager.header_loader is deprecated. Use LoginManager.request_loader instead.)printr9   r]   rA   rA   rB   header_loader   s   zLoginManager.header_loaderc                 C   r\   )a=  
        This sets the callback for loading a user from a Flask request.
        The function you set should take Flask request object and
        return a user object, or `None` if the user does not exist.

        :param callback: The callback for retrieving a user object.
        :type callback: callable
        )r:   r]   rA   rA   rB   request_loader   r`   zLoginManager.request_loaderc                 C   r\   )ab  
        This will set the callback for the `unauthorized` method, which among
        other things is used by `login_required`. It takes no arguments, and
        should return a response to be sent to the user instead of their
        normal view.

        :param callback: The callback for unauthorized users.
        :type callback: callable
        )r5   r]   rA   rA   rB   unauthorized_handler      
z!LoginManager.unauthorized_handlerc                 C   r\   )ai  
        This will set the callback for the `needs_refresh` method, which among
        other things is used by `fresh_login_required`. It takes no arguments,
        and should return a response to be sent to the user instead of their
        normal view.

        :param callback: The callback for unauthorized users.
        :type callback: callable
        )r6   r]   rA   rA   rB   needs_refresh_handler   re   z"LoginManager.needs_refresh_handlerc                 C   s   t t  | jr|  S | jstd | jdur&t| | j	| j
d nt| j	| j
d tj}|dtrSt| j}|  td< t|tjtd< t| j}t|S | j}t|tjd}t|S )a  
        This is called when the user is logged in, but they need to be
        reauthenticated because their session is stale. If you register a
        callback with `needs_refresh_handler`, then it will be called.
        Otherwise, it will take the following actions:

            - Flash :attr:`LoginManager.needs_refresh_message` to the user.

            - Redirect the user to :attr:`LoginManager.refresh_view`. (The page
              they were attempting to access will be passed in the ``next``
              query string variable, so you can redirect there if present
              instead of the homepage.)

        If :attr:`LoginManager.refresh_view` is not defined, then it will
        simply raise a HTTP 401 (Unauthorized) error instead.

        This should be returned from a view or before/after_request function,
        otherwise the redirect will have no effect.
        rL   NrM   r   rO   rP   rQ   )r   rS   r   rT   r6   r0   r   r4   r   r1   r2   rV   rW   r   r(   r;   r   r'   r
   rX   rY   r   )r>   rV   r"   rZ   rA   rA   rB   needs_refresh   s,   


zLoginManager.needs_refreshc                 C   s&   t j}|du r|  |_dS ||_dS )z!Store the given user as ctx.user.N)r   topr+   user)r>   ri   ctxrA   rA   rB   !_update_request_context_with_user$  s    z.LoginManager._update_request_context_with_userc           	      C   s   | j du r| jdu rtdtt  |  r|  S d}t	
d}|dur2| j dur2|  |}|du rvtj}|
dt}|
dt}|tjv oPt	
ddk}|r^tj| }| |}n| jrg| t}n|tjv rvtj| }| |}| |S )z;Loads user from session or remember_me cookie as applicableNznMissing user_loader or request_loader. Refer to http://flask-login.readthedocs.io/#how-it-works for more info._user_idREMEMBER_COOKIE_NAMEr   	_rememberclear)r8   r:   	Exceptionr    rS   r   rT   _session_protection_failedrk   r   rW   rV   r   r   r
   cookies_load_user_from_remember_cookie_load_user_from_requestheaders_load_user_from_header)	r>   ri   user_idrV   cookie_nameheader_name
has_cookiecookieheaderrA   rA   rB   
_load_user*  s6   







zLoginManager._load_userc                 C   s   t  }|  }t }|jd| j}|r|dvrdS |rR||dd krR|dks-|jr8d|d< t	| dS |dkrRt
D ]}||d  q>d|d	< t	| d
S dS )NSESSION_PROTECTION)r*   strongFrO   r*   _freshr   ro   rn   T)r   rT   r;   r   rV   rW   r3   	permanentr!   rS   r   pop)r>   sessidentr?   modekrA   rA   rB   rq   R  s$   

z'LoginManager._session_protection_failedc                 C   sZ   t |}|d ur+|td< dtd< d }| jr| |}|d ur+t }tj||d |S d S )Nrl   Fr   ri   )r&   r   r8   r   rT   r   rS   )r>   r{   rw   ri   r?   rA   rA   rB   rs   m  s   
z,LoginManager._load_user_from_remember_cookiec                 C   6   | j r|  |}|d urt }tj||d |S d S Nr   )r9   r   rT   r   rS   )r>   r|   ri   r?   rA   rA   rB   rv   {     
z#LoginManager._load_user_from_headerc                 C   r   r   )r:   r   rT   r   rS   )r>   r
   ri   r?   rA   rA   rB   rt     r   z$LoginManager._load_user_from_requestc                 C   sd   dt vrtjdrdt d< dt v r0t dd }|dkr'dt v r'| | |S |dkr0| | |S )Nrn   $REMEMBER_COOKIE_REFRESH_EACH_REQUESTsetrl   ro   )r   r   rV   rW   r   _set_cookie_clear_cookie)r>   response	operationrA   rA   rB   rJ     s   


z$LoginManager._update_remember_cookiec              	   C   s   t j}|dt}|d}|dd}|dt}|dt}dtv r,ttd d}n|d	t}t	t
td
 }	t|trDt|d}zt | }
W n ty\   tdd| w |j||	|
||||d d S )Nrm   REMEMBER_COOKIE_DOMAINREMEMBER_COOKIE_PATH/REMEMBER_COOKIE_SECUREREMEMBER_COOKIE_HTTPONLY_remember_seconds)secondsREMEMBER_COOKIE_DURATIONrl   z#REMEMBER_COOKIE_DURATION must be a z$datetime.timedelta, instead got: {0})valueexpiresdomainpathsecurehttponly)r   rV   rW   r   r   r   r   r   r   r%   r   
isinstanceintr   utcnow	TypeErrorrp   format
set_cookie)r>   r   rV   rx   r   r   r   r   durationdatar   rA   rA   rB   r     s:   



zLoginManager._set_cookiec                 C   s<   t j}|dt}|d}|dd}|j|||d d S )Nrm   r   r   r   )r   r   )r   rV   rW   r   delete_cookie)r>   r   rV   rx   r   r   rA   rA   rB   r     s
   
zLoginManager._clear_cookiec                 C   s   t  r
tjddS dS )z:Legacy property, use app.config['LOGIN_DISABLED'] instead.LOGIN_DISABLEDF)r	   r   rV   rW   )r>   rA   rA   rB   _login_disabled  s   zLoginManager._login_disabledc                 C   s   |t jd< dS )zALegacy property setter, use app.config['LOGIN_DISABLED'] instead.r   N)r   rV   )r>   newvaluerA   rA   rB   r     s   )NT)T)N)__name__
__module____qualname____doc__rC   rG   r<   r[   r_   rb   rc   rd   rf   rg   rk   r}   rq   rs   rv   rt   rJ   r   r   propertyr   setterrA   rA   rA   rB   r)      s2    

<
	8
/(		%
r)   )1r   rD   r   r   flaskr   r   r   r   r   r	   r
   r   _compatr   rV   r   r   r   r   r   r   r   r   r   r   r   r   mixinsr   signalsr   r   r   r   r   r    r!   utilsr"   rY   r#   r$   r%   r&   r'   r(   objectr)   rA   rA   rA   rB   <module>   s   (8$$