exceptionhandler.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. from rest_framework.views import exception_handler as rest_exception_handler
  2. from django.core.exceptions import PermissionDenied
  3. from django.http import Http404, HttpResponsePermanentRedirect, JsonResponse
  4. from django.urls import reverse
  5. from django.utils import six
  6. from . import errorpages
  7. from .exceptions import AjaxError, Banned, ExplicitFirstPage, OutdatedSlug
  8. HANDLED_EXCEPTIONS = (
  9. AjaxError, Banned, ExplicitFirstPage, Http404, OutdatedSlug, PermissionDenied
  10. )
  11. def is_misago_exception(exception):
  12. return exception.__class__ in HANDLED_EXCEPTIONS
  13. def handle_ajax_error(request, exception):
  14. json = {
  15. 'is_error': 1,
  16. 'message': six.text_type(exception.message),
  17. }
  18. return JsonResponse(json, status=exception.code)
  19. def handle_banned_exception(request, exception):
  20. return errorpages.banned(request, exception.ban)
  21. def handle_explicit_first_page_exception(request, exception):
  22. matched_url = request.resolver_match.url_name
  23. if request.resolver_match.namespace:
  24. matched_url = '%s:%s' % (request.resolver_match.namespace, matched_url)
  25. url_kwargs = request.resolver_match.kwargs
  26. del url_kwargs['page']
  27. new_url = reverse(matched_url, kwargs=url_kwargs)
  28. return HttpResponsePermanentRedirect(new_url)
  29. def handle_http404_exception(request, exception):
  30. return errorpages.page_not_found(request)
  31. def handle_outdated_slug_exception(request, exception):
  32. view_name = request.resolver_match.view_name
  33. model = exception.args[0]
  34. url_kwargs = request.resolver_match.kwargs
  35. url_kwargs['slug'] = model.slug
  36. new_url = reverse(view_name, kwargs=url_kwargs)
  37. return HttpResponsePermanentRedirect(new_url)
  38. def handle_permission_denied_exception(request, exception):
  39. try:
  40. error_message = exception.args[0]
  41. except IndexError:
  42. error_message = None
  43. return errorpages.permission_denied(request, error_message)
  44. EXCEPTION_HANDLERS = [
  45. (AjaxError, handle_ajax_error),
  46. (Banned, handle_banned_exception),
  47. (Http404, handle_http404_exception),
  48. (ExplicitFirstPage, handle_explicit_first_page_exception),
  49. (OutdatedSlug, handle_outdated_slug_exception),
  50. (PermissionDenied, handle_permission_denied_exception),
  51. ]
  52. def get_exception_handler(exception):
  53. for exception_type, handler in EXCEPTION_HANDLERS:
  54. if isinstance(exception, exception_type):
  55. return handler
  56. else:
  57. raise ValueError("%s is not Misago exception" % exception.__class__.__name__)
  58. def handle_misago_exception(request, exception):
  59. handler = get_exception_handler(exception)
  60. return handler(request, exception)
  61. def handle_api_exception(exception, context):
  62. response = rest_exception_handler(exception, context)
  63. if response:
  64. if isinstance(exception, Banned):
  65. response.data['ban'] = exception.ban.get_serialized_message()
  66. elif isinstance(exception, PermissionDenied):
  67. try:
  68. response.data['detail'] = exception.args[0]
  69. except IndexError:
  70. pass
  71. return response
  72. else:
  73. return None