
    sgh%                     J   d dl Z d dlZd dlZd dl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mZ d dlmZmZ d dlmZ d d	lmZ d d
lmZ e j2                  d        Zd ZddZddZddZddZ eee       Z! G d d      Z"d Z# G d d      Z$ G d d      Z% G d d      Z&y)    N)SequenceMatcher)Path)settings)FieldDoesNotExistImproperlyConfiguredValidationError)cached_propertylazy)format_htmlformat_html_join)import_string)gettext)ngettextc                  4    t        t        j                        S N)get_password_validatorsr   AUTH_PASSWORD_VALIDATORS     k/var/www/enzed_healthcare/enzed_env/lib/python3.12/site-packages/django/contrib/auth/password_validation.pyget_default_password_validatorsr      s    "8#D#DEEr   c                     g }| D ]8  }	 t        |d         }|j                   |di |j	                  di              : |S # t        $ r d}t        ||d   z        w xY w)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% 	A		@!)F"34E 	%?)--	2">?@	A   	@4  'sYv->'>??	@s   AAc                     g }|
t               }|D ]  }	 |j                  | |        |rt        |      y# t        $ r}|j                  |       Y d}~Ed}~ww xY w)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*   )   sr     F"=?( !		!x.!
 f%%   	!MM%  	!s   7	A AAc                 X    |
t               }|D ]  }t        |dd       } || |        y)zy
    Inform all validators that have implemented a password_changed() method
    that the password has been changed.
    Npassword_changedc                       y r   r   )as    r   <lambda>z"password_changed.<locals>.<lambda>D   s    r   )r   getattr)r%   r&   r'   r    r,   s        r   r,   r,   <   s<    
 "=?( )	"9.@/R4()r   c                 n    g }| 
t               } | D ]!  }|j                  |j                                # |S )zG
    Return a list of all help texts of all configured validators.
    )r   r   get_help_text)r'   
help_textsr    s      r   password_validators_help_textsr4   H   sD     J"=?( 5	)11345r   c                 `    t        |       }t        ddd |D              }|rt        d|      S dS )z`
    Return an HTML string with all help texts of all configured validators
    in an <ul>.
     z<li>{}</li>c              3   "   K   | ]  }|f 	 y wr   r   ).0	help_texts     r   	<genexpr>z6_password_validators_help_text_html.<locals>.<genexpr>[   s     EYYLEs   z<ul>{}</ul>)r4   r   r   )r'   r3   
help_itemss      r   #_password_validators_help_text_htmlr<   T   s=    
 00CDJ!
ME*EJ 6@;}j1GRGr   c                   ,    e Zd ZdZddZddZd Zd Zy)	MinimumLengthValidatorz<
    Validate that the password is of a minimum length.
    c                     || _         y r   )
min_length)selfr@   s     r   __init__zMinimumLengthValidator.__init__h   s	    $r   Nc                     t        |      | j                  k  r(t        | j                         dd| j                  i      y )Npassword_too_shortr@   codeparams)lenr@   r   get_error_messagerA   r%   r&   s      r   r$   zMinimumLengthValidator.validatek   s?    x=4??*!&&()$doo6  +r   c                 J    t        dd| j                        | j                  z  S )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   r@   rA   s    r   rI   z(MinimumLengthValidator.get_error_messages   s*    TU
 oo	
r   c                 N    t        dd| j                        d| j                  iz  S )Nz=Your password must contain at least %(min_length)d character.z>Your password must contain at least %(min_length)d characters.r@   rL   rM   s    r   r2   z$MinimumLengthValidator.get_help_text}   s/    KLOO
 4??+	, 	,r   )   r   )__name__
__module____qualname____doc__rB   r$   rI   r2   r   r   r   r>   r>   c   s    %
,r   r>   c                 \    t        |       }|dz  |z  }t        |      }|d|z  k\  xr ||k  S )a  
    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.
       
   )rH   )r%   max_similarityvaluepwd_lenlength_bound_similarity	value_lens         r   exceeds_maximum_length_ratior\      s@    0 (mG,q07:E
Ib9n$L5L)LLr   c                   4    e Zd ZdZdZedfdZd	dZd Zd Zy)
 UserAttributeSimilarityValidatora  
    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                 @    || _         |dk  rt        d      || _        y )Ng?z#max_similarity must be at least 0.1)user_attributes
