import logging import zlib from . import urls from django.http import JsonResponse from django.urls import reverse from django.shortcuts import redirect from .models import BankAccount, BankTransaction, \ BankAccountDoesNotExist, BankTransactionDoesNotExist from .views import \ (DebitLimitException, SameAccountException, LoginFailed, RejectNoRightsException, UnhandledException) from .schemas import \ (JSONFieldException, URLParamValidationError, InvalidSession) from taler.util.amount import \ (CurrencyMismatch, BadFormatAmount, NumberTooBig, NegativeNumber) LOGGER = logging.getLogger() ## # Class decompressing requests. class DecompressionMiddleware: ## # Init constructor. # # @param self the object itself. # @param get_response a Django-provided callable that calls # whatever comes next in the chain: a further middleware # or the view itself (please refer to the official # documentation for more details). def __init__(self, get_response): self.get_response = get_response ## # This function is transparently invoked by Django when # a request traverses the chain made of middleware classes # and the view itself as the last element in the chain. # # Here happens the decompression. # # @param self this class. # @param request Django-specific request object (of the same # type that is handed to views). # @return Django-specific response object. def __call__(self, request): if "deflate" == request.META.get("HTTP_CONTENT_ENCODING"): request._body = zlib.decompress(request.body) return self.get_response(request) ## # Class holding data needed by the handling logic. class ExceptionMiddleware: ## # Init constructor. # # @param self the object itself. # @param get_response a Django-provided callable that calls # whatever comes next in the chain: a further middleware # or the view itself (please refer to the official # documentation for more details). def __init__(self, get_response): self.get_response = get_response # Map between endpoints and Web pages to render # after the exception gets managed. self.render = { reverse("profile", urlconf=urls): "profile", reverse("register", urlconf=urls): "index", reverse("public-accounts", urlconf=urls): "index", } ## # This function is transparently invoked by Django when # a request traverses the chain made of middleware classes # and the view itself as the last element in the chain. # # @param self this class. # @param request Django-specific request object (of the same # type that is handed to views). # @return Django-specific response object. def __call__(self, request): return self.get_response(request) ## # Main logic for processing the exception. It checks # if the exception captured can be managed, and does it # if so. Otherwise, it lets the native handler operate. # # @param self a @a ExceptionMiddleware object. # @param request Django-specific HTTP request. # @param exception the exception raised from the bank. def process_exception(self, request, exception): LOGGER.error(repr(exception)) if not hasattr(exception, "taler_error_code"): exception = UnhandledException() render_to = self.render.get(request.path) if not render_to: return JsonResponse({"ec": exception.taler_error_code, "error": exception.hint}, status=exception.http_status_code) request.session["profile_hint"] = True, False, exception.hint return redirect(render_to) # [1] https://git.taler.net/exchange.git/tree/src/include/taler_error_codes.h