0001-authenticators-add-manager-role-66984.patch
src/authentic2/a2_rbac/management.py | ||
---|---|---|
91 | 91 |
'name': _('Manager of services'), |
92 | 92 |
'scoped_name': _('Services - {ou}'), |
93 | 93 |
}, |
94 |
('authenticators', 'baseauthenticator'): { |
|
95 |
'name': _('Manager of authenticators'), |
|
96 |
'scoped_name': _('Authenticators - {ou}'), |
|
97 |
}, |
|
94 | 98 |
} |
95 | 99 | |
96 | 100 |
src/authentic2/apps/authenticators/manager_urls.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
from django.contrib.auth.decorators import user_passes_test |
|
18 |
from django.core.exceptions import PermissionDenied |
|
19 | 17 |
from django.urls import path |
20 |
from django.utils.functional import lazy |
|
21 | ||
22 |
from authentic2.decorators import required |
|
23 |
from authentic2.utils import misc as utils_misc |
|
24 | 18 | |
25 | 19 |
from . import views |
26 | 20 | |
27 | ||
28 |
def superuser_required(function, login_url): |
|
29 |
def check_superuser(user): |
|
30 |
if user and user.is_superuser: |
|
31 |
return True |
|
32 |
if user and not user.is_anonymous: |
|
33 |
raise PermissionDenied() |
|
34 |
return False |
|
35 | ||
36 |
actual_decorator = user_passes_test(check_superuser, login_url=login_url) |
|
37 |
return actual_decorator(function) |
|
38 | ||
39 | ||
40 |
def superuser_login_required(func): |
|
41 |
return superuser_required(func, login_url=lazy(utils_misc.get_manager_login_url, str)()) |
|
42 | ||
43 | ||
44 |
urlpatterns = required( |
|
45 |
superuser_login_required, |
|
46 |
[ |
|
47 |
# Authenticators |
|
48 |
path('authenticators/', views.authenticators, name='a2-manager-authenticators'), |
|
49 |
path( |
|
50 |
'authenticators/add/', |
|
51 |
views.add, |
|
52 |
name='a2-manager-authenticator-add', |
|
53 |
), |
|
54 |
path( |
|
55 |
'authenticators/<int:pk>/detail/', |
|
56 |
views.detail, |
|
57 |
name='a2-manager-authenticator-detail', |
|
58 |
), |
|
59 |
path( |
|
60 |
'authenticators/<int:pk>/edit/', |
|
61 |
views.edit, |
|
62 |
name='a2-manager-authenticator-edit', |
|
63 |
), |
|
64 |
path( |
|
65 |
'authenticators/<int:pk>/delete/', |
|
66 |
views.delete, |
|
67 |
name='a2-manager-authenticator-delete', |
|
68 |
), |
|
69 |
path( |
|
70 |
'authenticators/<int:pk>/toggle/', |
|
71 |
views.toggle, |
|
72 |
name='a2-manager-authenticator-toggle', |
|
73 |
), |
|
74 |
path( |
|
75 |
'authenticators/<int:pk>/journal/', |
|
76 |
views.journal, |
|
77 |
name='a2-manager-authenticator-journal', |
|
78 |
), |
|
79 |
path('authenticators/<int:pk>/export/', views.export_json, name='a2-manager-authenticator-export'), |
|
80 |
path('authenticators/import/', views.import_json, name='a2-manager-authenticator-import'), |
|
81 |
path( |
|
82 |
'authenticators/order/', |
|
83 |
views.order, |
|
84 |
name='a2-manager-authenticators-order', |
|
85 |
), |
|
86 |
path( |
|
87 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/add/', |
|
88 |
views.add_related_object, |
|
89 |
name='a2-manager-authenticators-add-related-object', |
|
90 |
), |
|
91 |
path( |
|
92 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/edit/', |
|
93 |
views.edit_related_object, |
|
94 |
name='a2-manager-authenticators-edit-related-object', |
|
95 |
), |
|
96 |
path( |
|
97 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/delete/', |
|
98 |
views.delete_related_object, |
|
99 |
name='a2-manager-authenticators-delete-related-object', |
|
100 |
), |
|
101 |
], |
|
102 |
) |
|
21 |
urlpatterns = [ |
|
22 |
path('authenticators/', views.authenticators, name='a2-manager-authenticators'), |
|
23 |
path( |
|
24 |
'authenticators/add/', |
|
25 |
views.add, |
|
26 |
name='a2-manager-authenticator-add', |
|
27 |
), |
|
28 |
path( |
|
29 |
'authenticators/<int:pk>/detail/', |
|
30 |
views.detail, |
|
31 |
name='a2-manager-authenticator-detail', |
|
32 |
), |
|
33 |
path( |
|
34 |
'authenticators/<int:pk>/edit/', |
|
35 |
views.edit, |
|
36 |
name='a2-manager-authenticator-edit', |
|
37 |
), |
|
38 |
path( |
|
39 |
'authenticators/<int:pk>/delete/', |
|
40 |
views.delete, |
|
41 |
name='a2-manager-authenticator-delete', |
|
42 |
), |
|
43 |
path( |
|
44 |
'authenticators/<int:pk>/toggle/', |
|
45 |
views.toggle, |
|
46 |
name='a2-manager-authenticator-toggle', |
|
47 |
), |
|
48 |
path( |
|
49 |
'authenticators/<int:pk>/journal/', |
|
50 |
views.journal, |
|
51 |
name='a2-manager-authenticator-journal', |
|
52 |
), |
|
53 |
path('authenticators/<int:pk>/export/', views.export_json, name='a2-manager-authenticator-export'), |
|
54 |
path('authenticators/import/', views.import_json, name='a2-manager-authenticator-import'), |
|
55 |
path( |
|
56 |
'authenticators/order/', |
|
57 |
views.order, |
|
58 |
name='a2-manager-authenticators-order', |
|
59 |
), |
|
60 |
path( |
|
61 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/add/', |
|
62 |
views.add_related_object, |
|
63 |
name='a2-manager-authenticators-add-related-object', |
|
64 |
), |
|
65 |
path( |
|
66 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/edit/', |
|
67 |
views.edit_related_object, |
|
68 |
name='a2-manager-authenticators-edit-related-object', |
|
69 |
), |
|
70 |
path( |
|
71 |
'authenticators/<int:authenticator_pk>/<slug:model_name>/<int:pk>/delete/', |
|
72 |
views.delete_related_object, |
|
73 |
name='a2-manager-authenticators-delete-related-object', |
|
74 |
), |
|
75 |
] |
src/authentic2/apps/authenticators/views.py | ||
---|---|---|
32 | 32 | |
33 | 33 |
from authentic2.apps.journal.views import JournalViewWithContext |
34 | 34 |
from authentic2.manager.journal_views import BaseJournalView |
35 |
from authentic2.manager.views import MediaMixin, TitleMixin |
|
35 |
from authentic2.manager.views import MediaMixin, PermissionMixin, TitleMixin
|
|
36 | 36 | |
37 | 37 |
from . import forms |
38 | 38 |
from .models import AuthenticatorImportError, BaseAuthenticator |
39 | 39 | |
40 | 40 | |
41 |
class AuthenticatorsMixin(MediaMixin, TitleMixin): |
|
41 |
class AuthenticatorsMixin(MediaMixin, TitleMixin, PermissionMixin):
|
|
42 | 42 |
model = BaseAuthenticator |
43 |
permissions = ['authenticators.search_baseauthenticator'] |
|
43 | 44 | |
44 | 45 |
def get_queryset(self): |
45 | 46 |
return self.model.authenticators.all() |
... | ... | |
268 | 269 |
order = AuthenticatorsOrderView.as_view() |
269 | 270 | |
270 | 271 | |
271 |
class AuthenticatorRelatedObjectMixin(MediaMixin, TitleMixin): |
|
272 |
class AuthenticatorRelatedObjectMixin(MediaMixin, TitleMixin, PermissionMixin): |
|
273 |
permissions = ['authenticators.search_baseauthenticator'] |
|
274 | ||
272 | 275 |
def dispatch(self, request, *args, **kwargs): |
273 | 276 |
self.authenticator = get_object_or_404( |
274 | 277 |
BaseAuthenticator.authenticators.all(), pk=kwargs.get('authenticator_pk') |
src/authentic2/manager/urls.py | ||
---|---|---|
207 | 207 |
path('api-clients/<int:pk>/', apiclient_views.detail, name='a2-manager-api-client-detail'), |
208 | 208 |
path('api-clients/<int:pk>/edit/', apiclient_views.edit, name='a2-manager-api-client-edit'), |
209 | 209 |
path('api-clients/<int:pk>/delete/', apiclient_views.delete, name='a2-manager-api-client-delete'), |
210 |
], |
|
210 |
] |
|
211 |
+ authenticator_urlpatterns, |
|
211 | 212 |
) |
212 | 213 | |
213 |
urlpatterns += authenticator_urlpatterns |
|
214 | 214 |
urlpatterns += oidc_manager_urlpatterns |
215 | 215 | |
216 | 216 |
urlpatterns += [ |
src/authentic2/manager/views.py | ||
---|---|---|
669 | 669 |
'label': _('Authentication frontends'), |
670 | 670 |
'slug': 'authn', |
671 | 671 |
'href': reverse_lazy('a2-manager-authenticators'), |
672 |
'permissions': 'superuser',
|
|
672 |
'permissions': 'authenticators.search_baseauthenticator',
|
|
673 | 673 |
'place': 'sidebar', |
674 | 674 |
}, |
675 | 675 |
{ |
tests/test_a2_rbac.py | ||
---|---|---|
30 | 30 | |
31 | 31 | |
32 | 32 |
def test_update_rbac(db): |
33 |
# 3 content types managers and 1 global manager
|
|
34 |
assert Role.objects.count() == 5
|
|
35 |
# 3 content type global permissions, 1 role administration permissions (for the main manager
|
|
33 |
# 5 content types managers and 1 global manager
|
|
34 |
assert Role.objects.count() == 6
|
|
35 |
# 4 content type global permissions, 1 role administration permissions (for the main manager
|
|
36 | 36 |
# role which is self-administered) |
37 | 37 |
# and 1 user view permission (for the role administrator) |
38 | 38 |
# and 1 user manage authorizations permission (for the role administrator) |
39 | 39 |
# and 1 ou view permission (for the user and role administrators) |
40 |
assert Permission.objects.count() == 8
|
|
40 |
assert Permission.objects.count() == 9
|
|
41 | 41 | |
42 | 42 | |
43 | 43 |
def test_delete_role(db): |
... | ... | |
405 | 405 |
from django.core.management.sql import emit_post_migrate_signal |
406 | 406 | |
407 | 407 |
call_command('flush', verbosity=0, interactive=False, database='default', reset_sequences=False) |
408 |
assert Role.objects.count() == 5
|
|
408 |
assert Role.objects.count() == 6
|
|
409 | 409 |
OU.objects.create(name='OU1', slug='ou1') |
410 | 410 |
emit_post_migrate_signal(verbosity=0, interactive=False, db='default', created_models=[]) |
411 |
assert Role.objects.count() == 5 + 4 + 4
|
|
411 |
assert Role.objects.count() == 6 + 5 + 5
|
|
412 | 412 |
settings.A2_RBAC_MANAGED_CONTENT_TYPES = () |
413 | 413 |
call_command('flush', verbosity=0, interactive=False, database='default', reset_sequences=False) |
414 | 414 |
assert Role.objects.count() == 0 |
... | ... | |
424 | 424 |
user_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-users') |
425 | 425 |
role_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-roles') |
426 | 426 |
service_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-services') |
427 |
authenticator_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-authenticators') |
|
427 | 428 |
assert ou_manager in manager.parents() |
428 | 429 |
assert user_manager in manager.parents() |
429 | 430 |
assert role_manager in manager.parents() |
430 | 431 |
assert service_manager in manager.parents() |
431 |
assert manager.parents(include_self=False).count() == 4 |
|
432 |
assert Role.objects.count() == 5 |
|
432 |
assert authenticator_manager in manager.parents() |
|
433 |
assert manager.parents(include_self=False).count() == 5 |
|
434 |
assert Role.objects.count() == 6 |
|
433 | 435 |
assert OU.objects.count() == 1 |
434 | 436 | |
435 | 437 | |
... | ... | |
439 | 441 |
user_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-users') |
440 | 442 |
role_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-roles') |
441 | 443 |
service_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-services') |
444 |
authenticator_manager = Role.objects.get(ou__isnull=True, slug='_a2-manager-of-authenticators') |
|
442 | 445 |
assert ou_manager in manager.parents() |
443 | 446 |
assert user_manager in manager.parents() |
444 | 447 |
assert role_manager in manager.parents() |
445 | 448 |
assert service_manager in manager.parents() |
446 |
assert manager.parents(include_self=False).count() == 4 |
|
449 |
assert authenticator_manager in manager.parents() |
|
450 |
assert manager.parents(include_self=False).count() == 5 |
|
447 | 451 | |
448 | 452 |
for ou in [get_default_ou(), ou1]: |
449 | 453 |
manager = Role.objects.get(ou__isnull=True, slug=f'_a2-managers-of-{ou.slug}') |
450 | 454 |
user_manager = Role.objects.get(ou=ou, slug=f'_a2-manager-of-users-{ou.slug}') |
451 | 455 |
role_manager = Role.objects.get(ou=ou, slug=f'_a2-manager-of-roles-{ou.slug}') |
452 | 456 |
service_manager = Role.objects.get(ou=ou, slug=f'_a2-manager-of-services-{ou.slug}') |
457 |
authenticator_manager = Role.objects.get(ou=ou, slug=f'_a2-manager-of-authenticators-{ou.slug}') |
|
453 | 458 | |
454 | 459 |
assert user_manager in manager.parents() |
455 | 460 |
assert role_manager in manager.parents() |
456 | 461 |
assert service_manager in manager.parents() |
457 |
assert manager.parents(include_self=False).count() == 3 |
|
462 |
assert authenticator_manager in manager.parents() |
|
463 |
assert manager.parents(include_self=False).count() == 4 |
|
458 | 464 | |
459 |
# 5 global roles and 4 ou roles for both ous
|
|
460 |
assert Role.objects.count() == 5 + 4 + 4
|
|
465 |
# 6 global roles and 5 ou roles for both ous
|
|
466 |
assert Role.objects.count() == 6 + 5 + 5
|
|
461 | 467 | |
462 | 468 | |
463 | 469 |
@pytest.mark.parametrize( |
tests/test_manager.py | ||
---|---|---|
84 | 84 |
for section in sections: |
85 | 85 |
path = reverse('a2-manager-%s' % section) |
86 | 86 |
assert response.pyquery.remove_namespaces()('a.button[href=\'%s\']' % path) |
87 |
# only the journal is visible in the sidebar
|
|
88 |
assert len(response.pyquery('div.a2-manager-id-tools_content').children()) == 2
|
|
87 |
# only journal, api clients and authenticators are visible in the sidebar
|
|
88 |
assert len(response.pyquery('div.a2-manager-id-tools_content').children()) == 3
|
|
89 | 89 |
assert response.pyquery('a#journal') |
90 | 90 |
assert response.pyquery('a#api-clients') |
91 |
assert response.pyquery('a#authn') |
|
91 | 92 | |
92 | 93 | |
93 | 94 |
def test_manager_create_ou(superuser_or_admin, app): |
... | ... | |
467 | 468 |
form.set('search-internals', True) |
468 | 469 |
response = form.submit() |
469 | 470 |
q = response.pyquery.remove_namespaces() |
470 |
assert len(q('table tbody tr')) == 6
|
|
471 |
assert len(q('table tbody tr')) == 7
|
|
471 | 472 |
# admin enroled only in the Manager role, other roles are inherited |
472 |
assert len(q('table tbody tr td.via')) == 6
|
|
473 |
assert len(q('table tbody tr td.via')) == 7
|
|
473 | 474 |
assert len(q('table tbody tr td.via:empty')) == 2 |
474 | 475 |
for elt in q('table tbody td.name a'): |
475 | 476 |
assert 'Manager' in elt.text or elt.text == 'simple role' |
... | ... | |
491 | 492 |
response.form.set('search-internals', True) |
492 | 493 |
response = response.form.submit() |
493 | 494 |
q = response.pyquery.remove_namespaces() |
494 |
assert len(q('table tbody tr')) == 6
|
|
495 |
assert len(q('table tbody tr')) == 7
|
|
495 | 496 |
for elt in q('table tbody td.name a'): |
496 | 497 |
assert 'Manager' in elt.text or elt.text == 'simple role' |
497 | 498 | |
... | ... | |
542 | 543 |
form.set('search-internals', True) |
543 | 544 |
response = form.submit() |
544 | 545 |
q = response.pyquery.remove_namespaces() |
545 |
assert len(q('table tbody tr')) == 5
|
|
546 |
assert len(q('table tbody tr')) == 6
|
|
546 | 547 |
# admin enroled only in the Manager role, other roles are inherited |
547 |
assert len(q('table tbody tr td.via')) == 5
|
|
548 |
assert len(q('table tbody tr td.via')) == 6
|
|
548 | 549 |
assert len(q('table tbody tr td.via:empty')) == 1 |
549 | 550 |
for elt in q('table tbody td.name a'): |
550 | 551 |
assert 'Manager' in elt.text |
... | ... | |
554 | 555 |
form.set('search-internals', True) |
555 | 556 |
response = form.submit() |
556 | 557 |
q = response.pyquery.remove_namespaces() |
557 |
assert len(q('table tbody tr')) == 7
|
|
558 |
assert len(q('table tbody tr')) == 8
|
|
558 | 559 |
for elt in q('table tbody td.name a'): |
559 | 560 |
assert 'Manager' in elt.text |
560 | 561 | |
... | ... | |
586 | 587 |
response.form.set('search-internals', True) |
587 | 588 |
response = response.form.submit() |
588 | 589 |
q = response.pyquery.remove_namespaces() |
589 |
assert len(q('table tbody tr')) == 15
|
|
590 |
assert len(q('table tbody tr')) == 18
|
|
590 | 591 |
for elt in q('table tbody td.name a'): |
591 | 592 |
assert ( |
592 | 593 |
'OU1' in elt.text |
... | ... | |
600 | 601 |
response.form.set('search-internals', True) |
601 | 602 |
response = response.form.submit() |
602 | 603 |
q = response.pyquery.remove_namespaces() |
603 |
assert len(q('table tbody tr')) == 7
|
|
604 |
assert len(q('table tbody tr')) == 8
|
|
604 | 605 |
for elt in q('table tbody td.name a'): |
605 | 606 |
assert 'Manager' in elt.text |
606 | 607 | |
... | ... | |
647 | 648 |
response.form.set('search-internals', True) |
648 | 649 |
response = response.form.submit() |
649 | 650 |
q = response.pyquery.remove_namespaces() |
650 |
assert len(q('table tbody tr')) == 4
|
|
651 |
assert len(q('table tbody tr')) == 5
|
|
651 | 652 |
names = {elt.text for elt in q('table tbody td.name a')} |
652 |
assert names == {'Roles - OU1', 'Users - OU1', 'Services - OU1', 'role_ou1'} |
|
653 |
assert names == {'Roles - OU1', 'Users - OU1', 'Services - OU1', 'role_ou1', 'Authenticators - OU1'}
|
|
653 | 654 | |
654 | 655 |
# test role listing |
655 | 656 |
response = app.get('/manage/roles/') |
... | ... | |
668 | 669 |
response.form.set('search-internals', True) |
669 | 670 |
response = response.form.submit() |
670 | 671 |
q = response.pyquery.remove_namespaces() |
671 |
assert len(q('table tbody tr')) == 4
|
|
672 |
assert len(q('table tbody tr')) == 5
|
|
672 | 673 |
names = {elt.text for elt in q('table tbody td.name a')} |
673 |
assert names == {'Roles - OU1', 'Users - OU1', 'Services - OU1', 'role_ou1'} |
|
674 |
assert names == {'Roles - OU1', 'Users - OU1', 'Services - OU1', 'role_ou1', 'Authenticators - OU1'}
|
|
674 | 675 | |
675 | 676 |
test_user_listing_ou_admin(admin_ou1) |
676 | 677 |
tests/test_manager_authenticators.py | ||
---|---|---|
21 | 21 |
from django.utils.html import escape |
22 | 22 |
from webtest import Upload |
23 | 23 | |
24 |
from authentic2.a2_rbac.models import Role |
|
24 | 25 |
from authentic2.a2_rbac.utils import get_default_ou |
25 | 26 |
from authentic2.apps.authenticators.models import AddRoleAction, BaseAuthenticator, LoginPasswordAuthenticator |
26 | 27 |
from authentic2.models import Attribute |
... | ... | |
31 | 32 |
from .utils import assert_event, login, logout |
32 | 33 | |
33 | 34 | |
34 |
def test_authenticators_authorization(app, admin, superuser): |
|
35 |
resp = login(app, admin, path='/manage/') |
|
35 |
def test_authenticators_authorization(app, simple_user, simple_role, admin, superuser): |
|
36 |
simple_user.roles.add(simple_role.get_admin_role()) # grant user access to /manage/ |
|
37 | ||
38 |
resp = login(app, simple_user, path='/manage/') |
|
36 | 39 |
assert 'Authenticators' not in resp.text |
37 | 40 |
app.get('/manage/authenticators/', status=403) |
38 | 41 | |
42 |
role = Role.objects.get(name='Manager of authenticators') |
|
43 |
simple_user.roles.add(role) |
|
44 | ||
45 |
resp = app.get('/manage/') |
|
46 |
resp = resp.click('Authentication frontends') |
|
47 |
assert 'Authenticators' in resp.text |
|
48 | ||
49 |
logout(app) |
|
50 |
resp = login(app, admin, path='/manage/') |
|
51 |
assert 'Authentication frontends' in resp.text |
|
52 | ||
53 |
resp = resp.click('Authentication frontends') |
|
54 |
assert 'Authenticators' in resp.text |
|
55 | ||
39 | 56 |
logout(app) |
40 | 57 |
resp = login(app, superuser, path='/manage/') |
41 | 58 |
assert 'Authentication frontends' in resp.text |
... | ... | |
44 | 61 |
assert 'Authenticators' in resp.text |
45 | 62 | |
46 | 63 | |
47 |
def test_authenticators_password(app, superuser): |
|
48 |
resp = login(app, superuser, path='/manage/authenticators/') |
|
64 |
def test_authenticators_password(app, superuser_or_admin):
|
|
65 |
resp = login(app, superuser_or_admin, path='/manage/authenticators/')
|
|
49 | 66 |
# Password authenticator already exists |
50 | 67 |
assert 'Password' in resp.text |
51 | 68 |
authenticator = LoginPasswordAuthenticator.objects.get() |
... | ... | |
85 | 102 |
"Show condition: 'backoffice' in login_hint or remotre_addr == '1.2.3.4'" |
86 | 103 |
in resp.text |
87 | 104 |
) |
88 |
assert_event('authenticator.edit', user=superuser, session=app.session) |
|
105 |
assert_event('authenticator.edit', user=superuser_or_admin, session=app.session)
|
|
89 | 106 | |
90 | 107 |
resp = resp.click('Edit') |
91 | 108 |
resp.form['show_condition'] = "remote_addr in dnsbl('ddns.entrouvert.org')" |
tests/test_role_manager.py | ||
---|---|---|
524 | 524 |
assert select2_json['more'] is True |
525 | 525 | |
526 | 526 |
select2_json = request_select2(app, resp, fetch_all=True) |
527 |
assert len(select2_json['results']) == 17
|
|
527 |
assert len(select2_json['results']) == 20
|
|
528 | 528 |
choices = [x['text'] for x in select2_json['results']] |
529 | 529 |
assert choices == [ |
530 |
'Default organizational unit - Authenticators - Default organizational unit', |
|
530 | 531 |
'Default organizational unit - Managers of role "simple role"', |
531 | 532 |
'Default organizational unit - Roles - Default organizational unit', |
532 | 533 |
'Default organizational unit - Services - Default organizational unit', |
533 | 534 |
'Default organizational unit - Users - Default organizational unit', |
535 |
'OU1 - Authenticators - OU1', |
|
534 | 536 |
'OU1 - role_ou1', |
535 | 537 |
'OU1 - Roles - OU1', |
536 | 538 |
'OU1 - Services - OU1', |
537 | 539 |
'OU1 - Users - OU1', |
538 | 540 |
'Manager', |
541 |
'Manager of authenticators', |
|
539 | 542 |
'Manager of organizational units', |
540 | 543 |
'Manager of roles', |
541 | 544 |
'Manager of services', |
... | ... | |
558 | 561 |
assert select2_json['more'] is False |
559 | 562 | |
560 | 563 |
select2_json = request_select2(app, resp, term='Manager') |
561 |
assert len(select2_json['results']) == 8
|
|
564 |
assert len(select2_json['results']) == 9
|
|
562 | 565 |
select2_json = request_select2(app, resp, term='Manager of') |
563 |
assert len(select2_json['results']) == 7
|
|
566 |
assert len(select2_json['results']) == 8
|
|
564 | 567 |
select2_json = request_select2(app, resp, term='Manager of serv') |
565 | 568 |
assert len(select2_json['results']) == 1 |
566 | 569 | |
567 |
- |