# Path: doac/exceptions/invalid_request.py
# class CredentialsNotProvided(InvalidRequest):
#     reason = "No credentials were provided to authenticate the request to view this page."
# 
# Path: doac/exceptions/insufficient_scope.py
# class ScopeNotEnough(InsufficientScope):
#     reason = "The access token does not have enough scope to access this page."
# 
# Path: doac/decorators.py
# def scope_required(*scopes):
#     """
#     Test for specific scopes that the access token has been authenticated for before
#     processing the request and eventual response.
# 
#     The scopes that are passed in determine how the decorator will respond to incoming
#     requests:
# 
#     - If no scopes are passed in the arguments, the decorator will test for any available
#       scopes and determine the response based on that.
# 
#     - If specific scopes are passed, the access token will be checked to make sure it has
#       all of the scopes that were requested.
# 
#     This decorator will change the response if the access toke does not have the scope:
# 
#     - If an invalid scope is requested (one that does not exist), all requests will be
#       denied, as no access tokens will be able to fulfill the scope request and the
#       request will be denied.
# 
#     - If the access token does not have one of the requested scopes, the request will be
#       denied and the user will be returned one of two responses:
# 
#       - A 400 response (Bad Request) will be returned if an unauthenticated user tries to
#         access the resource.
# 
#       - A 403 response (Forbidden) will be returned if an authenticated user ties to access
#         the resource but does not have the correct scope.
#     """
#     
#     def decorator(view_func):
#     
#         @wraps(view_func, assigned=available_attrs(view_func))
#         def _wrapped_view(request, *args, **kwargs):
#             from django.http import HttpResponseBadRequest, HttpResponseForbidden
#             from .exceptions.base import InvalidRequest, InsufficientScope
#             from .models import Scope
#             from .utils import request_error_header
#             
#             try:
#                 if not hasattr(request, "access_token"):
#                     raise CredentialsNotProvided()
#                 
#                 access_token = request.access_token
#                 
#                 for scope_name in scopes:
#                     try:
#                         scope = access_token.scope.for_short_name(scope_name)
#                     except Scope.DoesNotExist:
#                         raise ScopeNotEnough()
#             except InvalidRequest as e:
#                 response = HttpResponseBadRequest()
#                 response["WWW-Authenticate"] = request_error_header(e)
#             
#                 return response
#             except InsufficientScope as e:
#                 response = HttpResponseForbidden()
#                 response["WWW-Authenticate"] = request_error_header(e)
#                 
#                 return response
#             
#             return view_func(request, *args, **kwargs)
#             
#         return _wrapped_view
#     
#     if scopes and hasattr(scopes[0], "__call__"):
#         func = scopes[0]
#         scopes = scopes[1:]
#         return decorator(func)
#     
#     return decorator
# 
# Path: doac/utils.py
# def request_error_header(exception):
#     """
#     Generates the error header for a request using a Bearer token based on a given OAuth exception.
#     """
# 
#     from .conf import options
#     
#     header = "Bearer realm=\"%s\"" % (options.realm, )
#     
#     if hasattr(exception, "error"):
#         header = header + ", error=\"%s\"" % (exception.error, )
#     
#     if hasattr(exception, "reason"):
#         header = header + ", error_description=\"%s\"" % (exception.reason, )
#     
#     return header
# 
# Path: tests/tests/test_cases.py
# class DecoratorTestCase(OAuthTestCase):
# 
#     def setUp(self):
#         from django.http import HttpRequest
#         from doac.middleware import AuthenticationMiddleware
# 
#         super(DecoratorTestCase, self).setUp()
# 
#         self.client_secret = self.oauth_client.secret
# 
#         self.authorization_token = AuthorizationToken(user=self.user, client=self.oauth_client)
#         self.authorization_token.save()
# 
#         self.authorization_token.scope = [self.scope]
#         self.authorization_token.save()
# 
#         self.authorization_token.generate_refresh_token()
#         self.authorization_token.refresh_token.generate_access_token()
# 
#         self.access_token = self.authorization_token.refresh_token.access_tokens.all()[0]
# 
#         self.request = HttpRequest()
#         self.mw = AuthenticationMiddleware()


from django.core.urlresolvers import reverse
from django.http import HttpResponse
from doac.exceptions.invalid_request import CredentialsNotProvided
from doac.exceptions.insufficient_scope import ScopeNotEnough
from doac.decorators import scope_required
from doac.utils import request_error_header
from .test_cases import DecoratorTestCase

class TestDecoratorErrors(DecoratorTestCase):

    def test_no_args(self):
        @scope_required
        def no_args(request):
            return HttpResponse("success")
            
        response = no_args(self.request)
        
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response["WWW-Authenticate"], request_error_header(CredentialsNotProvided))
        
        request = self.request
        request.META["HTTP_AUTHORIZATION"] = "Bearer %s" % (self.access_token.token, )
        self.mw.process_request(request)
        
        response = no_args(request)
        
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, "success")

    def test_no_args_with_parens(self):
        @scope_required()
        def no_args(request):
            return HttpResponse("success")
            
        response = no_args(self.request)
        
        self.assertEqual(response.status_code, 400)

