o
    {,h%                     @   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 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)ngettextc                   C   s
   t tjS N)get_password_validatorsr   AUTH_PASSWORD_VALIDATORS r   r   ]/var/www/html/rh/venv/lib/python3.10/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)validator_config
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>)r,   r   r
   )r"   r+   
help_itemsr   r   r   #_password_validators_help_text_htmlT   s
   r2   c                   @   s4   e Zd ZdZdddZdddZ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)selfr5   r   r   r   __init__h   s   
zMinimumLengthValidator.__init__Nc                 C   s*   t || jk rt|  dd| jidd S )Npassword_too_shortr5   codeparams)lenr5   r   get_error_messager6   r    r!   r   r   r   r   k   s   zMinimumLengthValidator.validatec                 C   s   t dd| j| j 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   r5   r6   r   r   r   r=   s   s   z(MinimumLengthValidator.get_error_messagec                 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.r5   r?   r@   r   r   r   r*   }   s   z$MinimumLengthValidator.get_help_text)r4   r   )__name__
__module____qualname____doc__r7   r   r=   r*   r   r   r   r   r3   c   s    


r3   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.
       
   )r<   )r    max_similarityvaluepwd_lenlength_bound_similarity	value_lenr   r   r   exceeds_maximum_length_ratio   s   rL   c                   @   s<   e Zd ZdZdZedfddZdddZ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.
    )username
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
ValueErrorrG   )r6   rR   rG   r   r   r   r7      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|  dd|idq*qd S )Nz\W+)r'   bpassword_too_similarverbose_namer9   )lowerrR   r)   
isinstancestrresplitrL   rG   r   quick_ratio_meta	get_fieldrV   r   r   r=   )	r6   r    r!   attribute_namerH   value_lowervalue_parts
value_partrV   r   r   r   r      s@   
z)UserAttributeSimilarityValidator.validatec                 C      t dS )Nz4The password is too similar to the %(verbose_name)s._r@   r   r   r   r=         z2UserAttributeSimilarityValidator.get_error_messagec                 C   rc   )NuH   Your password can’t be too similar to your other personal information.rd   r@   r   r   r   r*      s   z.UserAttributeSimilarityValidator.get_help_textr   )	rA   rB   rC   rD   DEFAULT_USER_ATTRIBUTESr7   r   r=   r*   r   r   r   r   rM      s    
 rM   c                   @   sB   e Zd ZdZedd ZefddZdddZ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 (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                 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   ro   r   rp   rr   r   r   r   rt      ru   )rh   rl   gzipopen	passwordsOSError)r6   password_list_pathfr   r   r   r7      s   
&
&z CommonPasswordValidator.__init__Nc                 C   s&   |   | jv rt|  ddd S )Npassword_too_commonr:   )rW   rq   rx   r   r=   r>   r   r   r   r      s   z CommonPasswordValidator.validatec                 C   rc   )NzThis password is too common.rd   r@   r   r   r   r=      rf   z)CommonPasswordValidator.get_error_messagec                 C   rc   )Nu2   Your password can’t be a commonly used password.rd   r@   r   r   r   r*     rf   z%CommonPasswordValidator.get_help_textr   )
rA   rB   rC   rD   r   rl   r7   r   r=   r*   r   r   r   r   rh      s    



rh   c                   @   s*   e Zd ZdZd	ddZdd Zdd ZdS )
NumericPasswordValidatorz=
    Validate that the password is not entirely numeric.
    Nc                 C   s   |  rt|  ddd S )Npassword_entirely_numericr}   )isdigitr   r=   r>   r   r   r   r     s   z!NumericPasswordValidator.validatec                 C   rc   )Nz"This password is entirely numeric.rd   r@   r   r   r   r=     rf   z*NumericPasswordValidator.get_error_messagec                 C   rc   )Nu*   Your password can’t be entirely numeric.rd   r@   r   r   r   r*     rf   z&NumericPasswordValidator.get_help_textr   )rA   rB   rC   rD   r   r=   r*   r   r   r   r   r~     s
    
r~   )NNr   )'	functoolsrv   rZ   difflibr   pathlibr   django.confr   django.core.exceptionsr   r   r   django.utils.functionalr   r	   django.utils.htmlr
   r   django.utils.module_loadingr   django.utils.translationr   re   r   cacher   r   r%   r&   r,   r2   rY   "password_validators_help_text_htmlr3   rL   rM   rh   r~   r   r   r   r   <module>   s2    





"='