ValueErrorrW   )rA   rd   rW   s      r   rB   z)UserAttributeSimilarityValidator.__init__   s&    .CBCC,r   Nc                 *   |sy |j                         }| j                  D ]  }t        ||d       }|rt        |t              s#|j                         }t        j                  d|      |gz   }|D ]  }t        || j                  |      rt        ||      j                         | j                  k\  sD	 t	        |j                  j                  |      j                        }t        | j!                         dd|i        y # t        $ r |}Y /w xY w)Nz\W+)r.   bpassword_too_similarverbose_namerE   )lowerrd   r0   
isinstancestrresplitr\   rW   r   quick_ratio_meta	get_fieldri   r   r   rI   )	rA   r%   r&   attribute_namerX   value_lowervalue_parts
value_partri   s	            r   r$   z)UserAttributeSimilarityValidator.validate   s   >>#"22 	ND.$7E
5# 6++-K((6;7;-GK) 
/d11: #h*=IIK**+6'* JJ00@MM(
 *..03 .= 	& - 6'56s   4.DDDc                     t        d      S )Nz4The password is too similar to the %(verbose_name)s._rM   s    r   rI   z2UserAttributeSimilarityValidator.get_error_message   s    GHHr   c                     t        d      S )NuH   Your password can’t be too similar to your other personal information.rw   rM   s    r   r2   z.UserAttributeSimilarityValidator.get_help_text   s    V
 	
r   r   )	rP   rQ   rR   rS   DEFAULT_USER_ATTRIBUTESrB   r$   rI   r2   r   r   r   r^   r^      s+    	 O'>s -@I
r   r^   c                   >    e Zd ZdZed        ZefdZddZd Zd Z	y)	CommonPasswordValidatora  
    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    t        t              j                         j                  dz  S )Nzcommon-passwords.txt.gz)r   __file__resolveparentrM   s    r   DEFAULT_PASSWORD_LIST_PATHz2CommonPasswordValidator.DEFAULT_PASSWORD_LIST_PATH   s!    H~%%'..1JJJr   c                    |t         j                  u r| j                  }	 t        j                  |dd      5 }|D ch c]  }|j	                          c}| _        d d d        y c c}w # 1 sw Y   y xY w# t        $ rM t        |      5 }|D ch c]  }|j	                          nc c}w c}| _        d d d        Y y # 1 sw Y   Y y xY ww xY w)Nrtzutf-8)encoding)r|   r   gzipopenstrip	passwordsOSError)rA   password_list_pathfxs       r   rB   z CommonPasswordValidator.__init__   s    !8!S!SS!%!@!@	8-tgF 8!56!7!'')!78 8!78 8 	8() 8Q56!7!'')!7!78 8 8	8sc   A6 A*A%A*A6 %A**A3/A6 3A6 6C
B>B'&B>4C>C	CCNc                     |j                         j                         | j                  v rt        | j	                         d      y )Npassword_too_commonrF   )rj   r   r   r   rI   rJ   s      r   r$   z CommonPasswordValidator.validate   s?    >>!!#t~~5!&&(*  6r   c                     t        d      S )NzThis password is too common.rw   rM   s    r   rI   z)CommonPasswordValidator.get_error_message   s    /00r   c                     t        d      S )Nu2   Your password can’t be a commonly used password.rw   rM   s    r   r2   z%CommonPasswordValidator.get_help_text  s    EFFr   r   )
rP   rQ   rR   rS   r	   r   rB   r$   rI   r2   r   r   r   r|   r|      s8     K K +E 81Gr   r|   c                   $    e Zd ZdZddZd Zd Zy)NumericPasswordValidatorz=
    Validate that the password is not entirely numeric.
    Nc                 Z    |j                         rt        | j                         d      y )Npassword_entirely_numericr   )isdigitr   rI   rJ   s      r   r$   z!NumericPasswordValidator.validate  s/    !&&(0  r   c                     t        d      S )Nz"This password is entirely numeric.rw   rM   s    r   rI   z*NumericPasswordValidator.get_error_message  s    566r   c                     t        d      S )Nu*   Your password can’t be entirely numeric.rw   rM   s    r   r2   z&NumericPasswordValidator.get_help_text  s    =>>r   r   )rP   rQ   rR   rS   r$   rI   r2   r   r   r   r   r     s    7?r   r   )NNr   )'	functoolsr   rm   difflibr   pathlibr   django.confr   django.core.exceptionsr   r   r   django.utils.functionalr	   r
   django.utils.htmlr   r   django.utils.module_loadingr   django.utils.translationr   rx   r   cacher   r   r*   r,   r4   r<   rl   "password_validators_help_text_htmlr>   r\   r^   r|   r   r   r   r   <module>r      s      	 #    
 : ; 5 1 - F F &&	)		H &**Ms%S ", ,DM<:
 :
z$G $GN? ?r   