From dbb134aafa280cfe3f49f1ea2cf526b214eacebc Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 13 Dec 2018 10:35:18 +0100 Subject: [PATCH] manager: use and operator to combine terms (fixes #28952) --- src/authentic2/manager/widgets.py | 19 ++++++++++++++++--- tests/test_manager.py | 31 +++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/authentic2/manager/widgets.py b/src/authentic2/manager/widgets.py index 39eaf91e..9fc8d15f 100644 --- a/src/authentic2/manager/widgets.py +++ b/src/authentic2/manager/widgets.py @@ -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', ] diff --git a/tests/test_manager.py b/tests/test_manager.py index d874344b..9d30ebcf 100644 --- a/tests/test_manager.py +++ b/tests/test_manager.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + import pytest import json from urlparse import urlparse @@ -790,3 +792,32 @@ def test_manager_add_user_querystring(superuser_or_admin, app, ou1): response = app.get(url) assert querystring in response.location + + +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' -- 2.20.1