o
    ÒŸŽi $  ã                   @   s&  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 jdd�dd„ ƒZdd„ Zd"dd„Zd"dd„Zd#dd„Zd#dd„Zeee ƒZ!G dd„ dƒZ"dd„ Z#G dd„ dƒZ$G dd„ dƒZ%G d d!„ d!ƒZ&dS )$é    N)ÚSequenceMatcher)ÚPath)Úsettings)ÚFieldDoesNotExistÚImproperlyConfiguredÚValidationError)Úcached_propertyÚlazy)Úformat_htmlÚformat_html_join)Úimport_string)Úgettext)Úngettext)Úmaxsizec                   C   s
   t tjƒS ©N)Úget_password_validatorsr   ZAUTH_PASSWORD_VALIDATORS© r   r   úqC:\Users\psant\Downloads\Anu Raj Backend\school\venv\Lib\site-packages\django/contrib/auth/password_validation.pyÚget_default_password_validators   s   
r   c              
   C   sb   g }| D ]*}zt |d ƒ}W n ty   d}t||d  ƒ‚w | |di | di ¡¤Ž¡ q|S )NÚNAMEzZThe module in NAME could not be imported: %s. Check your AUTH_PASSWORD_VALIDATORS setting.ÚOPTIONSr   )r   ÚImportErrorr   ÚappendÚget)Zvalidator_configZ
validatorsÚ	validatorÚklassÚmsgr   r   r   r      s   ÿûr   c                 C   sj   g }|du r	t ƒ }|D ]!}z| | |¡ W q ty, } z| |¡ W Y d}~qd}~ww |r3t|ƒ‚dS )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   Úerrorr   r   r   Úvalidate_password)   s   €ÿÿr#   c                 C   s6   |du rt ƒ }|D ]}t|ddd„ ƒ}|| |ƒ q	dS )zy
    Inform all validators that have implemented a password_changed() method
    that the password has been changed.
    NÚpassword_changedc                  W   s   d S r   r   )Úar   r   r   Ú<lambda>D   s    z"password_changed.<locals>.<lambda>)r   Úgetattr)r   r   r    r   r$   r   r   r   r$   <   s   þr$   c                 C   s.   g }| du r	t ƒ } | D ]	}| | ¡ ¡ q|S )zG
    Return a list of all help texts of all configured validators.
    N)r   r   Úget_help_text)r    Ú
help_textsr   r   r   r   Úpassword_validators_help_textsH   s   r*   c                 C   s0   t | ƒ}td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                 s   s   � | ]}|fV  qd S r   r   )Ú.0Ú	help_textr   r   r   Ú	<genexpr>[   s   € z6_password_validators_help_text_html.<locals>.<genexpr>z<ul>{}</ul>N)r*   r   r
   )r    r)   Z
help_itemsr   r   r   Ú#_password_validators_help_text_htmlT   s
   ÿr/   c                   @   s,   e Zd ZdZd
dd„Zddd„Zdd	„ ZdS )ÚMinimumLengthValidatorz<
    Validate that the password is of a minimum length.
    é   c                 C   s
   || _ d S r   )Ú
min_length)Úselfr2   r   r   r   Ú__init__h   s   
zMinimumLengthValidator.__init__Nc                 C   s0   t |ƒ| jk rttdd| jƒdd| jid�‚d S )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.Zpassword_too_shortr2   ©ÚcodeÚparams)Úlenr2   r   r   ©r3   r   r   r   r   r   r   k   s   û÷ÿzMinimumLengthValidator.validatec                 C   s   t dd| jƒd| ji S )Nz=Your password must contain at least %(min_length)d character.z>Your password must contain at least %(min_length)d characters.r2   )r   r2   ©r3   r   r   r   r(   y   s   ýüz$MinimumLengthValidator.get_help_text)r1   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r4   r   r(   r   r   r   r   r0   c   s
    

r0   c                 C   s0   t | ƒ}|d | }t |ƒ}|d| ko||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.
    é   é
   N)r8   )r   Úmax_similarityÚvalueZpwd_lenZlength_bound_similarityZ	value_lenr   r   r   Úexceeds_maximum_length_ratio�   s   rC   c                   @   s4   e Zd ZdZdZedfdd„Zddd„Zd	d
„ ZdS )Ú 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.
    )ÚusernameZ
