U
    g                     @  s   d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
mZ ddlmZ ddlmZ ddlmZmZ dd	lmZmZ d
dgZe
eef ZdddddZG dd
 d
eZdddddddddZdS )    )annotationsN)Any	AwaitableCallableIterableTuplecast   )Headers)InvalidHeader)build_www_authenticate_basicparse_authorization_basic   )HTTPResponseWebSocketServerProtocol BasicAuthWebSocketServerProtocolbasic_auth_protocol_factoryr   bool)valuereturnc              	   C  s@   z| \}}W n t tfk
r&   Y dS X t|to:t|tS d S NF)	TypeError
ValueError
isinstancestr)r   usernamepassword r   :/tmp/pip-unpacked-wheel-dx_q7dq3/websockets/legacy/auth.pyis_credentials   s
    r   c                      sx   e Zd ZU dZdZded< dZded< dddd	dd
d	dd fddZddddddZdddd fddZ	  Z
S )r   zC
    WebSocket server protocol that enforces HTTP Basic Auth.

     r   realmN
str | Noner   r!   check_credentialsr   ,Callable[[str, str], Awaitable[bool]] | NoneNone)argsr!   r$   kwargsr   c                  s&   |d k	r|| _ || _t j|| d S N)r!   _check_credentialssuper__init__)selfr!   r$   r'   r(   	__class__r   r   r,   .   s    z)BasicAuthWebSocketServerProtocol.__init__r   r   r   r   c                   s    | j dk	r|  ||I dH S dS )a  
        Check whether credentials are authorized.

        This coroutine may be overridden in a subclass, for example to
        authenticate against a database or an external service.

        Args:
            username: HTTP Basic Auth username.
            password: HTTP Basic Auth password.

        Returns:
            :obj:`True` if the handshake should continue;
            :obj:`False` if it should fail with an HTTP 401 error.

        NF)r*   )r-   r   r   r   r   r   r$   :   s    
z2BasicAuthWebSocketServerProtocol.check_credentialsr
   zHTTPResponse | None)pathrequest_headersr   c                   s   z|d }W n. t k
r:   tjjdt| jfgdf Y S X zt|\}}W n. tk
rz   tjjdt| jfgdf Y S X | ||I dH stjjdt| jfgdfS || _	t
 ||I dH S )zS
        Check HTTP Basic Auth and return an HTTP 401 response if needed.

        AuthorizationzWWW-Authenticates   Missing credentials
s   Unsupported credentials
Ns   Invalid credentials
)KeyErrorhttp
HTTPStatusUNAUTHORIZEDr   r!   r   r   r$   r   r+   process_request)r-   r1   r2   authorizationr   r   r.   r   r   r8   O   s*    	

z0BasicAuthWebSocketServerProtocol.process_request)__name__
__module____qualname____doc__r!   __annotations__r   r,   r$   r8   __classcell__r   r   r.   r   r      s   
r"   z*Credentials | Iterable[Credentials] | Noner%   z6Callable[..., BasicAuthWebSocketServerProtocol] | Nonez/Callable[..., BasicAuthWebSocketServerProtocol])r!   credentialsr$   create_protocolr   c                   s   |dk|dkkrt d|dk	rt|r6tt|g}nLt|trttttt |}tdd |D st d| nt d| t| dddd fd	d
}|dkrt	}tt
dt	f |}tj|| |dS )a  
    Protocol factory that enforces HTTP Basic Auth.

    :func:`basic_auth_protocol_factory` is designed to integrate with
    :func:`~websockets.legacy.server.serve` like this::

        serve(
            ...,
            create_protocol=basic_auth_protocol_factory(
                realm="my dev server",
                credentials=("hello", "iloveyou"),
            )
        )

    Args:
        realm: Scope of protection. It should contain only ASCII characters
            because the encoding of non-ASCII characters is undefined.
            Refer to section 2.2 of :rfc:`7235` for details.
        credentials: Hard coded authorized credentials. It can be a
            ``(username, password)`` pair or a list of such pairs.
        check_credentials: Coroutine that verifies credentials.
            It receives ``username`` and ``password`` arguments
            and returns a :class:`bool`. One of ``credentials`` or
            ``check_credentials`` must be provided but not both.
        create_protocol: Factory that creates the protocol. By default, this
            is :class:`BasicAuthWebSocketServerProtocol`. It can be replaced
            by a subclass.
    Raises:
        TypeError: If the ``credentials`` or ``check_credentials`` argument is
            wrong.

    Nz/provide either credentials or check_credentialsc                 s  s   | ]}t |V  qd S r)   )r   ).0itemr   r   r   	<genexpr>   s     z.basic_auth_protocol_factory.<locals>.<genexpr>zinvalid credentials argument: r   r   r0   c                   s0   z |  }W n t k
r"   Y dS X t||S r   )r4   hmaccompare_digest)r   r   Zexpected_passwordZcredentials_dictr   r   r$      s
    z6basic_auth_protocol_factory.<locals>.check_credentials.r#   )r   r   r   Credentialsr   r   listalldictr   r   	functoolspartial)r!   r@   r$   rA   Zcredentials_listr   rG   r   r   v   s.    &

 )NNNN)
__future__r   rL   rE   r5   typingr   r   r   r   r   r   Zdatastructuresr
   
exceptionsr   headersr   r   serverr   r   __all__r   rH   r   r   r   r   r   r   r   <module>   s"    	Z    