add a page for users to input their sms registration code (#69223)

This commit is contained in:
Paul Marillonnet 2022-10-13 13:27:51 +02:00
parent e35275fe45
commit 26f9d2098d
4 changed files with 85 additions and 1 deletions

View File

@ -20,11 +20,12 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.models import BaseUserManager, Group
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.forms import Form
from django.utils.translation import gettext
from django.utils.translation import gettext_lazy as _
from authentic2.a2_rbac.models import OrganizationalUnit
from authentic2.forms.fields import CheckPasswordField, NewPasswordField
from authentic2.forms.fields import CharField, CheckPasswordField, NewPasswordField
from authentic2.passwords import get_min_password_strength
from .. import app_settings, models
@ -191,3 +192,7 @@ class RegistrationCompletionForm(RegistrationCompletionFormNoPassword):
raise ValidationError(_("The two password fields didn't match."))
self.instance.set_password(self.cleaned_data['password1'])
return self.cleaned_data
class InputRegistrationCodeForm(Form):
registration_code = CharField()

View File

@ -0,0 +1,18 @@
{% extends "authentic2/base-page.html" %}
{% load i18n gadjo %}
{% block page-title %}
{{ view.title }}
{% endblock %}
{% block content %}
<form method="post" action=".">
<p>{% blocktrans trimmed %}Input your account activation code.{% endblocktrans %}</p>
{% csrf_token %}
{{ form }}
<div class="buttons">
<button class="submit-button">{% trans 'Submit' %}</button>
<button class="cancel-button" name="cancel" formnovalidate>{% trans "Cancel" %}</button>
</div>
</form>
{% endblock %}

View File

@ -114,6 +114,11 @@ urlpatterns = [
TemplateView.as_view(template_name='registration/registration_closed.html'),
name='registration_disallowed',
),
re_path(
'^register/input_code/(?P<token>[A-Za-z0-9_ -]+)/$',
views.input_registration_code,
name='input_registration_code',
),
# Password reset
re_path(
r'^password/reset/confirm/(?P<token>[A-Za-z0-9_ -]+)/$',

View File

@ -1203,6 +1203,62 @@ class BaseRegistrationView(HomeURLMixin, FormView):
return context
class InputRegistrationCodeView(cbv.ValidateCSRFMixin, FormView):
template_name = 'registration/sms_input_registration_code.html'
form_class = registration_forms.InputRegistrationCodeForm
success_url = '/accounts/'
title = _('Account activation')
def dispatch(self, request, *args, **kwargs):
token = kwargs.get('token')
try:
self.code = models.SMSCode.objects.get(url_token=token)
except models.SMSCode.DoesNotExist:
return HttpResponseBadRequest(_('Invalid account activation request'))
if not self.code.sent:
return HttpResponseBadRequest(_('Invalid account activation code'))
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
if 'cancel' in request.POST:
self.code.delete()
return utils_misc.redirect(request, reverse('auth_homepage'))
return super().post(request, *args, **kwargs)
@atomic(savepoint=False)
def form_valid(self, form):
super().form_valid(form)
registration_code = form.cleaned_data.pop('registration_code')
if self.code.value != registration_code:
# TODO ratelimit on erroneous code inputs(?)
# (code expires after 120 seconds)
form.add_error('registration_code', _('Wrong registration code.'))
return self.form_invalid(form)
if self.code.expires < timezone.now():
form.add_error('registration_code', _('The code has expired.'))
return self.form_invalid(form)
Lock.lock_identifier(self.code.phone)
content = {
# TODO missing ou registration management
'authentication_method': 'phone',
'phone': self.code.phone,
}
# create token to process final account activation and user-defined attributes
token = models.Token.create(
kind='registration',
content=content,
duration=120,
)
return utils_misc.redirect(
# TODO next_url management throughout account creation process
self.request,
reverse('registration_activate', kwargs={'registration_token': token.uuid}),
)
input_registration_code = InputRegistrationCodeView.as_view()
class RegistrationView(cbv.ValidateCSRFMixin, BaseRegistrationView):
pass