0009-add-a-page-for-users-to-input-their-sms-registration.patch
src/authentic2/forms/registration.py | ||
---|---|---|
20 | 20 |
from django.contrib.auth.models import BaseUserManager, Group |
21 | 21 |
from django.core.exceptions import ValidationError |
22 | 22 |
from django.core.validators import RegexValidator |
23 |
from django.forms import Form |
|
23 | 24 |
from django.utils.translation import ugettext |
24 | 25 |
from django.utils.translation import ugettext_lazy as _ |
25 | 26 | |
26 | 27 |
from authentic2.a2_rbac.models import OrganizationalUnit |
27 |
from authentic2.forms.fields import CheckPasswordField, NewPasswordField |
|
28 |
from authentic2.forms.fields import CharField, CheckPasswordField, NewPasswordField
|
|
28 | 29 |
from authentic2.passwords import get_min_password_strength |
29 | 30 | |
30 | 31 |
from .. import app_settings, models |
... | ... | |
186 | 187 |
raise ValidationError(_("The two password fields didn't match.")) |
187 | 188 |
self.instance.set_password(self.cleaned_data['password1']) |
188 | 189 |
return self.cleaned_data |
190 | ||
191 | ||
192 |
class InputRegistrationCodeForm(Form): |
|
193 |
registration_code = CharField() |
src/authentic2/templates/registration/sms_input_registration_code.html | ||
---|---|---|
1 |
{% load i18n gadjo %} |
|
2 | ||
3 |
{% block page-title %} |
|
4 |
{{ view.title }} |
|
5 |
{% endblock %} |
|
6 | ||
7 |
{% block content %} |
|
8 |
<form method="post" action="."> |
|
9 |
<p>{% blocktrans trimmed %}Input your account activation code.{% endblocktrans %}</p> |
|
10 |
{% csrf_token %} |
|
11 |
{{ form }} |
|
12 |
<div class="buttons"> |
|
13 |
<button class="submit-button">{% trans 'Submit' %}</button> |
|
14 |
<button class="cancel-button" name="cancel" formnovalidate>{% trans "Cancel" %}</button> |
|
15 |
</div> |
|
16 |
</form> |
|
17 |
{% endblock %} |
src/authentic2/urls.py | ||
---|---|---|
114 | 114 |
TemplateView.as_view(template_name='registration/registration_closed.html'), |
115 | 115 |
name='registration_disallowed', |
116 | 116 |
), |
117 |
path( |
|
118 |
'register/input_code/(?P<token>[A-Za-z0-9_ -]+)/', |
|
119 |
views.input_registration_code, |
|
120 |
name='input_registration_code', |
|
121 |
), |
|
117 | 122 |
# Password reset |
118 | 123 |
re_path( |
119 | 124 |
r'^password/reset/confirm/(?P<token>[A-Za-z0-9_ -]+)/$', |
src/authentic2/views.py | ||
---|---|---|
1202 | 1202 |
return context |
1203 | 1203 | |
1204 | 1204 | |
1205 |
class InputRegistrationCodeView(cbv.ValidateCSRFMixin, FormView): |
|
1206 |
template_name = 'registration/sms_input_registration_code.html' |
|
1207 |
form_class = registration_forms.InputRegistrationCodeForm |
|
1208 |
success_url = '/accounts/' |
|
1209 |
title = _('Account activation') |
|
1210 | ||
1211 |
def dispatch(self, request, *args, **kwargs): |
|
1212 |
token = kwargs.get('token') |
|
1213 |
try: |
|
1214 |
self.code = models.SMSCode.objects.get(url_token=token) |
|
1215 |
except models.SMSCode.DoesNotExist: |
|
1216 |
return HttpResponseBadRequest(_('Invalid account activation request')) |
|
1217 |
if not self.code.sent: |
|
1218 |
return HttpResponseBadRequest(_('Invalid account activation code')) |
|
1219 |
return super().dispatch(request, *args, **kwargs) |
|
1220 | ||
1221 |
def post(self, request, *args, **kwargs): |
|
1222 |
if 'cancel' in request.POST: |
|
1223 |
self.code.delete() |
|
1224 |
return utils_misc.redirect(request, reverse('auth_homepage')) |
|
1225 |
return super().post(request, *args, **kwargs) |
|
1226 | ||
1227 |
def form_valid(self, form): |
|
1228 |
super().form_valid(form) |
|
1229 |
registration_code = form.cleaned_data.pop('registration_code') |
|
1230 |
if self.code.value != registration_code: |
|
1231 |
# TODO ratelimit on erroneous code inputs(?) |
|
1232 |
# (code expires after 120 seconds) |
|
1233 |
form.add_error('registration_code', _('Wrong registration code.')) |
|
1234 |
return self.form_invalid(form) |
|
1235 |
if self.code.expires < timezone.now(): |
|
1236 |
form.add_error('registration_code', _('The code has expired.')) |
|
1237 |
return self.form_invalid(form) |
|
1238 |
Lock.lock_identifier(self.code.phone) |
|
1239 |
content = { |
|
1240 |
# TODO missing ou registration management |
|
1241 |
'authentication_method': 'phone', |
|
1242 |
'phone': self.code.phone, |
|
1243 |
} |
|
1244 |
# create token to process final account activation and user-defined attributes |
|
1245 |
token = models.Token.create( |
|
1246 |
kind='registration', |
|
1247 |
content=content, |
|
1248 |
duration=120, |
|
1249 |
) |
|
1250 |
return utils_misc.redirect( |
|
1251 |
# TODO next_url management throughout account creation process |
|
1252 |
self.request, |
|
1253 |
reverse('registration_activate', kwargs={'registration_token': token.uuid}), |
|
1254 |
) |
|
1255 | ||
1256 | ||
1257 |
input_registration_code = InputRegistrationCodeView.as_view() |
|
1258 | ||
1259 | ||
1205 | 1260 |
class RegistrationView(cbv.ValidateCSRFMixin, BaseRegistrationView): |
1206 | 1261 |
pass |
1207 | 1262 | |
1208 |
- |