diff --git a/src/authentic2/manager/app_settings.py b/src/authentic2/manager/app_settings.py
index 587c99c27..3a2f338f8 100644
--- a/src/authentic2/manager/app_settings.py
+++ b/src/authentic2/manager/app_settings.py
@@ -28,6 +28,7 @@ class AppSettings(object):
'USER_SEARCH_MINIMUM_CHARS': 0,
'LOGIN_URL': None,
'SITE_TITLE': None,
+ 'CHECK_DUPLICATE_USERS': False,
}
def __getattr__(self, name):
diff --git a/src/authentic2/manager/templates/authentic2/manager/duplicate_user_add.html b/src/authentic2/manager/templates/authentic2/manager/duplicate_user_add.html
new file mode 100644
index 000000000..54bd6b726
--- /dev/null
+++ b/src/authentic2/manager/templates/authentic2/manager/duplicate_user_add.html
@@ -0,0 +1,17 @@
+{% load i18n %}
+
+
+ {{ user.get_full_name }}
+ {% if user.email %}- {{ user.email }}{% endif %}
+ {% for attribute in user.attribute_values.all %}
+ {% if attribute.content and attribute.attribute.name != "first_name" and attribute.attribute.name != "last_name" %}
+ - {{ attribute.content }}
+ {% endif %}
+ {% endfor %}
+ - {% blocktrans with date=user.date_joined %}Created on {{ date }}{% endblocktrans %}
+ {% if user.last_login %}
+ - {% blocktrans with date=user.last_login %}Last login on {{ date }}{% endblocktrans %}
+ {% else %}
+ - {% trans "Never logged in" %}
+ {% endif %}
+
diff --git a/src/authentic2/manager/templates/authentic2/manager/user_add.html b/src/authentic2/manager/templates/authentic2/manager/user_add.html
index 2e4f31927..df1be0306 100644
--- a/src/authentic2/manager/templates/authentic2/manager/user_add.html
+++ b/src/authentic2/manager/templates/authentic2/manager/user_add.html
@@ -5,6 +5,20 @@
{% trans "Add an user" %}
{% endblock %}
+{% block beforeform %}
+{% if duplicate_users %}
+
+
+
{% trans "This user may already exist, please check the list below before creating it :" %}
+
+ {% for user in duplicate_users %}
+ {% include "authentic2/manager/duplicate_user_add.html" with user=user %}
+ {% endfor %}
+
+
+{% endif %}
+{% endblock %}
+
{% block hidden_inputs %}
{{ block.super }}
{% if next %}{% endif %}
diff --git a/src/authentic2/manager/user_views.py b/src/authentic2/manager/user_views.py
index 8d82d84ab..78d9fb79c 100644
--- a/src/authentic2/manager/user_views.py
+++ b/src/authentic2/manager/user_views.py
@@ -148,6 +148,7 @@ class UserAddView(BaseAddView):
form_class = UserAddForm
permissions = ['custom_user.add_user']
template_name = 'authentic2/manager/user_add.html'
+ duplicate_users = None
def dispatch(self, request, *args, **kwargs):
qs = request.user.ous_with_perm('custom_user.add_user')
@@ -193,9 +194,24 @@ class UserAddView(BaseAddView):
field_name='cancel')
context['next'] = select_next_url(self.request, default=None, include_post=True)
context['ou'] = self.ou
+ context['duplicate_users'] = self.duplicate_users
return context
def form_valid(self, form):
+ if app_settings.CHECK_DUPLICATE_USERS:
+ first_name = form.cleaned_data['first_name']
+ last_name = form.cleaned_data['last_name']
+ duplicate_users = User.objects.find_duplicates(
+ first_name=first_name,
+ last_name=last_name,
+ birthdate=form.cleaned_data.get('birthdate'),
+ )
+ token = self.request.POST.get('confirm-creation-token')
+ valid_confirmation_token = bool(token == '%s %s' % (first_name, last_name))
+ if duplicate_users and not valid_confirmation_token:
+ self.duplicate_users = duplicate_users
+ return self.form_invalid(form)
+
response = super(UserAddView, self).form_valid(form)
hooks.call_hooks('event', name='manager-add-user', user=self.request.user,
instance=form.instance, form=form)
diff --git a/tests/test_user_manager.py b/tests/test_user_manager.py
index 327042aa0..34fbf8b94 100644
--- a/tests/test_user_manager.py
+++ b/tests/test_user_manager.py
@@ -18,6 +18,7 @@
from __future__ import unicode_literals
import csv
+import datetime
import re
import time
from urllib.parse import urlparse
@@ -987,3 +988,50 @@ def test_manager_user_roles_breadcrumb(app, superuser, simple_user):
assert [x.text for x in resp.html.find('span', {'id': 'breadcrumb'}).find_all('a')] == [
'Homepage', 'Administration', 'Users',
'super user', 'Roles']
+
+
+def test_manager_create_user_duplicates(admin, app, ou1, settings):
+ settings.A2_MANAGER_CHECK_DUPLICATE_USERS = True
+ Attribute.objects.create(
+ kind='birthdate', name='birthdate', label='birthdate', required=False, searchable=True
+ )
+
+ user = User.objects.create(
+ first_name='Alexander', last_name='Longname', email='alexandre.longname@entrouvert.com'
+ )
+ user.attributes.birthdate = datetime.date(1980, 1, 2)
+ user2 = User.objects.create(first_name='Alexandra', last_name='Longname')
+ user3 = User.objects.create(first_name='Alex', last_name='Shortname')
+
+ login(app, admin)
+ resp = app.get('/manage/users/%s/add/' % ou1.pk)
+
+ form = resp.form
+ form.set('first_name', 'Alexandre')
+ form.set('last_name', 'Longname')
+ form.set('email', 'alex@entrouvert.com')
+ form.set('password1', 'ABcd1234')
+ form.set('password2', 'ABcd1234')
+ resp = form.submit()
+
+ assert 'user may already exist' in resp.text
+ assert 'Alexander Longname' in resp.text
+ assert '- alexandre.longname@entrouvert.com' in resp.text
+ assert '- 1980-01-02' in resp.text
+ assert '/users/%s/' % user.pk in resp.text
+ assert 'Alexandra Longname' in resp.text
+ assert '/users/%s/' % user2.pk in resp.text
+
+ # This user was in fact duplicate. Agent reuses the form to fill details on another user
+ form = resp.form
+ form.set('first_name', 'Alexa')
+ form.set('last_name', 'Shortname')
+ form.set('email', 'ashortname@entrouvert.com')
+ resp = form.submit()
+
+ assert 'user may already exist' in resp.text
+ assert '/users/%s/' % user3.pk in resp.text
+
+ # Not a duplicate this time. Simply submitting again creates user
+ resp = resp.form.submit().follow()
+ assert User.objects.filter(first_name='Alexa').count() == 1