diff options
author | Marcello Stanisci <stanisci.m@gmail.com> | 2019-06-29 12:08:51 +0200 |
---|---|---|
committer | Marcello Stanisci <stanisci.m@gmail.com> | 2019-06-29 12:08:51 +0200 |
commit | e8a670dc558df9fbe83e22a56fd2ee52b8936cae (patch) | |
tree | a4f789b0c9e2e1c49e0aab99124eee5a32297ea9 /talerbank | |
parent | c9ad08eeb82edaff2ec9bfa01618552ab892183e (diff) | |
download | bank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.tar.gz bank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.tar.bz2 bank-e8a670dc558df9fbe83e22a56fd2ee52b8936cae.zip |
Implement headless registration
Diffstat (limited to 'talerbank')
-rw-r--r-- | talerbank/app/tests.py | 23 | ||||
-rw-r--r-- | talerbank/app/urls.py | 1 | ||||
-rw-r--r-- | talerbank/app/views.py | 98 |
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. # |