a
    Sic^2                     @   s   d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	m
Z
 d dlmZ d dlmZ d dlmZmZmZ d dlmZ d d	lmZmZ d d
lmZmZmZmZmZ d dlmZm Z m!Z! d dl"m#Z# ee$Z%G dd deeZ&dS )    )	getLogger)Optional)transaction)FSumValueQ)Concat)timezone)clean_expired_user_attemptsget_user_attemptsreset_user_attempts)settings)AxesBaseHandlerAbstractAxesHandler)get_client_strget_client_usernameget_credentialsget_failure_limitget_query_str)	AccessLogAccessAttemptAccessFailureLog)user_locked_outc                   @   s   e Zd ZdZddddee ee eedddZddee ed	d
dZ	ddee ed	ddZ
ejdeee edddZd ee edddZd!edddZdd Zdd Zdd Zdd ZdS )"AxesDatabaseHandlera  
    Signal handler implementation that records user login attempts to database and locks users out if necessary.

    .. note:: The get_user_attempts function is called several time during the authentication and lockout
              process, caching its output can be dangerous.
    NF)
ip_addressusernameip_or_username)r   r   r   returnc                C   sf   t j }|r*|t|dt|dB }n |r:|j|d}|rJ|j|d}| \}}td| |S )N)r   r   z-AXES: Reset %d access attempts from database.)r   objectsallfilterr   deleteloginfo)selfr   r   r   attemptscount_ r*   R/var/www/html/django/DPS/env/lib/python3.9/site-packages/axes/handlers/database.pyreset_attempts%   s    
z"AxesDatabaseHandler.reset_attempts)age_days)r-   r   c                C   sd   |d u r(t j  \}}td| n8t tj|d }t jj	|d \}}td|| |S )Nz-AXES: Reset all %d access logs from database.daysZattempt_time__ltez<AXES: Reset %d access logs older than %d days from database.)
r   r    r!   r#   r$   r%   r
   now	timedeltar"   r&   r-   r(   r)   limitr*   r*   r+   
reset_logs;   s    zAxesDatabaseHandler.reset_logsc                C   sd   |d u r(t j  \}}td| n8t tj|d }t jj	|d \}}td|| |S )Nz5AXES: Reset all %d access failure logs from database.r.   r0   zDAXES: Reset %d access failure logs older than %d days from database.)
r   r    r!   r#   r$   r%   r
   r1   r2   r"   r3   r*   r*   r+   reset_failure_logsJ   s    z&AxesDatabaseHandler.reset_failure_logs)r4   )r   r4   r   c                C   sL   d}t jj|d}| | }|dkrH|d | D ]}|  |d7 }q2|S )Nr   r      )r   r    r"   r(   r#   )r&   r   r4   r(   failuresZout_of_limit_failures_logsfailurer*   r*   r+    remove_out_of_limit_failure_logsY   s    
z4AxesDatabaseHandler.remove_out_of_limit_failure_logs)credentialsr   c                 C   s    t ||}tdd |D }|S )Nc                 s   s$   | ]}| td d pdV  qdS )failures_since_startZfailures_since_start__sumr   N)	aggregater   ).0r'   r*   r*   r+   	<genexpr>j   s
   z3AxesDatabaseHandler.get_failures.<locals>.<genexpr>)r   max)r&   requestr;   Zattempts_listZattempt_countr*   r*   r+   get_failuresh   s
    
	z AxesDatabaseHandler.get_failures)r;   c                 K   sd  t d |du r t d dS t|j t||}t||j|j|j	|}t
jst|jrt||_tjd|||jd dS t|jdd}t|jdd}| ||rt d| dS t
jr|du rt d	 nt  tj j||j|j|||j|j	d
|jdd\}	}
|
r t d| nfd}tdt|| |	_ tdt|| |	_!|j|	_"|j	|	_#t$dd
 |	_%|j|	_&|	'  t d| W d   n1 s0    Y  | (||}||_)t
