summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcello Stanisci <stanisci.m@gmail.com>2019-05-31 19:36:23 +0200
committerMarcello Stanisci <stanisci.m@gmail.com>2019-05-31 19:36:23 +0200
commit47d6ec42a49e9a87681d386c4a1dfac5733d7f90 (patch)
tree91ad80b5b26757273ce5204a882c6b108aeede0b
parent79734f4aa3760aab92ff1326c701452738f40931 (diff)
downloadbank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.tar.gz
bank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.tar.bz2
bank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.zip
porting pin-question
-rw-r--r--talerbank/app/schemas.py85
-rw-r--r--talerbank/app/views.py35
2 files changed, 46 insertions, 74 deletions
diff --git a/talerbank/app/schemas.py b/talerbank/app/schemas.py
index d44a03b..a826549 100644
--- a/talerbank/app/schemas.py
+++ b/talerbank/app/schemas.py
@@ -28,6 +28,7 @@ from django.conf import settings
from django.core.exceptions import ValidationError
from django import forms
from django.core.validators import RegexValidator
+from urllib.parse import urlparse
##
@@ -46,8 +47,7 @@ AMOUNT_REGEX = "^[A-Za-z0-9_-]+:([0-9]+)\.?([0-9]+)?$"
##
# Exception class to be raised when at least one expected URL
# parameter is either not found or malformed.
-class URLParamValidationError(ValidationError):
-
+class URLParamValidationError(ValueError):
##
# Init method.
#
@@ -131,7 +131,6 @@ class HistoryParamsBase(forms.Form):
# FIXME: adjust min/max values.
account_number = forms.IntegerField(required=False)
-
class HistoryParams(HistoryParamsBase):
def clean_start(self):
@@ -150,6 +149,27 @@ class HistoryRangeParams(HistoryParamsBase):
end = forms.IntegerField()
start = forms.IntegerField()
+class PaytoField(forms.Field):
+ # TODO: try removing this method.
+ def to_python(self, value):
+ return value
+
+ def validate(self, value):
+ wire_uri = urlparse(value)
+ if "payto" != wire_uri.scheme:
+ raise ValidationError("URL is not 'payto'")
+
+class PinTanParams(forms.Form):
+ amount_currency = forms.CharField(
+ validators=[RegexValidator(
+ "^[A-Z]+$",
+ message="Currency is all upper case")])
+ amount_value = forms.IntegerField(min_value=0)
+ amount_fraction = forms.IntegerField(min_value=0)
+ exchange = forms.URLField()
+ reserve_pub = forms.CharField()
+ exchange_wire_details = PaytoField()
+
##
# Exception class to be raised when a expected URL parameter
# is not found.
@@ -255,64 +275,6 @@ AUTH_SCHEMA = {
}
}
-
-##
-# Definition for PIN/TAN request URL parameters.
-PIN_TAN_ARGS = {
- "type": "object",
- "properties": {
- "amount_value": {"format": "str_to_int"},
- "amount_fraction": {"format": "str_to_int"},
- "amount_currency": {"type": "string"},
- "exchange": {"type": "string"},
- "reserve_pub": {"type": "string"},
- "exchange_wire_details": {"format": "string"}
- }
-}
-
-##
-# Check the custom types for a PIN/TAN request. Those
-# types the strings that must represent integers (like
-# those used for amount's values and fractions), and the
-# stringification of a wire details object. All of them
-# get passed along the GET request's arguments by the
-# wallet.
-#
-# @param validator unused.
-# @param fieldname current name of the field being processed.
-# @param value current name of the value being processed.
-# @param format_option holds the format definition for the
-# current field being processed.
-def validate_pintan_types(validator, fieldname, value, format_option):
- del validator # pacify PEP checkers
- try:
- if format_option == "str_to_int":
- int(value)
- if format_option == "wiredetails_string":
- data = json.loads(value)
- validate_wiredetails(data)
- except Exception:
- raise FieldValidationError(
- "Malformed '%s'" % fieldname, fieldname, value)
-
-##
-# Check the GET arguments given along a /pin/question request.
-#
-# @param data GET arguments in a dict.
-def validate_pin_tan(data):
- format_dict = {
- "str_to_int": validate_pintan_types,
- "wiredetails_string": validate_pintan_types}
- validate(data, PIN_TAN_ARGS, format_validators=format_dict)
-
-##
-# Check wire details
-# (regardless of which endpoint triggered the check)
-#
-# @param wiredetails object representing wire details.
-def validate_wiredetails(wiredetails):
- validate(wiredetails, WIREDETAILS_SCHEMA)
-
##
# Check that the state corresponds to a withdrawal session.
#
@@ -335,7 +297,6 @@ def check_withdraw_session(data):
def validate_data(request, data):
switch = {
"/pin/verify": check_withdraw_session,
- "/pin/question": validate_pin_tan
}
try:
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index 88e5742..a5001e3 100644
--- a/talerbank/app/views.py
+++ b/talerbank/app/views.py
@@ -44,7 +44,7 @@ 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
+from .schemas import validate_data, HistoryParams, HistoryRangeParams, URLParamValidationError, RejectData, AddIncomingData, JSONFieldException, PinTanParams
LOGGER = logging.getLogger(__name__)
@@ -327,23 +327,34 @@ def get_acct_from_payto(uri_str: str) -> int:
@require_GET
@login_required
def pin_tan_question(request):
- validate_data(request, request.GET.dict())
+
+ get_params = PinTanParams(request.GET.dict())
+ if not get_params.is_valid():
+ raise URLParamValidationError(get_params.errors, 400)
+
+
user_account = BankAccount.objects.get(user=request.user)
- wire_details = request.GET["exchange_wire_details"]
+ wire_details = get_params.cleaned_data["exchange_wire_details"]
- request.session["exchange_account_number"] = get_acct_from_payto(wire_details)
- amount = Amount(request.GET["amount_currency"],
- int(request.GET["amount_value"]),
- int(request.GET["amount_fraction"]))
+ request.session["exchange_account_number"] = \
+ get_acct_from_payto(wire_details)
+ amount = Amount(get_params.cleaned_data["amount_currency"],
+ get_params.cleaned_data["amount_value"],
+ get_params.cleaned_data["amount_fraction"])
request.session["amount"] = amount.dump()
- request.session["reserve_pub"] = request.GET["reserve_pub"]
- fail_message, success_message, hint = get_session_hint(request, "captcha_failed")
+ request.session["reserve_pub"] = \
+ get_params.cleaned_data["reserve_pub"]
+
+ fail_message, success_message, hint = get_session_hint(
+ request,
+ "captcha_failed")
+
question, hashed_answer = make_question()
context = dict(
question=question,
hashed_answer=hashed_answer,
amount=amount.stringify(settings.TALER_DIGITS),
- exchange=request.GET["exchange"],
+ exchange=get_params.cleaned_data["exchange"],
fail_message=fail_message,
success_message=success_message,
hint=hint)
@@ -885,11 +896,11 @@ def withdraw_nojs(request):
# Make a wire transfer between two accounts (internal to the bank)
#
# @param amount how much money the wire transfer is worth.
+# FIXME: a check about whether this value is zero is missing
# @param debit_account the account that gives money.
# @param credit_account the account that receives money.
# @return a @a BankTransaction object.
-def wire_transfer(amount, debit_account, credit_account,
- subject):
+def wire_transfer(amount, debit_account, credit_account, subject):
LOGGER.debug("%s => %s, %s, %s" %
(debit_account.account_no,
credit_account.account_no,