""" Django views for the gooyal-dynamic-scopes package. """ import json import functools from django.conf import settings from django.http import HttpResponse, HttpResponseForbidden from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods, require_POST from oauthlib.oauth2 import Server from oauth2_provider.oauth2_backends import OAuthLibCore from oauth2_provider.views import IntrospectTokenView from apps.gooyal_oauth2.validators import IntrospectOAuth2Validator from .models import Scope def protected_resource(scopes=None): """ Implementation of protected_resource decorator that saves the client on the request for the view function to use. Cribbed from django-oauth-toolkit. """ _scopes = scopes or [] def decorator(view_func): @functools.wraps(view_func) def _validate(request, *args, **kwargs): validator = IntrospectOAuth2Validator() core = OAuthLibCore(Server(validator)) valid, oauthlib_req = core.verify_request(request, scopes=_scopes) if valid: request.client = oauthlib_req.client request.resource_owner = oauthlib_req.user return view_func(request, *args, **kwargs) return HttpResponseForbidden() return _validate return decorator @require_http_methods(['GET', 'POST']) @csrf_exempt @protected_resource(scopes=['introspection']) def introspect_token(request): """ Version of the introspection view protected by a regular scope instead of read-write scopes. Also allows for the required scope to be changed using a setting. """ if request.method == 'GET': token = request.GET.get("token", None) else: token = request.POST.get("token", None) return IntrospectTokenView.get_token_response(token) # @require_POST # @csrf_exempt # @protected_resource(scopes=[settings.REGISTER_SCOPE_SCOPE]) # def register_scope(request): # """ # Implements an endpoint for registering a scope. # """ # #  Get the scope data from the request body # scope_data = json.loads(request.body) if request.body else {} # try: # try: # #  If a scope with the given name already exists, find it # scope = Scope.objects.get(name=scope_data['name']) # except Scope.DoesNotExist: # #  If no scope with the given name exists, create it # _ = Scope.objects.create( # application=request.client, # name=scope_data['name'], # description=scope_data['description'], # is_default=scope_data.get('is_default', False) # ) # #  Respond with a 201 Created # return HttpResponse(status=201) # except KeyError as exc: # #  A key missing in the data should be reported as a bad request # return HttpResponse( # status=400, # content="'{}' must be given in request data".format(exc.args[0]), # content_type='text/plain' # ) # #  If the scope does exist, check that the current application is the # #  owner of the scope before updating it # if scope.application and scope.application == request.client: # scope.description = scope_data['description'] # scope.is_default = scope_data.get('is_default', False) # scope.save() # return HttpResponse(status=200) # else: # return HttpResponse(status=403)