B
    CVvg¥?  ã               @   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-install-o3oxmrkh/Django/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¡ ndyt|ƒ}W n& tk
rh   | dtdƒi¡ Y n2X x.| |¡ 	¡ D ]\}}| t|ƒ|dœ¡ qzW ||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                   s    e Zd ZeZ‡ fdd„Z‡  ZS )ÚReadOnlyPasswordHashFieldc                s*   |  dd¡ |  dd¡ tƒ j||Ž d S )NÚrequiredFÚdisabledT)Ú
setdefaultr    Ú__init__)r&   ÚargsÚkwargs)r+   r   r   r4   9   s    z"ReadOnlyPasswordHashField.__init__)r,   r-   r.   r   Úwidgetr4   r/   r   r   )r+   r   r0   6   s   r0   c                   s(   e Zd Z‡ fdd„Z‡ fdd„Z‡  ZS )ÚUsernameFieldc                s4   t ƒ  |¡}| jd k	r(t|ƒ| jkr(|S t d|¡S )Nr   )r    Ú	to_pythonÚ
max_lengthÚlenr   r   )r&   r   )r+   r   r   r9   @   s    zUsernameField.to_pythonc                s   t ƒ  |¡dddœ–S )NÚnoneÚusername)ZautocapitalizeÚautocomplete)r    Úwidget_attrs)r&   r7   )r+   r   r   r?   K   s    
zUsernameField.widget_attrs)r,   r-   r.   r9   r?   r/   r   r   )r+   r   r8   ?   s   r8   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_mismatchu'   The two password fields didnâ€™t match.ÚPasswordFr>   znew-password)r(   )r   Ústripr7   Ú	help_textzPassword confirmationz4Enter the same password as before, for verification.)r   r7   rC   rD   c               @   s   e Zd ZeZdZdeiZdS )zUserCreationForm.Meta)r=   r=   N)r,   r-   r.   r   ÚmodelÚfieldsr8   Úfield_classesr   r   r   r   ÚMetah   s   rH   c                s:   t ƒ j||Ž | jjj| jkr6d| j| jjj jjd< d S )NTÚ	autofocus)r    r4   Ú_metarE   ÚUSERNAME_FIELDrF   r7   r(   )r&   r5   r6   )r+   r   r   r4   m   s    zUserCreationForm.__init__c             C   s>   | j  d¡}| j  d¡}|r:|r:||kr:t| jd dd�‚|S )NÚ	password1Ú	password2rA   )Úcode)Úcleaned_dataÚgetr   Úerror_messages)r&   rL   rM   r   r   r   Úclean_password2r   s    z UserCreationForm.clean_password2c          
      s`   t ƒ  ¡  | j d¡}|r\yt || j¡ W n. tk
rZ } z|  d|¡ W d d }~X Y nX d S )NrM   )	r    Ú_post_cleanrO   rP   r   Úvalidate_passwordÚinstancer   Z	add_error)r&   ÚpasswordÚerror)r+   r   r   rS   |   s    
zUserCreationForm._post_cleanTc                s.   t ƒ jdd�}| | jd ¡ |r*| ¡  |S )NF)ÚcommitrL   )r    ÚsaveÚset_passwordrO   )r&   rX   Úuser)r+   r   r   rY   ‡   s
    zUserCreationForm.save)T)r,   r-   r.   Ú__doc__Ú_rQ   r   Ú	CharFieldÚPasswordInputr   Ú"password_validators_help_text_htmlrL   rM   rH   r4   rR   rS   rY   r/   r   r   )r+   r   r@   S   s"   
r@   c                   s>   e Zd Zeedƒedƒd�ZG dd„ dƒZ‡ fdd„Z‡  ZS )ÚUserChangeFormrB   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   rD   c               @   s   e Zd ZeZdZdeiZdS )zUserChangeForm.MetaÚ__all__r=   N)r,   r-   r.   r   rE   rF   r8   rG   r   r   r   r   rH   ™   s   rH   c                sN   t ƒ j||Ž | j d¡}|r,|j d¡|_| j d¡}|rJ|j d¡|_d S )NrV   z../password/Úuser_permissionsÚcontent_type)r    r4   rF   rP   rD   ÚformatZquerysetZselect_related)r&   r5   r6   rV   rc   )r+   r   r   r4   ž   s    zUserChangeForm.__init__)	r,   r-   r.   r0   r]   rV   rH   r4   r/   r   r   )r+   r   ra   �   s   
ra   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.
    rI   T)r(   )r7   rB   Fr>   zcurrent-password)r   rC   r7   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éþ   r=   Z	maxlength)ÚrequestÚ
user_cacher    r4   Ú	UserModelrJ   Ú	get_fieldrK   Úusername_fieldr:   rF   r7   r(   r   r   Úverbose_name)r&   rj   r5   r6   Zusername_max_length)r+   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 )Nr=   rV   )r=   rV   )rO   rP   r   rj   rk   Úget_invalid_login_errorÚconfirm_login_allowed)r&   r=   rV   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.
        rh   )rN   N)Ú	is_activer   rQ   )r&   r[   r   r   r   rq   Ú   s    z(AuthenticationForm.confirm_login_allowedc             C   s   | j S )N)rk   )r&   r   r   r   Úget_userë   s    zAuthenticationForm.get_userc             C   s   t | jd dd| jjid�S )Nrg   r=   )rN   Úparams)r   rQ   rn   ro   )r&   r   r   r   rp   î   s    z*AuthenticationForm.get_invalid_login_error)N)r,   r-   r.   r\   r8   r   Z	TextInputr=   r^   r]   r_   rV   rQ   r4   rr   rq   rt   rp   r/   r   r   )r+   r   rf   ¨   s   rf   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Emailri   r>   Úemail)r(   )r   r:   r7   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__iexactrs   Tc             3   s*   | ]"}|  ¡ rtˆ t|ˆƒƒr|V  qd S )N)Zhas_usable_passwordr   Úgetattr)Ú.0Úu)rw   Úemail_field_namer   r   ú	<genexpr>  s    z.PasswordResetForm.get_users.<locals>.<genexpr>)rl   Úget_email_field_nameZ_default_managerÚfilter)r&   rw   Zactive_usersr   )rw   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 ¡ }xf|  |
¡D ]X}t||ƒ}|||tt	|j
ƒƒ|| |¡|rrdnddœ|	p~i –}| j||||||d� q@W dS )zf
        Generate a one-use only link for resetting password and send it to the
        user.
        rw   ÚhttpsÚhttp)rw   ÚdomainÚ	site_nameÚuidr[   ÚtokenÚprotocol)r   N)rO   r
   r'   r�   rl   rˆ   rŠ   rƒ   r   r   ÚpkZ
make_tokenr‚   )r&   Zdomain_overrider|   r}   Z	use_httpsZtoken_generatorr~   rj   r   Zextra_email_contextrw   Zcurrent_siterŽ   r�   r†   r[   Z
user_emailr)   r   r   r   rY      s(    



zPasswordResetForm.save)N)r,   r-   r.   r   Z
EmailFieldr]   Z
EmailInputrw   r‚   rŠ   r	   rY   r   r   r   r   rv   ö   s   
rv   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
    rA   u'   The two password fields didnâ€™t match.zNew passwordr>   znew-password)r(   F)r   r7   rC   rD   zNew password confirmation)r   rC   r7   c                s   || _ tƒ j||Ž d S )N)r[   r    r4   )r&   r[   r5   r6   )r+   r   r   r4   X  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_password2rA   )rN   )rO   rP   r   rQ   r   rT   r[   )r&   rL   rM   r   r   r   Úclean_new_password2\  s    z#SetPasswordForm.clean_new_password2Tc             C   s*   | j d }| j |¡ |r$| j ¡  | jS )Nr”   )rO   r[   rZ   rY   )r&   rX   rV   r   r   r   rY   h  s
    

zSetPasswordForm.save)T)r,   r-   r.   r\   r]   rQ   r   r^   r_   r   r`   r”   r•   r4   r–   rY   r/   r   r   )r+   r   r“   D  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 passwordFzcurrent-passwordT)r>   rI   )r(   )r   rC   r7   Ú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˜   )rN   )rO   r[   Zcheck_passwordr   rQ   )r&   r™   r   r   r   Úclean_old_password�  s    
z%PasswordChangeForm.clean_old_passwordN)r,   r-   r.   r\   r“   rQ   r]   r   r^   r_   r™   Zfield_orderrš   r   r   r   r   r—   p  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.
    rA   u'   The two password fields didnâ€™t match.r1   rB   znew-passwordT)r>   rI   )r(   F)r   r7   rC   rD   zPassword (again)r>   z4Enter the same password as before, for verification.c                s   || _ tƒ j||Ž d S )N)r[   r    r4   )r&   r[   r5   r6   )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 )NrL   rM   rA   )rN   )rO   rP   r   rQ   r   rT   r[   )r&   rL   rM   r   r   r   rR   §  s    z'AdminPasswordChangeForm.clean_password2c             C   s*   | j d }| j |¡ |r$| j ¡  | jS )zSave the new password.rL   )rO   r[   rZ   rY   )r&   rX   rV   r   r   r   rY   ²  s
    

zAdminPasswordChangeForm.savec                s*   t ƒ j}x| jD ]}||krg S qW dgS )NrV   )r    Úchanged_datarF   )r&   Údatar'   )r+   r   r   rœ   º  s
    z$AdminPasswordChangeForm.changed_data)T)r,   r-   r.   r\   r]   rQ   Zrequired_css_classr   r^   r_   r   r`   rL   rM   r4   rR   rY   Úpropertyrœ   r/   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   r]   rl   r   ZWidgetr   ZFieldr0   r^   r8   Z	ModelFormr@   ra   ZFormrf   rv   r“   r—   r›   r   r   r   r   Ú<module>   s2   		<NN,