middleware.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. from urllib import parse
  2. from django.conf import settings
  3. from django.db import ProgrammingError
  4. from django.http import Http404, HttpResponseRedirect
  5. from django.urls import reverse
  6. from .api import is_api_request
  7. from .views import server_error
  8. class LoginRequiredMiddleware(object):
  9. """
  10. If LOGIN_REQUIRED is True, redirect all non-authenticated users to the login page.
  11. """
  12. def __init__(self, get_response):
  13. self.get_response = get_response
  14. def __call__(self, request):
  15. if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
  16. # Redirect unauthenticated requests to the login page. API requests are exempt from redirection as the API
  17. # performs its own authentication. Also metrics can be read without login.
  18. api_path = reverse('api-root')
  19. if not request.path_info.startswith((api_path, '/metrics')) and request.path_info != settings.LOGIN_URL:
  20. return HttpResponseRedirect(
  21. '{}?next={}'.format(
  22. settings.LOGIN_URL,
  23. parse.quote(request.get_full_path_info())
  24. )
  25. )
  26. return self.get_response(request)
  27. class APIVersionMiddleware(object):
  28. """
  29. If the request is for an API endpoint, include the API version as a response header.
  30. """
  31. def __init__(self, get_response):
  32. self.get_response = get_response
  33. def __call__(self, request):
  34. response = self.get_response(request)
  35. if is_api_request(request):
  36. response['API-Version'] = settings.REST_FRAMEWORK_VERSION
  37. return response
  38. class ExceptionHandlingMiddleware(object):
  39. """
  40. Intercept certain exceptions which are likely indicative of installation issues and provide helpful instructions
  41. to the user.
  42. """
  43. def __init__(self, get_response):
  44. self.get_response = get_response
  45. def __call__(self, request):
  46. return self.get_response(request)
  47. def process_exception(self, request, exception):
  48. # Don't catch exceptions when in debug mode
  49. if settings.DEBUG:
  50. return
  51. # Ignore Http404s (defer to Django's built-in 404 handling)
  52. if isinstance(exception, Http404):
  53. return
  54. # Determine the type of exception. If it's a common issue, return a custom error page with instructions.
  55. custom_template = None
  56. if isinstance(exception, ProgrammingError):
  57. custom_template = 'exceptions/programming_error.html'
  58. elif isinstance(exception, ImportError):
  59. custom_template = 'exceptions/import_error.html'
  60. elif isinstance(exception, PermissionError):
  61. custom_template = 'exceptions/permission_error.html'
  62. # Return a custom error message, or fall back to Django's default 500 error handling
  63. if custom_template:
  64. return server_error(request, template_name=custom_template)