U
    8ÄT_Ó?  ã                   @   sx  d dl 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 d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZmZ eƒ Z dd„ Z!G dd„ dej"ƒZ#G dd„ dej$ƒZ%G dd„ dej&ƒZ'G dd„ dej(ƒZ)G dd„ dej(ƒZ*G dd„ dej+ƒZ,G dd„ dej+ƒZ-G dd „ d ej+ƒZ.G d!d"„ d"e.ƒZ/G d#d$„ d$ej+ƒZ0dS )%é    N)Úforms)ÚauthenticateÚget_user_modelÚpassword_validation)ÚUNUSABLE_PASSWORD_PREFIXÚidentify_hasher)ÚUser)Údefault_token_generator)Úget_current_site)ÚValidationError)ÚEmailMultiAlternatives)Úloader)Úforce_bytes)Úurlsafe_base64_encode)Úcapfirst)ÚgettextÚgettext_lazyc                 C   s    t  d| ¡ ¡ t  d|¡ ¡ kS )z¡
    Perform case-insensitive comparison of two identifiers, using the
    recommended algorithm from Unicode Technical Report 36, section
    2.11.2(B)(2).
    ÚNFKC)ÚunicodedataÚ	normalizeÚcasefold)Ús1Ús2© r   ú=/tmp/pip-unpacked-wheel-dv63caxw/django/contrib/auth/forms.pyÚ_unicode_ci_compare   s    r   c                       s$   e Zd ZdZdZ‡ fdd„Z‡  ZS )ÚReadOnlyPasswordHashWidgetz)auth/widgets/read_only_password_hash.htmlTc           	         s¢   t ƒ  |||¡}g }|r"| t¡r6| dtdƒi¡ n`zt|ƒ}W n& tk
