diff options
author | Marcello Stanisci <stanisci.m@gmail.com> | 2019-05-31 19:36:23 +0200 |
---|---|---|
committer | Marcello Stanisci <stanisci.m@gmail.com> | 2019-05-31 19:36:23 +0200 |
commit | 47d6ec42a49e9a87681d386c4a1dfac5733d7f90 (patch) | |
tree | 91ad80b5b26757273ce5204a882c6b108aeede0b | |
parent | 79734f4aa3760aab92ff1326c701452738f40931 (diff) | |
download | bank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.tar.gz bank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.tar.bz2 bank-47d6ec42a49e9a87681d386c4a1dfac5733d7f90.zip |
porting pin-question
-rw-r--r-- | talerbank/app/schemas.py | 85 | ||||
-rw-r--r-- | talerbank/app/views.py | 35 |
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, |