diff --git a/passbook/flows/templates/flows/error.html b/passbook/flows/templates/flows/error.html new file mode 100644 index 000000000..9f549077c --- /dev/null +++ b/passbook/flows/templates/flows/error.html @@ -0,0 +1,22 @@ +{% load i18n %} + + + +
+

+ {% trans 'Whoops!' %} +

+
+
+

+ {% trans 'Something went wrong! Please try again later.' %} +

+ {% if debug %} +
{{ tb }}
+ {% endif %} +
diff --git a/passbook/flows/views.py b/passbook/flows/views.py index bbe010392..0e6d0fef5 100644 --- a/passbook/flows/views.py +++ b/passbook/flows/views.py @@ -1,4 +1,5 @@ """passbook multi-stage authentication engine""" +from traceback import format_tb from typing import Any, Dict, Optional from django.http import ( @@ -8,7 +9,7 @@ from django.http import ( HttpResponseRedirect, JsonResponse, ) -from django.shortcuts import get_object_or_404, redirect, reverse +from django.shortcuts import get_object_or_404, redirect, render, reverse from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views.decorators.clickjacking import xframe_options_sameorigin @@ -106,8 +107,18 @@ class FlowExecutorView(View): stage=self.current_stage, flow_slug=self.flow.slug, ) - stage_response = self.current_stage_view.get(request, *args, **kwargs) - return to_stage_response(request, stage_response) + try: + stage_response = self.current_stage_view.get(request, *args, **kwargs) + return to_stage_response(request, stage_response) + except Exception as exc: # pylint: disable=broad-except + return to_stage_response( + request, + render( + request, + "flows/error.html", + {"error": exc, "tb": "".join(format_tb(exc.__traceback__)),}, + ), + ) def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: """pass post request to current stage""" @@ -117,8 +128,18 @@ class FlowExecutorView(View): stage=self.current_stage, flow_slug=self.flow.slug, ) - stage_response = self.current_stage_view.post(request, *args, **kwargs) - return to_stage_response(request, stage_response) + try: + stage_response = self.current_stage_view.post(request, *args, **kwargs) + return to_stage_response(request, stage_response) + except Exception as exc: # pylint: disable=broad-except + return to_stage_response( + request, + render( + request, + "flows/error.html", + {"error": exc, "tb": "".join(format_tb(exc.__traceback__)),}, + ), + ) def _initiate_plan(self) -> FlowPlan: planner = FlowPlanner(self.flow)