first_nameÚ	last_nameÚemailgffffffæ?c                 C   s    || _ |dk rtdƒ‚|| _d S )Ngš™™™™™¹?z#max_similarity must be at least 0.1)Úuser_attributesÚ
ValueErrorrA   )r3   rH   rA   r   r   r   r4   ­   s   
z)UserAttributeSimilarityValidator.__init__Nc           	   
   C   sÊ   |sd S |  ¡ }| jD ]W}t||d ƒ}|rt|tƒsq|  ¡ }t d|¡|g }|D ]7}t|| j|ƒr4q*t	||d� 
¡ | jkrazt|j |¡jƒ}W n tyU   |}Y nw ttdƒdd|id�‚q*qd S )Nz\W+)r%   Úbz4The password is too similar to the %(verbose_name)s.Zpassword_too_similarÚverbose_namer5   )ÚlowerrH   r'   Ú
isinstanceÚstrÚreÚsplitrC   rA   r   Zquick_ratioZ_metaÚ	get_fieldrK   r   r   Ú_)	r3   r   r   Zattribute_namerB   Zvalue_lowerZvalue_partsZ
value_partrK   r   r   r   r   ³   sB   
ÿÿÿÿÿýöûúz)UserAttributeSimilarityValidator.validatec                 C   ó   t dƒS )NuH   Your password canâ€™t be too similar to your other personal information.©rR   r:   r   r   r   r(   Ó   s   ÿz.UserAttributeSimilarityValidator.get_help_textr   )r;   r<   r=   r>   ZDEFAULT_USER_ATTRIBUTESr4   r   r(   r   r   r   r   rD   Ÿ   s    
 rD   c                   @   s:   e Zd ZdZedd„ ƒZefdd„Zddd„Zd	d
„ ZdS )Ú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 (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                 C   s   t tƒ ¡ jd S )Nzcommon-passwords.txt.gz)r   Ú__file__ÚresolveÚparentr:   r   r   r   ÚDEFAULT_PASSWORD_LIST_PATHä   s   z2CommonPasswordValidator.DEFAULT_PASSWORD_LIST_PATHc                 C   s¬   |t ju r| j}z%tj|ddd��}dd„ |D ƒ| _W d   ƒ W d S 1 s&w   Y  W d S  tyU   t|ƒ�}dd„ |D ƒ| _W d   ƒ Y d S 1 sMw   Y  Y d S w )NÚrtzutf-8)Úencodingc                 S   ó   h | ]}|  ¡ ’qS r   ©Ústrip©r,   Úxr   r   r   Ú	<setcomp>í   ó    z3CommonPasswordValidator.__init__.<locals>.<setcomp>c                 S   r\   r   r]   r_   r   r   r   ra   ð   rb   )rU   rY   ÚgzipÚopenÚ	passwordsÚOSError)r3   Zpassword_list_pathÚfr   r   r   r4   è   s   
&ÿ
&ÿÿz CommonPasswordValidator.__init__Nc                 C   s&   |  ¡  ¡ | jv rttdƒdd�‚d S )NzThis password is too common.Zpassword_too_common©r6   )rL   r^   re   r   rR   r9   r   r   r   r   ò   s   þÿz CommonPasswordValidator.validatec                 C   rS   )Nu2   Your password canâ€™t be a commonly used password.rT   r:   r   r   r   r(   ù   ó   z%CommonPasswordValidator.get_help_textr   )	r;   r<   r=   r>   r   rY   r4   r   r(   r   r   r   r   rU   Ù   s    



rU   c                   @   s"   e Zd ZdZddd„Zdd„ ZdS )ÚNumericPasswordValidatorz=
    Validate that the password is not entirely numeric.
    Nc                 C   s   |  ¡ rttdƒdd�‚d S )Nz"This password is entirely numeric.Zpassword_entirely_numericrh   )Úisdigitr   rR   r9   r   r   r   r     s   þÿz!NumericPasswordValidator.validatec                 C   rS   )Nu*   Your password canâ€™t be entirely numeric.rT   r:   r   r   r   r(   	  ri   z&NumericPasswordValidator.get_help_textr   )r;   r<   r=   r>   r   r(   r   r   r   r   rj   ý   s    
rj   )NNr   )'Ú	functoolsrc   rO   Údifflibr   Úpathlibr   Zdjango.confr   Zdjango.core.exceptionsr   r   r   Zdjango.utils.functionalr   r	   Zdjango.utils.htmlr
   r   Zdjango.utils.module_loadingr   Zdjango.utils.translationr   rR   r   Ú	lru_cacher   r   r#   r$   r*   r/   rN   Z"password_validators_help_text_htmlr0   rC   rD   rU   rj   r   r   r   r   Ú<module>   s2    






:$