j*r|t+||krt d| d|_||_tjd|||jd t
j,r`t B t-jj.||j|j|j|j	|j|jd | j/|d W d   n1 sV0    Y  dS )zWhen user login fails, save AccessFailureLog record in database,
        save AccessAttempt record in database, mark request with
        lockout attribute and emit lockout signal.

        z>AXES: User login failed, running database handler for failure.NzPAXES: AxesDatabaseHandler.user_login_failed does not function without a request.axes)rA   r   r    Z0x00z.AXES: Login failed from whitelisted client %s.z^AXES: Username is None and AXES_ONLY_USER_FAILURES is enabled, new record will NOT be created.r7   )get_data	post_datahttp_accept	path_infor<   attempt_time)r   r   
user_agentdefaultszBAXES: New login failure by %s. Created new record in the database.z
---------
rE   rF   r<   zLAXES: Repeated login failure by %s. Updated existing record in the database.z3AXES: Locking out %s after repeated login failures.T)r   r   rJ   rG   rH   rI   
locked_outr   )0r$   r%   errorr   axes_attempt_timer   r   axes_ip_addressaxes_user_agentaxes_path_infor   -AXES_RESET_COOL_OFF_ON_FAILURE_DURING_LOCKOUTaxes_locked_outaxes_credentialsr   sendr   GETreplacePOSTis_whitelistedAXES_ONLY_USER_FAILURESwarningr   atomicr   r    select_for_updateget_or_createaxes_http_acceptr	   r   rE   rF   rG   rH   r   r<   rI   saverB   axes_failures_since_startAXES_LOCK_OUT_AT_FAILUREr   AXES_ENABLE_ACCESS_FAILURE_LOGr   creater:   )r&   senderr;   rA   kwargsr   
client_strrE   rF   attemptcreated	separatorr<   r*   r*   r+   user_login_failedu   s    






$
	z%AxesDatabaseHandler.user_login_failedc           	      K   s   t |j | }t|}t||j|j|j|}t	d| t
jsdtjj||j|j|j|j|jd t
jrt||}t	d|| dS )zN
        When user logs in, update the AccessLog related to the user.
        zAXES: Successful login by %s.)r   r   rJ   rG   rH   rI   z;AXES: Deleted %d failed login attempts by %s from database.N)r   rN   get_usernamer   r   rO   rP   rQ   r$   r%   r   AXES_DISABLE_ACCESS_LOGr   r    rd   r_   AXES_RESET_ON_SUCCESSr   )	r&   re   rA   userrf   r   r;   rg   r(   r*   r*   r+   user_logged_in   s6    
	
z"AxesDatabaseHandler.user_logged_inc                 K   sd   t |j |r| nd}t||j|j|j|}td| |r`t	j
s`tjj|ddj|jd dS )zO
        When user logs out, update the AccessLog related to the user.
        NzAXES: Successful logout by %s.T)r   Zlogout_time__isnull)logout_time)r   rN   rl   r   rO   rP   rQ   r$   r%   r   rm   r   r    r"   update)r&   re   rA   ro   rf   r   rg   r*   r*   r+   user_logged_out(  s     

z#AxesDatabaseHandler.user_logged_outc                 K   s   dS )z
        Handles the ``axes.models.AccessAttempt`` object post save signal.

        When needed, all post_save actions for this backend should be located
        here.
        Nr*   r&   instancerf   r*   r*   r+   post_save_access_attemptA  s    z,AxesDatabaseHandler.post_save_access_attemptc                 K   s   dS )z
        Handles the ``axes.models.AccessAttempt`` object post delete signal.

        When needed, all post_delete actions for this backend should be located
        here.
        Nr*   rt   r*   r*   r+   post_delete_access_attemptI  s    z.AxesDatabaseHandler.post_delete_access_attempt)N)N)__name__
__module____qualname____doc__r   strboolintr,   r5   r6   r   &AXES_ACCESS_FAILURE_LOG_PER_USER_LIMITr:   dictrB   rk   rp   rs   rv   rw   r*   r*   r*   r+   r      s2   
 (r   N)'loggingr   typingr   	django.dbr   django.db.modelsr   r   r   r   django.db.models.functionsr	   django.utilsr
   Zaxes.attemptsr   r   r   	axes.confr   axes.handlers.baser   r   axes.helpersr   r   r   r   r   Zaxes.modelsr   r   r   Zaxes.signalsr   rx   r$   r   r*   r*   r*   r+   <module>   s   