rh   | dtdƒi¡ Y n.X | |¡ 	¡ D ]\}}| t|ƒ|dœ¡ qx||d< |S )NÚlabelzNo password set.z5Invalid password format or unknown hashing algorithm.)r   ÚvalueÚsummary)
ÚsuperÚget_contextÚ
startswithr   Úappendr   r   Ú
ValueErrorZsafe_summaryÚitems)	ÚselfÚnamer   ÚattrsÚcontextr   ZhasherÚkeyZvalue_©Ú	__class__r   r   r!   %   s    z&ReadOnlyPasswordHashWidget.get_context)Ú__name__Ú
__module__Ú__qualname__Ztemplate_nameZ	read_onlyr!   Ú__classcell__r   r   r+   r   r   !   s   r   c                       s0   e Zd ZeZ‡ fdd„Zdd„ Zdd„ Z‡  ZS )ÚReadOnlyPasswordHashFieldc                    s   |  dd¡ tƒ j||Ž d S )NÚrequiredF)Ú
setdefaultr    Ú__init__©r&   ÚargsÚkwargsr+   r   r   r4   9   s    z"ReadOnlyPasswordHashField.__init__c                 C   s   |S ©Nr   )r&   ÚdataÚinitialr   r   r   Ú
bound_data=   s    z$ReadOnlyPasswordHashField.bound_datac                 C   s   dS )NFr   )r&   r:   r9   r   r   r   Úhas_changedB   s    z%ReadOnlyPasswordHashField.has_changed)	r-   r.   r/   r   Úwidgetr4   r;   r<   r0   r   r   r+   r   r1   6   s   r1   c                       s(   e Zd Z‡ fdd„Z‡ fdd„Z‡  ZS )ÚUsernameFieldc                    s   t  dtƒ  |¡¡S )Nr   )r   r   r    Ú	to_python)r&   r   r+   r   r   r?   G   s    zUsernameField.to_pythonc                    s   t ƒ  |¡dddœ–S )NÚnoneÚusername)ZautocapitalizeÚautocomplete)r    Úwidget_attrs)r&   r=   r+   r   r   rC   J   s    
ýzUsernameField.widget_attrs)r-   r.   r/   r?   rC   r0   r   r   r+   r   r>   F   s   r>   c                       s¨   e Zd ZdZdedƒiZejedƒdejddid�e	 
¡ d	�Zejed
ƒejddid�dedƒd�ZG dd„ dƒZ‡ fdd„Zdd„ Z‡ fdd„Zd‡ fdd„	Z‡  ZS )ÚUserCreationFormzc
    A form that creates a user, with no privileges, from the given username and
    password.
    Úpassword_mismatchõ'   The two password fields didnâ€™t match.ÚPasswordFrB   únew-password©r(   )r   Ústripr=   Ú	help_textzPassword confirmationú4Enter the same password as before, for verification.©r   r=   rJ   rK   c                   @   s   e Zd ZeZdZdeiZdS )zUserCreationForm.Meta)rA   rA   N©r-   r.   r/   r   ÚmodelÚfieldsr>   Zfield_classesr   r   r   r   ÚMetag   s   rQ   c                    s:   t ƒ j||Ž | jjj| jkr6d| j| jjj jjd< d S )NTÚ	autofocus)r    r4   Ú_metarO   ÚUSERNAME_FIELDrP   r=   r(   r5   r+   r   r   r4   l   s    zUserCreationForm.__init__c                 C   s>   | j  d¡}| j  d¡}|r:|r:||kr:t| jd dd�‚|S ©NÚ	password1Ú	password2rE   ©Úcode)Úcleaned_dataÚgetr   Úerror_messages©r&   rV   rW   r   r   r   Úclean_password2q   s    þz UserCreationForm.clean_password2c              
      s`   t ƒ  ¡  | j d¡}|r\zt || j¡ W n. tk
rZ } z|  d|¡ W 5 d }~X Y nX d S )NrW   )	r    Ú_post_cleanrZ   r[   r   Úvalidate_passwordÚinstancer   Z	add_error)r&   ÚpasswordÚerrorr+   r   r   r_   {   s    
zUserCreationForm._post_cleanTc                    s.   t ƒ jdd�}| | jd ¡ |r*| ¡  |S )NF)ÚcommitrV   )r    ÚsaveÚset_passwordrZ   )r&   rd   Úuserr+   r   r   re   †   s
    zUserCreationForm.save)T)r-   r.   r/   Ú__doc__Ú_r\   r   Ú	CharFieldÚPasswordInputr   Ú"password_validators_help_text_htmlrV   rW   rQ   r4   r^   r_   re   r0   r   r   r+   r   rD   R   s*    ÿüü
rD   c                       sF   e Zd Zeedƒedƒd�ZG dd„ dƒZ‡ fdd„Zdd	„ Z‡  Z	S )
ÚUserChangeFormrG   u‘   Raw passwords are not stored, so there is no way to see this userâ€™s password, but you can change the password using <a href="{}">this form</a>.)r   rK   c                   @   s   e Zd ZeZdZdeiZdS )zUserChangeForm.MetaÚ__all__rA   NrN   r   r   r   r   rQ   ˜   s   rQ   c                    sN   t ƒ j||Ž | j d¡}|r,|j d¡|_| j d¡}|rJ|j d¡|_d S )Nrb   z../password/Úuser_permissionsÚcontent_type)r    r4   rP   r[   rK   ÚformatZquerysetZselect_related)r&   r6   r7   rb   ro   r+   r   r   r4   �   s    zUserChangeForm.__init__c                 C   s   | j  d¡S ©Nrb   )r:   r[   ©r&   r   r   r   Úclean_password¦   s    zUserChangeForm.clean_password)
r-   r.   r/   r1   ri   rb   rQ   r4   rt   r0   r   r   r+   r   rm   Ž   s   ÿþ		rm   c                       sŠ   e Zd ZdZeejddid�d�Zeje	dƒdej
dd	id�d
�Ze	dƒe	dƒdœZd‡ fdd„	Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )ÚAuthenticationFormzs
    Base class for authenticating users. Extend this to get a form that accepts
    username/password logins.
    rR   TrI   )r=   rG   FrB   úcurrent-password©r   rJ   r=   z^Please enter a correct %(username)s and password. Note that both fields may be case-sensitive.zThis account is inactive.)Úinvalid_loginÚinactiveNc                    s|   || _ d| _tƒ j||Ž tj tj¡| _| jj	p4d}|| j
d _	|| j
d jjd< | j
d jdkrxt| jjƒ| j
d _dS )z‘
        The 'request' parameter is set for custom auth use by subclasses.
        The form data comes in via the standard 'data' kwarg.
        Néþ   rA   Z	maxlength)ÚrequestÚ
user_cacher    r4   Ú	UserModelrS   Ú	get_fieldrT   Úusername_fieldÚ
max_lengthrP   r=   r(   r   r   Úverbose_name)r&   r{   r6   r7   Zusername_max_lengthr+   r   r   r4   Á   s    zAuthenticationForm.__init__c                 C   s\   | j  d¡}| j  d¡}|d k	rV|rVt| j||d�| _| jd krJ|  ¡ ‚n|  | j¡ | j S )NrA   rb   )rA   rb   )rZ   r[   r   r{   r|   Úget_invalid_login_errorÚconfirm_login_allowed)r&   rA   rb   r   r   r   ÚcleanÒ   s    

zAuthenticationForm.cleanc                 C   s   |j st| jd dd�‚dS )a•  
        Controls whether the given User may log in. This is a policy setting,
        independent of end-user authentication. This default behavior is to
        allow login by active users, and reject login by inactive users.

        If the given user cannot log in, this method should raise a
        ``ValidationError``.

        If the given user may log in, this method should return None.
        ry   rX   N)Ú	is_activer   r\   )r&   rg   r   r   r   rƒ   ß   s
    þz(AuthenticationForm.confirm_login_allowedc                 C   s   | j S r8   )r|   rs   r   r   r   Úget_userð   s    zAuthenticationForm.get_userc                 C   s   t | jd dd| jjid�S )Nrx   rA   )rY   Úparams)r   r\   r   r�   rs   r   r   r   r‚   ó   s
    
ýz*AuthenticationForm.get_invalid_login_error)N)r-   r.   r/   rh   r>   r   Z	TextInputrA   rj   ri   rk   rb   r\   r4   r„   rƒ   r†   r‚   r0   r   r   r+   r   ru   ­   s"   ýÿûru   c                	   @   sZ   e Zd Zejedƒdejddid�d�Zddd	„Zd
d„ Z	dddde
ddddf	dd„ZdS )ÚPasswordResetFormZEmailrz   rB   ÚemailrI   )r   r€   r=   Nc                 C   sb   t  ||¡}d | ¡ ¡}t  ||¡}t||||gƒ}	|dk	rVt  ||¡}
|	 |
d¡ |	 ¡  dS )zO
        Send a django.core.mail.EmailMultiAlternatives to `to_email`.
        Ú Nz	text/html)r   Zrender_to_stringÚjoinÚ
splitlinesr   Zattach_alternativeÚsend)r&   Úsubject_template_nameÚemail_template_namer)   Ú
from_emailZto_emailÚhtml_email_template_nameÚsubjectÚbodyZemail_messageZ
html_emailr   r   r   Ú	send_mail  s    zPasswordResetForm.send_mailc                    s6   t  ¡ ‰t jjf dˆ ˆ ddiŽ}‡ ‡fdd„|D ƒS )a  Given an email, return matching user(s) who should receive a reset.

        This allows subclasses to more easily customize the default policies
        that prevent inactive users and users with unusable passwords from
        resetting their password.
        z
%s__iexactr…   Tc                 3   s*   | ]"}|  ¡ rtˆ t|ˆƒƒr|V  qd S r8   )Zhas_usable_passwordr   Úgetattr)Ú.0Úu©r‰   Úemail_field_namer   r   Ú	<genexpr>  s   þz.PasswordResetForm.get_users.<locals>.<genexpr>)r}   Úget_email_field_nameZ_default_managerÚfilter)r&   r‰   Zactive_usersr   r˜   r   Ú	get_users  s      þÿzPasswordResetForm.get_usersz'registration/password_reset_subject.txtz&registration/password_reset_email.htmlFc
              	   C   sœ   | j d }
|s$t|ƒ}|j}|j}n| }}t ¡ }|  |
¡D ]X}t||ƒ}|||tt	|j
ƒƒ|| |¡|rpdnddœ|	p|i –}| j||||||d� q>dS )zf
        Generate a one-use only link for resetting password and send it to the
        user.
        r‰   ÚhttpsÚhttp)r‰   ÚdomainÚ	site_nameÚuidrg   ÚtokenÚprotocol)r‘   N)rZ   r
   r'   r    r}   r›   r�   r•   r   r   ÚpkZ
make_tokenr”   )r&   Zdomain_overriderŽ   r�   Z	use_httpsZtoken_generatorr�   r{   r‘   Zextra_email_contextr‰   Zcurrent_siter¡   r    r™   rg   Z
user_emailr)   r   r   r   re   %  s6    



ùø
    þzPasswordResetForm.save)N)r-   r.   r/   r   Z
EmailFieldri   Z
EmailInputr‰   r”   r�   r	   re   r   r   r   r   rˆ   û   s$   ý ÿ
   ûrˆ   c                       s„   e Zd ZdZdedƒiZejedƒejddid�de	 
¡ d	�Zejed
ƒdejddid�d�Z‡ fdd„Zdd„ Zddd„Z‡  ZS )ÚSetPasswordFormza
    A form that lets a user change set their password without entering the old
    password
    rE   rF   zNew passwordrB   rH   rI   FrM   zNew password confirmationrw   c                    s   || _ tƒ j||Ž d S r8   ©rg   r    r4   ©r&   rg   r6   r7   r+   r   r   r4   ]  s    zSetPasswordForm.__init__c                 C   sL   | j  d¡}| j  d¡}|r:|r:||kr:t| jd dd�‚t || j¡ |S )NÚnew_password1Únew_password2rE   rX   ©rZ   r[   r   r\   r   r`   rg   r]   r   r   r   Úclean_new_password2a  s    þz#SetPasswordForm.clean_new_password2Tc                 C   s*   | j d }| j |¡ |r$| j ¡  | jS )Nr©   ©rZ   rg   rf   re   ©r&   rd   rb   r   r   r   re   m  s
    

