[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [taler-bank] branch master updated (c9ad08e -> ca847cf)
From: |
gnunet |
Subject: |
[GNUnet-SVN] [taler-bank] branch master updated (c9ad08e -> ca847cf) |
Date: |
Sun, 30 Jun 2019 20:46:39 +0200 |
This is an automated email from the git hooks/post-receive script.
marcello pushed a change to branch master
in repository bank.
from c9ad08e ux
new e8a670d Implement headless registration
new ca847cf Define headless-withdrawal validator
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
talerbank/app/schemas.py | 8 ++++
talerbank/app/tests.py | 23 ++++++++++
talerbank/app/urls.py | 2 +
talerbank/app/views.py | 108 +++++++++++++++++++++++++++++++++++------------
4 files changed, 113 insertions(+), 28 deletions(-)
diff --git a/talerbank/app/schemas.py b/talerbank/app/schemas.py
index 37094b4..db2ce7b 100644
--- a/talerbank/app/schemas.py
+++ b/talerbank/app/schemas.py
@@ -186,6 +186,14 @@ class PaytoField(forms.Field):
if "payto" != wire_uri.scheme:
raise ValidationError("URL is not 'payto'")
+class WithdrawHeadless(forms.Form):
+ auth = AuthField()
+ amount = forms.CharField(validators=[
+ RegexValidator(AMOUNT_REGEX,
+ message="Format CURRENCY:X[.Y] not respected")])
+ reserve_pub = forms.CharField()
+ exchange_wire_details = PaytoField(required=False)
+
class PinTanParams(forms.Form):
amount_currency = forms.CharField(
validators=[RegexValidator(
diff --git a/talerbank/app/tests.py b/talerbank/app/tests.py
index 3a8dc26..9a14498 100644
--- a/talerbank/app/tests.py
+++ b/talerbank/app/tests.py
@@ -181,6 +181,29 @@ class RegisterTestCase(TestCase):
# this assertion tests "/profile""s view
self.assertEqual(200, response.status_code)
+ def test_register_headless(self):
+ client = Client()
+
+ response = client.post(reverse("register-headless", urlconf=urls),
+ {"username": "test_register_headless",
+ "password": "password*+#@"})
+ self.assertEqual(200, response.status_code)
+
+ # Double-check account creation.
+ self.assertTrue(self.client.login(username="test_register_headless",
+ password="password*+#@"))
+
+ response = client.post(reverse("register-headless", urlconf=urls),
+ {"username": "test_register_headless",
+ "password": "password"})
+ self.assertEqual(409, response.status_code)
+
+ # NOTE: Django 2.2.2 allows ANY character!
+ response = client.post(reverse("register-headless", urlconf=urls),
+ {"username": "'''+++;;;'''",
+ "password": "password2"})
+ self.assertEqual(200, response.status_code)
+
class LoginTestCase(TestCase):
"""User login"""
diff --git a/talerbank/app/urls.py b/talerbank/app/urls.py
index d18f971..8a2d1e5 100644
--- a/talerbank/app/urls.py
+++ b/talerbank/app/urls.py
@@ -36,11 +36,13 @@ urlpatterns = [
name="login"),
url(r'^logout/$', views.logout_view, name="logout"),
url(r'^accounts/register/$', views.register, name="register"),
+ url(r'^register$', views.register_headless, name="register-headless"),
url(r'^profile$', views.profile_page, name="profile"),
url(r'^history$', views.serve_history, name="history"),
url(r'^history-range$', views.serve_history_range, name="history-range"),
url(r'^reject$', views.reject, name="reject"),
url(r'^withdraw$', views.withdraw_nojs, name="withdraw-nojs"),
+ url(r'^taler/withdraw$', views.withdraw_nojs, name="withdraw-headless"),
url(r'^public-accounts$', views.serve_public_accounts,
name="public-accounts"),
url(r'^public-accounts/(?P<name>[a-zA-Z0-9]+)$',
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index 550f658..e868a4b 100644
--- a/talerbank/app/views.py
+++ b/talerbank/app/views.py
@@ -67,6 +67,13 @@ class LoginFailed(Exception):
hint = "Wrong username/password"
http_status_code = 401
+class InvalidInputData(Exception):
+ def __init__(self, msg):
+ super(msg)
+
+class UsernameUnavailable(Exception):
+ pass
+
##
# Exception raised when the public history from
# a ordinary user account is tried to be accessed.
@@ -402,8 +409,6 @@ def pin_tan_verify(request):
request.session["just_withdrawn"] = True
return redirect("profile")
-
-
##
# Class representing the registration form.
class UserReg(forms.Form):
@@ -411,6 +416,54 @@ class UserReg(forms.Form):
password = forms.CharField(widget=forms.PasswordInput())
+def internal_register(request):
+ input_data = UserReg(request.POST)
+
+ if not input_data.is_valid():
+ msg = "Wrong field(s): %s." % \
+ ", ".join(input_data.errors.keys())
+ raise InvalidInputData(msg)
+
+ username = input_data.cleaned_data["username"]
+ password = input_data.cleaned_data["password"]
+
+ if User.objects.filter(username=username).exists():
+ raise UsernameUnavailable()
+
+ # Registration goes through.
+ with transaction.atomic():
+ user = User.objects.create_user(
+ username=username,
+ password=password)
+ user_account = BankAccount(user=user)
+ user_account.save()
+ bank_internal_account = BankAccount.objects.get(account_no=1)
+ wire_transfer(Amount(settings.TALER_CURRENCY, 100, 0),
+ bank_internal_account,
+ user_account,
+ "Joining bonus")
+ return user
+
+
+##
+# This method serves the request for programmatically
+# registering a user.
+#
+# @param request Django-specific HTTP request object.
+# @return Django-specific HTTP response object.
+@require_POST
+def register_headless(request):
+
+ try:
+ user = internal_register(request)
+
+ except UsernameUnavailable:
+ return HttpResponse(status=409) # Conflict
+
+ except InvalidInputData:
+ return HttpResponse(status=406) # Not Acceptable
+
+ return HttpResponse(status=200)
##
# This method serves the request for registering a user.
@@ -423,38 +476,25 @@ class UserReg(forms.Form):
def register(request):
if request.method != "POST":
return render(request, "register.html")
- form = UserReg(request.POST)
- if not form.is_valid():
+
+ # Process POST.
+
+ try:
+ user = internal_register(request)
+
+ except UsernameUnavailable as e:
return render(request, "register.html",
- {"fail_message": True,
- "success_message": False,
- "hint": "Wrong field(s): %s." % ",
".join(form.errors.keys())})
- username = form.cleaned_data["username"]
- password = form.cleaned_data["password"]
- if User.objects.filter(username=username).exists():
+ {"not_available": True})
+
+ except InvalidInputData as e:
return render(request, "register.html",
- {"fail_message": True,
- "success_message": False,
- "hint": "Username not available."})
- with transaction.atomic():
- user = User.objects.create_user(
- username=username,
- password=password)
- user_account = BankAccount(user=user)
- user_account.save()
- bank_internal_account = BankAccount.objects.get(account_no=1)
- wire_transfer(Amount(settings.TALER_CURRENCY, 100, 0),
- bank_internal_account,
- user_account,
- "Joining bonus")
+ {"wrong": True,
+ "hint": "Wrong field(s): %s." % ",
".join(form.errors.keys())})
+
request.session["profile_hint"] = False, True, "Registration successful!"
- user = django.contrib.auth.authenticate(
- username=username, password=password)
django.contrib.auth.login(request, user)
return redirect("profile")
-
-
##
# Logs the user out, redirecting it to the bank's homepage.
#
@@ -876,6 +916,18 @@ def add_incoming(request, user_account):
"timestamp": "/Date(%s)/" % int(wtrans.date.timestamp())})
##
+# Serves a headless withdrawal request for the Taler protocol.
+#
+# @param request Django-specific HTTP request.
+# @return Django-specific HTTP response object.
+@login_via_headers
+@csrf_exempt
+@require_POST
+def withdraw_headless(request):
+ pass
+
+
+##
# Serve a Taler withdrawal request; takes the amount chosen
# by the user, and builds a response to trigger the wallet into
# the withdrawal protocol
--
To stop receiving notification emails like this one, please contact
address@hidden.
- [GNUnet-SVN] [taler-bank] branch master updated (c9ad08e -> ca847cf),
gnunet <=