o
    RDi5                     @   s  d dl Z d dlZd dlZd dlmZ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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$ ddl%m&Z& ddl'm(Z( ddl)m*Z* ddl+m,Z, e-dZ.eeddG dd dee,eZ/dZ0G dd de/eZ1eeddeeddG dd  d e,eZ2eeddeeddG d!d" d"e,eZ3dS )#    N)	parse_qsl	urlencodeurlparse)LoginRequiredMixin)redirect_to_login)HttpResponse)resolve_url)timezone)method_decorator)csrf_exempt)sensitive_post_parameters)FormViewView   )login_not_required)OAuthToolkitError)	AllowForm)OAuth2ResponseRedirect)get_access_token_modelget_application_model)get_scopes_backend)oauth2_settings)app_authorized   )OAuthLibMixinoauth2_providerdispatch)namec                       s4   e Zd ZdZ fddZ fddZdd Z  ZS )BaseAuthorizationViewa  
    Implements a generic endpoint to handle *Authorization Requests* as in :rfc:`4.1.1`. The view
    does not implement any strategy to determine *authorize/do not authorize* logic.
    The endpoint is used in the following flows:

    * Authorization code
    * Implicit grant

    c                    s    i | _ t j|g|R i |S N)oauth2_datasuperr   )selfrequestargskwargs	__class__ S/var/www/Datamplify/venv/lib/python3.10/site-packages/oauth2_provider/views/base.pyr   +   s   zBaseAuthorizationView.dispatchc                    sD   t  j|fi |\}}|r| |d |S |d j}| j||dS )z
        Handle errors either by redirecting to redirect_uri with a json in the body containing
        error details or providing an error response
        urlerror)status)r!   error_responseredirectstatus_coderender_to_response)r"   r+   applicationr%   r.   r-   r,   r&   r(   r)   r-   /   s
   
z$BaseAuthorizationView.error_responsec                 C   s"   |d u rt j}n| }t||S r   )r   ALLOWED_REDIRECT_URI_SCHEMESget_allowed_schemesr   )r"   redirect_tor1   allowed_schemesr(   r(   r)   r.   <   s   
zBaseAuthorizationView.redirect)__name__
__module____qualname____doc__r   r-   r.   __classcell__r(   r(   r&   r)   r      s
    
r   z%Y-%m-%dT%H:%M:%SZc                       sL   e Zd ZdZdZeZdZdd Zdd Z	dd	 Z
d
d Z fddZ  ZS )AuthorizationViewa  
    Implements an endpoint to handle *Authorization Requests* as in :rfc:`4.1.1` and prompting the
    user with a form to determine if she authorizes the client application to access her data.
    This endpoint is reached two times during the authorization process:
    * first receive a ``GET`` request from user asking authorization for a certain client
    application, a form is served possibly showing some useful info and prompting for
    *authorize/do not authorize*.

    * then receive a ``POST`` request possibly after user authorized the access

    Some information contained in the ``GET`` request and needed to create a Grant token during
    the ``POST`` request would be lost between the two steps above, so they are temporarily stored in
    hidden fields on the form.
    A possible alternative could be keeping such information in the session.

    The endpoint is used in the following flows:
    * Authorization code
    * Implicit grant
    zoauth2_provider/authorize.htmlFc                 C   s   | j d| j dg }| j dd d|| j dd | j dd | j dd | j dd | j d	d | j d
d | j dd d	}|S )Nscopescopesredirect_uri nonce	client_idstateresponse_typecode_challengecode_challenge_methodclaims)	r>   r<   r@   rA   rB   rC   rD   rE   rF   )r    getjoin)r"   r=   initial_datar(   r(   r)   get_initialc   s   zAuthorizationView.get_initialc              
   C   sT  |j d }t jj|d}|j d|j d|j dd |j dd d}|j ddr5|j d|d< |j d	drD|j d	|d	< |j d
drS|j d
|d
< |j ddrb|j d|d< |j d}|j d}z| j| j|||d\}}}	}
W n ty } z| ||W  Y d }~S d }~ww || _t	
d| j | | j|S )NrA   rA   r>   rC   rB   )rA   r>   rC   rB   rD   FrE   r@   rF   r<   allowr#   r=   credentialsrL   z Success url for the request: {0})cleaned_datar   objectsrG   create_authorization_responser#   r   r-   success_urllogdebugformatr.   )r"   formrA   r1   rN   r=   rL   uriheadersbodyr,   r+   r(   r(   r)   
form_valids   s8   



zAuthorizationView.form_validc              
      sz  z	|  |\}}W n ty" } z| j|d dW  Y d }~S d }~ww |jd}|dkr1|  S t    fdd|D |d< ||d< t j	j|d d	}||d
