Ë
    0]jeE  ã                   ó  — d dl mZ d dlmZ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 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mZ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) d dl*m+Z+  ee,«      Z- G d„ dee«      Z.y)é    )Ú	getLogger)ÚListÚOptional)ÚrouterÚtransaction)ÚFÚQÚQuerySetÚSumÚValue)ÚConcat)ÚHttpRequest)Útimezone)Úget_cool_off_threshold)Úsettings)ÚAbstractAxesHandlerÚAxesBaseHandler)	Úget_client_parametersÚget_client_session_hashÚget_client_strÚget_client_usernameÚget_credentialsÚget_failure_limitÚget_lockout_parametersÚget_query_strÚget_attempt_expiration)ÚAccessAttemptÚAccessAttemptExpirationÚAccessFailureLogÚ	AccessLog)Úuser_locked_outc            	       ót  — e Zd ZdZddddœdee   dee   dedefd	„Zdd
œdee   defd„Z	dd
œdee   defd„Z
ej                  dœdedee   defd„Zddee   defd„Zddefd„Zd„ Zd„ Z	 ddedee   dee   fd„Z	 ddedee   dee   fd„Z	 	 ddee   dee   defd„Z	 ddedee   defd„Zd„ Zd„ Zy)Ú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_usernamer$   r%   r&   Úreturnc                ó:  — t         j                  j                  «       }|r)|j                  t	        |¬«      t	        |¬«      z  «      }n(|r|j                  |¬«      }|r|j                  |¬«      }|j                  «       \  }}t        j                  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Ú_s          úM/var/www/zogu/zoguvenv/lib/python3.12/site-packages/axes/handlers/database.pyÚreset_attemptsz"AxesDatabaseHandler.reset_attempts+   s‚   € ô !×(Ñ(×,Ñ,Ó.ˆáØ—‘¤q°JÔ'?Ä!ÈXÔBVÑ'VÓW‰HáØ#Ÿ?™?°j˜?ÓA�ÙØ#Ÿ?™?°H˜?Ó=�à—?‘?Ó$‰ˆˆqÜ�‰Ð@À%ÔHàˆó    )Úage_daysr7   c                ó~  — |€Gt         j                  j                  «       j                  «       \  }}t        j                  d|«       |S t        j                  «       t        j                  |¬«      z
  }t         j                  j                  |¬«      j                  «       \  }}t        j                  d||«       |S )Nz-AXES: Reset all %d access logs from database.©Údays©Úattempt_time__ltez<AXES: Reset %d access logs older than %d days from database.)
r    r*   r+   r-   r.   r/   r   ÚnowÚ	timedeltar,   ©r0   r7   r2   r3   Úlimits        r4   Ú
reset_logszAxesDatabaseHandler.reset_logsA   sž   € ØÐÜ ×(Ñ(×,Ñ,Ó.×5Ñ5Ó7‰HˆE�1Ü�H‰HÐDÀeÔLð ˆô —L‘L“N¤X×%7Ñ%7¸XÔ%FÑFˆEÜ ×(Ñ(×/Ñ/À%Ð/ÓH×OÑOÓQ‰HˆE�1Ü�H‰HØNØØôð ˆr6   c                ó~  — |€Gt         j                  j                  «       j                  «       \  }}t        j                  d|«       |S t        j                  «       t        j                  |¬«      z
  }t         j                  j                  |¬«      j                  «       \  }}t        j                  d||«       |S )Nz5AXES: Reset all %d access failure logs from database.r9   r;   zDAXES: Reset %d access failure logs older than %d days from database.)
r   r*   r+   r-   r.   r/   r   r=   r>   r,   r?   s        r4   Úreset_failure_logsz&AxesDatabaseHandler.reset_failure_logsP   sž   € ØÐÜ'×/Ñ/×3Ñ3Ó5×<Ñ<Ó>‰HˆE�1Ü�H‰HÐLÈeÔTð ˆô —L‘L“N¤X×%7Ñ%7¸XÔ%FÑFˆEÜ'×/Ñ/×6Ñ6ÈÐ6ÓO×VÑVÓX‰HˆE�1Ü�H‰HØVØØôð ˆr6   )r@   r@   c                ó¸   — d}t         j                  j                  |¬«      }|j                  «       |z
  }|dkD  r|d | D ]  }|j	                  «        |dz  }Œ |S )Nr   r)   é   )r   r*   r,   r2   r-   )r0   r%   r@   r2   ÚfailuresÚout_of_limit_failures_logsÚfailures          r4   Ú remove_out_of_limit_failure_logsz4AxesDatabaseHandler.remove_out_of_limit_failure_logs_   sn   € ð ˆÜ#×+Ñ+×2Ñ2¸HÐ2ÓEˆØ%-§^¡^Ó%5¸Ñ%=Ð"Ø%¨Ò)Ø#Ð$?Ð%?Ð@ò �Ø—‘Ô Ø˜‘
