0001-create-import_site-and-export_site-commands-16514.patch
src/authentic2/a2_rbac/models.py | ||
---|---|---|
92 | 92 |
def cached(cls): |
93 | 93 |
return cls.objects.all() |
94 | 94 | |
95 |
def export_json(self, full=False): |
|
96 |
d = {'uuid': self.uuid, 'slug': self.slug, 'name': self.name} |
|
97 |
if full: |
|
98 |
extension = { |
|
99 |
'description': self.description, 'default': self.default, |
|
100 |
'email_is_unique': self.email_is_unique, |
|
101 |
'username_is_unique': self.username_is_unique, |
|
102 |
'validate_emails': self.validate_emails |
|
103 |
} |
|
104 |
d.update(extension) |
|
105 |
return d |
|
106 | ||
95 | 107 | |
96 | 108 |
class Permission(PermissionAbstractBase): |
97 | 109 |
class Meta: |
... | ... | |
207 | 219 |
'ou__slug': self.ou.slug if self.ou else None, |
208 | 220 |
} |
209 | 221 | |
222 |
def export_json(self, attributes=False, parents=False, permissions=False): |
|
223 |
d = { |
|
224 |
'uuid': self.uuid, 'slug': self.slug, 'name': self.name, |
|
225 |
'description': self.description, 'admin_scope_id': self.admin_scope_id, |
|
226 |
'admin_scope_ct_id': self.admin_scope_ct_id, 'external_id': self.external_id, |
|
227 |
'ou': self.ou and self.ou.export_json(False), |
|
228 |
'service': self.service and self.service.export_json(False) |
|
229 |
} |
|
230 | ||
231 |
if attributes: |
|
232 |
for attribute in self.attributes.all(): |
|
233 |
d.setdefault('attributes', []).append(attribute.to_json()) |
|
234 | ||
235 |
if parents: |
|
236 |
RoleParenting = rbac_utils.get_role_parenting_model() |
|
237 |
for parenting in RoleParenting.objects.filter(child_id=self.id, direct=True): |
|
238 |
d.setdefault('parents', []).append(parenting.parent.export_json()) |
|
239 | ||
240 |
if permissions: |
|
241 |
for perm in self.permissions.all(): |
|
242 |
d.setdefault('permissions', []).append(perm.export_json()) |
|
243 | ||
244 |
return d |
|
245 | ||
210 | 246 | |
211 | 247 |
class RoleParenting(RoleParentingAbstractBase): |
212 | 248 |
class Meta(RoleParentingAbstractBase.Meta): |
... | ... | |
239 | 275 |
('role', 'name', 'kind', 'value'), |
240 | 276 |
) |
241 | 277 | |
278 |
def to_json(self): |
|
279 |
return {'name': self.name, 'kind': self.kind, 'value': self.value} |
|
280 | ||
281 | ||
242 | 282 |
GenericRelation(Permission, |
243 | 283 |
content_type_field='target_ct', |
244 | 284 |
object_id_field='target_id').contribute_to_class(ContentType, 'admin_perms') |
src/authentic2/data_transfer.py | ||
---|---|---|
1 |
from django.contrib.contenttypes.models import ContentType |
|
2 | ||
3 |
from django_rbac.models import Operation |
|
4 |
from django_rbac.utils import ( |
|
5 |
get_ou_model, get_role_model, get_role_parenting_model, get_permission_model) |
|
6 |
from authentic2.a2_rbac.models import RoleAttribute |
|
7 |
from authentic2.utils import update_model |
|
8 | ||
9 | ||
10 |
def export_site(): |
|
11 |
return { |
|
12 |
'roles': export_roles(get_role_model().objects.all()), |
|
13 |
'ous': export_ou(get_ou_model().objects.all()) |
|
14 |
} |
|
15 | ||
16 | ||
17 |
def export_ou(ou_query_set): |
|
18 |
return [ou.export_json() for ou in ou_query_set] |
|
19 | ||
20 | ||
21 |
def export_roles(role_queryset): |
|
22 |
""" Serialize roles in role_queryset |
|
23 |
""" |
|
24 |
return [ |
|
25 |
role.export_json(attributes=True, parents=True, permissions=True) |
|
26 |
for role in role_queryset |
|
27 |
] |
|
28 | ||
29 | ||
30 |
def build_ou_natural_key(d): |
|
31 |
return None if d['ou'] is None else [d['ou']['slug']] |
|
32 | ||
33 | ||
34 |
def build_role_natural_key(role_d): |
|
35 |
role_slug = role_d['slug'] |
|
36 |
ou_nk = build_ou_natural_key(role_d) |
|
37 |
service_nk = None if role_d['service'] is None else [ |
|
38 |
build_ou_natural_key(role_d['service']), role_d['service']['slug']] |
|
39 |
return [role_slug, ou_nk, service_nk] |
|
40 | ||
41 | ||
42 |
def search_ou(ou_natural_key): |
|
43 |
""" ou_natural_key: ['ou-slug'] or None |
|
44 |
""" |
|
45 |
if ou_natural_key: |
|
46 |
try: |
|
47 |
OU = get_ou_model() |
|
48 |
return OU.objects.get_by_natural_key(*ou_natural_key) |
|
49 |
except OU.DoesNotExist: |
|
50 |
pass |
|
51 |
return None |
|
52 | ||
53 | ||
54 |
def search_role(role_d): |
|
55 |
Role = get_role_model() |
|
56 |
try: |
|
57 |
return Role.objects.get(uuid=role_d['uuid']) |
|
58 |
except Role.DoesNotExist: |
|
59 |
pass |
|
60 |
try: |
|
61 |
return Role.objects.get_by_natural_key(*build_role_natural_key(role_d)) |
|
62 |
except Role.DoesNotExist: |
|
63 |
return None |
|
64 | ||
65 | ||
66 |
class ImportContext(object): |
|
67 |
""" Holds information on how to perform the import. |
|
68 | ||
69 |
ou_delete_orphans: if True any existing ou that is not found in the export will |
|
70 |
be deleted |
|
71 | ||
72 |
role_delete_orphans: if True any existing role that is not found in the export will |
|
73 |
be deleted |
|
74 | ||
75 | ||
76 |
role_attributes_update: for each role in the import data, |
|
77 |
attributes will deleted and re-created |
|
78 | ||
79 | ||
80 |
role_parentings_update: for each role in the import data, |
|
81 |
parentings will deleted and re-created |
|
82 | ||
83 |
role_permissions_update: for each role in the import data, |
|
84 |
permissions will deleted and re-created |
|
85 |
""" |
|
86 | ||
87 |
def __init__( |
|
88 |
self, role_delete_orphans=False, role_parentings_update=True, |
|
89 |
role_permissions_update=True, role_attributes_update=True, |
|
90 |
ou_delete_orphans=False): |
|
91 |
self.role_delete_orphans = role_delete_orphans |
|
92 |
self.ou_delete_orphans = ou_delete_orphans |
|
93 |
self.role_parentings_update = role_parentings_update |
|
94 |
self.role_permissions_update = role_permissions_update |
|
95 |
self.role_attributes_update = role_attributes_update |
|
96 | ||
97 | ||
98 |
class DataImportError(Exception): |
|
99 |
pass |
|
100 | ||
101 | ||
102 |
class RoleDeserializer(object): |
|
103 | ||
104 |
def __init__(self, d, import_context): |
|
105 |
self._import_context = import_context |
|
106 |
self._obj = None |
|
107 |
self._ou = None |
|
108 |
self._parents = None |
|
109 |
self._attributes = None |
|
110 |
self._permissions = None |
|
111 | ||
112 |
self._role_d = dict() |
|
113 |
for key, value in d.items(): |
|
114 |
if key == 'parents': |
|
115 |
self._parents = value |
|
116 |
elif key == 'attributes': |
|
117 |
self._attributes = value |
|
118 |
elif key == 'permissions': |
|
119 |
self._permissions = value |
|
120 |
else: |
|
121 |
self._role_d[key] = value |
|
122 | ||
123 |
ou_natural_key = build_ou_natural_key(self._role_d) |
|
124 |
if ou_natural_key: |
|
125 |
self._ou = search_ou(ou_natural_key) |
|
126 |
if self._ou is None: |
|
127 |
raise DataImportError( |
|
128 |
"Can't import role because missing Organizational Unit : " |
|
129 |
"%s" % ou_natural_key[0]) |
|
130 | ||
131 |
def deserialize(self): |
|
132 |
kwargs = self._role_d.copy() |
|
133 |
obj = search_role(self._role_d) |
|
134 |
del kwargs['ou'] |
|
135 |
del kwargs['service'] |
|
136 |
if obj: # Role already exist |
|
137 |
self._obj = obj |
|
138 |
status = 'updated' |
|
139 |
update_model(self._obj, kwargs) |
|
140 |
if self._ou and (self._obj.ou != self._ou): |
|
141 |
# Need to update ou |
|
142 |
self._obj.ou = self._ou |
|
143 |
self._obj.save() |
|
144 |
else: # Create role |
|
145 |
self._obj = get_role_model().objects.create(**kwargs) |
|
146 |
if self._ou: |
|
147 |
self._obj.ou = self._ou |
|
148 |
self._obj.save() |
|
149 |
status = 'created' |
|
150 | ||
151 |
# Ensure admin role is created |
|
152 |
self._obj.get_admin_role() |
|
153 |
return self._obj, status |
|
154 | ||
155 |
def attributes(self): |
|
156 |
""" Update attributes (delete everything then create) |
|
157 |
""" |
|
158 |
created, deleted = [], [] |
|
159 |
for attr in self._obj.attributes.all(): |
|
160 |
attr.delete() |
|
161 |
deleted.append(attr) |
|
162 |
# Create attributes |
|
163 |
if self._attributes: |
|
164 |
for attr_dict in self._attributes: |
|
165 |
attr_dict['role'] = self._obj |
|
166 |
created.append(RoleAttribute.objects.create(**attr_dict)) |
|
167 | ||
168 |
return created, deleted |
|
169 | ||
170 |
def parentings(self): |
|
171 |
""" Update parentings (delete everything then create) |
|
172 |
""" |
|
173 |
created, deleted = [], [] |
|
174 |
Parenting = get_role_parenting_model() |
|
175 |
for parenting in Parenting.objects.filter(child=self._obj, direct=True): |
|
176 |
parenting.delete() |
|
177 |
deleted.append(parenting) |
|
178 | ||
179 |
if self._parents: |
|
180 |
for parent_d in self._parents: |
|
181 |
parent = search_role(parent_d) |
|
182 |
if not parent: |
|
183 |
raise DataImportError("Could not find role : %s" % parent_d) |
|
184 |
created.append(Parenting.objects.create( |
|
185 |
child=self._obj, direct=True, parent=parent)) |
|
186 | ||
187 |
return created, deleted |
|
188 | ||
189 |
def permissions(self): |
|
190 |
""" Update permissions (delete everything then create) |
|
191 |
""" |
|
192 |
created, deleted = [], [] |
|
193 |
for perm in self._obj.permissions.all(): |
|
194 |
perm.delete() |
|
195 |
deleted.append(perm) |
|
196 |
self._obj.permissions.clear() |
|
197 |
if self._permissions: |
|
198 |
for perm in self._permissions: |
|
199 |
op = Operation.objects.get_by_natural_key(perm['operation']['slug']) |
|
200 |
ou = get_ou_model().objects.get_by_natural_key( |
|
201 |
perm['ou']['slug']) if perm['ou'] else None |
|
202 |
ct = ContentType.objects.get_by_natural_key(*perm['target_ct']) |
|
203 |
target = ct.model_class().objects.get_by_natural_key(*perm['target']) |
|
204 |
perm = get_permission_model().objects.create( |
|
205 |
operation=op, ou=ou, target_ct=ct, target_id=target.pk) |
|
206 |
self._obj.permissions.add(perm) |
|
207 |
created.append(perm) |
|
208 | ||
209 |
return created, deleted |
|
210 | ||
211 | ||
212 |
class ImportResult(object): |
|
213 | ||
214 |
def __init__(self): |
|
215 |
self.roles = {'created': [], 'updated': []} |
|
216 |
self.ous = {'created': [], 'updated': []} |
|
217 |
self.attributes = {'created': [], 'deleted': []} |
|
218 |
self.parentings = {'created': [], 'deleted': []} |
|
219 |
self.permissions = {'created': [], 'deleted': []} |
|
220 | ||
221 |
def update_roles(self, role, d_status): |
|
222 |
self.roles[d_status].append(role) |
|
223 | ||
224 |
def update_ous(self, ou, status): |
|
225 |
self.ous[status].append(ou) |
|
226 | ||
227 |
def _bulk_update(self, attrname, created, deleted): |
|
228 |
attr = getattr(self, attrname) |
|
229 |
attr['created'].extend(created) |
|
230 |
attr['deleted'].extend(deleted) |
|
231 | ||
232 |
def update_attributes(self, created, deleted): |
|
233 |
self._bulk_update('attributes', created, deleted) |
|
234 | ||
235 |
def update_parentings(self, created, deleted): |
|
236 |
self._bulk_update('parentings', created, deleted) |
|
237 | ||
238 |
def update_permissions(self, created, deleted): |
|
239 |
self._bulk_update('permissions', created, deleted) |
|
240 | ||
241 |
def to_str(self, verbose=False): |
|
242 |
res = "" |
|
243 |
for attr in ('roles', 'ous', 'parentings', 'permissions', 'attributes'): |
|
244 |
data = getattr(self, attr) |
|
245 |
for status in ('created', 'updated', 'deleted'): |
|
246 |
if status in data: |
|
247 |
s_data = data[status] |
|
248 |
res += "%s %s %s\n" % (len(s_data), attr, status) |
|
249 |
return res |
|
250 | ||
251 | ||
252 |
def import_ou(ou_d): |
|
253 |
OU = get_ou_model() |
|
254 |
ou = search_ou([ou_d['slug']]) |
|
255 |
if ou is None: |
|
256 |
ou = OU.objects.create(**ou_d) |
|
257 |
status = 'created' |
|
258 |
else: |
|
259 |
update_model(ou, ou_d) |
|
260 |
status = 'updated' |
|
261 |
# Ensure admin role is created |
|
262 |
ou.get_admin_role() |
|
263 |
return ou, status |
|
264 | ||
265 | ||
266 |
def import_site(json_d, import_context): |
|
267 |
result = ImportResult() |
|
268 | ||
269 |
for ou_d in json_d.get('ous', []): |
|
270 |
result.update_ous(*import_ou(ou_d)) |
|
271 | ||
272 |
roles_ds = [RoleDeserializer(role_d, import_context) for role_d in json_d.get('roles', []) |
|
273 |
if not role_d['slug'].startswith('_')] |
|
274 | ||
275 |
for ds in roles_ds: |
|
276 |
result.update_roles(*ds.deserialize()) |
|
277 | ||
278 |
if import_context.role_attributes_update: |
|
279 |
for ds in roles_ds: |
|
280 |
result.update_attributes(*ds.attributes()) |
|
281 | ||
282 |
if import_context.role_parentings_update: |
|
283 |
for ds in roles_ds: |
|
284 |
result.update_parentings(*ds.parentings()) |
|
285 | ||
286 |
if import_context.role_permissions_update: |
|
287 |
for ds in roles_ds: |
|
288 |
result.update_permissions(*ds.permissions()) |
|
289 | ||
290 |
if import_context.ou_delete_orphans: |
|
291 |
raise DataImportError( |
|
292 |
"Unsupported context value for ou_delete_orphans : %s" % ( |
|
293 |
import_context.ou_delete_orphans)) |
|
294 | ||
295 |
if import_context.role_delete_orphans: |
|
296 |
# FIXME : delete each role that is in DB but not in the export |
|
297 |
raise DataImportError( |
|
298 |
"Unsupported context value for role_delete_orphans : %s" % ( |
|
299 |
import_context.role_delete_orphans)) |
|
300 | ||
301 |
return result |
src/authentic2/management/commands/export_site.py | ||
---|---|---|
1 |
import json |
|
2 |
import sys |
|
3 | ||
4 |
from django.core.management.base import BaseCommand |
|
5 | ||
6 |
from authentic2.data_transfer import export_site |
|
7 |
from django_rbac.utils import get_role_model |
|
8 | ||
9 | ||
10 |
class Command(BaseCommand): |
|
11 |
help = 'Export site' |
|
12 | ||
13 |
def add_arguments(self, parser): |
|
14 |
parser.add_argument('--output', metavar='FILE', default=None, |
|
15 |
help='name of a file to write output to') |
|
16 | ||
17 |
def handle(self, *args, **options): |
|
18 |
if options['output']: |
|
19 |
output, close = open(options['output'], 'w'), True |
|
20 |
else: |
|
21 |
output, close = sys.stdout, False |
|
22 |
json.dump(export_site(), output, indent=4) |
|
23 |
if close: |
|
24 |
output.close() |
src/authentic2/management/commands/import_site.py | ||
---|---|---|
1 |
import contextlib |
|
2 |
import json |
|
3 |
import sys |
|
4 | ||
5 |
from django.conf import settings |
|
6 |
from django.core.management.base import BaseCommand |
|
7 |
from django.db import transaction |
|
8 |
from django.utils import translation |
|
9 | ||
10 |
from authentic2.data_transfer import import_site, ImportContext |
|
11 | ||
12 | ||
13 |
class DryRunException(Exception): |
|
14 |
pass |
|
15 | ||
16 | ||
17 |
# Borrowed from http://code.activestate.com/recipes/577058/ |
|
18 |
def query_yes_no(question, default="yes"): |
|
19 |
"""Ask a yes/no question via raw_input() and return their answer. |
|
20 | ||
21 |
"question" is a string that is presented to the user. |
|
22 |
"default" is the presumed answer if the user just hits <Enter>. |
|
23 |
It must be "yes" (the default), "no" or None (meaning |
|
24 |
an answer is required of the user). |
|
25 | ||
26 |
The "answer" return value is True for "yes" or False for "no". |
|
27 |
""" |
|
28 |
valid = {"yes": True, "y": True, "ye": True, |
|
29 |
"no": False, "n": False} |
|
30 |
if default is None: |
|
31 |
prompt = " [y/n] " |
|
32 |
elif default == "yes": |
|
33 |
prompt = " [Y/n] " |
|
34 |
elif default == "no": |
|
35 |
prompt = " [y/N] " |
|
36 |
else: |
|
37 |
raise ValueError("invalid default answer: '%s'" % default) |
|
38 | ||
39 |
while True: |
|
40 |
sys.stdout.write(question + prompt) |
|
41 |
choice = raw_input().lower() |
|
42 |
if default is not None and choice == '': |
|
43 |
return valid[default] |
|
44 |
elif choice in valid: |
|
45 |
return valid[choice] |
|
46 |
else: |
|
47 |
sys.stdout.write("Please respond with 'yes' or 'no' " |
|
48 |
"(or 'y' or 'n').\n") |
|
49 | ||
50 | ||
51 |
def create_context_args(options): |
|
52 |
kwargs = {} |
|
53 |
if options['option']: |
|
54 |
for context_op in options['option']: |
|
55 |
context_op = context_op.replace('-', '_') |
|
56 |
if context_op.startswith('no_'): |
|
57 |
kwargs[context_op[3:]] = False |
|
58 |
else: |
|
59 |
kwargs[context_op] = True |
|
60 |
return kwargs |
|
61 | ||
62 | ||
63 |
# Borrowed from https://bugs.python.org/issue10049#msg118599 |
|
64 |
@contextlib.contextmanager |
|
65 |
def provision_contextm(dry_run, settings): |
|
66 |
if dry_run and 'hobo.agent.authentic2' in settings.INSTALLED_APPS: |
|
67 |
import hobo.agent.authentic2 |
|
68 |
with hobo.agent.authentic2.provisionning.Provisionning(): |
|
69 |
yield |
|
70 |
else: |
|
71 |
yield |
|
72 | ||
73 | ||
74 |
class Command(BaseCommand): |
|
75 |
help = 'Import site' |
|
76 | ||
77 |
def add_arguments(self, parser): |
|
78 |
parser.add_argument( |
|
79 |
'filename', metavar='FILENAME', type=str, help='name of file to import') |
|
80 |
parser.add_argument( |
|
81 |
'--dry-run', action='store_true', dest='dry_run', help='Really perform the import') |
|
82 |
parser.add_argument( |
|
83 |
'--noinput', '--no-input', action='store_true', dest='skip_confirm', |
|
84 |
help='Skip confirmation prompt') |
|
85 |
parser.add_argument( |
|
86 |
'-o', '--option', action='append', help='Import context options', |
|
87 |
choices=[ |
|
88 |
'role-delete-orphans', 'ou-delete-orphans', 'no-role-permissions-update', |
|
89 |
'no-role-attributes-update', 'no-role-parentings-update']) |
|
90 | ||
91 |
def handle(self, filename, **options): |
|
92 |
translation.activate(settings.LANGUAGE_CODE) |
|
93 |
dry_run = options['dry_run'] |
|
94 |
skip_confirm = options['skip_confirm'] |
|
95 |
if not (dry_run or skip_confirm): |
|
96 |
if not query_yes_no("Do you really want to perform the import ?"): |
|
97 |
sys.exit() |
|
98 |
msg = "Dry run\n" if dry_run else "Real run\n" |
|
99 |
c_kwargs = create_context_args(options) |
|
100 |
try: |
|
101 |
with open(filename, 'r') as f: |
|
102 |
with provision_contextm(dry_run, settings): |
|
103 |
with transaction.atomic(): |
|
104 |
sys.stdout.write(msg) |
|
105 |
result = import_site(json.load(f), ImportContext(**c_kwargs)) |
|
106 |
if dry_run: |
|
107 |
raise DryRunException() |
|
108 |
except DryRunException: |
|
109 |
pass |
|
110 |
sys.stdout.write(result.to_str()) |
|
111 |
sys.stdout.write("Success\n") |
|
112 |
translation.deactivate() |
src/authentic2/models.py | ||
---|---|---|
406 | 406 |
'roles': [role.to_json() for role in roles], |
407 | 407 |
} |
408 | 408 | |
409 |
def export_json(self, full=False): |
|
410 |
if full: |
|
411 |
raise NotImplementedError() |
|
412 |
return {'name': self.name, 'slug': self.slug, 'ou': self.ou and self.ou.export_json(False)} |
|
413 | ||
409 | 414 | |
410 | 415 |
class AuthorizedRole(models.Model): |
411 | 416 |
service = models.ForeignKey(Service, on_delete=models.CASCADE) |
src/authentic2/utils.py | ||
---|---|---|
1047 | 1047 |
context=ctx, |
1048 | 1048 |
legacy_subject_templates=legacy_subject_templates, |
1049 | 1049 |
legacy_body_templates=legacy_body_templates) |
1050 | ||
1051 | ||
1052 |
def update_model(obj, d): |
|
1053 |
for attr, value in d.items(): |
|
1054 |
setattr(obj, attr, value) |
src/django_rbac/models.py | ||
---|---|---|
114 | 114 |
def __unicode__(self): |
115 | 115 |
return unicode(_(self.name)) |
116 | 116 | |
117 |
def export_json(self): |
|
118 |
return {'slug': self.slug, 'name': self.name} |
|
119 | ||
117 | 120 |
objects = managers.OperationManager() |
118 | 121 | |
119 | 122 | |
... | ... | |
142 | 145 |
self.target and self.target_ct.natural_key(), |
143 | 146 |
self.target and self.target.natural_key()] |
144 | 147 | |
148 |
def export_json(self): |
|
149 |
return { |
|
150 |
"operation": self.operation.export_json(), |
|
151 |
"ou": self.ou and self.ou.export_json(full=False), |
|
152 |
"target_ct": self.target and self.target_ct.natural_key(), |
|
153 |
"target": self.target and self.target.natural_key() |
|
154 |
} |
|
155 | ||
145 | 156 |
def __unicode__(self): |
146 | 157 |
ct = ContentType.objects.get_for_id(self.target_ct_id) |
147 | 158 |
ct_ct = ContentType.objects.get_for_model(ContentType) |
tests/data/export_site.json | ||
---|---|---|
1 |
{ |
|
2 |
"ous": [ |
|
3 |
{ |
|
4 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
5 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
6 |
"slug": "default" |
|
7 |
}, |
|
8 |
{ |
|
9 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
10 |
"name": "ou deux", |
|
11 |
"slug": "ou-deux" |
|
12 |
}, |
|
13 |
{ |
|
14 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
15 |
"name": "ou un ", |
|
16 |
"slug": "ou-un" |
|
17 |
} |
|
18 |
], |
|
19 |
"roles": [ |
|
20 |
{ |
|
21 |
"uuid": "0b47461473144334a3d5266b91adfa55", |
|
22 |
"service": { |
|
23 |
"ou": { |
|
24 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
25 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
26 |
"slug": "default" |
|
27 |
}, |
|
28 |
"name": "Hobo", |
|
29 |
"slug": "hobo" |
|
30 |
}, |
|
31 |
"attributes": [ |
|
32 |
{ |
|
33 |
"kind": "string", |
|
34 |
"name": "is_superuser", |
|
35 |
"value": "true" |
|
36 |
} |
|
37 |
], |
|
38 |
"admin_scope_id": null, |
|
39 |
"ou": { |
|
40 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
41 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
42 |
"slug": "default" |
|
43 |
}, |
|
44 |
"description": "", |
|
45 |
"admin_scope_ct_id": null, |
|
46 |
"external_id": "", |
|
47 |
"slug": "_a2-hobo-superuser", |
|
48 |
"name": "Administrateur de Hobo" |
|
49 |
}, |
|
50 |
{ |
|
51 |
"uuid": "540fe45b326040b2b891fc350635e891", |
|
52 |
"service": { |
|
53 |
"ou": { |
|
54 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
55 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
56 |
"slug": "default" |
|
57 |
}, |
|
58 |
"name": "Portail Citoyen", |
|
59 |
"slug": "portal" |
|
60 |
}, |
|
61 |
"attributes": [ |
|
62 |
{ |
|
63 |
"kind": "string", |
|
64 |
"name": "is_superuser", |
|
65 |
"value": "true" |
|
66 |
} |
|
67 |
], |
|
68 |
"admin_scope_id": null, |
|
69 |
"ou": { |
|
70 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
71 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
72 |
"slug": "default" |
|
73 |
}, |
|
74 |
"description": "", |
|
75 |
"admin_scope_ct_id": null, |
|
76 |
"external_id": "", |
|
77 |
"slug": "_a2-hobo-superuser", |
|
78 |
"name": "Administrateur de Portail Citoyen" |
|
79 |
}, |
|
80 |
{ |
|
81 |
"uuid": "abd2d89a4e354cbc9b8fdc1d977c96da", |
|
82 |
"service": { |
|
83 |
"ou": { |
|
84 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
85 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
86 |
"slug": "default" |
|
87 |
}, |
|
88 |
"name": "D\u00e9marches", |
|
89 |
"slug": "services" |
|
90 |
}, |
|
91 |
"attributes": [ |
|
92 |
{ |
|
93 |
"kind": "string", |
|
94 |
"name": "is_superuser", |
|
95 |
"value": "true" |
|
96 |
} |
|
97 |
], |
|
98 |
"admin_scope_id": null, |
|
99 |
"ou": { |
|
100 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
101 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
102 |
"slug": "default" |
|
103 |
}, |
|
104 |
"description": "", |
|
105 |
"admin_scope_ct_id": null, |
|
106 |
"external_id": "", |
|
107 |
"slug": "_a2-hobo-superuser", |
|
108 |
"name": "Administrateur de D\u00e9marches" |
|
109 |
}, |
|
110 |
{ |
|
111 |
"uuid": "d064a245046743a0baac8513c009554d", |
|
112 |
"service": { |
|
113 |
"ou": { |
|
114 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
115 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
116 |
"slug": "default" |
|
117 |
}, |
|
118 |
"name": "Portail Agent", |
|
119 |
"slug": "portal-agent" |
|
120 |
}, |
|
121 |
"attributes": [ |
|
122 |
{ |
|
123 |
"kind": "string", |
|
124 |
"name": "is_superuser", |
|
125 |
"value": "true" |
|
126 |
} |
|
127 |
], |
|
128 |
"admin_scope_id": null, |
|
129 |
"ou": { |
|
130 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
131 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
132 |
"slug": "default" |
|
133 |
}, |
|
134 |
"description": "", |
|
135 |
"admin_scope_ct_id": null, |
|
136 |
"external_id": "", |
|
137 |
"slug": "_a2-hobo-superuser", |
|
138 |
"name": "Administrateur de Portail Agent" |
|
139 |
}, |
|
140 |
{ |
|
141 |
"uuid": "dce09d79743d496eaa50bbd96c04c65e", |
|
142 |
"service": { |
|
143 |
"ou": { |
|
144 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
145 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
146 |
"slug": "default" |
|
147 |
}, |
|
148 |
"name": "Passerelle", |
|
149 |
"slug": "passerelle" |
|
150 |
}, |
|
151 |
"attributes": [ |
|
152 |
{ |
|
153 |
"kind": "string", |
|
154 |
"name": "is_superuser", |
|
155 |
"value": "true" |
|
156 |
} |
|
157 |
], |
|
158 |
"admin_scope_id": null, |
|
159 |
"ou": { |
|
160 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
161 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
162 |
"slug": "default" |
|
163 |
}, |
|
164 |
"description": "", |
|
165 |
"admin_scope_ct_id": null, |
|
166 |
"external_id": "", |
|
167 |
"slug": "_a2-hobo-superuser", |
|
168 |
"name": "Administrateur de Passerelle" |
|
169 |
}, |
|
170 |
{ |
|
171 |
"uuid": "b043396ad9e942bcb6dd21a467e0f230", |
|
172 |
"service": { |
|
173 |
"ou": { |
|
174 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
175 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
176 |
"slug": "default" |
|
177 |
}, |
|
178 |
"name": "Porte-documents", |
|
179 |
"slug": "porte-doc" |
|
180 |
}, |
|
181 |
"attributes": [ |
|
182 |
{ |
|
183 |
"kind": "string", |
|
184 |
"name": "is_superuser", |
|
185 |
"value": "true" |
|
186 |
} |
|
187 |
], |
|
188 |
"admin_scope_id": null, |
|
189 |
"ou": { |
|
190 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
191 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
192 |
"slug": "default" |
|
193 |
}, |
|
194 |
"description": "", |
|
195 |
"admin_scope_ct_id": null, |
|
196 |
"external_id": "", |
|
197 |
"slug": "_a2-hobo-superuser", |
|
198 |
"name": "Administrateur de Porte-documents" |
|
199 |
}, |
|
200 |
{ |
|
201 |
"uuid": "bc6582d1fec549ff86c5ea6e91756e7b", |
|
202 |
"service": { |
|
203 |
"ou": { |
|
204 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
205 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
206 |
"slug": "default" |
|
207 |
}, |
|
208 |
"name": "Agendas", |
|
209 |
"slug": "agendas" |
|
210 |
}, |
|
211 |
"attributes": [ |
|
212 |
{ |
|
213 |
"kind": "string", |
|
214 |
"name": "is_superuser", |
|
215 |
"value": "true" |
|
216 |
} |
|
217 |
], |
|
218 |
"admin_scope_id": null, |
|
219 |
"ou": { |
|
220 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
221 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
222 |
"slug": "default" |
|
223 |
}, |
|
224 |
"description": "", |
|
225 |
"admin_scope_ct_id": null, |
|
226 |
"external_id": "", |
|
227 |
"slug": "_a2-hobo-superuser", |
|
228 |
"name": "Administrateur de Agendas" |
|
229 |
}, |
|
230 |
{ |
|
231 |
"uuid": "479ada08e2274067b969d290685f1496", |
|
232 |
"service": null, |
|
233 |
"permissions": [ |
|
234 |
{ |
|
235 |
"operation": { |
|
236 |
"slug": "change", |
|
237 |
"name": "Modifier" |
|
238 |
}, |
|
239 |
"ou": null, |
|
240 |
"target_ct": [ |
|
241 |
"a2_rbac", |
|
242 |
"role" |
|
243 |
], |
|
244 |
"target": [ |
|
245 |
"_a2-managers-of-role-role-deux", |
|
246 |
[ |
|
247 |
"default" |
|
248 |
], |
|
249 |
null |
|
250 |
] |
|
251 |
}, |
|
252 |
{ |
|
253 |
"operation": { |
|
254 |
"slug": "view", |
|
255 |
"name": "Visualisation" |
|
256 |
}, |
|
257 |
"ou": null, |
|
258 |
"target_ct": [ |
|
259 |
"contenttypes", |
|
260 |
"contenttype" |
|
261 |
], |
|
262 |
"target": [ |
|
263 |
"custom_user", |
|
264 |
"user" |
|
265 |
] |
|
266 |
}, |
|
267 |
{ |
|
268 |
"operation": { |
|
269 |
"slug": "admin", |
|
270 |
"name": "Administration" |
|
271 |
}, |
|
272 |
"ou": { |
|
273 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
274 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
275 |
"slug": "default" |
|
276 |
}, |
|
277 |
"target_ct": [ |
|
278 |
"a2_rbac", |
|
279 |
"role" |
|
280 |
], |
|
281 |
"target": [ |
|
282 |
"role-deux", |
|
283 |
[ |
|
284 |
"default" |
|
285 |
], |
|
286 |
null |
|
287 |
] |
|
288 |
} |
|
289 |
], |
|
290 |
"admin_scope_id": 9, |
|
291 |
"ou": { |
|
292 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
293 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
294 |
"slug": "default" |
|
295 |
}, |
|
296 |
"description": "", |
|
297 |
"admin_scope_ct_id": 36, |
|
298 |
"external_id": "", |
|
299 |
"slug": "_a2-managers-of-role-role-deux", |
|
300 |
"name": "Administrateur du r\u00f4le \u00ab\u00a0role deux\u00a0\u00bb" |
|
301 |
}, |
|
302 |
{ |
|
303 |
"uuid": "6de808e99fb3442ea7bc4ae8d8c33a43", |
|
304 |
"service": null, |
|
305 |
"permissions": [ |
|
306 |
{ |
|
307 |
"operation": { |
|
308 |
"slug": "change", |
|
309 |
"name": "Modifier" |
|
310 |
}, |
|
311 |
"ou": null, |
|
312 |
"target_ct": [ |
|
313 |
"a2_rbac", |
|
314 |
"role" |
|
315 |
], |
|
316 |
"target": [ |
|
317 |
"_a2-managers-of-role-role-un", |
|
318 |
[ |
|
319 |
"default" |
|
320 |
], |
|
321 |
null |
|
322 |
] |
|
323 |
}, |
|
324 |
{ |
|
325 |
"operation": { |
|
326 |
"slug": "view", |
|
327 |
"name": "Visualisation" |
|
328 |
}, |
|
329 |
"ou": null, |
|
330 |
"target_ct": [ |
|
331 |
"contenttypes", |
|
332 |
"contenttype" |
|
333 |
], |
|
334 |
"target": [ |
|
335 |
"custom_user", |
|
336 |
"user" |
|
337 |
] |
|
338 |
}, |
|
339 |
{ |
|
340 |
"operation": { |
|
341 |
"slug": "admin", |
|
342 |
"name": "Administration" |
|
343 |
}, |
|
344 |
"ou": { |
|
345 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
346 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
347 |
"slug": "default" |
|
348 |
}, |
|
349 |
"target_ct": [ |
|
350 |
"a2_rbac", |
|
351 |
"role" |
|
352 |
], |
|
353 |
"target": [ |
|
354 |
"role-un", |
|
355 |
[ |
|
356 |
"ou-un" |
|
357 |
], |
|
358 |
null |
|
359 |
] |
|
360 |
} |
|
361 |
], |
|
362 |
"admin_scope_id": 7, |
|
363 |
"ou": { |
|
364 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
365 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
366 |
"slug": "default" |
|
367 |
}, |
|
368 |
"description": "", |
|
369 |
"admin_scope_ct_id": 36, |
|
370 |
"external_id": "", |
|
371 |
"slug": "_a2-managers-of-role-role-un", |
|
372 |
"name": "Administrateur du r\u00f4le \u00ab\u00a0role un\u00a0\u00bb" |
|
373 |
}, |
|
374 |
{ |
|
375 |
"description": "role deux descr", |
|
376 |
"slug": "role-deux", |
|
377 |
"name": "role deux", |
|
378 |
"uuid": "9e4f8189c5054c109ae25b8c633eca78", |
|
379 |
"service": null, |
|
380 |
"admin_scope_id": null, |
|
381 |
"admin_scope_ct_id": null, |
|
382 |
"parents": [ |
|
383 |
{ |
|
384 |
"uuid": "aa83b6c8f7f2420ea855b6c06e5f7e80", |
|
385 |
"service": null, |
|
386 |
"admin_scope_id": 26, |
|
387 |
"ou": { |
|
388 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
389 |
"name": "ou un ", |
|
390 |
"slug": "ou-un" |
|
391 |
}, |
|
392 |
"description": "", |
|
393 |
"admin_scope_ct_id": 36, |
|
394 |
"external_id": "", |
|
395 |
"slug": "_a2-managers-of-role-role-un", |
|
396 |
"name": "Administrateur du r\u00f4le \u00ab\u00a0role un\u00a0\u00bb" |
|
397 |
} |
|
398 |
], |
|
399 |
"attributes": [ |
|
400 |
{ |
|
401 |
"kind": "json", |
|
402 |
"name": "emails", |
|
403 |
"value": "[]" |
|
404 |
}, |
|
405 |
{ |
|
406 |
"kind": "json", |
|
407 |
"name": "details", |
|
408 |
"value": "\"role deux detail\"" |
|
409 |
}, |
|
410 |
{ |
|
411 |
"kind": "json", |
|
412 |
"name": "emails_to_members", |
|
413 |
"value": "true" |
|
414 |
} |
|
415 |
], |
|
416 |
"ou": { |
|
417 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
418 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
419 |
"slug": "default" |
|
420 |
}, |
|
421 |
"permissions": [ |
|
422 |
{ |
|
423 |
"operation": { |
|
424 |
"slug": "delete", |
|
425 |
"name": "Supprimer" |
|
426 |
}, |
|
427 |
"ou": { |
|
428 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
429 |
"name": "ou deux", |
|
430 |
"slug": "ou-deux" |
|
431 |
}, |
|
432 |
"target_ct": [ |
|
433 |
"contenttypes", |
|
434 |
"contenttype" |
|
435 |
], |
|
436 |
"target": [ |
|
437 |
"custom_user", |
|
438 |
"user" |
|
439 |
] |
|
440 |
}, |
|
441 |
{ |
|
442 |
"operation": { |
|
443 |
"slug": "search", |
|
444 |
"name": "Rechercher" |
|
445 |
}, |
|
446 |
"ou": { |
|
447 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
448 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
449 |
"slug": "default" |
|
450 |
}, |
|
451 |
"target_ct": [ |
|
452 |
"contenttypes", |
|
453 |
"contenttype" |
|
454 |
], |
|
455 |
"target": [ |
|
456 |
"admin", |
|
457 |
"logentry" |
|
458 |
] |
|
459 |
}, |
|
460 |
{ |
|
461 |
"operation": { |
|
462 |
"slug": "view", |
|
463 |
"name": "Visualisation" |
|
464 |
}, |
|
465 |
"ou": { |
|
466 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
467 |
"name": "ou un ", |
|
468 |
"slug": "ou-un" |
|
469 |
}, |
|
470 |
"target_ct": [ |
|
471 |
"contenttypes", |
|
472 |
"contenttype" |
|
473 |
], |
|
474 |
"target": [ |
|
475 |
"dashboard", |
|
476 |
"dashboardpreferences" |
|
477 |
] |
|
478 |
} |
|
479 |
], |
|
480 |
"external_id": "" |
|
481 |
}, |
|
482 |
{ |
|
483 |
"uuid": "486cf6897b9743b18f74c7047cf054d9", |
|
484 |
"service": null, |
|
485 |
"permissions": [ |
|
486 |
{ |
|
487 |
"operation": { |
|
488 |
"slug": "admin", |
|
489 |
"name": "Administration" |
|
490 |
}, |
|
491 |
"ou": { |
|
492 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
493 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
494 |
"slug": "default" |
|
495 |
}, |
|
496 |
"target_ct": [ |
|
497 |
"contenttypes", |
|
498 |
"contenttype" |
|
499 |
], |
|
500 |
"target": [ |
|
501 |
"a2_rbac", |
|
502 |
"role" |
|
503 |
] |
|
504 |
}, |
|
505 |
{ |
|
506 |
"operation": { |
|
507 |
"slug": "view", |
|
508 |
"name": "Visualisation" |
|
509 |
}, |
|
510 |
"ou": { |
|
511 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
512 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
513 |
"slug": "default" |
|
514 |
}, |
|
515 |
"target_ct": [ |
|
516 |
"contenttypes", |
|
517 |
"contenttype" |
|
518 |
], |
|
519 |
"target": [ |
|
520 |
"custom_user", |
|
521 |
"user" |
|
522 |
] |
|
523 |
}, |
|
524 |
{ |
|
525 |
"operation": { |
|
526 |
"slug": "search", |
|
527 |
"name": "Rechercher" |
|
528 |
}, |
|
529 |
"ou": null, |
|
530 |
"target_ct": [ |
|
531 |
"a2_rbac", |
|
532 |
"organizationalunit" |
|
533 |
], |
|
534 |
"target": [ |
|
535 |
"default" |
|
536 |
] |
|
537 |
} |
|
538 |
], |
|
539 |
"admin_scope_id": 12, |
|
540 |
"ou": { |
|
541 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
542 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
543 |
"slug": "default" |
|
544 |
}, |
|
545 |
"description": "", |
|
546 |
"admin_scope_ct_id": 36, |
|
547 |
"external_id": "", |
|
548 |
"slug": "_a2-administrateur-des-roles-default", |
|
549 |
"name": "R\u00f4les - Collectivit\u00e9 par d\u00e9faut" |
|
550 |
}, |
|
551 |
{ |
|
552 |
"uuid": "d472b169995043ebbe6658b351a70f86", |
|
553 |
"service": null, |
|
554 |
"permissions": [ |
|
555 |
{ |
|
556 |
"operation": { |
|
557 |
"slug": "admin", |
|
558 |
"name": "Administration" |
|
559 |
}, |
|
560 |
"ou": { |
|
561 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
562 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
563 |
"slug": "default" |
|
564 |
}, |
|
565 |
"target_ct": [ |
|
566 |
"contenttypes", |
|
567 |
"contenttype" |
|
568 |
], |
|
569 |
"target": [ |
|
570 |
"custom_user", |
|
571 |
"user" |
|
572 |
] |
|
573 |
}, |
|
574 |
{ |
|
575 |
"operation": { |
|
576 |
"slug": "search", |
|
577 |
"name": "Rechercher" |
|
578 |
}, |
|
579 |
"ou": null, |
|
580 |
"target_ct": [ |
|
581 |
"a2_rbac", |
|
582 |
"organizationalunit" |
|
583 |
], |
|
584 |
"target": [ |
|
585 |
"default" |
|
586 |
] |
|
587 |
} |
|
588 |
], |
|
589 |
"admin_scope_id": 15, |
|
590 |
"ou": { |
|
591 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
592 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
593 |
"slug": "default" |
|
594 |
}, |
|
595 |
"description": "", |
|
596 |
"admin_scope_ct_id": 36, |
|
597 |
"external_id": "", |
|
598 |
"slug": "_a2-administrateur-des-utilisateurs-default", |
|
599 |
"name": "Utilisateurs - Collectivit\u00e9 par d\u00e9faut" |
|
600 |
}, |
|
601 |
{ |
|
602 |
"uuid": "69bd392d338f437eb908d16de3af9723", |
|
603 |
"service": null, |
|
604 |
"permissions": [ |
|
605 |
{ |
|
606 |
"operation": { |
|
607 |
"slug": "admin", |
|
608 |
"name": "Administration" |
|
609 |
}, |
|
610 |
"ou": { |
|
611 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
612 |
"name": "ou deux", |
|
613 |
"slug": "ou-deux" |
|
614 |
}, |
|
615 |
"target_ct": [ |
|
616 |
"contenttypes", |
|
617 |
"contenttype" |
|
618 |
], |
|
619 |
"target": [ |
|
620 |
"a2_rbac", |
|
621 |
"role" |
|
622 |
] |
|
623 |
}, |
|
624 |
{ |
|
625 |
"operation": { |
|
626 |
"slug": "view", |
|
627 |
"name": "Visualisation" |
|
628 |
}, |
|
629 |
"ou": { |
|
630 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
631 |
"name": "ou deux", |
|
632 |
"slug": "ou-deux" |
|
633 |
}, |
|
634 |
"target_ct": [ |
|
635 |
"contenttypes", |
|
636 |
"contenttype" |
|
637 |
], |
|
638 |
"target": [ |
|
639 |
"custom_user", |
|
640 |
"user" |
|
641 |
] |
|
642 |
}, |
|
643 |
{ |
|
644 |
"operation": { |
|
645 |
"slug": "search", |
|
646 |
"name": "Rechercher" |
|
647 |
}, |
|
648 |
"ou": null, |
|
649 |
"target_ct": [ |
|
650 |
"a2_rbac", |
|
651 |
"organizationalunit" |
|
652 |
], |
|
653 |
"target": [ |
|
654 |
"ou-deux" |
|
655 |
] |
|
656 |
} |
|
657 |
], |
|
658 |
"admin_scope_id": 22, |
|
659 |
"ou": { |
|
660 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
661 |
"name": "ou deux", |
|
662 |
"slug": "ou-deux" |
|
663 |
}, |
|
664 |
"description": "", |
|
665 |
"admin_scope_ct_id": 36, |
|
666 |
"external_id": "", |
|
667 |
"slug": "_a2-administrateur-des-roles-ou-deux", |
|
668 |
"name": "R\u00f4les - ou deux" |
|
669 |
}, |
|
670 |
{ |
|
671 |
"uuid": "7ca8d6f933054021a179a3d86ca19efb", |
|
672 |
"service": null, |
|
673 |
"permissions": [ |
|
674 |
{ |
|
675 |
"operation": { |
|
676 |
"slug": "admin", |
|
677 |
"name": "Administration" |
|
678 |
}, |
|
679 |
"ou": { |
|
680 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
681 |
"name": "ou deux", |
|
682 |
"slug": "ou-deux" |
|
683 |
}, |
|
684 |
"target_ct": [ |
|
685 |
"contenttypes", |
|
686 |
"contenttype" |
|
687 |
], |
|
688 |
"target": [ |
|
689 |
"custom_user", |
|
690 |
"user" |
|
691 |
] |
|
692 |
}, |
|
693 |
{ |
|
694 |
"operation": { |
|
695 |
"slug": "search", |
|
696 |
"name": "Rechercher" |
|
697 |
}, |
|
698 |
"ou": null, |
|
699 |
"target_ct": [ |
|
700 |
"a2_rbac", |
|
701 |
"organizationalunit" |
|
702 |
], |
|
703 |
"target": [ |
|
704 |
"ou-deux" |
|
705 |
] |
|
706 |
} |
|
707 |
], |
|
708 |
"admin_scope_id": 25, |
|
709 |
"ou": { |
|
710 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
711 |
"name": "ou deux", |
|
712 |
"slug": "ou-deux" |
|
713 |
}, |
|
714 |
"description": "", |
|
715 |
"admin_scope_ct_id": 36, |
|
716 |
"external_id": "", |
|
717 |
"slug": "_a2-administrateur-des-utilisateurs-ou-deux", |
|
718 |
"name": "Utilisateurs - ou deux" |
|
719 |
}, |
|
720 |
{ |
|
721 |
"uuid": "aa83b6c8f7f2420ea855b6c06e5f7e80", |
|
722 |
"service": null, |
|
723 |
"permissions": [ |
|
724 |
{ |
|
725 |
"operation": { |
|
726 |
"slug": "change", |
|
727 |
"name": "Modifier" |
|
728 |
}, |
|
729 |
"ou": null, |
|
730 |
"target_ct": [ |
|
731 |
"a2_rbac", |
|
732 |
"role" |
|
733 |
], |
|
734 |
"target": [ |
|
735 |
"_a2-managers-of-role-role-un", |
|
736 |
[ |
|
737 |
"ou-un" |
|
738 |
], |
|
739 |
null |
|
740 |
] |
|
741 |
}, |
|
742 |
{ |
|
743 |
"operation": { |
|
744 |
"slug": "view", |
|
745 |
"name": "Visualisation" |
|
746 |
}, |
|
747 |
"ou": null, |
|
748 |
"target_ct": [ |
|
749 |
"contenttypes", |
|
750 |
"contenttype" |
|
751 |
], |
|
752 |
"target": [ |
|
753 |
"custom_user", |
|
754 |
"user" |
|
755 |
] |
|
756 |
}, |
|
757 |
{ |
|
758 |
"operation": { |
|
759 |
"slug": "admin", |
|
760 |
"name": "Administration" |
|
761 |
}, |
|
762 |
"ou": { |
|
763 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
764 |
"name": "ou un ", |
|
765 |
"slug": "ou-un" |
|
766 |
}, |
|
767 |
"target_ct": [ |
|
768 |
"a2_rbac", |
|
769 |
"role" |
|
770 |
], |
|
771 |
"target": [ |
|
772 |
"role-un", |
|
773 |
[ |
|
774 |
"ou-un" |
|
775 |
], |
|
776 |
null |
|
777 |
] |
|
778 |
} |
|
779 |
], |
|
780 |
"admin_scope_id": 26, |
|
781 |
"ou": { |
|
782 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
783 |
"name": "ou un ", |
|
784 |
"slug": "ou-un" |
|
785 |
}, |
|
786 |
"description": "", |
|
787 |
"admin_scope_ct_id": 36, |
|
788 |
"external_id": "", |
|
789 |
"slug": "_a2-managers-of-role-role-un", |
|
790 |
"name": "Administrateur du r\u00f4le \u00ab\u00a0role un\u00a0\u00bb" |
|
791 |
}, |
|
792 |
{ |
|
793 |
"uuid": "241492ead56c4773abf97271ea88b0a9", |
|
794 |
"service": null, |
|
795 |
"permissions": [ |
|
796 |
{ |
|
797 |
"operation": { |
|
798 |
"slug": "admin", |
|
799 |
"name": "Administration" |
|
800 |
}, |
|
801 |
"ou": { |
|
802 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
803 |
"name": "ou un ", |
|
804 |
"slug": "ou-un" |
|
805 |
}, |
|
806 |
"target_ct": [ |
|
807 |
"contenttypes", |
|
808 |
"contenttype" |
|
809 |
], |
|
810 |
"target": [ |
|
811 |
"a2_rbac", |
|
812 |
"role" |
|
813 |
] |
|
814 |
}, |
|
815 |
{ |
|
816 |
"operation": { |
|
817 |
"slug": "view", |
|
818 |
"name": "Visualisation" |
|
819 |
}, |
|
820 |
"ou": { |
|
821 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
822 |
"name": "ou un ", |
|
823 |
"slug": "ou-un" |
|
824 |
}, |
|
825 |
"target_ct": [ |
|
826 |
"contenttypes", |
|
827 |
"contenttype" |
|
828 |
], |
|
829 |
"target": [ |
|
830 |
"custom_user", |
|
831 |
"user" |
|
832 |
] |
|
833 |
}, |
|
834 |
{ |
|
835 |
"operation": { |
|
836 |
"slug": "search", |
|
837 |
"name": "Rechercher" |
|
838 |
}, |
|
839 |
"ou": null, |
|
840 |
"target_ct": [ |
|
841 |
"a2_rbac", |
|
842 |
"organizationalunit" |
|
843 |
], |
|
844 |
"target": [ |
|
845 |
"ou-un" |
|
846 |
] |
|
847 |
} |
|
848 |
], |
|
849 |
"admin_scope_id": 17, |
|
850 |
"ou": { |
|
851 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
852 |
"name": "ou un ", |
|
853 |
"slug": "ou-un" |
|
854 |
}, |
|
855 |
"description": "", |
|
856 |
"admin_scope_ct_id": 36, |
|
857 |
"external_id": "", |
|
858 |
"slug": "_a2-administrateur-des-roles-ou-un", |
|
859 |
"name": "R\u00f4les - ou un " |
|
860 |
}, |
|
861 |
{ |
|
862 |
"description": "role un descr", |
|
863 |
"slug": "role-un", |
|
864 |
"name": "role un", |
|
865 |
"uuid": "8bf850a1d43e4df4a8162d4108366f5c", |
|
866 |
"service": null, |
|
867 |
"admin_scope_id": null, |
|
868 |
"admin_scope_ct_id": null, |
|
869 |
"parents": [ |
|
870 |
{ |
|
871 |
"uuid": "aa83b6c8f7f2420ea855b6c06e5f7e80", |
|
872 |
"service": null, |
|
873 |
"admin_scope_id": 26, |
|
874 |
"ou": { |
|
875 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
876 |
"name": "ou un ", |
|
877 |
"slug": "ou-un" |
|
878 |
}, |
|
879 |
"description": "", |
|
880 |
"admin_scope_ct_id": 36, |
|
881 |
"external_id": "", |
|
882 |
"slug": "_a2-managers-of-role-role-un", |
|
883 |
"name": "Administrateur du r\u00f4le \u00ab\u00a0role un\u00a0\u00bb" |
|
884 |
}, |
|
885 |
{ |
|
886 |
"uuid": "9e4f8189c5054c109ae25b8c633eca78", |
|
887 |
"service": null, |
|
888 |
"admin_scope_id": null, |
|
889 |
"ou": { |
|
890 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
891 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
892 |
"slug": "default" |
|
893 |
}, |
|
894 |
"description": "role deux descr", |
|
895 |
"admin_scope_ct_id": null, |
|
896 |
"external_id": "", |
|
897 |
"slug": "role-deux", |
|
898 |
"name": "role deux" |
|
899 |
} |
|
900 |
], |
|
901 |
"attributes": [ |
|
902 |
{ |
|
903 |
"kind": "json", |
|
904 |
"name": "details", |
|
905 |
"value": "\"role un detail\"" |
|
906 |
}, |
|
907 |
{ |
|
908 |
"kind": "json", |
|
909 |
"name": "emails", |
|
910 |
"value": "[]" |
|
911 |
}, |
|
912 |
{ |
|
913 |
"kind": "json", |
|
914 |
"name": "emails_to_members", |
|
915 |
"value": "true" |
|
916 |
} |
|
917 |
], |
|
918 |
"ou": { |
|
919 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
920 |
"name": "ou un ", |
|
921 |
"slug": "ou-un" |
|
922 |
}, |
|
923 |
"external_id": "" |
|
924 |
}, |
|
925 |
{ |
|
926 |
"uuid": "1b8d7e5f421640f69af5692e876b96d9", |
|
927 |
"service": null, |
|
928 |
"permissions": [ |
|
929 |
{ |
|
930 |
"operation": { |
|
931 |
"slug": "admin", |
|
932 |
"name": "Administration" |
|
933 |
}, |
|
934 |
"ou": { |
|
935 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
936 |
"name": "ou un ", |
|
937 |
"slug": "ou-un" |
|
938 |
}, |
|
939 |
"target_ct": [ |
|
940 |
"contenttypes", |
|
941 |
"contenttype" |
|
942 |
], |
|
943 |
"target": [ |
|
944 |
"custom_user", |
|
945 |
"user" |
|
946 |
] |
|
947 |
}, |
|
948 |
{ |
|
949 |
"operation": { |
|
950 |
"slug": "search", |
|
951 |
"name": "Rechercher" |
|
952 |
}, |
|
953 |
"ou": null, |
|
954 |
"target_ct": [ |
|
955 |
"a2_rbac", |
|
956 |
"organizationalunit" |
|
957 |
], |
|
958 |
"target": [ |
|
959 |
"ou-un" |
|
960 |
] |
|
961 |
} |
|
962 |
], |
|
963 |
"admin_scope_id": 20, |
|
964 |
"ou": { |
|
965 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
966 |
"name": "ou un ", |
|
967 |
"slug": "ou-un" |
|
968 |
}, |
|
969 |
"description": "", |
|
970 |
"admin_scope_ct_id": 36, |
|
971 |
"external_id": "", |
|
972 |
"slug": "_a2-administrateur-des-utilisateurs-ou-un", |
|
973 |
"name": "Utilisateurs - ou un " |
|
974 |
}, |
|
975 |
{ |
|
976 |
"description": "", |
|
977 |
"slug": "_a2-manager", |
|
978 |
"permissions": [ |
|
979 |
{ |
|
980 |
"operation": { |
|
981 |
"slug": "change", |
|
982 |
"name": "Modifier" |
|
983 |
}, |
|
984 |
"ou": null, |
|
985 |
"target_ct": [ |
|
986 |
"a2_rbac", |
|
987 |
"role" |
|
988 |
], |
|
989 |
"target": [ |
|
990 |
"_a2-manager", |
|
991 |
null, |
|
992 |
null |
|
993 |
] |
|
994 |
} |
|
995 |
], |
|
996 |
"uuid": "daf3857c77bd41f0b10fa94a6e360f84", |
|
997 |
"service": null, |
|
998 |
"admin_scope_id": null, |
|
999 |
"admin_scope_ct_id": null, |
|
1000 |
"name": "Administrateur", |
|
1001 |
"parents": [ |
|
1002 |
{ |
|
1003 |
"uuid": "5d1ccc95259b4a0694e9c66ae04293c3", |
|
1004 |
"service": null, |
|
1005 |
"admin_scope_id": 4, |
|
1006 |
"ou": null, |
|
1007 |
"description": "", |
|
1008 |
"admin_scope_ct_id": 36, |
|
1009 |
"external_id": "", |
|
1010 |
"slug": "_a2-administrateur-des-utilisateurs", |
|
1011 |
"name": "Administrateur des utilisateurs" |
|
1012 |
}, |
|
1013 |
{ |
|
1014 |
"uuid": "ab0a5e998a9f47dcad9a90729d4087ea", |
|
1015 |
"service": null, |
|
1016 |
"admin_scope_id": 5, |
|
1017 |
"ou": null, |
|
1018 |
"description": "", |
|
1019 |
"admin_scope_ct_id": 36, |
|
1020 |
"external_id": "", |
|
1021 |
"slug": "_a2-administrateur-des-roles", |
|
1022 |
"name": "Administrateur des r\u00f4les" |
|
1023 |
}, |
|
1024 |
{ |
|
1025 |
"uuid": "9a05246e3f5041b8935f98051aa1054f", |
|
1026 |
"service": null, |
|
1027 |
"admin_scope_id": 6, |
|
1028 |
"ou": null, |
|
1029 |
"description": "", |
|
1030 |
"admin_scope_ct_id": 36, |
|
1031 |
"external_id": "", |
|
1032 |
"slug": "_a2-administrateur-des-entites", |
|
1033 |
"name": "Administrateur des entit\u00e9s" |
|
1034 |
} |
|
1035 |
], |
|
1036 |
"ou": null, |
|
1037 |
"external_id": "" |
|
1038 |
}, |
|
1039 |
{ |
|
1040 |
"description": "", |
|
1041 |
"slug": "_a2-managers-of-default", |
|
1042 |
"permissions": [ |
|
1043 |
{ |
|
1044 |
"operation": { |
|
1045 |
"slug": "view", |
|
1046 |
"name": "Visualisation" |
|
1047 |
}, |
|
1048 |
"ou": null, |
|
1049 |
"target_ct": [ |
|
1050 |
"a2_rbac", |
|
1051 |
"organizationalunit" |
|
1052 |
], |
|
1053 |
"target": [ |
|
1054 |
"default" |
|
1055 |
] |
|
1056 |
} |
|
1057 |
], |
|
1058 |
"uuid": "b2f44cfdedcb48b996ab2885bf024e7c", |
|
1059 |
"service": null, |
|
1060 |
"admin_scope_id": 11, |
|
1061 |
"admin_scope_ct_id": 36, |
|
1062 |
"name": "Administrateur de la collectivit\u00e9 \u00ab\u00a0Collectivit\u00e9 par d\u00e9faut\u00a0\u00bb", |
|
1063 |
"parents": [ |
|
1064 |
{ |
|
1065 |
"uuid": "486cf6897b9743b18f74c7047cf054d9", |
|
1066 |
"service": null, |
|
1067 |
"admin_scope_id": 12, |
|
1068 |
"ou": { |
|
1069 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
1070 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
1071 |
"slug": "default" |
|
1072 |
}, |
|
1073 |
"description": "", |
|
1074 |
"admin_scope_ct_id": 36, |
|
1075 |
"external_id": "", |
|
1076 |
"slug": "_a2-administrateur-des-roles-default", |
|
1077 |
"name": "R\u00f4les - Collectivit\u00e9 par d\u00e9faut" |
|
1078 |
}, |
|
1079 |
{ |
|
1080 |
"uuid": "d472b169995043ebbe6658b351a70f86", |
|
1081 |
"service": null, |
|
1082 |
"admin_scope_id": 15, |
|
1083 |
"ou": { |
|
1084 |
"uuid": "ba60d9e6c2874636883bdd604b23eab2", |
|
1085 |
"name": "Collectivit\u00e9 par d\u00e9faut", |
|
1086 |
"slug": "default" |
|
1087 |
}, |
|
1088 |
"description": "", |
|
1089 |
"admin_scope_ct_id": 36, |
|
1090 |
"external_id": "", |
|
1091 |
"slug": "_a2-administrateur-des-utilisateurs-default", |
|
1092 |
"name": "Utilisateurs - Collectivit\u00e9 par d\u00e9faut" |
|
1093 |
} |
|
1094 |
], |
|
1095 |
"ou": null, |
|
1096 |
"external_id": "" |
|
1097 |
}, |
|
1098 |
{ |
|
1099 |
"description": "", |
|
1100 |
"slug": "_a2-managers-of-ou-deux", |
|
1101 |
"permissions": [ |
|
1102 |
{ |
|
1103 |
"operation": { |
|
1104 |
"slug": "view", |
|
1105 |
"name": "Visualisation" |
|
1106 |
}, |
|
1107 |
"ou": null, |
|
1108 |
"target_ct": [ |
|
1109 |
"a2_rbac", |
|
1110 |
"organizationalunit" |
|
1111 |
], |
|
1112 |
"target": [ |
|
1113 |
"ou-deux" |
|
1114 |
] |
|
1115 |
} |
|
1116 |
], |
|
1117 |
"uuid": "341e1030af4846f9be8f3e520a876220", |
|
1118 |
"service": null, |
|
1119 |
"admin_scope_id": 21, |
|
1120 |
"admin_scope_ct_id": 36, |
|
1121 |
"name": "Administrateur de la collectivit\u00e9 \u00ab\u00a0ou deux\u00a0\u00bb", |
|
1122 |
"parents": [ |
|
1123 |
{ |
|
1124 |
"uuid": "69bd392d338f437eb908d16de3af9723", |
|
1125 |
"service": null, |
|
1126 |
"admin_scope_id": 22, |
|
1127 |
"ou": { |
|
1128 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
1129 |
"name": "ou deux", |
|
1130 |
"slug": "ou-deux" |
|
1131 |
}, |
|
1132 |
"description": "", |
|
1133 |
"admin_scope_ct_id": 36, |
|
1134 |
"external_id": "", |
|
1135 |
"slug": "_a2-administrateur-des-roles-ou-deux", |
|
1136 |
"name": "R\u00f4les - ou deux" |
|
1137 |
}, |
|
1138 |
{ |
|
1139 |
"uuid": "7ca8d6f933054021a179a3d86ca19efb", |
|
1140 |
"service": null, |
|
1141 |
"admin_scope_id": 25, |
|
1142 |
"ou": { |
|
1143 |
"uuid": "dd13db24a1754ed19288dcb147f9e73a", |
|
1144 |
"name": "ou deux", |
|
1145 |
"slug": "ou-deux" |
|
1146 |
}, |
|
1147 |
"description": "", |
|
1148 |
"admin_scope_ct_id": 36, |
|
1149 |
"external_id": "", |
|
1150 |
"slug": "_a2-administrateur-des-utilisateurs-ou-deux", |
|
1151 |
"name": "Utilisateurs - ou deux" |
|
1152 |
} |
|
1153 |
], |
|
1154 |
"ou": null, |
|
1155 |
"external_id": "" |
|
1156 |
}, |
|
1157 |
{ |
|
1158 |
"description": "", |
|
1159 |
"slug": "_a2-managers-of-ou-un", |
|
1160 |
"permissions": [ |
|
1161 |
{ |
|
1162 |
"operation": { |
|
1163 |
"slug": "view", |
|
1164 |
"name": "Visualisation" |
|
1165 |
}, |
|
1166 |
"ou": null, |
|
1167 |
"target_ct": [ |
|
1168 |
"a2_rbac", |
|
1169 |
"organizationalunit" |
|
1170 |
], |
|
1171 |
"target": [ |
|
1172 |
"ou-un" |
|
1173 |
] |
|
1174 |
} |
|
1175 |
], |
|
1176 |
"uuid": "79a890b193914797b5699f5b43ccda01", |
|
1177 |
"service": null, |
|
1178 |
"admin_scope_id": 16, |
|
1179 |
"admin_scope_ct_id": 36, |
|
1180 |
"name": "Administrateur de la collectivit\u00e9 \u00ab\u00a0ou un \u00a0\u00bb", |
|
1181 |
"parents": [ |
|
1182 |
{ |
|
1183 |
"uuid": "241492ead56c4773abf97271ea88b0a9", |
|
1184 |
"service": null, |
|
1185 |
"admin_scope_id": 17, |
|
1186 |
"ou": { |
|
1187 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
1188 |
"name": "ou un ", |
|
1189 |
"slug": "ou-un" |
|
1190 |
}, |
|
1191 |
"description": "", |
|
1192 |
"admin_scope_ct_id": 36, |
|
1193 |
"external_id": "", |
|
1194 |
"slug": "_a2-administrateur-des-roles-ou-un", |
|
1195 |
"name": "R\u00f4les - ou un " |
|
1196 |
}, |
|
1197 |
{ |
|
1198 |
"uuid": "1b8d7e5f421640f69af5692e876b96d9", |
|
1199 |
"service": null, |
|
1200 |
"admin_scope_id": 20, |
|
1201 |
"ou": { |
|
1202 |
"uuid": "0c2eb94896e4440bb2ca53091948cdf4", |
|
1203 |
"name": "ou un ", |
|
1204 |
"slug": "ou-un" |
|
1205 |
}, |
|
1206 |
"description": "", |
|
1207 |
"admin_scope_ct_id": 36, |
|
1208 |
"external_id": "", |
|
1209 |
"slug": "_a2-administrateur-des-utilisateurs-ou-un", |
|
1210 |
"name": "Utilisateurs - ou un " |
|
1211 |
} |
|
1212 |
], |
|
1213 |
"ou": null, |
|
1214 |
"external_id": "" |
|
1215 |
}, |
|
1216 |
{ |
|
1217 |
"uuid": "9a05246e3f5041b8935f98051aa1054f", |
|
1218 |
"service": null, |
|
1219 |
"permissions": [ |
|
1220 |
{ |
|
1221 |
"operation": { |
|
1222 |
"slug": "admin", |
|
1223 |
"name": "Administration" |
|
1224 |
}, |
|
1225 |
"ou": null, |
|
1226 |
"target_ct": [ |
|
1227 |
"contenttypes", |
|
1228 |
"contenttype" |
|
1229 |
], |
|
1230 |
"target": [ |
|
1231 |
"a2_rbac", |
|
1232 |
"organizationalunit" |
|
1233 |
] |
|
1234 |
}, |
|
1235 |
{ |
|
1236 |
"operation": { |
|
1237 |
"slug": "search", |
|
1238 |
"name": "Rechercher" |
|
1239 |
}, |
|
1240 |
"ou": null, |
|
1241 |
"target_ct": [ |
|
1242 |
"contenttypes", |
|
1243 |
"contenttype" |
|
1244 |
], |
|
1245 |
"target": [ |
|
1246 |
"a2_rbac", |
|
1247 |
"organizationalunit" |
|
1248 |
] |
|
1249 |
} |
|
1250 |
], |
|
1251 |
"admin_scope_id": 6, |
|
1252 |
"ou": null, |
|
1253 |
"description": "", |
|
1254 |
"admin_scope_ct_id": 36, |
|
1255 |
"external_id": "", |
|
1256 |
"slug": "_a2-administrateur-des-entites", |
|
1257 |
"name": "Administrateur des entit\u00e9s" |
|
1258 |
}, |
|
1259 |
{ |
|
1260 |
"uuid": "ab0a5e998a9f47dcad9a90729d4087ea", |
|
1261 |
"service": null, |
|
1262 |
"permissions": [ |
|
1263 |
{ |
|
1264 |
"operation": { |
|
1265 |
"slug": "admin", |
|
1266 |
"name": "Administration" |
|
1267 |
}, |
|
1268 |
"ou": null, |
|
1269 |
"target_ct": [ |
|
1270 |
"contenttypes", |
|
1271 |
"contenttype" |
|
1272 |
], |
|
1273 |
"target": [ |
|
1274 |
"a2_rbac", |
|
1275 |
"role" |
|
1276 |
] |
|
1277 |
}, |
|
1278 |
{ |
|
1279 |
"operation": { |
|
1280 |
"slug": "view", |
|
1281 |
"name": "Visualisation" |
|
1282 |
}, |
|
1283 |
"ou": null, |
|
1284 |
"target_ct": [ |
|
1285 |
"contenttypes", |
|
1286 |
"contenttype" |
|
1287 |
], |
|
1288 |
"target": [ |
|
1289 |
"custom_user", |
|
1290 |
"user" |
|
1291 |
] |
|
1292 |
}, |
|
1293 |
{ |
|
1294 |
"operation": { |
|
1295 |
"slug": "search", |
|
1296 |
"name": "Rechercher" |
|
1297 |
}, |
|
1298 |
"ou": null, |
|
1299 |
"target_ct": [ |
|
1300 |
"contenttypes", |
|
1301 |
"contenttype" |
|
1302 |
], |
|
1303 |
"target": [ |
|
1304 |
"a2_rbac", |
|
1305 |
"organizationalunit" |
|
1306 |
] |
|
1307 |
} |
|
1308 |
], |
|
1309 |
"admin_scope_id": 5, |
|
1310 |
"ou": null, |
|
1311 |
"description": "", |
|
1312 |
"admin_scope_ct_id": 36, |
|
1313 |
"external_id": "", |
|
1314 |
"slug": "_a2-administrateur-des-roles", |
|
1315 |
"name": "Administrateur des r\u00f4les" |
|
1316 |
}, |
|
1317 |
{ |
|
1318 |
"uuid": "5d1ccc95259b4a0694e9c66ae04293c3", |
|
1319 |
"service": null, |
|
1320 |
"permissions": [ |
|
1321 |
{ |
|
1322 |
"operation": { |
|
1323 |
"slug": "admin", |
|
1324 |
"name": "Administration" |
|
1325 |
}, |
|
1326 |
"ou": null, |
|
1327 |
"target_ct": [ |
|
1328 |
"contenttypes", |
|
1329 |
"contenttype" |
|
1330 |
], |
|
1331 |
"target": [ |
|
1332 |
"custom_user", |
|
1333 |
"user" |
|
1334 |
] |
|
1335 |
}, |
|
1336 |
{ |
|
1337 |
"operation": { |
|
1338 |
"slug": "search", |
|
1339 |
"name": "Rechercher" |
|
1340 |
}, |
|
1341 |
"ou": null, |
|
1342 |
"target_ct": [ |
|
1343 |
"contenttypes", |
|
1344 |
"contenttype" |
|
1345 |
], |
|
1346 |
"target": [ |
|
1347 |
"a2_rbac", |
|
1348 |
"organizationalunit" |
|
1349 |
] |
|
1350 |
} |
|
1351 |
], |
|
1352 |
"admin_scope_id": 4, |
|
1353 |
"ou": null, |
|
1354 |
"description": "", |
|
1355 |
"admin_scope_ct_id": 36, |
|
1356 |
"external_id": "", |
|
1357 |
"slug": "_a2-administrateur-des-utilisateurs", |
|
1358 |
"name": "Administrateur des utilisateurs" |
|
1359 |
} |
|
1360 |
] |
|
1361 |
} |
tests/test_a2_rbac.py | ||
---|---|---|
1 | 1 |
import pytest |
2 | 2 | |
3 |
from django.contrib.contenttypes.models import ContentType |
|
4 |
from django_rbac.utils import get_permission_model |
|
5 |
from django_rbac.models import Operation |
|
6 |
from authentic2.a2_rbac.models import Role, OrganizationalUnit as OU, RoleAttribute |
|
3 | 7 |
from authentic2.models import Service |
4 |
from authentic2.a2_rbac.models import Role, OrganizationalUnit as OU
|
|
8 |
from authentic2.utils import get_hex_uuid
|
|
5 | 9 | |
6 | 10 | |
7 | 11 |
def test_role_natural_key(db): |
... | ... | |
24 | 28 |
Role.objects.get_by_natural_key(*r2.natural_key()) |
25 | 29 |
with pytest.raises(Role.DoesNotExist): |
26 | 30 |
Role.objects.get_by_natural_key(*r4.natural_key()) |
31 | ||
32 | ||
33 |
def test_basic_role_export_json(db): |
|
34 |
role = Role.objects.create( |
|
35 |
name='basic role', slug='basic-role', description='basic role description') |
|
36 |
role_dict = role.export_json() |
|
37 |
assert role_dict['name'] == role.name |
|
38 |
assert role_dict['slug'] == role.slug |
|
39 |
assert role_dict['uuid'] == role.uuid |
|
40 |
assert role_dict['description'] == role.description |
|
41 |
assert role_dict['admin_scope_id'] == role.admin_scope_id |
|
42 |
assert role_dict['external_id'] == role.external_id |
|
43 |
assert role_dict['ou'] is None |
|
44 |
assert role_dict['service'] is None |
|
45 | ||
46 | ||
47 |
def test_role_with_ou_export_json(db): |
|
48 |
ou = OU.objects.create(name='ou', slug='ou') |
|
49 |
role = Role.objects.create(name='some role', ou=ou) |
|
50 |
role_dict = role.export_json() |
|
51 |
assert role_dict['ou'] == {'uuid': ou.uuid, 'slug': ou.slug, 'name': ou.name} |
|
52 | ||
53 | ||
54 |
def test_role_with_service_export_json(db): |
|
55 |
service = Service.objects.create(name='service name', slug='service-name') |
|
56 |
role = Role.objects.create(name='some role', service=service) |
|
57 |
role_dict = role.export_json() |
|
58 |
assert role_dict['service'] == {'slug': service.slug, 'name': service.name, 'ou': None} |
|
59 | ||
60 | ||
61 |
def test_role_with_service_with_ou_export_json(db): |
|
62 |
ou = OU.objects.create(name='ou', slug='ou') |
|
63 |
service = Service.objects.create(name='service name', slug='service-name', ou=ou) |
|
64 |
role = Role.objects.create(name='some role', service=service) |
|
65 |
role_dict = role.export_json() |
|
66 |
assert role_dict['service'] == { |
|
67 |
'slug': service.slug, 'name': service.name, |
|
68 |
'ou': {'uuid': ou.uuid, 'slug': 'ou', 'name': 'ou'}} |
|
69 | ||
70 | ||
71 |
def test_role_with_attributes_export_json(db): |
|
72 |
role = Role.objects.create(name='some role') |
|
73 |
attr1 = RoleAttribute.objects.create( |
|
74 |
role=role, name='attr1_name', kind='string', value='attr1_value') |
|
75 |
attr2 = RoleAttribute.objects.create( |
|
76 |
role=role, name='attr2_name', kind='string', value='attr2_value') |
|
77 | ||
78 |
role_dict = role.export_json(attributes=True) |
|
79 |
attributes = role_dict['attributes'] |
|
80 |
assert len(attributes) == 2 |
|
81 | ||
82 |
expected_attr_names = set([attr1.name, attr2.name]) |
|
83 |
for attr_dict in attributes: |
|
84 |
assert attr_dict['name'] in expected_attr_names |
|
85 |
expected_attr_names.remove(attr_dict['name']) |
|
86 |
target_attr = RoleAttribute.objects.filter(name=attr_dict['name']).first() |
|
87 |
assert attr_dict['kind'] == target_attr.kind |
|
88 |
assert attr_dict['value'] == target_attr.value |
|
89 | ||
90 | ||
91 |
def test_role_with_parents_export_json(db): |
|
92 |
grand_parent_role = Role.objects.create( |
|
93 |
name='test grand parent role', slug='test-grand-parent-role') |
|
94 |
parent_1_role = Role.objects.create( |
|
95 |
name='test parent 1 role', slug='test-parent-1-role') |
|
96 |
parent_1_role.add_parent(grand_parent_role) |
|
97 |
parent_2_role = Role.objects.create( |
|
98 |
name='test parent 2 role', slug='test-parent-2-role') |
|
99 |
parent_2_role.add_parent(grand_parent_role) |
|
100 |
child_role = Role.objects.create( |
|
101 |
name='test child role', slug='test-child-role') |
|
102 |
child_role.add_parent(parent_1_role) |
|
103 |
child_role.add_parent(parent_2_role) |
|
104 | ||
105 |
child_role_dict = child_role.export_json(parents=True) |
|
106 |
assert child_role_dict['slug'] == child_role.slug |
|
107 |
parents = child_role_dict['parents'] |
|
108 |
assert len(parents) == 2 |
|
109 |
expected_slugs = set([parent_1_role.slug, parent_2_role.slug]) |
|
110 |
for parent in parents: |
|
111 |
assert parent['slug'] in expected_slugs |
|
112 |
expected_slugs.remove(parent['slug']) |
|
113 | ||
114 |
grand_parent_role_dict = grand_parent_role.export_json(parents=True) |
|
115 |
assert grand_parent_role_dict['slug'] == grand_parent_role.slug |
|
116 |
assert 'parents' not in grand_parent_role_dict |
|
117 | ||
118 |
parent_1_role_dict = parent_1_role.export_json(parents=True) |
|
119 |
assert parent_1_role_dict['slug'] == parent_1_role.slug |
|
120 |
parents = parent_1_role_dict['parents'] |
|
121 |
assert len(parents) == 1 |
|
122 |
assert parents[0]['slug'] == grand_parent_role.slug |
|
123 | ||
124 |
parent_2_role_dict = parent_2_role.export_json(parents=True) |
|
125 |
assert parent_2_role_dict['slug'] == parent_2_role.slug |
|
126 |
parents = parent_2_role_dict['parents'] |
|
127 |
assert len(parents) == 1 |
|
128 |
assert parents[0]['slug'] == grand_parent_role.slug |
|
129 | ||
130 | ||
131 |
def test_role_with_permission_export_json(db): |
|
132 |
some_ou = OU.objects.create(name='some ou', slug='some-ou') |
|
133 |
role = Role.objects.create(name='role name', slug='role-slug') |
|
134 |
other_role = Role.objects.create( |
|
135 |
name='other role name', slug='other-role-slug', uuid=get_hex_uuid(), ou=some_ou) |
|
136 |
ou = OU.objects.create(name='basic ou', slug='basic-ou', description='basic ou description') |
|
137 |
Permission = get_permission_model() |
|
138 |
op = Operation.objects.first() |
|
139 |
perm_saml = Permission.objects.create( |
|
140 |
operation=op, ou=ou, |
|
141 |
target_ct=ContentType.objects.get_for_model(ContentType), |
|
142 |
target_id=ContentType.objects.get(app_label="saml", model="libertyprovider").pk) |
|
143 |
role.permissions.add(perm_saml) |
|
144 |
perm_role = Permission.objects.create( |
|
145 |
operation=op, ou=None, |
|
146 |
target_ct=ContentType.objects.get_for_model(Role), |
|
147 |
target_id=other_role.pk) |
|
148 |
role.permissions.add(perm_role) |
|
149 | ||
150 |
export = role.export_json(permissions=True) |
|
151 |
permissions = export['permissions'] |
|
152 |
assert len(permissions) == 2 |
|
153 | ||
154 |
assert permissions[0] == { |
|
155 |
'operation': {'slug': 'add', 'name': 'Add'}, |
|
156 |
'ou': ou.export_json(full=False), |
|
157 |
'target_ct': (u'contenttypes', u'contenttype'), |
|
158 |
'target': (u'saml', u'libertyprovider') |
|
159 |
} |
|
160 |
assert permissions[1] == { |
|
161 |
'operation': {'slug': 'add', 'name': 'Add'}, |
|
162 |
'ou': None, |
|
163 |
'target_ct': (u'a2_rbac', u'role'), |
|
164 |
'target': [u'other-role-slug', ['some-ou'], None] |
|
165 |
} |
|
166 | ||
167 | ||
168 |
def test_ou_export_json(db): |
|
169 |
ou = OU.objects.create( |
|
170 |
name='basic ou', slug='basic-ou', description='basic ou description', |
|
171 |
username_is_unique=True, email_is_unique=True, default=False, validate_emails=True) |
|
172 |
ou_dict = ou.export_json(full=True) |
|
173 |
assert ou_dict['name'] == ou.name |
|
174 |
assert ou_dict['slug'] == ou.slug |
|
175 |
assert ou_dict['uuid'] == ou.uuid |
|
176 |
assert ou_dict['description'] == ou.description |
|
177 |
assert ou_dict['username_is_unique'] == ou.username_is_unique |
|
178 |
assert ou_dict['email_is_unique'] == ou.email_is_unique |
|
179 |
assert ou_dict['default'] == ou.default |
|
180 |
assert ou_dict['validate_emails'] == ou.validate_emails |
tests/test_data_transfer.py | ||
---|---|---|
1 |
import json |
|
2 | ||
3 |
from django_rbac.utils import get_role_model, get_ou_model |
|
4 |
import py |
|
5 |
import pytest |
|
6 | ||
7 |
from authentic2.a2_rbac.models import RoleParenting |
|
8 |
from authentic2.data_transfer import ( |
|
9 |
DataImportError, export_roles, import_site, export_ou, ImportContext, |
|
10 |
RoleDeserializer, search_role, import_ou, build_role_natural_key) |
|
11 |
from authentic2.utils import get_hex_uuid |
|
12 | ||
13 | ||
14 |
Role = get_role_model() |
|
15 |
OU = get_ou_model() |
|
16 | ||
17 | ||
18 |
def test_export_basic_role(db): |
|
19 |
role = Role.objects.create(name='basic role', slug='basic-role', uuid=get_hex_uuid()) |
|
20 |
query_set = Role.objects.filter(uuid=role.uuid) |
|
21 |
roles = export_roles(query_set) |
|
22 |
assert len(roles) == 1 |
|
23 |
role_dict = roles[0] |
|
24 |
for key, value in role.export_json().items(): |
|
25 |
assert role_dict[key] == value |
|
26 | ||
27 | ||
28 |
def test_export_role_with_parents(db): |
|
29 |
grand_parent_role = Role.objects.create( |
|
30 |
name='test grand parent role', slug='test-grand-parent-role', uuid=get_hex_uuid()) |
|
31 |
parent_1_role = Role.objects.create( |
|
32 |
name='test parent 1 role', slug='test-parent-1-role', uuid=get_hex_uuid()) |
|
33 |
parent_1_role.add_parent(grand_parent_role) |
|
34 |
parent_2_role = Role.objects.create( |
|
35 |
name='test parent 2 role', slug='test-parent-2-role', uuid=get_hex_uuid()) |
|
36 |
parent_2_role.add_parent(grand_parent_role) |
|
37 |
child_role = Role.objects.create( |
|
38 |
name='test child role', slug='test-child-role', uuid=get_hex_uuid()) |
|
39 |
child_role.add_parent(parent_1_role) |
|
40 |
child_role.add_parent(parent_2_role) |
|
41 | ||
42 |
query_set = Role.objects.filter(slug__startswith='test').order_by('slug') |
|
43 |
roles = export_roles(query_set) |
|
44 |
assert len(roles) == 4 |
|
45 | ||
46 |
child_role_dict = roles[0] |
|
47 |
assert child_role_dict['slug'] == child_role.slug |
|
48 |
parents = child_role_dict['parents'] |
|
49 |
assert len(parents) == 2 |
|
50 |
expected_slugs = set([parent_1_role.slug, parent_2_role.slug]) |
|
51 |
for parent in parents: |
|
52 |
assert parent['slug'] in expected_slugs |
|
53 |
expected_slugs.remove(parent['slug']) |
|
54 | ||
55 |
grand_parent_role_dict = roles[1] |
|
56 |
assert grand_parent_role_dict['slug'] == grand_parent_role.slug |
|
57 | ||
58 |
parent_1_role_dict = roles[2] |
|
59 |
assert parent_1_role_dict['slug'] == parent_1_role.slug |
|
60 |
parents = parent_1_role_dict['parents'] |
|
61 |
assert len(parents) == 1 |
|
62 |
assert parents[0]['slug'] == grand_parent_role.slug |
|
63 | ||
64 |
parent_2_role_dict = roles[3] |
|
65 |
assert parent_2_role_dict['slug'] == parent_2_role.slug |
|
66 |
parents = parent_2_role_dict['parents'] |
|
67 |
assert len(parents) == 1 |
|
68 |
assert parents[0]['slug'] == grand_parent_role.slug |
|
69 | ||
70 | ||
71 |
def test_export_ou(db): |
|
72 |
ou = OU.objects.create(name='ou name', slug='ou-slug') |
|
73 |
ous = export_ou(OU.objects.filter(name='ou name')) |
|
74 |
assert len(ous) == 1 |
|
75 |
ou_d = ous[0] |
|
76 |
assert ou_d['name'] == ou.name |
|
77 |
assert ou_d['slug'] == ou.slug |
|
78 | ||
79 | ||
80 |
def test_search_role_by_uuid(db): |
|
81 |
uuid = get_hex_uuid() |
|
82 |
role_d = {'uuid': uuid, 'slug': 'role-slug'} |
|
83 |
role = Role.objects.create(**role_d) |
|
84 |
assert role == search_role({'uuid': uuid, 'slug': 'other-role-slug'}) |
|
85 | ||
86 | ||
87 |
def test_search_role_by_slug(db): |
|
88 |
role_d = {'uuid': get_hex_uuid(), 'slug': 'role-slug'} |
|
89 |
role = Role.objects.create(**role_d) |
|
90 |
assert role == search_role({ |
|
91 |
'uuid': get_hex_uuid(), 'slug': 'role-slug', |
|
92 |
'ou': None, 'service': None}) |
|
93 | ||
94 | ||
95 |
def test_search_role_not_found(db): |
|
96 |
assert search_role( |
|
97 |
{ |
|
98 |
'uuid': get_hex_uuid(), 'slug': 'role-slug', 'name': 'role name', |
|
99 |
'ou': None, 'service': None}) is None |
|
100 | ||
101 | ||
102 |
def test_search_role_slug_not_unique(db): |
|
103 |
role1_d = {'uuid': get_hex_uuid(), 'slug': 'role-slug', 'name': 'role name'} |
|
104 |
role2_d = {'uuid': get_hex_uuid(), 'slug': 'role-slug', 'name': 'role name'} |
|
105 |
ou = OU.objects.create(name='some ou', slug='some-ou') |
|
106 |
role1 = Role.objects.create(ou=ou, **role1_d) |
|
107 |
Role.objects.create(**role2_d) |
|
108 |
assert role1 == search_role(role1.export_json()) |
|
109 | ||
110 | ||
111 |
def test_role_deserializer(db): |
|
112 |
rd = RoleDeserializer({ |
|
113 |
'name': 'some role', 'description': 'some role description', 'slug': 'some-role', |
|
114 |
'uuid': get_hex_uuid(), 'ou': None, 'service': None}, ImportContext()) |
|
115 |
assert rd._ou is None |
|
116 |
assert rd._parents is None |
|
117 |
assert rd._attributes is None |
|
118 |
assert rd._obj is None |
|
119 |
role, status = rd.deserialize() |
|
120 |
assert status == 'created' |
|
121 |
assert role.name == 'some role' |
|
122 |
assert role.description == 'some role description' |
|
123 |
assert role.slug == 'some-role' |
|
124 |
assert rd._obj == role |
|
125 | ||
126 | ||
127 |
def test_role_deserializer_with_ou(db): |
|
128 |
ou = OU.objects.create(name='some ou', slug='some-ou') |
|
129 |
rd = RoleDeserializer({ |
|
130 |
'uuid': get_hex_uuid(), 'name': 'some role', 'description': 'some role description', |
|
131 |
'slug': 'some-role', 'ou': {'slug': 'some-ou'}, 'service': None}, ImportContext()) |
|
132 |
role, status = rd.deserialize() |
|
133 |
assert role.ou == ou |
|
134 | ||
135 | ||
136 |
def test_role_deserializer_missing_ou(db): |
|
137 |
with pytest.raises(DataImportError): |
|
138 |
RoleDeserializer({ |
|
139 |
'uuid': get_hex_uuid(), 'name': 'some role', 'description': 'role description', |
|
140 |
'slug': 'some-role', 'ou': {'slug': 'some-ou'}, 'service': None}, |
|
141 |
ImportContext()) |
|
142 | ||
143 | ||
144 |
def test_role_deserializer_update_ou(db): |
|
145 |
ou1 = OU.objects.create(name='ou 1', slug='ou-1') |
|
146 |
ou2 = OU.objects.create(name='ou 2', slug='ou-2') |
|
147 |
uuid = get_hex_uuid() |
|
148 |
existing_role = Role.objects.create(uuid=uuid, slug='some-role', ou=ou1) |
|
149 |
rd = RoleDeserializer({ |
|
150 |
'uuid': uuid, 'name': 'some-role', 'slug': 'some-role', |
|
151 |
'ou': {'slug': 'ou-2'}, 'service': None}, ImportContext()) |
|
152 |
role, status = rd.deserialize() |
|
153 |
assert role == existing_role |
|
154 |
assert role.ou == ou2 |
|
155 | ||
156 | ||
157 |
def test_role_deserializer_update_fields(db): |
|
158 |
uuid = get_hex_uuid() |
|
159 |
existing_role = Role.objects.create(uuid=uuid, slug='some-role', name='some role') |
|
160 |
rd = RoleDeserializer({ |
|
161 |
'uuid': uuid, 'slug': 'some-role', 'name': 'some role changed', |
|
162 |
'ou': None, 'service': None}, ImportContext()) |
|
163 |
role, status = rd.deserialize() |
|
164 |
assert role == existing_role |
|
165 |
assert role.name == 'some role changed' |
|
166 | ||
167 | ||
168 |
def test_role_deserializer_with_attributes(db): |
|
169 | ||
170 |
attributes_data = { |
|
171 |
'attr1_name': dict(name='attr1_name', kind='string', value='attr1_value'), |
|
172 |
'attr2_name': dict(name='attr2_name', kind='string', value='attr2_value') |
|
173 |
} |
|
174 |
rd = RoleDeserializer({ |
|
175 |
'uuid': get_hex_uuid(), 'name': 'some role', 'description': 'some role description', |
|
176 |
'slug': 'some-role', 'attributes': list(attributes_data.values()), |
|
177 |
'ou': None, 'service': None}, ImportContext()) |
|
178 |
role, status = rd.deserialize() |
|
179 |
created, deleted = rd.attributes() |
|
180 |
assert role.attributes.count() == 2 |
|
181 |
assert len(created) == 2 |
|
182 | ||
183 |
for attr in created: |
|
184 |
attr_dict = attributes_data[attr.name] |
|
185 |
assert attr_dict['name'] == attr.name |
|
186 |
assert attr_dict['kind'] == attr.kind |
|
187 |
assert attr_dict['value'] == attr.value |
|
188 |
del attributes_data[attr.name] |
|
189 | ||
190 | ||
191 |
def test_role_deserializer_creates_admin_role(db): |
|
192 |
role_dict = { |
|
193 |
'name': 'some role', 'slug': 'some-role', 'uuid': get_hex_uuid(), |
|
194 |
'ou': None, 'service': None} |
|
195 |
rd = RoleDeserializer(role_dict, ImportContext()) |
|
196 |
rd.deserialize() |
|
197 |
Role.objects.get(slug='_a2-managers-of-role-some-role') |
|
198 | ||
199 | ||
200 |
def test_role_deserializer_parenting_existing_parent(db): |
|
201 |
parent_role_dict = { |
|
202 |
'name': 'grand parent role', 'slug': 'grand-parent-role', 'uuid': get_hex_uuid(), |
|
203 |
'ou': None, 'service': None} |
|
204 |
parent_role = Role.objects.create(**parent_role_dict) |
|
205 |
child_role_dict = { |
|
206 |
'name': 'child role', 'slug': 'child-role', 'parents': [parent_role_dict], |
|
207 |
'uuid': get_hex_uuid(), 'ou': None, 'service': None} |
|
208 | ||
209 |
rd = RoleDeserializer(child_role_dict, ImportContext()) |
|
210 |
child_role, status = rd.deserialize() |
|
211 |
created, deleted = rd.parentings() |
|
212 | ||
213 |
assert len(created) == 1 |
|
214 |
parenting = created[0] |
|
215 |
assert parenting.direct is True |
|
216 |
assert parenting.parent == parent_role |
|
217 |
assert parenting.child == child_role |
|
218 | ||
219 | ||
220 |
def test_role_deserializer_parenting_non_existing_parent(db): |
|
221 |
parent_role_dict = { |
|
222 |
'name': 'grand parent role', 'slug': 'grand-parent-role', 'uuid': get_hex_uuid(), |
|
223 |
'ou': None, 'service': None} |
|
224 |
child_role_dict = { |
|
225 |
'name': 'child role', 'slug': 'child-role', 'parents': [parent_role_dict], |
|
226 |
'uuid': get_hex_uuid(), 'ou': None, 'service': None} |
|
227 |
rd = RoleDeserializer(child_role_dict, ImportContext()) |
|
228 |
rd.deserialize() |
|
229 |
with pytest.raises(DataImportError) as excinfo: |
|
230 |
rd.parentings() |
|
231 | ||
232 |
assert "Could not find role" in str(excinfo.value) |
|
233 | ||
234 | ||
235 |
def test_role_deserializer_permissions(db): |
|
236 |
ou = OU.objects.create(slug='some-ou') |
|
237 |
other_role_dict = { |
|
238 |
'name': 'other role', 'slug': 'other-role-slug', 'uuid': get_hex_uuid(), 'ou': ou} |
|
239 |
other_role = Role.objects.create(**other_role_dict) |
|
240 |
some_role_dict = { |
|
241 |
'name': 'some role', 'slug': 'some-role', 'uuid': get_hex_uuid(), |
|
242 |
'ou': None, 'service': None} |
|
243 |
some_role_dict['permissions'] = [ |
|
244 |
{ |
|
245 |
'operation': {'slug': 'add'}, |
|
246 |
'ou': None, |
|
247 |
'target_ct': (u'a2_rbac', u'role'), |
|
248 |
'target': [u'other-role-slug', ['some-ou'], None] |
|
249 |
} |
|
250 |
] |
|
251 | ||
252 |
import_context = ImportContext() |
|
253 |
rd = RoleDeserializer(some_role_dict, import_context) |
|
254 |
rd.deserialize() |
|
255 |
perm_created, perm_deleted = rd.permissions() |
|
256 | ||
257 |
assert len(perm_created) == 1 |
|
258 |
assert len(perm_deleted) == 0 |
|
259 |
del some_role_dict['permissions'] |
|
260 |
role = Role.objects.get(slug=some_role_dict['slug']) |
|
261 |
assert role.permissions.count() == 1 |
|
262 |
perm = role.permissions.first() |
|
263 |
assert perm.operation.slug == 'add' |
|
264 |
assert not perm.ou |
|
265 |
assert perm.target == other_role |
|
266 | ||
267 |
# that one should delete permissions |
|
268 |
rd = RoleDeserializer(some_role_dict, import_context) |
|
269 |
role, _ = rd.deserialize() |
|
270 |
perm_created, perm_deleted = rd.permissions() |
|
271 |
assert role.permissions.count() == 0 |
|
272 |
assert len(perm_created) == 0 |
|
273 |
assert len(perm_deleted) == 1 |
|
274 | ||
275 | ||
276 |
def import_ou_created(db): |
|
277 |
uuid = get_hex_uuid() |
|
278 |
ou_d = {'uuid': uuid, 'slug': 'ou-slug', 'name': 'ou name'} |
|
279 |
ou, status = import_ou(ou_d) |
|
280 |
assert status == 'created' |
|
281 |
assert ou.uuid == ou_d['uuid'] |
|
282 |
assert ou.slug == ou_d['slug'] |
|
283 |
assert ou.name == ou_d['name'] |
|
284 | ||
285 | ||
286 |
def import_ou_updated(db): |
|
287 |
ou = OU.objects.create(slug='some-ou', name='ou name') |
|
288 |
ou_d = {'uuid': ou.uuid, 'slug': ou.slug, 'name': 'new name'} |
|
289 |
ou_updated, status = import_ou(ou_d) |
|
290 |
assert status == 'updated' |
|
291 |
assert ou == ou_updated |
|
292 |
assert ou.name == 'new name' |
|
293 | ||
294 | ||
295 |
def testi_import_site_empty(): |
|
296 |
res = import_site({}, ImportContext()) |
|
297 |
assert res.roles == {'created': [], 'updated': []} |
|
298 |
assert res.ous == {'created': [], 'updated': []} |
|
299 |
assert res.parentings == {'created': [], 'deleted': []} |
|
300 | ||
301 | ||
302 |
def test_import_site_roles(db): |
|
303 |
parent_role_dict = { |
|
304 |
'name': 'grand parent role', 'slug': 'grand-parent-role', 'uuid': get_hex_uuid(), |
|
305 |
'ou': None, 'service': None} |
|
306 |
child_role_dict = { |
|
307 |
'name': 'child role', 'slug': 'child-role', 'parents': [parent_role_dict], |
|
308 |
'uuid': get_hex_uuid(), 'ou': None, 'service': None} |
|
309 |
roles = [ |
|
310 |
parent_role_dict, |
|
311 |
child_role_dict |
|
312 |
] |
|
313 |
res = import_site({'roles': roles}, ImportContext()) |
|
314 |
created_roles = res.roles['created'] |
|
315 |
assert len(created_roles) == 2 |
|
316 |
parent_role = Role.objects.get(**parent_role_dict) |
|
317 |
del child_role_dict['parents'] |
|
318 |
child_role = Role.objects.get(**child_role_dict) |
|
319 |
assert created_roles[0] == parent_role |
|
320 |
assert created_roles[1] == child_role |
|
321 | ||
322 |
assert len(res.parentings['created']) == 1 |
|
323 |
assert res.parentings['created'][0] == RoleParenting.objects.get( |
|
324 |
child=child_role, parent=parent_role, direct=True) |
|
325 | ||
326 | ||
327 |
def test_roles_import_ignore_technical_role(db): |
|
328 |
roles = [{ |
|
329 |
'name': 'some role', 'description': 'some role description', 'slug': '_some-role'}] |
|
330 |
res = import_site({'roles': roles}, ImportContext()) |
|
331 |
assert res.roles == {'created': [], 'updated': []} |
|
332 | ||
333 | ||
334 |
def test_roles_import_ignore_technical_role_with_service(db): |
|
335 |
roles = [{ |
|
336 |
'name': 'some role', 'description': 'some role description', 'slug': '_some-role'}] |
|
337 |
res = import_site({'roles': roles}, ImportContext()) |
|
338 |
assert res.roles == {'created': [], 'updated': []} |
|
339 | ||
340 | ||
341 |
def test_import_role_handle_manager_role_parenting(db): |
|
342 |
parent_role_dict = { |
|
343 |
'name': 'grand parent role', 'slug': 'grand-parent-role', 'uuid': get_hex_uuid(), |
|
344 |
'ou': None, 'service': None} |
|
345 |
parent_role_manager_dict = { |
|
346 |
'name': 'Administrateur du role grand parent role', |
|
347 |
'slug': '_a2-managers-of-role-grand-parent-role', 'uuid': get_hex_uuid(), |
|
348 |
'ou': None, 'service': None} |
|
349 |
child_role_dict = { |
|
350 |
'name': 'child role', 'slug': 'child-role', |
|
351 |
'parents': [parent_role_dict, parent_role_manager_dict], |
|
352 |
'uuid': get_hex_uuid(), 'ou': None, 'service': None} |
|
353 |
import_site({'roles': [child_role_dict, parent_role_dict]}, ImportContext()) |
|
354 |
child = Role.objects.get(slug='child-role') |
|
355 |
manager = Role.objects.get(slug='_a2-managers-of-role-grand-parent-role') |
|
356 |
RoleParenting.objects.get(child=child, parent=manager, direct=True) |
|
357 | ||
358 | ||
359 |
def test_import_roles_role_delete_orphans(db): |
|
360 |
roles = [{ |
|
361 |
'name': 'some role', 'description': 'some role description', 'slug': '_some-role'}] |
|
362 |
with pytest.raises(DataImportError): |
|
363 |
import_site({'roles': roles}, ImportContext(role_delete_orphans=True)) |
|
364 | ||
365 | ||
366 |
def test_import_ou(db): |
|
367 |
uuid = get_hex_uuid() |
|
368 |
name = 'ou name' |
|
369 |
ous = [{'uuid': uuid, 'slug': 'ou-slug', 'name': name}] |
|
370 |
res = import_site({'ous': ous}, ImportContext()) |
|
371 |
assert len(res.ous['created']) == 1 |
|
372 |
ou = res.ous['created'][0] |
|
373 |
assert ou.uuid == uuid |
|
374 |
assert ou.name == name |
|
375 |
Role.objects.get(slug='_a2-managers-of-ou-slug') |
|
376 | ||
377 | ||
378 |
def test_import_ou_already_existing(db): |
|
379 |
uuid = get_hex_uuid() |
|
380 |
ou_d = {'uuid': uuid, 'slug': 'ou-slug', 'name': 'ou name'} |
|
381 |
ou = OU.objects.create(**ou_d) |
|
382 |
num_ous = OU.objects.count() |
|
383 |
res = import_site({'ous': [ou_d]}, ImportContext()) |
|
384 |
assert len(res.ous['created']) == 0 |
|
385 |
assert num_ous == OU.objects.count() |
|
386 |
assert ou == OU.objects.get(uuid=uuid) |
|
387 | ||
388 | ||
389 |
def test_import_site_raw(db): |
|
390 |
data_dir = py.path.local(__file__).dirpath().join('data') |
|
391 |
export_site = data_dir.join('export_site.json') |
|
392 |
with export_site.open('r') as f: |
|
393 |
json_d = json.load(f) |
|
394 |
result = import_site(json_d, ImportContext()) |
|
395 |
role = Role.objects.get(slug='role-deux') |
|
396 |
assert role.permissions.count() == 3 |
tests/test_import_export_site_cmd.py | ||
---|---|---|
1 |
import __builtin__ |
|
2 |
import json |
|
3 | ||
4 |
from django.core import management |
|
5 |
import pytest |
|
6 | ||
7 |
from django_rbac.utils import get_role_model |
|
8 | ||
9 | ||
10 |
def dummy_export_site(*args): |
|
11 |
return {'roles': [{'name': 'role1'}]} |
|
12 | ||
13 | ||
14 |
def test_export_role_cmd_stdout(db, capsys, monkeypatch): |
|
15 |
import authentic2.management.commands.export_site |
|
16 |
monkeypatch.setattr( |
|
17 |
authentic2.management.commands.export_site, 'export_site', dummy_export_site) |
|
18 |
management.call_command('export_site') |
|
19 |
out, err = capsys.readouterr() |
|
20 |
assert json.loads(out) == dummy_export_site() |
|
21 | ||
22 | ||
23 |
def test_export_role_cmd_to_file(db, monkeypatch, tmpdir): |
|
24 |
import authentic2.management.commands.export_site |
|
25 |
monkeypatch.setattr( |
|
26 |
authentic2.management.commands.export_site, 'export_site', dummy_export_site) |
|
27 |
outfile = tmpdir.join('export.json') |
|
28 |
management.call_command('export_site', '--output', outfile.strpath) |
|
29 |
with outfile.open('r') as f: |
|
30 |
assert json.loads(f.read()) == dummy_export_site() |
|
31 | ||
32 | ||
33 |
def test_import_site_cmd(db, tmpdir, monkeypatch): |
|
34 |
export_file = tmpdir.join('roles-export.json') |
|
35 |
with export_file.open('w'): |
|
36 |
export_file.write(json.dumps({'roles': []})) |
|
37 |
management.call_command('import_site', '--noinput', export_file.strpath) |
|
38 | ||
39 | ||
40 |
def test_import_site_cmd_infos_on_stdout(db, tmpdir, monkeypatch, capsys): |
|
41 |
export_file = tmpdir.join('roles-export.json') |
|
42 |
with export_file.open('w'): |
|
43 |
export_file.write(json.dumps( |
|
44 |
{'roles': [{ |
|
45 |
'uuid': 'dqfewrvesvews2532', 'slug': 'role-slug', 'name': 'role-name', |
|
46 |
'ou': None, 'service': None}]})) |
|
47 | ||
48 |
management.call_command('import_site', '--noinput', export_file.strpath) |
|
49 | ||
50 |
out, err = capsys.readouterr() |
|
51 |
assert "Real run" in out |
|
52 |
assert "1 roles created" in out |
|
53 |
assert "0 roles updated" in out |
|
54 | ||
55 | ||
56 |
def test_import_site_transaction_rollback_on_error(db, tmpdir, monkeypatch, capsys): |
|
57 |
export_file = tmpdir.join('roles-export.json') |
|
58 |
with export_file.open('w'): |
|
59 |
export_file.write(json.dumps({'roles': []})) |
|
60 | ||
61 |
Role = get_role_model() |
|
62 | ||
63 |
def exception_import_site(*args): |
|
64 |
Role.objects.create(slug='role-slug') |
|
65 |
raise Exception() |
|
66 | ||
67 |
import authentic2.management.commands.import_site |
|
68 |
monkeypatch.setattr( |
|
69 |
authentic2.management.commands.import_site, 'import_site', exception_import_site) |
|
70 | ||
71 |
with pytest.raises(Exception): |
|
72 |
management.call_command('import_site', '--noinput', export_file.strpath) |
|
73 | ||
74 |
with pytest.raises(Role.DoesNotExist): |
|
75 |
Role.objects.get(slug='role-slug') |
|
76 | ||
77 | ||
78 |
def test_import_site_transaction_rollback_on_dry_run(db, tmpdir, monkeypatch, capsys): |
|
79 |
export_file = tmpdir.join('roles-export.json') |
|
80 |
with export_file.open('w'): |
|
81 |
export_file.write(json.dumps( |
|
82 |
{'roles': [{ |
|
83 |
'uuid': 'dqfewrvesvews2532', 'slug': 'role-slug', 'name': 'role-name', |
|
84 |
'ou': None, 'service': None}]})) |
|
85 | ||
86 |
Role = get_role_model() |
|
87 | ||
88 |
management.call_command('import_site', '--dry-run', export_file.strpath) |
|
89 | ||
90 |
with pytest.raises(Role.DoesNotExist): |
|
91 |
Role.objects.get(slug='role-slug') |
|
92 | ||
93 | ||
94 |
def test_import_site_cmd_unhandled_context_option(db, tmpdir, monkeypatch, capsys): |
|
95 |
from authentic2.data_transfer import DataImportError |
|
96 | ||
97 |
export_file = tmpdir.join('roles-export.json') |
|
98 |
with export_file.open('w'): |
|
99 |
export_file.write(json.dumps( |
|
100 |
{'roles': [{ |
|
101 |
'uuid': 'dqfewrvesvews2532', 'slug': 'role-slug', 'name': 'role-name', |
|
102 |
'ou': None, 'service': None}]})) |
|
103 | ||
104 |
get_role_model().objects.create(uuid='dqfewrvesvews2532', slug='role-slug', name='role-name') |
|
105 | ||
106 |
with pytest.raises(DataImportError): |
|
107 |
management.call_command( |
|
108 |
'import_site', '--noinput', '-o', 'role-delete-orphans', export_file.strpath) |
|
109 | ||
110 | ||
111 |
def test_import_site_cmd_unknown_context_option(db, tmpdir, monkeypatch, capsys): |
|
112 |
from django.core.management.base import CommandError |
|
113 |
export_file = tmpdir.join('roles-export.json') |
|
114 |
with pytest.raises(CommandError): |
|
115 |
management.call_command('import_site', '--noinput', '-o', 'unknown-option', export_file.strpath) |
|
116 | ||
117 | ||
118 |
def test_import_site_confirm_prompt_yes(db, tmpdir, monkeypatch): |
|
119 |
export_file = tmpdir.join('roles-export.json') |
|
120 |
with export_file.open('w'): |
|
121 |
export_file.write(json.dumps( |
|
122 |
{'roles': [{ |
|
123 |
'uuid': 'dqfewrvesvews2532', 'slug': 'role-slug', 'name': 'role-name', |
|
124 |
'ou': None, 'service': None}]})) |
|
125 | ||
126 |
def yes_raw_input(*args, **kwargs): |
|
127 |
return 'yes' |
|
128 | ||
129 |
monkeypatch.setattr(__builtin__, 'raw_input', yes_raw_input) |
|
130 | ||
131 |
management.call_command('import_site', export_file.strpath, stdin='yes') |
|
132 |
assert get_role_model().objects.get(uuid='dqfewrvesvews2532') |
|
133 | ||
134 | ||
135 |
def test_import_site_confirm_prompt_no(db, monkeypatch, tmpdir): |
|
136 |
export_file = tmpdir.join('roles-export.json') |
|
137 |
with export_file.open('w'): |
|
138 |
export_file.write(json.dumps( |
|
139 |
{'roles': [{ |
|
140 |
'uuid': 'dqfewrvesvews2532', 'slug': 'role-slug', 'name': 'role-name', |
|
141 |
'ou': None, 'service': None}]})) |
|
142 | ||
143 |
def no_raw_input(*args, **kwargs): |
|
144 |
return 'no' |
|
145 | ||
146 |
monkeypatch.setattr(__builtin__, 'raw_input', no_raw_input) |
|
147 | ||
148 |
with pytest.raises(SystemExit): |
|
149 |
management.call_command('import_site', export_file.strpath) |
|
150 | ||
151 |
Role = get_role_model() |
|
152 |
with pytest.raises(Role.DoesNotExist): |
|
153 |
Role.objects.get(uuid='dqfewrvesvews2532') |
|
0 |
- |