summaryrefslogtreecommitdiff
path: root/talerbank
diff options
context:
space:
mode:
authorMarcello Stanisci <stanisci.m@gmail.com>2019-06-29 12:08:51 +0200
committerMarcello Stanisci <stanisci.m@gmail.com>2019-06-29 12:08:51 +0200
commite8a670dc558df9fbe83e22a56fd2ee52b8936cae (patch)
treea4f789b0c9e2e1c49e0aab99124eee5a32297ea9 /talerbank
parentc9ad08eeb82edaff2ec9bfa01618552ab892183e (diff)
downloadbank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.tar.gz
bank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.tar.bz2
bank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.zip
Implement headless registration
Diffstat (limited to 'talerbank')
-rw-r--r--talerbank/app/tests.py23
-rw-r--r--talerbank/app/urls.py1
-rw-r--r--talerbank/app/views.py98
3 files changed, 94 insertions, 28 deletions
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..4c52782 100644
--- a/talerbank/app/urls.py
+++ b/talerbank/app/urls.py
@@ -36,6 +36,7 @@ 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"),
diff --git a/talerbank/app/views.py b/talerbank/app/views.py
index 550f658..4cc509c 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,56 @@ 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 registering a user.
+ # If successful, it redirects the user to their profile page;
+ # otherwise it will show again the same form (currently, without
+ # displaying _any_ error/warning message.)
+ #
+ # @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 +478,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.
#