‘ðð ˆr6   Úcredentialsc                 óN   — | j                  ||«      }t        d„ |D «       «      }|S )Nc              3   ó^   K  — | ]%  }|j                  t        d «      «      d   xs d–— Œ' y­w)Úfailures_since_startÚfailures_since_start__sumr   N)Ú	aggregater   )Ú.0r1   s     r4   ú	<genexpr>z3AxesDatabaseHandler.get_failures.<locals>.<genexpr>p   sB   è ø€ ò 
ð ð ×"Ñ"¤3Ð'=Ó#>Ó?Ø/ñò ð óñ
ùs   ‚+-)Úget_user_attemptsÚmax)r0   ÚrequestrJ   Úattempts_listÚattempt_counts        r4   Úget_failuresz AxesDatabaseHandler.get_failuresn   s5   € Ø×.Ñ.¨w¸ÓDˆÜñ 
ð *ô
ó 
ˆð Ðr6   c                 ó¬	  — t         j                  d«       |€t         j                  d«       y| j                  ||«       t	        ||«      }t        ||j                  |j                  |j                  |«      }t        j                  s7|j                  r+||_        t        j                  d|||j                  ¬«       yt        |j                   «      j#                  dd«      }t        |j$                  «      j#                  dd«      }| j'                  ||«      rt         j                  d|«       yt)        ||«      }	|	d	gk(  r|€t         j+                  d
«       �n$t-        j.                  t1        j2                  t4        «      ¬«      5  t4        j6                  j9                  «       j;                  ||j                  |j                  |||j<                  |j                  d|j>                  dœ¬«      \  }
}|rt         j+                  d|«       n¨d}tA        dtC        ||z   «      «      |
_"        tA        dtC        ||z   «      «      |
_#        |j<                  |
_$        |j                  |
_%        tM        d«      dz   |
_'        |j>                  |
_(        |
jS                  «        t         j+                  d|«       t        jT                  r°tW        |
d«      r|
jX                  €Ft         j[                  d|«       t\        j6                  j_                  |
ta        |«      ¬«      |
_,        nRtc        ta        |«      |
jX                  jd                  «      |
jX                  _2        |
jX                  jS                  «        ddd«       | jg                  ||«      }||_4        t        jj                  rV|tm        ||«      k\  rGt         j+                  d|«       d|_        ||_        t        j                  d|||j                  ¬«       t        jn                  r«t-        j.                  t1        j2                  tp        «      ¬«      5  tp        j6                  j_                  ||j                  |j                  |j<                  |j                  |j>                  |j                  ¬«       | js                  |¬«       ddd«       yy# 1 sw Y   �ŒExY w# 1 sw Y   yxY w)zÆ
        When 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)rT   r%   r$   ú Ú0x00z.AXES: Login failed from whitelisted client %s.r%   zfAXES: Username is None and username is the only one lockout parameter, new record will NOT be created.)ÚusingrE   )Úget_dataÚ	post_dataÚhttp_acceptÚ	path_inforM   Úattempt_time)r%   r$   Ú