# Path: doac/exceptions/invalid_request.py
# class CredentialsNotProvided(InvalidRequest):
#     reason = "No credentials were provided to authenticate the request to view this page."
# 
# Path: doac/exceptions/insufficient_scope.py
# class ScopeNotEnough(InsufficientScope):
#     reason = "The access token does not have enough scope to access this page."
# 
# Path: doac/decorators.py
# def scope_required(*scopes):
#     """
#     Test for specific scopes that the access token has been authenticated for before
#     processing the request and eventual response.
# 
#     The scopes that are passed in determine how the decorator will respond to incoming
#     requests:
# 
#     - If no scopes are passed in the arguments, the decorator will test for any available
#       scopes and determine the response based on that.
# 
#     - If specific scopes are passed, the access token will be checked to make sure it has
#       all of the scopes that were requested.
# 
#     This decorator will change the response if the access toke does not have the scope:
# 
#     - If an invalid scope is requested (one that does not exist), all requests will be
#       denied, as no access tokens will be able to fulfill the scope request and the
#       request will be denied.
# 
#     - If the access token does not have one of the requested scopes, the request will be
#       denied and the user will be returned one of two responses:
# 
#       - A 400 response (Bad Request) will be returned if an unauthenticated user tries to
#         access the resource.
# 
#       - A 403 response (Forbidden) will be returned if an authenticated user ties to access
#         the resource but does not have the correct scope.
#     """
#     
#     def decorator(view_func):
#     
#         @wraps(view_func, assigned=available_attrs(view_func))
#         def _wrapped_view(request, *args, **kwargs):
#             from django.http import HttpResponseBadRequest, HttpResponseForbidden
#             from .exceptions.base import InvalidRequest, InsufficientScope
#             from .models import Scope
#             from .utils import request_error_header
#             
#             try:
#                 if not hasattr(request, "access_token"):
#                     raise CredentialsNotProvided()
#                 
#                 access_token = request.access_token
#                 
#                 for scope_name in scopes:
#                     try:
#                         scope = access_token.scope.for_short_name(scope_name)
#                     except Scope.DoesNotExist:
#                         raise ScopeNotEnough()
#             except InvalidRequest as e:
#                 response = HttpResponseBadRequest()
#                 response["WWW-Authenticate"] = request_error_header(e)
#             
#                 return response
#             except InsufficientScope as e:
#                 response = HttpResponseForbidden()
#                 response["WWW-Authenticate"] = request_error_header(e)
#                 
#                 return response
#             
#             return view_func(request, *args, **kwargs)
#             
#         return _wrapped_view
#     
#     if scopes and hasattr(scopes[0], "__call__"):
#         func = scopes[0]
#         scopes = scopes[1:]
#         return decorator(func)
#     
#     return decorator
# 
# Path: doac/utils.py
# def request_error_header(exception):
#     """
#     Generates the error header for a request using a Bearer token based on a given OAuth exception.
#     """
# 
#     from .conf import options
#     
#     header = "Bearer realm=\"%s\"" % (options.realm, )
#     
#     if hasattr(exception, "error"):
#         header = header + ", error=\"%s\"" % (exception.error, )
#     
#     if hasattr(exception, "reason"):
#         header = header + ", error_description=\"%s\"" % (exception.reason, )
#     
#     return header
# 
# Path: tests/tests/test_cases.py
# class DecoratorTestCase(OAuthTestCase):
# 
#     def setUp(self):
#         from django.http import HttpRequest
#         from doac.middleware import AuthenticationMiddleware
# 
#         super(DecoratorTestCase, self).setUp()
# 
#         self.client_secret = self.oauth_client.secret
# 
#         self.authorization_token = AuthorizationToken(user=self.user, client=self.oauth_client)
#         self.authorization_token.save()
# 
#         self.authorization_token.scope = [self.scope]
#         self.authorization_token.save()
# 
#         self.authorization_token.generate_refresh_token()
#         self.authorization_token.refresh_token.generate_access_token()
# 
#         self.access_token = self.authorization_token.refresh_token.access_tokens.all()[0]
# 
#         self.request = HttpRequest()
#         self.mw = AuthenticationMiddleware()


# Path: tests/tests/test_decorators.py
from django.core.urlresolvers import reverse
from django.http import HttpResponse
from doac.exceptions.invalid_request import CredentialsNotProvided
from doac.exceptions.insufficient_scope import ScopeNotEnough
from doac.decorators import scope_required
from doac.utils import request_error_header
from .test_cases import DecoratorTestCase


class TestDecoratorErrors(DecoratorTestCase):

    def test_no_args(self):
        @scope_required
        def no_args(request):
            return HttpResponse("success")
            
        response = no_args(self.request)
        
        self.assertEqual(response.status_code, 400)
        self.assertEqual(response["WWW-Authenticate"], request_error_header(CredentialsNotProvided))
        
        request = self.request
        request.META["HTTP_AUTHORIZATION"] = "Bearer %s" % (self.access_token.token, )
        self.mw.process_request(request)
        
        response = no_args(request)
        
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, "success")

    def test_no_args_with_parens(self):
        @scope_required()
        def no_args(request):
            return HttpResponse("success")
            
        response = no_args(self.request)
        
        self.assertEqual(response.status_code, 400)

        self.assertEqual(response["WWW-Authenticate"], request_error_header(CredentialsNotProvided))