zSetPasswordForm.save)T)r-   r.   r/   rh   ri   r\   r   rj   rk   r   rl   r©   rª   r4   r¬   re   r0   r   r   r+   r   r¦   I  s$    ÿüýr¦   c                   @   sV   e Zd ZdZejdedƒi–Zejedƒdej	dddœd	�d
�Z
dddgZdd„ ZdS )ÚPasswordChangeFormz[
    A form that lets a user change their password by entering their old
    password.
    Úpassword_incorrectzAYour old password was entered incorrectly. Please enter it again.zOld passwordFrv   T©rB   rR   rI   rw   Úold_passwordr©   rª   c                 C   s,   | j d }| j |¡s(t| jd dd�‚|S )zB
        Validate that the old_password field is correct.
        r²   r°   rX   )rZ   rg   Zcheck_passwordr   r\   )r&   r²   r   r   r   Úclean_old_password†  s    
þz%PasswordChangeForm.clean_old_passwordN)r-   r.   r/   rh   r¦   r\   ri   r   rj   rk   r²   Zfield_orderr³   r   r   r   r   r¯   u  s    þý
r¯   c                       s    e Zd ZdZdedƒiZdZejedƒej	dddœd	�d
e
 ¡ d�Zejedƒej	ddid	�d
edƒd�Z‡ fdd„Zdd„ Zddd„Ze‡ fdd„ƒZ‡  ZS )ÚAdminPasswordChangeFormzN
    A form used to change the password of a user in the admin interface.
    rE   rF   r2   rG   rH   Tr±   rI   FrM   zPassword (again)rB   rL   c                    s   || _ tƒ j||Ž d S r8   r§   r¨   r+   r   r   r4   ¨  s    z AdminPasswordChangeForm.__init__c                 C   sL   | j  d¡}| j  d¡}|r:|r:||kr:t| jd dd�‚t || j¡ |S rU   r«   r]   r   r   r   r^   ¬  s    þz'AdminPasswordChangeForm.clean_password2c                 C   s*   | j d }| j |¡ |r$| j ¡  | jS )zSave the new password.rV   r­   r®   r   r   r   re   ¸  s
    

zAdminPasswordChangeForm.savec                    s*   t ƒ j}| jD ]}||krg   S qdgS rr   )r    Úchanged_datarP   )r&   r9   r'   r+   r   r   rµ   À  s
    

z$AdminPasswordChangeForm.changed_data)T)r-   r.   r/   rh   ri   r\   Zrequired_css_classr   rj   rk   r   rl   rV   rW   r4   r^   re   Úpropertyrµ   r0   r   r   r+   r   r´   “  s,    ÿüü
r´   )1r   Zdjangor   Zdjango.contrib.authr   r   r   Zdjango.contrib.auth.hashersr   r   Zdjango.contrib.auth.modelsr   Zdjango.contrib.auth.tokensr	   Zdjango.contrib.sites.shortcutsr
   Zdjango.core.exceptionsr   Zdjango.core.mailr   Zdjango.templater   Zdjango.utils.encodingr   Zdjango.utils.httpr   Zdjango.utils.textr   Zdjango.utils.translationr   r   ri   r}   r   ZWidgetr   ZFieldr1   rj   r>   Z	ModelFormrD   rm   ZFormru   rˆ   r¦   r¯   r´   r   r   r   r   Ú<module>   s2   	<NN,