user_agentÚdefaultszBAXES: New login failure by %s. Created new record in the database.z
---------
r]   r^   rM   zLAXES: Repeated login failure by %s. Updated existing record in the database.Ú
expirationz1AXES: Creating new AccessAttemptExpiration for %s)Úaccess_attemptÚ
expires_atz3AXES: Locking out %s after repeated login failures.T)r%   r$   rb   r_   r`   ra   Ú
locked_outr)   ):r.   r/   ÚerrorÚclean_expired_user_attemptsr   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_whitelistedr   Úwarningr   Úatomicr   Údb_for_writer   r*   Úselect_for_updateÚget_or_createÚaxes_http_acceptÚaxes_attempt_timer   r   r]   r^   r_   r`   r   rM   ra   ÚsaveÚAXES_USE_ATTEMPT_EXPIRATIONÚhasattrrd   Údebugr   Úcreater   rS   rf   rW   Úaxes_failures_since_startÚAXES_LOCK_OUT_AT_FAILUREr   ÚAXES_ENABLE_ACCESS_FAILURE_LOGr   rI   )r0   ÚsenderrJ   rT   Úkwargsr%   Ú
client_strr]   r^   Úlockout_parametersÚattemptÚcreatedÚ	separatorrM   s                 r4   Úuser_login_failedz%AxesDatabaseHandler.user_login_failed{   sV  € ô 	�‰ÐQÔRàˆ?Ü�I‰IØbôð ð 	×(Ñ(¨°+Ô>ä& w°Ó<ˆÜ#ØØ×#Ñ#Ø×#Ñ#Ø×"Ñ"Øó
ˆ
ô ×FÒFØ×'Ò'à'2ˆGÔ$Ü× Ñ ØØØ!Ø"×2Ñ2õ	ð ô ! §¡Ó-×5Ñ5°d¸FÓCˆÜ! '§,¡,Ó/×7Ñ7¸¸fÓEˆ	à×Ñ˜w¨Ô4Ü�H‰HÐEÀzÔRØô 4°G¸[ÓIÐØ * Ò-°(Ð2BÜ�K‰KØxöô ×#Ñ#¬&×*=Ñ*=¼mÓ*LÔMñ @2ô "×)Ñ)×;Ñ;Ó=×KÑKØ%Ø&×6Ñ6Ø&×6Ñ6à$,Ø%.Ø'.×'?Ñ'?Ø%,×%;Ñ%;Ø01Ø(/×(AÑ(Añð	 Ló ñØØñ$ Ü—K‘KØ\Ø"õð !0�Iä'-¨j¼%À	ÈHÑ@TÓ:UÓ'V�GÔ$Ü(.Ø#¤U¨9°yÑ+@Ó%Aó)�GÔ%ð +2×*BÑ*B�GÔ'Ø(/×(>Ñ(>�GÔ%Ü34Ð5KÓ3LÈqÑ3P�GÔ0Ø+2×+DÑ+D�GÔ(Ø—L‘L”Nä—K‘KØfØ"ôô
 ×7Ò7Ü" 7¨LÔ9¸W×=OÑ=OÐ=WÜŸ	™	ØOØ&ôô .E×-LÑ-L×-SÑ-SØ+2Ü'=¸gÓ'Fð .Tó .˜Õ*ô
 9<Ü2°7Ó;Ø#×.Ñ.×9Ñ9ó9˜×*Ñ*Ô5ð  ×*Ñ*×/Ñ/Ô1÷A@2ðF  $×0Ñ0°¸+ÓFÐØ,@ˆÔ)ô ×-Ò-Ø$Ô(9¸'À;Ó(OÒOä�K‰KØEÀzôð '+ˆGÔ#Ø'2ˆGÔ$Ü× Ñ ØØØ!Ø"×2Ñ2õ	ô ×2Ò2Ü×#Ñ#¬&×*=Ñ*=Ô>NÓ*OÔPñ 
IÜ ×(Ñ(×/Ñ/Ø%Ø&×6Ñ6Ø&×6Ñ6Ø '× 8Ñ 8Ø%×4Ñ4Ø!(×!:Ñ!:Ø&×6Ñ6ð 0ô ð ×5Ñ5¸xÐ5ÔH÷
Ið 
Ið 3÷q@2ñ @2ú÷r
Ið 
Iús   ÆG/R=Ð>A5S
Ò=SÓ
Sc                 ó:  — |j                  «       }t        |«      }t        ||j                  |j                  |j
                  |«      }t        j                  d|«       | j                  ||«       t        j                  sat        j                  j                  ||j                  |j                  |j                  |j
                  |j                  t!        |«      ¬«       t        j"                  r*| j%                  ||«      }t        j                  d||«       yy)zN
        When user logs in, update the AccessLog related to the user.
        zAXES: Successful login by %s.)r%   r$   rb   r_   r`   ra   Úsession_hashz;AXES: Deleted %d failed login attempts by %s from database.N)Úget_usernamer   r   rj   rk   rl   r.   r/   ri   r   ÚAXES_DISABLE_ACCESS_LOGr    r*   r€   rz   r{   r   ÚAXES_RESET_ON_SUCCESSÚreset_user_attempts)	r0   r„   rT   Úuserr…   r%   rJ   r†   r2   s	            r4   Úuser_logged_inz"AxesDatabaseHandler.user_logged_in  sý   € ð
 ×$Ñ$Ó&ˆÜ% hÓ/ˆÜ#ØØ×#Ñ#Ø×#Ñ#Ø×"Ñ"Øó
ˆ
ô 	�‰Ð0°*Ô=ð 	×(Ñ(¨°+Ô>ä×/Ò/ä×Ñ×$Ñ$Ø!Ø"×2Ñ2Ø"×2Ñ2Ø#×4Ñ4Ø!×0Ñ0Ø$×6Ñ6ô 5°WÓ=ð %ô 
ô ×)Ò)à×,Ñ,¨W°kÓBˆEÜ�H‰HØMØØõð *r6   c                 ó¦  — |r|j                  «       nd}|rt        |«      nd}t        ||j                  |j                  |j
                  |«      }| j                  ||«       t        j                  d|«       |rWt        j                  sFt        j                  j                  |dt        |«      ¬«      j                  |j                   ¬«       yyy)zO
        When user logs out, update the AccessLog related to the user.
        NzAXES: Successful logout by %s.T)r%   Úlogout_time__isnullr�   )Úlogout_time)rŽ   r   r   rj   rk   rl   ri   r.   r/   r   r�   r    r*   r,   r   Úupdater{   )r0   r„   rT   r’   r…   r%   rJ   r†   s           r4   Úuser_logged_outz#AxesDatabaseHandler.user_logged_outC  s½   € ñ
 +/�4×$Ñ$Ô&°DˆÙ3;”o hÔ/ÀˆÜ#ØØ×#Ñ#Ø×#Ñ#Ø×"Ñ"Øó
ˆ
ð 	×(Ñ(¨°+Ô>ä�‰Ð1°:Ô>áœH×<Ò<ä×Ñ×$Ñ$Ø!Ø$(ä4°WÓ=ð	 %ó ÷
 ‰f ×!:Ñ!:ˆfÕ;ð =ˆ8r6   rT   c                 óÆ   — t        ||«      }t        ||j                  |j                  ||«      }|D �cg c]!  }t	        j
                  j                  di |¤Ž‘Œ# }}|S c c}w )zi
        Return a list querysets of AccessAttempts that match the given request and credentials.
        © )r   r   rj   rk   r   r*   r,   )r0   rT   rJ   r%   Úfilter_kwargs_listÚfilter_kwargsrU   s          r4   Úfilter_user_attemptsz(AxesDatabaseHandler.filter_user_attempts`  sv   € ô ' w°Ó<ˆä2ØØ×#Ñ#Ø×#Ñ#ØØó
Ðð "4ö
àô ×!Ñ!×(Ñ(Ñ9¨=Ó9ð
ˆð 
ð Ðùò	
s   ´&Ac                 ó   — | j                  ||«      }t        j                  €t        j	                  d«       |S t        |«      }t        j	                  d|«       |D �cg c]  }|j                  |¬«      ‘Œ c}S c c}w )zn
        Get list of querysets with valid user attempts that match the given request and credentials.
        zZAXES: Getting all access attempts from database because no AXES_COOLOFF_TIME is configuredz4AXES: Getting access attempts that are newer than %s)Úattempt_time__gte)r�   r   ÚAXES_COOLOFF_TIMEr.   r   r   r,   )r0   rT   rJ   rU   Ú	thresholdr1   s         r4   rR   z%AxesDatabaseHandler.get_user_attemptsv  sz   € ð ×1Ñ1°'¸;ÓGˆä×%Ñ%Ð-Ü�I‰IØlôð !Ð ä*¨7Ó3ˆ	Ü�	‰	ÐHÈ)ÔTàIVö
