
    h%                     R   S SK r S SKrS SKrS SKJr  S SKJr  S SKJr  S SK	J
r
JrJr  S SKJrJr  S SKJrJr  S SKJr  S S	KJr  S S
KJr  \ R2                  S 5       rS rSS jrSS jrSS jrSS jr\" \\ 5      r! " S S5      r"S r# " S S5      r$ " S S5      r% " S S5      r&g)    N)SequenceMatcher)Path)settings)FieldDoesNotExistImproperlyConfiguredValidationError)cached_propertylazy)format_htmlformat_html_join)import_string)gettext)ngettextc                  4    [        [        R                  5      $ N)get_password_validatorsr   AUTH_PASSWORD_VALIDATORS     f/var/www/html/tms-backend/venv/lib/python3.13/site-packages/django/contrib/auth/password_validation.pyget_default_password_validatorsr      s    "8#D#DEEr   c                     / nU  H9  n [        US   5      nUR                  U" S0 UR	                  S0 5      D65        M;     U$ ! [         a    Sn[        XBS   -  5      ef = f)NNAMEzZThe module in NAME could not be imported: %s. Check your AUTH_PASSWORD_VALIDATORS setting.OPTIONSr   )r   ImportErrorr   appendget)validator_config
validators	validatorklassmsgs        r   r   r      s    J%		@!)F"34E 	%?)--	2">?@ &   	@4  'sv->'>??	@s   AA!c                     / nUc
  [        5       nU H  n UR                  X5        M     U(       a  [        U5      eg! [         a  nUR                  U5         SnAMM  SnAff = f)z
Validate that the password meets all validator requirements.

If the password is valid, return ``None``.
If the password is invalid, raise ValidationError with all error messages.
N)r   validater   r   )passworduserpassword_validatorserrorsr    errors         r   validate_passwordr*   )   sk     F"=?(		!x. )
 f%%   	!MM%  	!s   >
A$AA$c                 \    Uc
  [        5       nU H  n[        USS 5      nU" X5        M     g)zm
Inform all validators that have implemented a password_changed() method
that the password has been changed.
Npassword_changedc                      g r   r   )as    r   <lambda>"password_changed.<locals>.<lambda>D   s    Tr   )r   getattr)r%   r&   r'   r    r,   s        r   r,   r,   <   s5    
 "=?(	"9.@/R( )r   c                 t    / nU c
  [        5       n U  H"  nUR                  UR                  5       5        M$     U$ )z?
Return a list of all help texts of all configured validators.
)r   r   get_help_text)r'   
help_textsr    s      r   password_validators_help_textsr5   H   s?     J"=?(	)1134 )r   c                 j    [        U 5      n[        SSS U 5       5      nU(       a  [        SU5      $ S$ )zT
Return an HTML string with all help texts of all configured validators
in an <ul>.
 z<li>{}</li>c              3   $   #    U H  o4v   M	     g 7fr   r   ).0	help_texts     r   	<genexpr>6_password_validators_help_text_html.<locals>.<genexpr>[   s     E*YL*s   z<ul>{}</ul>)r5   r   r   )r'   r4   
help_itemss      r   #_password_validators_help_text_htmlr>   T   s=    
 00CDJ!
ME*EJ 6@;}j1GRGr   c                   8    \ rS rSrSrS	S jrS
S jrS rS rSr	g)MinimumLengthValidatorc   z4
Validate that the password is of a minimum length.
c                     Xl         g r   
min_length)selfrD   s     r   __init__MinimumLengthValidator.__init__h   s    $r   Nc                     [        U5      U R                  :  a%  [        U R                  5       SSU R                  0S9eg )Npassword_too_shortrD   codeparams)lenrD   r   get_error_messagerE   r%   r&   s      r   r$   MinimumLengthValidator.validatek   s?    x=4??*!&&()$doo6  +r   c                 J    [        SSU R                  5      U R                  -  $ )NzBThis password is too short. It must contain at least %d character.zCThis password is too short. It must contain at least %d characters.r   rD   rE   s    r   rN   (MinimumLengthValidator.get_error_messages   s*    TU
 oo	
r   c                 N    [        SSU R                  5      SU R                  0-  $ )Nz=Your password must contain at least %(min_length)d character.z>Your password must contain at least %(min_length)d characters.rD   rR   rS   s    r   r3   $MinimumLengthValidator.get_help_text}   s/    KLOO
 4??+	, 	,r   rC   )   r   )
