Projet

Général

Profil

0001-manager-look-for-duplicates-on-user-creation-45419.patch

Valentin Deniaud, 13 octobre 2020 12:00

Télécharger (8,06 ko)

Voir les différences:

Subject: [PATCH] manager: look for duplicates on user creation (#45419)

 src/authentic2/custom_user/models.py          |  3 ++
 src/authentic2/manager/app_settings.py        |  1 +
 .../manager/duplicate_user_add.html           | 17 ++++++
 .../authentic2/manager/user_add.html          | 14 +++++
 src/authentic2/manager/user_views.py          | 16 ++++++
 tests/test_user_manager.py                    | 53 +++++++++++++++++++
 6 files changed, 104 insertions(+)
 create mode 100644 src/authentic2/manager/templates/authentic2/manager/duplicate_user_add.html
src/authentic2/custom_user/models.py
310 310
    def has_verified_attributes(self):
311 311
        return AttributeValue.objects.with_owner(self).filter(verified=True).exists()
312 312

  
313
    def searchable_attribute_values(self):
314
        return self.attribute_values.filter(attribute__searchable=True)
315

  
313 316
    def to_json(self):
314 317
        d = {}
315 318
        attributes_map = get_attributes_map()
src/authentic2/manager/app_settings.py
28 28
        'USER_SEARCH_MINIMUM_CHARS': 0,
29 29
        'LOGIN_URL': None,
30 30
        'SITE_TITLE': None,
31
        'CHECK_DUPLICATE_USERS': False,
31 32
    }
32 33

  
33 34
    def __getattr__(self, name):
src/authentic2/manager/templates/authentic2/manager/duplicate_user_add.html
1
{% load i18n %}
2

  
3
<li>
4
  <a href="{% url 'a2-manager-user-detail' pk=user.pk %}">{{ user.get_full_name }}</a>
5
  {% if user.email %}- {{ user.email }}{% endif %}
6
  {% for attribute in user.searchable_attribute_values %}
7
  {% if attribute.content and attribute.attribute.name != "first_name" and attribute.attribute.name != "last_name" %}
8
  - {{ attribute.content }}
9
  {% endif %}
10
  {% endfor %}
11
  - {% blocktrans with date=user.date_joined %}Created on {{ date }}{% endblocktrans %}
12
  {% if user.last_login %}
13
  - {% blocktrans with date=user.last_login %}Last login on {{ date }}{% endblocktrans %}
14
  {% else %}
15
  - {% trans "Never logged in" %}
16
  {% endif %}
17
</li>
src/authentic2/manager/templates/authentic2/manager/user_add.html
5 5
  {% trans "Add an user" %}
6 6
{% endblock %}
7 7

  
8
{% block beforeform %}
9
{% if duplicate_users %}
10
<input type="hidden" name="confirm-creation-token" value="{{ form.cleaned_data.first_name }} {{ form.cleaned_data.last_name }}">
11
<div class=warningnotice>
12
  <p>{% trans "This user may already exist, please check the list below before creating it :" %}</p>
13
  <ul class="user-duplicates">
14
    {% for user in duplicate_users %}
15
    {% include "authentic2/manager/duplicate_user_add.html" with user=user %}
16
    {% endfor %}
17
  </ul>
18
</div>
19
{% endif %}
20
{% endblock %}
21

  
8 22
{% block hidden_inputs %}
9 23
  {{ block.super }}
10 24
  {% if next %}<input type="hidden" name="next" value="{{ next }}">{% endif %}
src/authentic2/manager/user_views.py
148 148
    form_class = UserAddForm
149 149
    permissions = ['custom_user.add_user']
150 150
    template_name = 'authentic2/manager/user_add.html'
151
    duplicate_users = None
151 152

  
152 153
    def dispatch(self, request, *args, **kwargs):
153 154
        qs = request.user.ous_with_perm('custom_user.add_user')
......
193 194
            field_name='cancel')
194 195
        context['next'] = select_next_url(self.request, default=None, include_post=True)
