
    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     Y/var/www/html/env/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                   2    \ rS rSrSrSS jrS	S j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,  [        [        SSU R                  5      SSU R                  0S9eg )NzNThis password is too short. It must contain at least %(min_length)d character.zOThis password is too short. It must contain at least %(min_length)d characters.password_too_shortrD   codeparams)lenrD   r   r   rE   r%   r&   s      r   r$   MinimumLengthValidator.validatek   sN    x=4??*!01OO *$doo6
 
 +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   )r   rD   rE   s    r   r3   $MinimumLengthValidator.get_help_texty   s/    KLOO
 4??+	, 	,r   rC   )   r   )	__name__
__module____qualname____firstlineno____doc__rF   r$   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_ratiorb      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	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
ValueErrorr]   )rE   rk   r]   s      r   rF   )UserAttributeSimilarityValidator.__init__   s"    .CBCC,r   Nc                 H   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[        [!        S5      SSU0S9e   M     g ! [         a    Un N+f = f)Nz\W+)r.   bz4The password is too similar to the %(verbose_name)s.password_too_similarverbose_namerJ   )lowerrk   r1   
isinstancestrresplitrb   r]   r   quick_ratio_meta	get_fieldrq   r   r   _)	rE   r%   r&   attribute_namer^   value_lowervalue_parts
value_partrq   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(
 *PQ3 .=  * 3& - 6'56s   .DD! D!c                     [        S5      $ )NuH   Your password can’t be too similar to your other personal information.rz   rQ   s    r   r3   .UserAttributeSimilarityValidator.get_help_text   s    V
 	
r   )r]   rk   r   )
rT   rU   rV   rW   rX   DEFAULT_USER_ATTRIBUTESrF   r$   r3   rY   r   r   r   rd   rd      s%    	 O'>s -@
r   rd   c                   D    \ rS rSrSr\S 5       r\4S jrS	S j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 (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parentrQ   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! [         aT    [        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++
A95A< 9A< <CCB0/C=C
C	CCNc                     UR                  5       R                  5       U R                  ;   a  [        [	        S5      SS9eg )NzThis password is too common.password_too_commonrK   )rr   r   r   r   rz   rN   s      r   r$    CommonPasswordValidator.validate   s<    >>!!#t~~5!01*  6r   c                     [        S5      $ )Nu2   Your password can’t be a commonly used password.r   rQ   s    r   r3   %CommonPasswordValidator.get_help_text   s    EFFr   )r   r   )rT   rU   rV   rW   rX   r	   r   rF   r$   r3   rY   r   r   r   r   r      s3     K K +E 8Gr   r   c                   (    \ rS rSrSrSS jrS rSrg)NumericPasswordValidator   z5
Validate that the password is not entirely numeric.
Nc                 T    UR                  5       (       a  [        [        S5      SS9eg )Nz"This password is entirely numeric.password_entirely_numericr   )isdigitr   rz   rN   s      r   r$   !NumericPasswordValidator.validate  s/    !670  r   c                     [        S5      $ )Nu*   Your password can’t be entirely numeric.r   rQ   s    r   r3   &NumericPasswordValidator.get_help_text	  s    =>>r   r   r   )rT   rU   rV   rW   rX   r$   r3   rY   r   r   r   r   r      s    ?r   r   )NNr   )'	functoolsr   ru   difflibr   pathlibr   django.confr   django.core.exceptionsr   r   r   django.utils.functionalr	   r
   django.utils.htmlr   r   django.utils.module_loadingr   django.utils.translationr   rz   r   cacher   r   r*   r,   r5   r>   rt   "password_validators_help_text_htmlr@   rb   rd   r   r   r   r   r   <module>r      s      	 #    
 : ; 5 1 - F F &&	)		H &**Ms%S ", ,<M<7
 7
t!G !GH? ?r   