__name__
__module____qualname____firstlineno____doc__rF   r$   rN   r3   __static_attributes__r   r   r   r@   r@   c   s    %
,r   r@   c                 d    [        U 5      nUS-  U-  n[        U5      nUSU-  :  =(       a    XT:  $ )ay  
Test that value is within a reasonable range of password.

The following ratio calculations are based on testing SequenceMatcher like
this:

for i in range(0,6):
  print(10**i, SequenceMatcher(a='A', b='A'*(10**i)).quick_ratio())

which yields:

1 1.0
10 0.18181818181818182
100 0.019801980198019802
1000 0.001998001998001998
10000 0.00019998000199980003
100000 1.999980000199998e-05

This means a length_ratio of 10 should never yield a similarity higher than
0.2, for 100 this is down to 0.02 and for 1000 it is 0.002. This can be
calculated via 2 / length_ratio. As a result we avoid the potentially
expensive sequence matching.
   
   )rM   )r%   max_similarityvaluepwd_lenlength_bound_similarity	value_lens         r   exceeds_maximum_length_ratiorf      s=    0 (mG,q07:E
Ib9n$L)LLr   c                   @    \ rS rSrSrSr\S4S jrSS jrS rS	 r	S
r
g) UserAttributeSimilarityValidator   a  
Validate that the password is sufficiently different from the user's
attributes.

If no specific attributes are provided, look at a sensible list of
defaults. Attributes that don't exist are ignored. Comparison is made to
not only the full attribute value, but also its components, so that, for
example, a password is validated against either part of an email address,
as well as the full address.
)username
first_name	last_nameemailgffffff?c                 >    Xl         US:  a  [        S5      eX l        g )Ng?z#max_similarity must be at least 0.1)user_attributes
ValueErrorra   )rE   ro   ra   s      r   rF   )UserAttributeSimilarityValidator.__init__   s"    .CBCC,r   Nc                 R   U(       d  g UR                  5       nU R                   H  n[        X#S 5      nU(       a  [        U[        5      (       d  M-  UR                  5       n[
        R                  " SU5      U/-   nU H  n[        XR                  U5      (       a  M   [        XS9R                  5       U R                  :  d  MG   [	        UR                  R                  U5      R                  5      n[        U R!                  5       SSU0S9e   M     g ! [         a    Un N0f = f)Nz\W+)r.   bpassword_too_similarverbose_namerJ   )lowerro   r1   
isinstancestrresplitrf   ra   r   quick_ratio_meta	get_fieldru   r   r   rN   )	rE   r%   r&   attribute_namerb   value_lowervalue_parts
value_partru   s	            r   r$   )UserAttributeSimilarityValidator.validate   s   >>#"22ND$7E
5# 6 6++-K((6;7;-GK)
/11:  #h=IIK**+6'* JJ00@MM(
 *..03 .=  * 3& - 6'56s   .DD&%D&c                     [        S5      $ )Nz4The password is too similar to the %(verbose_name)s._rS   s    r   rN   2UserAttributeSimilarityValidator.get_error_message   s    GHHr   c                     [        S5      $ )NuH   Your password can’t be too similar to your other personal information.r   rS   s    r   r3   .UserAttributeSimilarityValidator.get_help_text   s    V
 	
