o
    RD©iº  ã                   @   sª   d dl Z d dlmZ d dlmZ d dlmZmZmZ ddl	m
Z
 ddlmZ e  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G dd„ deƒZdS )é    N)ÚImproperlyConfigured)ÚPermissionDenied)ÚSAFE_METHODSÚBasePermissionÚIsAuthenticatedé   )Úoauth2_settingsé   )ÚOAuth2AuthenticationÚoauth2_providerc                   @   ó    e Zd ZdZdd„ Zdd„ ZdS )ÚTokenHasScopeúW
    The request is authenticated as a user and the token used has the right scope
    c                 C   s„   |j }|sdS t|dƒr>|  ||¡}t d |¡¡ | |¡r!dS tjo0|o0| 	¡  o0| 
|¡ }|r<tjt|ƒdœ| _dS J dƒ‚)NFÚscopez'Required scopes to access resource: {0}T)ÚdetailÚrequired_scopeszpTokenHasScope requires the`oauth2_provider.rest_framework.OAuth2Authentication` authentication class to be used.)ÚauthÚhasattrÚ
get_scopesÚlogÚdebugÚformatÚis_validr   ÚERROR_RESPONSE_WITH_SCOPESÚ
is_expiredÚallow_scopesr   Údefault_detailÚlistÚmessage)ÚselfÚrequestÚviewÚtokenr   Úinclude_required_scope© r$   úk/var/www/Datamplify/venv/lib/python3.10/site-packages/oauth2_provider/contrib/rest_framework/permissions.pyÚhas_permission   s.   

ÿþ
üþÿzTokenHasScope.has_permissionc                 C   ó$   zt |dƒW S  ty   tdƒ‚w )Nr   zGTokenHasScope requires the view to define the required_scopes attribute©ÚgetattrÚAttributeErrorr   ©r   r    r!   r$   r$   r%   r   6   ó   ÿÿzTokenHasScope.get_scopesN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r&   r   r$   r$   r$   r%   r      s    #r   c                       ó    e Zd ZdZ‡ fdd„Z‡  ZS )ÚTokenHasReadWriteScoper   c                    sP   z	t ƒ  ||¡}W n ty   g }Y nw |j ¡ tv r tj}ntj}||g S )N©	Úsuperr   r   ÚmethodÚupperr   r   Ú
READ_SCOPEÚWRITE_SCOPE)r   r    r!   r   Úread_write_scope©Ú	__class__r$   r%   r   D   s   ÿ
z!TokenHasReadWriteScope.get_scopes©r-   r.   r/   r0   r   Ú__classcell__r$   r$   r:   r%   r2   ?   ó    r2   c                       r1   )ÚTokenHasResourceScoper   c                    s\   z	t ƒ  ||¡}W n ty   g }Y nw |j ¡ tv r tj‰ ntj‰ ‡ fdd„|D ƒ}|S )Nc                    s   g | ]}d   |ˆ ¡‘qS )z{}:{})r   )Ú.0r   ©Ú
scope_typer$   r%   Ú
<listcomp>c   s    z4TokenHasResourceScope.get_scopes.<locals>.<listcomp>r3   )r   r    r!   Úview_scopesr   r:   rA   r%   r   X   s   ÿz TokenHasResourceScope.get_scopesr<   r$   r$   r:   r%   r?   S   r>   r?   c                   @   s   e Zd ZdZdd„ ZdS )ÚIsAuthenticatedOrTokenHasScopeaÍ  
    The user is authenticated using some backend or the token has the right scope
    This only returns True if the user is authenticated, but not using a token
    or using a token, and the token has the correct scope.

    This is useful when combined with the DjangoModelPermissions to allow people browse
    the browsable api's if they log in using the a non token bassed middleware,
    and let them access the api's using a rest client with a token
    c                 C   s>   t ƒ  ||¡}d}|rt|jtƒ}tƒ }|r| p| ||¡S )NF)r   r&   Ú
isinstanceÚsuccessful_authenticatorr
   r   )r   r    r!   Úis_authenticatedÚoauth2authenticatedÚtoken_has_scoper$   r$   r%   r&   s   s   z-IsAuthenticatedOrTokenHasScope.has_permissionN)r-   r.   r/   r0   r&   r$   r$   r$   r%   rE   h   s    
rE   c                   @   r   )ÚTokenMatchesOASRequirementsaÍ  
    :attr:alternate_required_scopes: dict keyed by HTTP method name with value: iterable alternate scope lists

    This fulfills the [Open API Specification (OAS; formerly Swagger)](https://www.openapis.org/)
    list of alternative Security Requirements Objects for oauth2 or openIdConnect:
      When a list of Security Requirement Objects is defined on the Open API object or Operation Object,
      only one of Security Requirement Objects in the list needs to be satisfied to authorize the request.
    [1](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securityRequirementObject)

    For each method, a list of lists of allowed scopes is tried in order and the first to match succeeds.

    @example
    required_alternate_scopes = {
       'GET': [['read']],
       'POST': [['create1','scope2'], ['alt-scope3'], ['alt-scope4','alt-scope5']],
    }

    TODO: DRY: subclass TokenHasScope and iterate over values of required_scope?
    c                 C   sˆ   |j }|sdS t|dƒr@|  ||¡}|j ¡ }||v r6t d || ¡¡ || D ]
}| |¡r3 dS q)dS t 	d |¡¡ dS J dƒ‚)NFr   z4Required scopes alternatives to access resource: {0}Tz*no scope alternates defined for method {0}z~TokenMatchesOASRequirements requires the`oauth2_provider.rest_framework.OAuth2Authentication` authentication class to be used.)
r   r   Úget_required_alternate_scopesr5   r6   r   r   r   r   Úwarning)r   r    r!   r"   Úrequired_alternate_scopesÚmÚaltr$   r$   r%   r&   ’   s,   

ÿÿ
ÿÿz*TokenMatchesOASRequirements.has_permissionc                 C   r'   )NrN   z_TokenMatchesOASRequirements requires the view to define the required_alternate_scopes attributer(   r+   r$   r$   r%   rL   °   r,   z9TokenMatchesOASRequirements.get_required_alternate_scopesN)r-   r.   r/   r0   r&   rL   r$   r$   r$   r%   rK   }   s    rK   )ÚloggingÚdjango.core.exceptionsr   Úrest_framework.exceptionsr   Úrest_framework.permissionsr   r   r   Úsettingsr   Úauthenticationr
   Ú	getLoggerr   r   r2   r?   rE   rK   r$   r$   r$   r%   Ú<module>   s    
1