views: enforce A2_EMAIL_IS_UNIQUE on email change (fixes #19712)
This commit is contained in:
parent
2ad841c017
commit
16afddc6b9
|
@ -1,4 +1,21 @@
|
|||
{% load i18n %}{% autoescape off %}{% blocktrans with name=user.get_short_name old_email=user.email %}Hi {{ name }} !
|
||||
{% load i18n %}{% autoescape off %}{% if email_is_not_unique%}{% blocktrans with name=user.get_short_name old_email=user.email %}Hi {{ name }} !
|
||||
|
||||
You asked for changing your email on {{ domain }} from:
|
||||
|
||||
{{ old_email }}
|
||||
|
||||
to:
|
||||
|
||||
{{ email }}
|
||||
|
||||
But this email is already linked to another account.
|
||||
|
||||
You can recover this account password using the password reset form:
|
||||
|
||||
{{ password_reset_url }}
|
||||
|
||||
--
|
||||
{{ domain }}{% endblocktrans %}{% else %}{% blocktrans with name=user.get_short_name old_email=user.email %}Hi {{ name }} !
|
||||
|
||||
You asked for changing your email on {{ domain }} from:
|
||||
|
||||
|
@ -15,5 +32,4 @@ To validate this change please click on the following link:
|
|||
This link will be valid for {{ token_lifetime }}.
|
||||
|
||||
--
|
||||
{{ domain }}
|
||||
{% endblocktrans %}{% endautoescape %}
|
||||
{{ domain }}{% endblocktrans %}{% endif %}{% endautoescape %}
|
||||
|
|
|
@ -178,7 +178,14 @@ class EmailChangeView(cbv.TemplateNamesMixin, FormView):
|
|||
'link': link,
|
||||
'domain': request.get_host(),
|
||||
'token_lifetime': utils.human_duration(app_settings.A2_EMAIL_CHANGE_TOKEN_LIFETIME),
|
||||
'password_reset_url': request.build_absolute_uri(reverse('password_reset')),
|
||||
}
|
||||
qs = compat.get_user_model().objects.all()
|
||||
if app_settings.A2_EMAIL_IS_UNIQUE:
|
||||
ctx['email_is_not_unique'] = qs.filter(email=email).exclude(pk=user.pk).exists()
|
||||
elif user.ou and user.ou.email_is_unique:
|
||||
ctx['email_is_not_unique'] = qs.filter(email=email,
|
||||
ou=user.ou).exclude(pk=user.pk).exists()
|
||||
|
||||
utils.send_templated_mail(
|
||||
email,
|
||||
|
@ -213,6 +220,14 @@ class EmailChangeVerifyView(TemplateView):
|
|||
user_pk = token['user_pk']
|
||||
email = token['email']
|
||||
user = User.objects.get(pk=user_pk)
|
||||
non_unique = False
|
||||
if app_settings.A2_EMAIL_IS_UNIQUE:
|
||||
non_unique = User.objects.filter(email=email).exclude(pk=user_pk).exists()
|
||||
elif user.ou and user.ou.email_is_unique:
|
||||
non_unique = User.objects.filter(email=email, ou=user.ou).exclude(
|
||||
pk=user_pk).exists()
|
||||
if non_unique:
|
||||
raise forms.ValidationError(_('This email is already used by another account.'))
|
||||
old_email = user.email
|
||||
user.email = email
|
||||
user.save()
|
||||
|
@ -234,6 +249,8 @@ class EmailChangeVerifyView(TemplateView):
|
|||
except User.DoesNotExist:
|
||||
messages.error(request, _('your request for changing your email is for '
|
||||
'an unknown user, try again'))
|
||||
except forms.ValidationError as e:
|
||||
messages.error(request, e.message)
|
||||
else:
|
||||
return shortcuts.redirect('account_management')
|
||||
return shortcuts.redirect('email-change')
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import re
|
||||
|
||||
import utils
|
||||
|
||||
|
||||
def change_email(app, user, email, mailoutbox):
|
||||
utils.login(app, user)
|
||||
l = len(mailoutbox)
|
||||
response = app.get('/accounts/change-email/')
|
||||
response.form.set('email', email)
|
||||
response.form.set('password', user.username)
|
||||
response = response.form.submit()
|
||||
assert len(mailoutbox) == l + 1
|
||||
return mailoutbox[-1]
|
||||
|
||||
|
||||
def test_change_email(app, simple_user, user_ou1, mailoutbox):
|
||||
email = change_email(app, simple_user, user_ou1.email, mailoutbox)
|
||||
links = re.findall('https?://[^ \n]*', email.body)
|
||||
assert links
|
||||
link = links[0]
|
||||
app.get(link)
|
||||
simple_user.refresh_from_db()
|
||||
# ok it worked
|
||||
assert simple_user.email == user_ou1.email
|
||||
|
||||
|
||||
def test_change_email_email_is_unique(app, settings, simple_user, user_ou1, mailoutbox):
|
||||
settings.A2_EMAIL_IS_UNIQUE = True
|
||||
email = change_email(app, simple_user, user_ou1.email, mailoutbox)
|
||||
links = re.findall('https?://[^ \n]*', email.body)
|
||||
assert links
|
||||
link = links[0]
|
||||
# email change is impossible as email is already taken
|
||||
assert 'password/reset' in link
|
||||
|
||||
|
||||
def test_change_email_ou_email_is_unique(app, simple_user, user_ou1, user_ou2, mailoutbox):
|
||||
user_ou1.ou.email_is_unique = True
|
||||
user_ou1.ou.save()
|
||||
user_ou2.email = 'john.doe-ou2@example.net'
|
||||
user_ou2.save()
|
||||
email = change_email(app, simple_user, user_ou2.email, mailoutbox)
|
||||
links = re.findall('https?://[^ \n]*', email.body)
|
||||
assert links
|
||||
link = links[0]
|
||||
app.get(link)
|
||||
simple_user.refresh_from_db()
|
||||
# ok it worked for a differnt ou
|
||||
assert simple_user.email == user_ou2.email
|
||||
# now set simple_user in same ou as user_ou1
|
||||
simple_user.ou = user_ou1.ou
|
||||
simple_user.save()
|
||||
email = change_email(app, simple_user, user_ou1.email, mailoutbox)
|
||||
links = re.findall('https?://[^ \n]*', email.body)
|
||||
assert links
|
||||
link = links[0]
|
||||
# email change is impossible as email is already taken in the same ou
|
||||
assert 'password/reset' in link
|
Loading…
Reference in New Issue