r   )ra   ro   r   )rX   rY   rZ   r[   r\   DEFAULT_USER_ATTRIBUTESrF   r$   rN   r3   r]   r   r   r   rh   rh      s+    	 O'>s -@I
r   rh   c                   J    \ rS rSrSr\S 5       r\4S jrS
S jrS r	S r
S	rg)CommonPasswordValidator   a  
Validate that the password is not a common password.

The password is rejected if it occurs in a provided list of passwords,
which may be gzipped. The list Django ships with contains 20000 common
passwords (unhexed, lowercased and deduplicated), created by Royce Williams:
https://gist.github.com/roycewilliams/226886fd01572964e1431ac8afc999ce
The password list must be lowercased to match the comparison in validate().
c                 V    [        [        5      R                  5       R                  S-  $ )Nzcommon-passwords.txt.gz)r   __file__resolveparentrS   s    r   DEFAULT_PASSWORD_LIST_PATH2CommonPasswordValidator.DEFAULT_PASSWORD_LIST_PATH   s!    H~%%'..1JJJr   c                    U[         R                  L a  U R                  n [        R                  " USSS9 nU Vs1 sH  o3R	                  5       iM     snU l        S S S 5        g s  snf ! , (       d  f       g = f! [         aS    [        U5       nU Vs1 sH  o3R	                  5       iM     Os  snf snU l        S S S 5         g ! , (       d  f        g = ff = f)Nrtzutf-8)encoding)r   r   gzipopenstrip	passwordsOSError)rE   password_list_pathfxs       r   rF    CommonPasswordValidator.__init__   s    !8!S!SS!%!@!@	8-tgF!56!7Q'')Q!7 GF!7 GF 	8()Q56!7Q'')Q!7 *)))	8sc   A; A*A%A*A; %A**
A84A; 8A; ;CCB.-C;C
C	CCNc                     UR                  5       R                  5       U R                  ;   a  [        U R	                  5       SS9eg )Npassword_too_commonrK   )rv   r   r   r   rN   rO   s      r   r$    CommonPasswordValidator.validate   s?    >>!!#t~~5!&&(*  6r   c                     [        S5      $ )NzThis password is too common.r   rS   s    r   rN   )CommonPasswordValidator.get_error_message   s    /00r   c                     [        S5      $ )Nu2   Your password can’t be a commonly used password.r   rS   s    r   r3   %CommonPasswordValidator.get_help_text  s    EFFr   )r   r   )rX   rY   rZ   r[   r\   r	   r   rF   r$   rN   r3   r]   r   r   r   r   r      s8     K K +E 81Gr   r   c                   .    \ rS rSrSrSS jrS rS rSrg)	NumericPasswordValidatori  z5
Validate that the password is not entirely numeric.
Nc                 ^    UR                  5       (       a  [        U R                  5       SS9eg )Npassword_entirely_numericr   )isdigitr   rN   rO   s      r   r$   !NumericPasswordValidator.validate  s2    !&&(0  r   c                     [        S5      $ )Nz"This password is entirely numeric.r   rS   s    r   rN   *NumericPasswordValidator.get_error_message  s    566r   c                     [        S5      $ )Nu*   Your password can’t be entirely numeric.r   rS   s    r   r3   &NumericPasswordValidator.get_help_text  s    =>>r   r   r   )	rX   rY   rZ   r[   r\   r$   rN   r3   r]   r   r   r   r   r     s    7?r   r   )NNr   )'	functoolsr   ry   difflibr   pathlibr   django.confr   django.core.exceptionsr   r   r   django.utils.functionalr	   r
   django.utils.htmlr   r   django.utils.module_loadingr   django.utils.translationr   r   r   cacher   r   r*   r,   r5   r>   rx   "password_validators_help_text_htmlr@   rf   rh   r   r   r   r   r   <module>r      s      	 #    
 : ; 5 1 - F F &&	)		H &**Ms%S ", ,DM<:
 :
z$G $GN? ?r   