manager: use and operator to combine terms (fixes #28952)

This commit is contained in:
Benjamin Dauvergne 2018-12-13 10:35:18 +01:00
parent a855c86c29
commit b03a76dfff
2 changed files with 47 additions and 3 deletions

View File

@ -1,3 +1,6 @@
import operator
from six.moves import reduce
from django_select2.forms import ModelSelect2Widget, ModelSelect2MultipleWidget
from django.contrib.auth import get_user_model
@ -11,13 +14,19 @@ from . import utils
class SplitTermMixin(object):
split_term_operator = operator.__or__
def filter_queryset(self, term, queryset=None):
if queryset is not None:
qs = queryset.none()
qs = queryset
else:
qs = self.get_queryset().none()
qs = self.get_queryset()
if not term.strip():
return qs.all()
queries = []
for term in term.split():
qs |= super(SplitTermMixin, self).filter_queryset(term, queryset=queryset)
queries.append(super(SplitTermMixin, self).filter_queryset(term, queryset=qs))
qs = reduce(self.split_term_operator, queries)
return qs
@ -79,6 +88,7 @@ class ChooseUsersWidget(SecurityCheckMixin, ModelSelect2MultipleWidget):
class ChooseRoleWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect2Widget):
queryset = get_role_model().objects.exclude(slug__startswith='_')
split_term_operator = operator.__and__
search_fields = [
'name__icontains',
'service__name__icontains',
@ -88,6 +98,7 @@ class ChooseRoleWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect2Widget):
class ChooseRolesWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect2MultipleWidget):
queryset = get_role_model().objects.exclude(slug__startswith='_')
split_term_operator = operator.__and__
search_fields = [
'name__icontains',
'service__name__icontains',
@ -98,6 +109,7 @@ class ChooseRolesWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect2Multiple
class ChooseRolesForChangeWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect2MultipleWidget):
operations = ['change']
queryset = get_role_model().objects.all()
split_term_operator = 'AND'
search_fields = [
'name__icontains',
'service__name__icontains',
@ -107,6 +119,7 @@ class ChooseRolesForChangeWidget(RoleLabelMixin, SecurityCheckMixin, ModelSelect
class ChooseOUWidget(SecurityCheckMixin, ModelSelect2Widget):
model = get_ou_model()
split_term_operator = 'AND'
search_fields = [
'name__icontains',
]

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import json
from urlparse import urlparse
@ -805,3 +807,32 @@ def test_manager_edit_user_next_form_error(superuser_or_admin, app, ou1, simple_
form.set('email', 'jd') # erroneous
resp = form.submit()
assert '<input type="hidden" name="next" value="%s">' % next_url in resp.ubody
def test_roles_widget(admin, app, db):
from django.core import signing
from django_rbac.utils import get_role_model, get_ou_model
from authentic2.manager.forms import ChooseRoleForm
login(app, admin, '/manage/')
OU = get_ou_model()
cassis = OU.objects.create(name=u'Cassis')
la_bedoule = OU.objects.create(name=u'La Bédoule')
cuges = OU.objects.create(name=u'Cuges')
Role = get_role_model()
Role.objects.create(ou=cassis, name=u'Administrateur')
Role.objects.create(ou=la_bedoule, name=u'Administrateur')
Role.objects.create(ou=cuges, name=u'Administrateur')
form = ChooseRoleForm()
assert form.as_p()
field_id = signing.dumps(id(form.fields['role'].widget))
url = reverse('django_select2-json')
response = app.get(url, params={'field_id': field_id, 'term': 'Admin'})
assert len(response.json['results']) == 3
response = app.get(url, params={'field_id': field_id, 'term': 'Admin cass'})
assert len(response.json['results']) == 1
assert response.json['results'][0]['text'] == u'Cassis - Administrateur'
response = app.get(url, params={'field_id': field_id, 'term': 'Admin édou'})
assert len(response.json['results']) == 1
assert response.json['results'][0]['text'] == u'La Bédoule - Administrateur'