195 196
        context['ou'] = self.ou
197
        context['duplicate_users'] = self.duplicate_users
196 198
        return context
197 199

  
198 200
    def form_valid(self, form):
201
        if app_settings.CHECK_DUPLICATE_USERS:
202
            first_name = form.cleaned_data['first_name']
203
            last_name = form.cleaned_data['last_name']
204
            duplicate_users = User.objects.find_duplicates(
205
                first_name=first_name,
206
                last_name=last_name,
207
                birthdate=form.cleaned_data.get('birthdate'),
208
            )
209
            token = self.request.POST.get('confirm-creation-token')
210
            valid_confirmation_token = bool(token == '%s %s' % (first_name, last_name))
211
            if duplicate_users and not valid_confirmation_token:
212
                self.duplicate_users = duplicate_users
213
                return self.form_invalid(form)
214

  
199 215
        response = super(UserAddView, self).form_valid(form)
200 216
        hooks.call_hooks('event', name='manager-add-user', user=self.request.user,
201 217
                         instance=form.instance, form=form)
tests/test_user_manager.py
18 18
from __future__ import unicode_literals
19 19

  
20 20
import csv
21
import datetime
21 22
import re
22 23
import time
23 24
from urllib.parse import urlparse
......
987 988
    assert [x.text for x in resp.html.find('span', {'id': 'breadcrumb'}).find_all('a')] == [
988 989
        'Homepage', 'Administration', 'Users',
989 990
        'super user', 'Roles']
991

  
992

  
993
def test_manager_create_user_duplicates(admin, app, ou1, settings):
994
    settings.A2_MANAGER_CHECK_DUPLICATE_USERS = True
995
    Attribute.objects.create(
996
        kind='birthdate', name='birthdate', label='birthdate', required=False, searchable=True
997
    )
998
    Attribute.objects.create(
999
        kind='string', name='address', label='address', required=False, searchable=False
1000
    )
1001

  
1002
    user = User.objects.create(
1003
        first_name='Alexander', last_name='Longname', email='alexandre.longname@entrouvert.com'
1004
    )
1005
    user.attributes.birthdate = datetime.date(1980, 1, 2)
1006
    user.attributes.address = '2 baker street'
1007
    user2 = User.objects.create(first_name='Alexandra', last_name='Longname')
1008
    user3 = User.objects.create(first_name='Alex', last_name='Shortname')
1009

  
1010
    login(app, admin)
1011
    resp = app.get('/manage/users/%s/add/' % ou1.pk)
1012

  
1013
    form = resp.form
1014
    form.set('first_name', 'Alexandre')
1015
    form.set('last_name', 'Longname')
1016
    form.set('email', 'alex@entrouvert.com')
1017
    form.set('password1', 'ABcd1234')
1018
    form.set('password2', 'ABcd1234')
1019
    resp = form.submit()
1020

  
1021
    assert 'user may already exist' in resp.text
1022
    assert 'Alexander Longname' in resp.text
1023
    assert '- alexandre.longname@entrouvert.com' in resp.text
1024
    assert '- 1980-01-02' in resp.text
1025
    assert not 'baker street' in resp.text
1026
    assert '/users/%s/' % user.pk in resp.text
1027
    assert 'Alexandra Longname' in resp.text
1028
    assert '/users/%s/' % user2.pk in resp.text
1029

  
1030
    # This user was in fact duplicate. Agent reuses the form to fill details on another user
1031
    form = resp.form
1032
    form.set('first_name', 'Alexa')
1033
    form.set('last_name', 'Shortname')
1034
    form.set('email', 'ashortname@entrouvert.com')
1035
    resp = form.submit()
1036

  
1037
    assert 'user may already exist' in resp.text
1038
    assert '/users/%s/' % user3.pk in resp.text
1039

  
1040
    # Not a duplicate this time. Simply submitting again creates user
1041
    resp = resp.form.submit().follow()
1042
    assert User.objects.filter(first_name='Alexa').count() == 1
990
-