summaryrefslogtreecommitdiff
path: root/talerbank/app/middleware.py
blob: 08c85aa7877ec488d1538158fb4c319f73d9fafe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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