13
13
UserPermissionGroupOrganisationPermission ,
14
14
)
15
15
from projects .models import (
16
+ Project ,
16
17
UserPermissionGroupProjectPermission ,
17
18
UserProjectPermission ,
18
19
)
19
20
20
- from .permission_service import is_user_project_admin
21
21
from .rbac_wrapper import ( # type: ignore[attr-defined]
22
22
get_roles_permission_data_for_environment ,
23
23
get_roles_permission_data_for_organisation ,
@@ -99,6 +99,8 @@ class DetailedPermissionsData:
99
99
@dataclass
100
100
class UserDetailedPermissionsData :
101
101
admin : bool
102
+ derived_from : PermissionDerivedFromData
103
+ is_directly_granted : bool
102
104
permissions : typing .List [DetailedPermissionsData ]
103
105
104
106
@@ -113,15 +115,21 @@ class PermissionData:
113
115
roles : typing .List [RolePermissionData ]
114
116
is_organisation_admin : bool = False
115
117
admin_override : bool = False
118
+ inherited_admin_groups : typing .List [GroupPermissionData ] = field (
119
+ default_factory = list
120
+ )
121
+ inherited_admin_roles : typing .List [RolePermissionData ] = field (default_factory = list )
116
122
117
123
@property
118
124
def admin (self ) -> bool :
119
- return (
125
+ return bool (
120
126
self .is_organisation_admin
121
127
or self .user .admin
122
128
or any (group .admin for group in self .groups )
123
129
or any (role .admin for role in self .roles )
124
130
or self .admin_override
131
+ or self .inherited_admin_groups
132
+ or self .inherited_admin_roles
125
133
)
126
134
127
135
@property
@@ -157,8 +165,10 @@ def tag_based_permissions(self) -> list[dict]: # type: ignore[type-arg]
157
165
if role_permission .role .tags
158
166
]
159
167
160
- def to_detailed_permissions_data (self ) -> UserDetailedPermissionsData :
168
+ def to_detailed_permissions_data (self ) -> UserDetailedPermissionsData : # noqa: C901
161
169
permission_map = {}
170
+ is_admin_permission_directly_granted = False
171
+ admin_permission_derived_from = PermissionDerivedFromData ()
162
172
163
173
def add_permission (
164
174
permission_key : str ,
@@ -178,32 +188,38 @@ def add_permission(
178
188
179
189
# Add user's direct permissions
180
190
for permission_key in self .user .permissions :
191
+ if self .user .admin :
192
+ is_admin_permission_directly_granted = True
193
+
181
194
add_permission (permission_key , None , None )
182
195
183
196
# Add group permissions
184
197
for group_permission in self .groups :
198
+ if group_permission .admin :
199
+ admin_permission_derived_from .groups .append (group_permission .group )
200
+
185
201
for permission_key in group_permission .permissions :
186
202
add_permission (permission_key , group_permission .group , None )
187
203
188
204
# Add role permissions
189
205
for role_permission in self .roles :
206
+ if role_permission .admin :
207
+ admin_permission_derived_from .roles .append (role_permission .role )
208
+
190
209
for permission_key in role_permission .permissions :
191
210
add_permission (permission_key , None , role_permission .role )
192
211
212
+ if self .is_organisation_admin or self .user .admin or self .admin_override :
213
+ is_admin_permission_directly_granted = True
214
+
193
215
return UserDetailedPermissionsData (
194
- admin = self .admin , permissions = list (permission_map .values ())
216
+ admin = self .admin ,
217
+ is_directly_granted = is_admin_permission_directly_granted ,
218
+ derived_from = admin_permission_derived_from ,
219
+ permissions = list (permission_map .values ()),
195
220
)
196
221
197
222
198
- def get_project_permission_data (project_id : int , user_id : int ) -> PermissionData :
199
- project_permission_svc = _ProjectPermissionService (project_id , user_id )
200
- return PermissionData (
201
- groups = get_groups_permission_data (project_permission_svc .group_qs ),
202
- user = get_user_permission_data (project_permission_svc .user_permission ), # type: ignore[arg-type]
203
- roles = get_roles_permission_data_for_project (project_id , user_id ),
204
- )
205
-
206
-
207
223
def get_organisation_permission_data (
208
224
organisation_id : int , user : "FFAdminUser"
209
225
) -> PermissionData :
@@ -212,19 +228,42 @@ def get_organisation_permission_data(
212
228
is_organisation_admin = user .is_organisation_admin (organisation_id ),
213
229
groups = get_groups_permission_data (org_permission_svc .group_qs ),
214
230
user = get_user_permission_data (org_permission_svc .user_permission ), # type: ignore[arg-type]
215
- roles = get_roles_permission_data_for_organisation (organisation_id , user .id ),
231
+ roles = org_permission_svc .roles ,
232
+ )
233
+
234
+
235
+ def get_project_permission_data (
236
+ project : Project , user : "FFAdminUser"
237
+ ) -> PermissionData :
238
+ project_permission_svc = _ProjectPermissionService (project .id , user .id )
239
+ return PermissionData (
240
+ is_organisation_admin = user .is_organisation_admin (project .organisation_id ),
241
+ groups = get_groups_permission_data (project_permission_svc .group_qs ),
242
+ user = get_user_permission_data (project_permission_svc .user_permission ), # type: ignore[arg-type]
243
+ roles = project_permission_svc .roles ,
216
244
)
217
245
218
246
219
247
def get_environment_permission_data (
220
248
environment : "Environment" , user : "FFAdminUser"
221
249
) -> PermissionData :
222
- environment_permission_svc = _EnvironmentPermissionService (environment .id , user .id )
250
+ project_permission_svc = _ProjectPermissionService (environment .project_id , user .id )
251
+ environment_permission_svc = _EnvironmentPermissionService (
252
+ environment .id , user .id , project_permission_svc = project_permission_svc
253
+ )
254
+
223
255
return PermissionData (
256
+ is_organisation_admin = user .is_organisation_admin (
257
+ environment .project .organisation_id
258
+ ),
224
259
groups = get_groups_permission_data (environment_permission_svc .group_qs ),
225
260
user = get_user_permission_data (environment_permission_svc .user_permission ), # type: ignore[arg-type]
226
- roles = get_roles_permission_data_for_environment (environment .id , user .id ),
227
- admin_override = is_user_project_admin (user , project = environment .project ),
261
+ roles = environment_permission_svc .roles_data ,
262
+ inherited_admin_groups = get_groups_permission_data (
263
+ environment_permission_svc .inherited_admin_group_qs
264
+ ),
265
+ inherited_admin_roles = environment_permission_svc .inherited_admin_roles ,
266
+ admin_override = environment_permission_svc .inherited_user_admin ,
228
267
)
229
268
230
269
@@ -289,11 +328,46 @@ def group_qs(self) -> GroupPermissionQs:
289
328
group__users = self .user_id , organisation = self .organisation_id
290
329
)
291
330
331
+ @property
332
+ def roles (self ) -> typing .List [RolePermissionData ]:
333
+ roles_permission_data : typing .List [RolePermissionData ] = (
334
+ get_roles_permission_data_for_organisation (
335
+ self .organisation_id , self .user_id
336
+ )
337
+ )
338
+ return roles_permission_data
339
+
340
+
341
+ @dataclass
342
+ class _ProjectPermissionService :
343
+ project_id : int
344
+ user_id : int
345
+
346
+ @property
347
+ def user_permission (self ) -> typing .Optional [UserProjectPermission ]:
348
+ return UserProjectPermission .objects .filter (
349
+ project_id = self .project_id , user_id = self .user_id
350
+ ).first ()
351
+
352
+ @property
353
+ def group_qs (self ) -> GroupPermissionQs :
354
+ return UserPermissionGroupProjectPermission .objects .filter (
355
+ group__users = self .user_id , project = self .project_id
356
+ )
357
+
358
+ @property
359
+ def roles (self ) -> typing .List [RolePermissionData ]:
360
+ roles_permission_data : typing .List [RolePermissionData ] = (
361
+ get_roles_permission_data_for_project (self .project_id , self .user_id )
362
+ )
363
+ return roles_permission_data
364
+
292
365
293
366
@dataclass
294
367
class _EnvironmentPermissionService :
295
368
environment_id : int
296
369
user_id : int
370
+ project_permission_svc : _ProjectPermissionService
297
371
298
372
@property
299
373
def user_permission (self ) -> typing .Optional [UserEnvironmentPermission ]:
@@ -307,20 +381,23 @@ def group_qs(self) -> GroupPermissionQs:
307
381
group__users = self .user_id , environment = self .environment_id
308
382
)
309
383
384
+ @property
385
+ def roles_data (self ) -> typing .List [RolePermissionData ]:
386
+ roles_permission_data : typing .List [RolePermissionData ] = (
387
+ get_roles_permission_data_for_environment (self .environment_id , self .user_id )
388
+ )
389
+ return roles_permission_data
310
390
311
- @dataclass
312
- class _ProjectPermissionService :
313
- project_id : int
314
- user_id : int
391
+ @property
392
+ def inherited_user_admin (self ) -> bool :
393
+ if user_permission := self .project_permission_svc .user_permission :
394
+ return user_permission .admin
395
+ return False
315
396
316
397
@property
317
- def user_permission (self ) -> typing .Optional [UserProjectPermission ]:
318
- return UserProjectPermission .objects .filter (
319
- project_id = self .project_id , user_id = self .user_id
320
- ).first ()
398
+ def inherited_admin_group_qs (self ) -> GroupPermissionQs :
399
+ return self .project_permission_svc .group_qs .filter (admin = True )
321
400
322
401
@property
323
- def group_qs (self ) -> GroupPermissionQs :
324
- return UserPermissionGroupProjectPermission .objects .filter (
325
- group__users = self .user_id , project = self .project_id
326
- )
402
+ def inherited_admin_roles (self ) -> typing .List [RolePermissionData ]:
403
+ return [role for role in self .project_permission_svc .roles if role .admin ]
0 commit comments