summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--talerbank/app/middleware.py4
-rw-r--r--talerbank/app/models.py22
-rw-r--r--talerbank/app/schemas.py13
-rw-r--r--talerbank/app/views.py79
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()