from django.http import JsonResponse from django.shortcuts import render from django.utils.translation import gettext as _ from social_core import exceptions as social_exceptions from ..admin.views.errorpages import admin_csrf_failure, admin_error_page from ..socialauth.providers import providers from .exceptions import SocialAuthBanned, SocialAuthFailed from .utils import get_exception_message, is_request_to_misago def _is_ajax(request): # Request is AJAX when done with XMLHttpRequest if request.headers.get("x-requested-with") == "XMLHttpRequest": return True # Assume that request is AJAX when it has JSON payload return "application/json" in request.headers.get("content-type", "") def _ajax_error(code, exception=None, default_message=None): return JsonResponse( {"detail": get_exception_message(exception, default_message)}, status=code ) @admin_error_page def _error_page(request, code, exception=None, default_message=None): request.frontend_context.update({"CURRENT_LINK": "misago:error-%s" % code}) return render( request, "misago/errorpages/%s.html" % code, {"message": get_exception_message(exception, default_message)}, status=code, ) def banned(request, exception): ban = exception.ban request.frontend_context.update( {"MESSAGE": ban.get_serialized_message(), "CURRENT_LINK": "misago:error-banned"} ) return render(request, "misago/errorpages/banned.html", {"ban": ban}, status=403) def permission_denied(request, exception): if _is_ajax(request): return _ajax_error(403, exception, _("Permission denied.")) return _error_page(request, 403, exception) def page_not_found(request, exception): if _is_ajax(request): return _ajax_error(404, exception, "Not found.") return _error_page(request, 404, exception) def social_auth_failed(request, exception): backend_name = None ban = None help_text = None message = None try: backend_name = exception.backend_name except AttributeError: pass try: exception_backend = exception.backend backend_name = providers.get_name(exception_backend.name) except AttributeError: pass if isinstance(exception, social_exceptions.NotAllowedToDisconnect): message = _( "A problem was encountered when disconnecting your account " "from the remote site." ) help_text = _( "You are not allowed to disconnect your account from the other site, " "because currently it's the only way to sign in to your account." ) elif backend_name: message = _( "A problem was encountered when signing you in using %(backend)s." ) % {"backend": backend_name} if isinstance(exception, social_exceptions.AuthCanceled): help_text = _("The sign in process has been canceled by user.") if isinstance(exception, social_exceptions.AuthUnreachableProvider): help_text = _("The other service could not be reached.") if isinstance(exception, SocialAuthFailed): help_text = exception.message if isinstance(exception, SocialAuthBanned): ban = exception.ban else: message = _("Unexpected problem has been encountered during sign in process.") return render( request, "misago/errorpages/social.html", { "backend_name": backend_name, "ban": ban, "message": message, "help_text": help_text, }, status=403, ) @admin_csrf_failure def csrf_failure(request, reason=""): if _is_ajax(request): return JsonResponse( { "detail": _( "Your request was rejected because your browser didn't " "send the CSRF cookie, or the cookie sent was invalid." ) }, status=403, ) return render(request, "misago/errorpages/csrf_failure.html", status=403) def not_allowed(request): return _error_page(request, 405) # Decorators for custom error page handlers def shared_403_exception_handler(f): def page_decorator(request, *args, **kwargs): if is_request_to_misago(request): return permission_denied(request, *args, **kwargs) return f(request, *args, **kwargs) return page_decorator def shared_404_exception_handler(f): def page_decorator(request, *args, **kwargs): if is_request_to_misago(request): return page_not_found(request, *args, **kwargs) return f(request, *args, **kwargs) return page_decorator