summaryrefslogtreecommitdiff
path: root/talerbank/app
diff options
context:
space:
mode:
authorMarcello Stanisci <stanisci.m@gmail.com>2019-05-31 20:11:56 +0200
committerMarcello Stanisci <stanisci.m@gmail.com>2019-05-31 20:11:56 +0200
commitc43180054aa9440916cf417cd9b123beaedfd078 (patch)
tree5b46f23f9b9e9125c6504a4667a3686666d5297c /talerbank/app
parent47d6ec42a49e9a87681d386c4a1dfac5733d7f90 (diff)
downloadbank-c43180054aa9440916cf417cd9b123beaedfd078.tar.gz
bank-c43180054aa9440916cf417cd9b123beaedfd078.tar.bz2
bank-c43180054aa9440916cf417cd9b123beaedfd078.zip
5715.
Porting the withdraw-state checking logic, and removig all the old Validictory data/functions.
Diffstat (limited to 'talerbank/app')
-rw-r--r--talerbank/app/middleware.py13
-rw-r--r--talerbank/app/schemas.py196
-rw-r--r--talerbank/app/views.py16
3 files changed, 76 insertions, 149 deletions
diff --git a/talerbank/app/middleware.py b/talerbank/app/middleware.py
index dd1b3ac..d7c3775 100644
--- a/talerbank/app/middleware.py
+++ b/talerbank/app/middleware.py
@@ -6,9 +6,12 @@ from .models import BankAccount, BankTransaction
from .views import \
(DebitLimitException, SameAccountException,
LoginFailed, RejectNoRightsException)
+
from .schemas import \
- (URLParameterMissing, URLParameterMalformed,
- JSONFieldException, URLParamValidationError)
+ (JSONFieldException,
+ URLParamValidationError,
+ InvalidSession)
+
from .amount import \
(CurrencyMismatch, BadFormatAmount,
NumberTooBig, NegativeNumber)
@@ -70,8 +73,10 @@ class ExceptionMiddleware:
BankTransaction.DoesNotExist: 1,
SameAccountException: 2,
DebitLimitException: 3,
- URLParameterMissing: 8,
- URLParameterMalformed: 9,
+
+ ##
+ # FIXME: needs own error code.
+ InvalidSession: 0,
##
# This one unified class kills the distinction
diff --git a/talerbank/app/schemas.py b/talerbank/app/schemas.py
index a826549..37094b4 100644
--- a/talerbank/app/schemas.py
+++ b/talerbank/app/schemas.py
@@ -20,10 +20,6 @@
# @brief definitions of JSON schemas for validating data
import json
-from validictory import validate
-from validictory.validator import \
- (RequiredFieldValidationError,
- FieldValidationError)
from django.conf import settings
from django.core.exceptions import ValidationError
from django import forms
@@ -45,6 +41,38 @@ UINT64_MAX = (2**64) - 1
AMOUNT_REGEX = "^[A-Za-z0-9_-]+:([0-9]+)\.?([0-9]+)?$"
##
+# Exception class to be raised when a expected URL parameter
+# is not found.
+class InvalidSession(ValueError):
+ ##
+ # Init method.
+ #
+ # @param self the object itself.
+ # @param http_status_code the HTTP response code to return
+ # to the caller (client).
+ def __init__(self, http_status_code):
+ self.hint = "Landed on a broken session"
+ self.http_status_code = http_status_code
+ super().__init__()
+
+##
+# Exception class to be raised when a JSON
+# object does not respect a specification.
+class JSONFieldException(ValueError):
+
+ ##
+ # Init method.
+ #
+ # @param self the object itself.
+ # @param error object containing the hint.
+ # @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())
+ self.http_status_code = http_status_code
+ super().__init__()
+
+##
# Exception class to be raised when at least one expected URL
# parameter is either not found or malformed.
class URLParamValidationError(ValueError):
@@ -56,12 +84,11 @@ class URLParamValidationError(ValueError):
# @param http_status_code the HTTP response code to return
# to the caller (client).
def __init__(self, error, http_status_code):
- self.hint = ["%s: %s, " % (k, error[k]) for k in error]
+ self.hint = json.stringify(error.as_json())
self.http_status_code = http_status_code
super().__init__()
class AuthForm(forms.Form):
-
type = forms.CharField(
validators=[RegexValidator(
"^basic$",
@@ -170,144 +197,27 @@ class PinTanParams(forms.Form):
reserve_pub = forms.CharField()
exchange_wire_details = PaytoField()
-##
-# Exception class to be raised when a expected URL parameter
-# is not found.
-class URLParameterMissing(ValueError):
-
- ##
- # Init method.
- #
- # @param self the object itself.
- # @param param the missing URL parameter name.
- # @param http_status_code the HTTP response code to return
- # to the caller (client).
- def __init__(self, param, http_status_code):
- self.hint = "URL parameter '%s' is missing" % param
- self.http_status_code = http_status_code
- super().__init__()
-
-##
-# Exception class to be raised when a expected URL parameter
-# is malformed.
-class URLParameterMalformed(ValueError):
+class SenderWireDetails(forms.Form):
+ # FIXME: must be changed to 'payto' format.
+ type = forms.CharField()
+ bank_url = forms.URLField()
+ account_number = forms.IntegerField(min_value=1)
- ##
- # Init method.
- #
- # @param self the object itself.
- # @param param the malformed URL parameter name.
- # @param http_status_code the HTTP response code to return
- # to the caller (client).
- def __init__(self, param, http_status_code):
- self.hint = "URL parameter '%s' is malformed" % param
- self.http_status_code = http_status_code
- super().__init__()
-
-
-##
-# Exception class to be raised when a JSON
-# object does not respect a specification.
-class JSONFieldException(ValueError):
-
- ##
- # Init method.
- #
- # @param self the object itself.
- # @param error object containing the hint.
- # @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())
- self.http_status_code = http_status_code
- super().__init__()
-
-##
-# Pattern for amounts.
-AMOUNT_SCHEMA = {
- "type": "string",
- "pattern": "^[A-Za-z0-9_-]+:([0-9]+)\.?([0-9]+)?$"}
-
-##
-# Definition that withdraw request bodies have to match.
-WITHDRAW_SESSION_SCHEMA = {
- "type": "object",
- "properties": {
- "amount": {"type": AMOUNT_SCHEMA},
- "reserve_pub": {"type": "string"},
- "exchange_account_number": {"type": "integer"},
- "sender_wiredetails": {
- "type": "object",
- "properties": {
- "type": {"type": "string"},
- "bank_url": {"type": "string"},
- "account_number": {"type": "integer"}
- }
- }
- }
-}
-
-##
-# Definition for wire details.
-WIREDETAILS_SCHEMA = {
- "type": "object",
- "properties": {
- "test": {
- "type": "object",
- "properties": {
- "type": {"type": "string"},
- "account_number": {"type": "integer"},
- "bank_url": {"type": "string"},
- "name": {"type": "string", "required": False},
- }
- }
- }
-}
-
-##
-# Definition for authentication objects.
-AUTH_SCHEMA = {
- "type": "object",
- "properties": {
- "type": {"type": "string",
- "pattern": "^basic$"},
- "data": {"type": "object", "required": False}
- }
-}
-
-##
-# Check that the state corresponds to a withdrawal session.
-#
-# @param data the dict representing the server state. So not
-# strictly an 'input' sent by any client; we use this just
-# as a double-checking mechanism to see if the server is
-# well-behaved.
-def check_withdraw_session(data):
- validate(data, WITHDRAW_SESSION_SCHEMA)
+class SenderWireDetailsField(forms.Field):
+ def to_python(self, value):
+ return value
+ def validate(self, value):
+ swd = SenderWireDetails(value)
+ if not swd.is_valid():
+ raise ValidationError(
+ json.dumps(swd.errors.as_json()))
+class WithdrawSessionData(forms.Form):
+ amount = forms.CharField(validators=[RegexValidator(
+ AMOUNT_REGEX,
+ message="Could not find valid amount in state..")])
+ reserve_pub = forms.CharField()
+ exchange_account_number = forms.IntegerField(min_value=1)
+ sender_wiredetails = SenderWireDetailsField()
-##
-# Abstraction over the real validators. Do not return,
-# but rather raise exceptions if the data is invalid.
-#
-# @param request Django-specific HTTP request object.
-# @param data data to validate. May be a POST body or
-# a dict holding the param-value pairs from a GET
-# request.
-def validate_data(request, data):
- switch = {
- "/pin/verify": check_withdraw_session,
- }
- try:
- switch.get(request.path_info)(data)
- except RequiredFieldValidationError as exc:
- if request.method == "GET":
- raise URLParameterMissing(exc.fieldname, 400)
- raise JSONFieldException(
- "Field '%s' is missing" % exc.fieldname, 400)
- except FieldValidationError as exc:
- if request.method == "GET":
- raise URLParameterMalformed(exc.fieldname, 400)
- raise JSONFieldException(
- "Malformed '%s' field" % exc.fieldname, 400)
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index a5001e3..550f658 100644
--- a/talerbank/app/views.py
+++ b/talerbank/app/views.py
@@ -44,7 +44,12 @@ from django.shortcuts import render, redirect
from datetime import datetime
from .models import BankAccount, BankTransaction
from .amount import Amount
-from .schemas import validate_data, HistoryParams, HistoryRangeParams, URLParamValidationError, RejectData, AddIncomingData, JSONFieldException, PinTanParams
+from .schemas import \
+ (HistoryParams, HistoryRangeParams,
+ URLParamValidationError, RejectData,
+ AddIncomingData, JSONFieldException,
+ PinTanParams, InvalidSession,
+ WithdrawSessionData)
LOGGER = logging.getLogger(__name__)
@@ -378,7 +383,14 @@ def pin_tan_verify(request):
request.session["captcha_failed"] = True, False, "Wrong CAPTCHA answer."
return redirect(request.POST.get("question_url", "profile"))
# Check the session is a "pin tan" one
- validate_data(request, request.session)
+
+ if not WithdrawSessionData(request.session):
+ # The session is not valid: either because the client simply
+ # requested the page without passing through the prior step,
+ # or because the bank broke it in the meanwhile. Let's blame
+ # ourselves for now.
+ raise InvalidSession(503)
+
amount = Amount(**request.session["amount"])
exchange_bank_account = BankAccount.objects.get(
account_no=request.session["exchange_account_number"])