From 81bc320721b461578948e11d1a062d45d2758c77 Mon Sep 17 00:00:00 2001 From: Marcello Stanisci Date: Tue, 3 Dec 2019 19:21:33 +0100 Subject: making logs more verbose --- talerbank/app/middleware.py | 4 ++- talerbank/app/models.py | 22 +++++++------ talerbank/app/schemas.py | 13 +++++--- talerbank/app/views.py | 79 ++++++++++++++++++++++++--------------------- 4 files changed, 66 insertions(+), 52 deletions(-) diff --git a/talerbank/app/middleware.py b/talerbank/app/middleware.py index cff5006..af2a748 100644 --- a/talerbank/app/middleware.py +++ b/talerbank/app/middleware.py @@ -99,10 +99,12 @@ class ExceptionMiddleware: # @param request Django-specific HTTP request. # @param exception the exception raised from the bank. def process_exception(self, request, exception): - LOGGER.error(repr(exception)) + LOGGER.error(f"Error: {exception}, while serving {request.get_full_path()}") if not hasattr(exception, "taler_error_code"): + print("####### Exception without Taler Error Code ########") traceback.print_exc() + print("###################################################") exception = UnhandledException() render_to = self.render.get(request.path) diff --git a/talerbank/app/models.py b/talerbank/app/models.py index 692d6b8..f869ea3 100644 --- a/talerbank/app/models.py +++ b/talerbank/app/models.py @@ -119,22 +119,24 @@ class AmountField(models.Field): return Amount.parse(settings.TALER_CURRENCY) return Amount.parse(value) except BadFormatAmount: - raise ValidationError( - "Invalid input for an amount string: %s" % value) + raise ValidationError("Invalid input for an amount string: %s" % value) class BankAccountDoesNotExist(Exception): - def __init__(self): - self.hint = "Bank account not found" + def __init__(self, msg): + super(BankAccountDoesNotExist, self).__init__(msg) + self.hint = msg self.http_status_code = 404 self.taler_error_code = 5110 - self.minor_error_code = 0 class BankTransactionDoesNotExist(Exception): - def __init__(self): - self.hint = "Bank transaction not found" + def __init__(self, msg): + super(BankTransactionDoesNotExist, self).__init__(msg) + self.hint = msg self.http_status_code = 404 self.taler_error_code = 5111 - self.minor_error_code = 0 + +def join_dict(**inputDict): + return ", ".join(['%s==%s' % (key, value) for (key, value) in inputDict.items()]) class CustomManager(models.Manager): @@ -148,9 +150,9 @@ class CustomManager(models.Manager): try: return super(CustomManager, self).get(*args, **kwargs) except BankAccount.DoesNotExist: - raise BankAccountDoesNotExist() + raise BankAccountDoesNotExist(f"Bank account not found for {join_dict(**kwargs)}") except BankTransaction.DoesNotExist: - raise BankTransactionDoesNotExist() + raise BankTransactionDoesNotExist(f"Bank transaction not found for {join_dict(**kwargs)}") ## # The class representing a bank account. diff --git a/talerbank/app/schemas.py b/talerbank/app/schemas.py index 26bda90..2825241 100644 --- a/talerbank/app/schemas.py +++ b/talerbank/app/schemas.py @@ -69,15 +69,18 @@ class JSONFieldException(ValueError): # Init method. # # @param self the object itself. - # @param error object containing the hint. + # @param error object containing the hint, as created by + # the Form API. # @param http_status_code the HTTP response code to return # to the caller (client). def __init__(self, error, http_status_code): - self.hint = json.dumps(error.as_json()) + for k, errors in error.as_data().items(): + messages = [", ".join(error.messages) for error in errors] + line = f"{k}: " + "".join(messages) + super(JSONFieldException, self).__init__(line) + self.hint = line self.http_status_code = http_status_code self.taler_error_code = 5106 - super().__init__() - ## # Exception class to be raised when at least one expected URL @@ -124,6 +127,8 @@ class AuthField(forms.Field): raise ValidationError(json.dumps(af.errors.as_json())) +## +# Common logic to inherit from all the other validators class BankValidator(): def __init__(self, validator, data): self.validation_result = validator(data) diff --git a/talerbank/app/views.py b/talerbank/app/views.py index d340ce1..0466a8e 100644 --- a/talerbank/app/views.py +++ b/talerbank/app/views.py @@ -66,34 +66,45 @@ UINT64_MAX = (2**64) - 1 # Exception raised upon failing login. # class LoginFailed(Exception): - hint = "Wrong username/password" - http_status_code = 401 - taler_error_code = 5109 + def __init__(self, msg): + super(LoginFailed, self).__init__(msg) + self.hint = "Wrong password given" + self.http_status_code = 401 + self.taler_error_code = 5109 class InvalidInputData(Exception): def __init__(self, msg): - super().__init__(msg) - + super(InvalidInputData, self).__init__(msg) + self.hint = msg # should mention the picked username + self.http_status_code = 400 + self.taler_error_code = 5400 class UsernameUnavailable(Exception): - pass - + def __init__(self, msg): + super(UsernameUnavailable, self).__init__(msg) + self.hint = msg # should mention the picked username + self.http_status_code = 406 + self.taler_error_code = 5400 ## # Exception raised when the public history from # a ordinary user account is tried to be accessed. class PrivateAccountException(Exception): - hint = "The selected account is private" - http_status_code = 402 + def __init__(self, msg): + super(PrivateAccountException, self).__init__(msg) + self.hint = "Cannot show history from private persons accounts" + self.http_status_code = 402 ## # Exception raised when some financial operation goes # beyond the limit threshold. class DebitLimitException(Exception): - hint = "Insufficient credit, operation not acceptable." - http_status_code = 406 - taler_error_code = 5103 + def __init__(self, msg): + super(DebitLimitException, self).__init__(msg) + self.hint = "Payment aborted for insufficient credit" + self.http_status_code = 406 + self.taler_error_code = 5103 ## @@ -101,9 +112,11 @@ class DebitLimitException(Exception): # attempted and both parties are the same account number. # class SameAccountException(Exception): - hint = "Debit and credit account are the same." - http_status_code = 403 - taler_error_code = 5102 + def __init__(self, msg): + super(SameAccountException, self).__init__(msg) + self.hint = "Cannot send payment to oneself." + self.http_status_code = 403 + self.taler_error_code = 5102 ## @@ -111,18 +124,18 @@ class SameAccountException(Exception): # transaction, but they have no rights to accomplish # such operation. class RejectNoRightsException(Exception): - hint = "You weren't the transaction credit account, " \ - "no rights to reject." - http_status_code = 403 - taler_error_code = 5200 + def __init__(self, msg): + super(RejectNoRightsException, self).__init__(msg) + self.hint = "Only original payer can reject." + self.http_status_code = 403 + self.taler_error_code = 5200 class UnhandledException(Exception): - hint = "Unhandled exception happened!" - http_status_code = 500 - taler_error_code = 5300 - - - + def __init__(self, msg="Unhandled exception happened!"): + super(UnhandledException, self).__init__(msg) + self.hint = msg + self.http_status_code = 500 + self.taler_error_code = 5300 ## # The authentication for users to log in the bank. @@ -286,8 +299,7 @@ def profile_page(request): account_no=wtf.cleaned_data.get("receiver") ), wtf.cleaned_data.get("subject") ) - request.session["profile_hint" - ] = False, True, "Wire transfer successful!" + request.session["profile_hint"] = False, True, "Wire transfer successful!" return redirect("profile") wtf = WTForm() fail_message, success_message, hint = get_session_hint( @@ -379,7 +391,7 @@ def internal_register(request): password = input_data.cleaned_data["password"] if User.objects.filter(username=username).exists(): - raise UsernameUnavailable() + raise UsernameUnavailable(f"Username {username} is unavailable") # Registration goes through. with transaction.atomic(): @@ -592,7 +604,6 @@ def login_via_headers(view_func): def _decorator(request, *args, **kwargs): user_account = auth_and_login(request) if not user_account: - LOGGER.error("authentication failed") raise LoginFailed("authentication failed") return view_func(request, user_account, *args, **kwargs) @@ -801,7 +812,6 @@ def auth_and_login(request): username = request.META.get("HTTP_X_TALER_BANK_USERNAME") password = request.META.get("HTTP_X_TALER_BANK_PASSWORD") if not username or not password: - LOGGER.error("user or password not given") raise LoginFailed("missing user/password") return django.contrib.auth.authenticate( username=username, password=password @@ -1162,14 +1172,9 @@ def wire_transfer(amount, debit_account, credit_account, subject): and Amount.cmp(Amount(settings.TALER_CURRENCY), threshold) != 0 \ and debit_account.debit: - LOGGER.info( - "Negative balance '%s' not allowed.\ - " % json.dumps(debit_account.amount.dump()) + raise DebitLimitException( + f"Aborting payment initiated by '{debit_account.user.username}' for debit unallowed" ) - LOGGER.info("%s's threshold is: '%s'." \ - % (debit_account.user.username, - json.dumps(threshold.dump()))) - raise DebitLimitException() with transaction.atomic(): debit_account.save() -- cgit v1.2.3