< |d |d< |d |d< |d |d< |d |d< d|v ru|d |d< d|v r|d |d< d|v r|d |d< d|v rt
|d |d< || _| |  }	|	|d< |jdtj}
d|v rt|d trd|d |d< zX|jr| j| jd||dd\}}}}| ||W S |
dkrt j	j|j|d
 t d }|D ]"}||r| j| jd||dd\}}}}| ||  W S qW n ty1 } z| ||W  Y d }~S d }~ww | | j di |S )Nr1   promptloginc                    s   g | ]} | qS r(   r(   ).0r<   
all_scopesr(   r)   
<listcomp>   s    z)AuthorizationView.get.<locals>.<listcomp>scopes_descriptionsr=   rA   rK   r1   r>   rC   rB   rD   rE   r@   rF   rV   approval_prompt
ui_localesr?   TrM   auto)userr1   expires__gtr(   )!validate_authorization_requestr   r-   GETrG   handle_prompt_loginr   get_all_scopesr   rP   jsondumpsr    get_formget_form_classr   REQUEST_APPROVAL_PROMPT
isinstancelistrH   skip_authorizationrQ   r#   r.   r   filterrf   r	   nowallallow_scopesr0   get_context_data)r"   r#   r$   r%   r=   rN   r+   r\   r1   rV   require_approvalrW   rX   rY   r,   tokenstokenr(   r_   r)   rG      sz   

		zAuthorizationView.getc           	      C   s   | j  }t|  }t|d d \}}t|d d \}}|r%||kr0|r+||kr0| j  }t|}tt|j}|	d |j
t|d}t| ||  S )Nr   r\   )query)r#   build_absolute_urir   get_login_urlr   get_full_pathdictr   r|   pop_replacer   r   geturlget_redirect_field_name)	r"   pathresolved_login_urllogin_schemelogin_netloccurrent_schemecurrent_netlocparsedparsed_queryr(   r(   r)   rj      s$   


z%AuthorizationView.handle_prompt_loginc                    s   | j jd}| j jd}|dkr<|r<ddi}| j jd}|r%||d< d|v r+dnd}|| t| }| j|d	d
S t  S )aG  
        Generate response for unauthorized users.

        If prompt is set to none, then we redirect with an error code
        as defined by OIDC 3.1.2.6

        Some code copied from OAuthLibMixin.error_response, but that is designed
        to operated on OAuth1Error from oauthlib wrapped in a OAuthToolkitError
        r\   r>   noner+   login_requiredrB   ?&Nr[   )r#   ri   rG   r   r.   r!   handle_no_permission)r"   r\   r>   response_parametersrB   	separatorr4   r&   r(   r)   r      s   

z&AuthorizationView.handle_no_permission)r6   r7   r8   r9   template_namer   
form_classskip_authorization_completelyrJ   rZ   rG   rj   r   r:   r(   r(   r&   r)   r;   I   s     Rr;   c                   @   s$   e Zd ZdZeeddd ZdS )	TokenViewz
    Implements an endpoint to provide access tokens

    The endpoint is used in the following flows:
    * Authorization code
    * Password
    * Client credentials
    passwordc                 O   s   |  |\}}}}|dkr3t|d}|d ur3t|d }	t j	j|	d}
t
j| ||
d t||d}| D ]\}}|||< q=|S )N   access_tokenzutf-8)token_checksum)senderr#   r{   contentr,   )create_token_responserl   loadsrG   hashlibsha256encode	hexdigestr   rP   r   sendr   items)r"   r#   r$   r%   r*   rX   rY   r,   r   r   r{   responsekvr(   r(   r)   post'  s   
zTokenView.postN)r6   r7   r8   r9   r
   r   r   r(   r(   r(   r)   r     s    
	r   c                   @   s   e Zd ZdZdd ZdS )RevokeTokenViewzC
    Implements an endpoint to revoke access or refresh tokens
    c                 O   s@   |  |\}}}}t|pd|d}| D ]\}	}
|
||	< q|S )N r   )create_revocation_responser   r   )r"   r#   r$   r%   r*   rX   rY   r,   r   r   r   r(   r(   r)   r   >  s
   
zRevokeTokenView.postN)r6   r7   r8   r9   r   r(   r(   r(   r)   r   7  s    r   )4r   rl   loggingurllib.parser   r   r   django.contrib.auth.mixinsr   django.contrib.auth.viewsr   django.httpr   django.shortcutsr   django.utilsr	   django.utils.decoratorsr
   django.views.decorators.csrfr   django.views.decorators.debugr   django.views.genericr   r   compatr   
exceptionsr   formsr   httpr   modelsr   r   r=   r   settingsr   signalsr   mixinsr   	getLoggerrS   r   RFC3339r;   r   r   r(   r(   r(   r)   <module>   sD    

& 
S