Ø=EˆH�O‰O¨iˆOÕ8ò
ð 	
ùò 
s   ÁA;c                 óÔ  — t         j                  €t        j                  d«       yt         j                  r^t        j                  «       }t        j                  j                  |¬«      j                  «       \  }}t        j                  d||«       |S t        |«      }t        j                  j                  |¬«      j                  «       \  }}t        j                  d||«       |S )z@
        Clean expired user attempts from the database.
        z[AXES: Skipping clean for expired access attempts because no AXES_COOLOFF_TIME is configuredr   )Úexpiration__expires_at__ltezXAXES: Cleaned up %s expired access attempts from database that expiry were older than %sr;   zQAXES: Cleaned up %s expired access attempts from database that were older than %s)r   r    r.   r   r}   r   r=   r   r*   r,   r-   r/   r   )r0   rT   rJ   r¡   r2   r3   s         r4   ri   z/AxesDatabaseHandler.clean_expired_user_attempts‹  sØ   € ô ×%Ñ%Ð-Ü�I‰IØmôð ä×/Ò/Ü Ÿ™›ˆIÜ$×,Ñ,×3Ñ3Ø,5ð 4ó ç‰f‹hñ ˆE�1ô �H‰HØjØØôð ˆô /¨wÓ7ˆIÜ$×,Ñ,×3Ñ3Ø"+ð 4ó ç‰f‹hñ ˆE�1ô �H‰HØcØØôð
 ˆr6   c                 ó˜   — | j                  ||«      }d}|D ]  }|j                  «       \  }}||z  }Œ t        j                  d|«       |S )zW
        Reset all user attempts that match the given request and credentials.
        r   z-AXES: Reset %s access attempts from database.)r�   r-   r.   r/   )r0   rT   rJ   rU   r2   r1   Ú_countr3   s           r4   r‘   z'AxesDatabaseHandler.reset_user_attempts°  sY   € ð ×1Ñ1°'¸;ÓGˆàˆØ%ò 	ˆHØ Ÿ™Ó)‰IˆF�AØ�V‰O‰Eð	ô 	�‰Ð@À%ÔHàˆr6   c                  ó   — y)z±
        Handles the ``axes.models.AccessAttempt`` object post save signal.

        When needed, all post_save actions for this backend should be located
        here.
        Nrš   ©r0   Úinstancer…   s      r4   Úpost_save_access_attemptz,AxesDatabaseHandler.post_save_access_attemptÁ  ó   � r6   c                  ó   — y)zµ
        Handles the ``axes.models.AccessAttempt`` object post delete signal.

        When needed, all post_delete actions for this backend should be located
        here.
        Nrš   r§   s      r4   Úpost_delete_access_attemptz.AxesDatabaseHandler.post_delete_access_attemptÉ  rª   r6   )N)NN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚstrÚboolÚintr5   rA   rC   r   Ú&AXES_ACCESS_FAILURE_LOG_PER_USER_LIMITrI   ÚdictrW   r‹   r“   r˜   r   r   r
   r�   rR   ri   r‘   r©   r¬   rš   r6   r4   r#   r#   #   s¢  „ ñð %)Ø"&Ø$òð ˜S‘Mðð ˜3‘-ð	ð
 ðð 
