U
    ‰d;  ã                   @   s¶   d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z
 ddlmZmZ dd„ ZG d	d
„ d
eƒZG dd„ dƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdS )z+
Provides various authentication policies.
é    N)ÚauthenticateÚget_user_model)ÚCsrfViewMiddleware)Úgettext_lazy)ÚHTTP_HEADER_ENCODINGÚ
exceptionsc                 C   s&   | j  dd¡}t|tƒr"| t¡}|S )z‰
    Return request's 'Authorization:' header, as a bytestring.

    Hide some test client ickyness where the header can be unicode.
    ZHTTP_AUTHORIZATIONó    )ÚMETAÚgetÚ
isinstanceÚstrÚencoder   )ÚrequestÚauth© r   úA/tmp/pip-unpacked-wheel-quko9yh2/rest_framework/authentication.pyÚget_authorization_header   s    

r   c                   @   s   e Zd Zdd„ ZdS )Ú	CSRFCheckc                 C   s   |S ©Nr   )Úselfr   Úreasonr   r   r   Ú_reject   s    zCSRFCheck._rejectN)Ú__name__Ú
__module__Ú__qualname__r   r   r   r   r   r      s   r   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚBaseAuthenticationzF
    All authentication classes should extend BaseAuthentication.
    c                 C   s   t dƒ‚dS )zS
        Authenticate the request and return a two-tuple of (user, token).
        z#.authenticate() must be overridden.N)ÚNotImplementedError©r   r   r   r   r   r   &   s    zBaseAuthentication.authenticatec                 C   s   dS )zç
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        Nr   r   r   r   r   Úauthenticate_header,   s    z&BaseAuthentication.authenticate_headerN)r   r   r   Ú__doc__r   r   r   r   r   r   r   !   s   r   c                   @   s.   e Zd ZdZdZdd„ Zd
dd„Zdd	„ ZdS )ÚBasicAuthenticationz>
    HTTP Basic authentication against username/password.
    Úapic              
   C   s  t |ƒ ¡ }|r |d  ¡ dkr$dS t|ƒdkrDtdƒ}t |¡‚nt|ƒdkrbtdƒ}t |¡‚zPzt |d ¡ 	d¡}W n( t
k
r¤   t |d ¡ 	d	¡}Y nX | d
¡}W n. tt
tjfk
rà   tdƒ}t |¡‚Y nX |d |d  }}|  |||¡S )zœ
        Returns a `User` if a correct username and password have been supplied
        using HTTP Basic authentication.  Otherwise returns `None`.
        r   s   basicNé   z.Invalid basic header. No credentials provided.é   zCInvalid basic header. Credentials string should not contain spaces.zutf-8zlatin-1ú:z?Invalid basic header. Credentials not correctly base64 encoded.)r   ÚsplitÚlowerÚlenÚ_r   ÚAuthenticationFailedÚbase64Ú	b64decodeÚdecodeÚUnicodeDecodeErrorÚ	partitionÚ	TypeErrorÚbinasciiÚErrorÚauthenticate_credentials)r   r   r   ÚmsgZauth_decodedZ
auth_partsÚuseridÚpasswordr   r   r   r   ;   s(    
z BasicAuthentication.authenticateNc                 C   sT   t ƒ j|d|i}tf d|i|—Ž}|dkr8t tdƒ¡‚|jsLt tdƒ¡‚|dfS )z
        Authenticate the userid and password against username and password
        with optional request for context.
        r5   r   NzInvalid username/password.úUser inactive or deleted.)r   ZUSERNAME_FIELDr   r   r)   r(   Ú	is_active)r   r4   r5   r   ÚcredentialsÚuserr   r   r   r2   Y   s      þz,BasicAuthentication.authenticate_credentialsc                 C   s
   d| j  S )NzBasic realm="%s")Úwww_authenticate_realmr   r   r   r   r   l   s    z'BasicAuthentication.authenticate_header)N)r   r   r   r   r:   r   r2   r   r   r   r   r   r    5   s
   