óð, 7;ò  h¨s¡mð ¸só ð ?Cò ¨h°s©mð Àsó ð&  (×NÑNò	ð ðð ˜‰}ð	ð
 
óñ°¸$±ð È3ó ñ[I°Tó [Iòz)òV<ð< CGñØ"ðØ19¸$±ðà	ˆh‰óð. CGñ
Ø"ð
Ø19¸$±ð
à	ˆh‰ó
ð. *.Ø&*ñ#à˜+Ñ&ð#ð ˜d‘^ð#ð 
ó	#ðL CGñØ"ðØ19¸$±ðà	óò"ór6   r#   N)/Úloggingr   Útypingr   r   Ú	django.dbr   r   Údjango.db.modelsr   r	   r
   r   r   Údjango.db.models.functionsr   Údjango.httpr   Údjango.utilsr   Úaxes.attemptsr   Ú	axes.confr   Úaxes.handlers.baser   r   Úaxes.helpersr   r   r   r   r   r   r   r   r   Úaxes.modelsr   r   r   r    Úaxes.signalsr!   r­   r.   r#   rš   r6   r4   ú<module>rÃ      s_   ðÝ ß !ç )ß 7Õ 7Ý -Ý #Ý !å 0Ý ß C÷
÷ 
õ 
÷ó õ )á�Ó€ôlÐ-¨õ lr6   