r    c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚSessionAuthenticationz<
    Use Django's session framework for authentication.
    c                 C   s.   t |jddƒ}|r|jsdS |  |¡ |dfS )z{
        Returns a `User` if the request session currently has a logged in user.
        Otherwise returns `None`.
        r9   N)ÚgetattrÚ_requestr7   Úenforce_csrf©r   r   r9   r   r   r   r   u   s
    

z"SessionAuthentication.authenticatec                 C   s@   dd„ }t |ƒ}| |¡ | |ddi ¡}|r<t d| ¡‚dS )zK
        Enforce CSRF validation for session based authentication.
        c                 S   s   d S r   r   )r   r   r   r   Údummy_get_response‹   s    z>SessionAuthentication.enforce_csrf.<locals>.dummy_get_responseNr   zCSRF Failed: %s)r   Úprocess_requestZprocess_viewr   ZPermissionDenied)r   r   r@   Úcheckr   r   r   r   r>   ‡   s    
z"SessionAuthentication.enforce_csrfN)r   r   r   r   r   r>   r   r   r   r   r;   p   s   r;   c                   @   s8   e Zd ZdZdZdZdd„ Zdd„ Zdd	„ Zd
d„ Z	dS )ÚTokenAuthenticationa  
    Simple token based authentication.

    Clients should authenticate by passing the token key in the "Authorization"
    HTTP header, prepended with the string "Token ".  For example:

        Authorization: Token 401f7ac837da42b97f613d789819ff93537bee6a
    ÚTokenNc                 C   s    | j d k	r| j S ddlm} |S )Nr   )rD   )ÚmodelZrest_framework.authtoken.modelsrD   )r   rD   r   r   r   Ú	get_model¤   s    
zTokenAuthentication.get_modelc                 C   s®   t |ƒ ¡ }|r*|d  ¡ | j ¡  ¡ kr.d S t|ƒdkrNtdƒ}t |¡‚nt|ƒdkrltdƒ}t |¡‚z|d  	¡ }W n& t
k
r¢   tdƒ}t |¡‚Y nX |  |¡S )Nr   r"   z.Invalid token header. No credentials provided.r#   z=Invalid token header. Token string should not contain spaces.zIInvalid token header. Token string should not contain invalid characters.)r   r%   r&   Úkeywordr   r'   r(   r   r)   r,   ÚUnicodeErrorr2   )r   r   r   r3   Útokenr   r   r   r   ±   s    
z TokenAuthentication.authenticatec                 C   sf   |   ¡ }z|j d¡j|d}W n$ |jk
rD   t tdƒ¡‚Y nX |jj	s\t tdƒ¡‚|j|fS )Nr9   )ÚkeyzInvalid token.r6   )
rF   ZobjectsZselect_relatedr
   ZDoesNotExistr   r)   r(   r9   r7   )r   rJ   rE   rI   r   r   r   r2   Æ   s    z,TokenAuthentication.authenticate_credentialsc                 C   s   | j S r   )rG   r   r   r   r   r   Ò   s    z'TokenAuthentication.authenticate_header)
r   r   r   r   rG   rE   rF   r   r2   r   r   r   r   r   rC   —   s   	rC   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚRemoteUserAuthenticationa  
    REMOTE_USER authentication.

    To use this, set up your web server to perform authentication, which will
    set the REMOTE_USER environment variable. You will need to have
    'django.contrib.auth.backends.RemoteUserBackend in your
    AUTHENTICATION_BACKENDS setting
    ZREMOTE_USERc                 C   s,   t ||j | j¡d}|r(|jr(|d fS d S )N)r   Zremote_user)r   r	   r
   Úheaderr7   r?   r   r   r   r   å   s    
z%RemoteUserAuthentication.authenticateN)r   r   r   r   rL   r   r   r   r   r   rK   Ö   s   rK   )r   r*   r0   Zdjango.contrib.authr   r   Zdjango.middleware.csrfr   Zdjango.utils.translationr   r(   Zrest_frameworkr   r   r   r   r   r    r;   rC   rK   r   r   r   r   Ú<module>   s   ;'?