12
12
from services .access_service import AccessService , AuthConfigValidationError , UserRoleAssignmentError
13
13
from core import config
14
14
from db .errors import EntityDoesNotExist
15
- from models .domain .authentication import User , AssignableUser , Role , RoleAssignment
15
+ from models .domain .authentication import AssignedRole , AssignedUser , AssignmentType , User , AssignableUser , Role , RoleAssignment
16
16
from models .domain .workspace import Workspace , WorkspaceRole
17
17
from resources import strings
18
18
from db .repositories .workspaces import WorkspaceRepository
21
21
from cryptography .hazmat .primitives .asymmetric import rsa
22
22
from cryptography .hazmat .backends import default_backend
23
23
from cryptography .hazmat .primitives import serialization
24
+ import json
24
25
25
26
26
27
MICROSOFT_GRAPH_URL = config .MICROSOFT_GRAPH_URL .strip ("/" )
@@ -263,14 +264,14 @@ def _get_user_details(self, roles_graph_data, msgraph_token):
263
264
264
265
return users_graph_data
265
266
266
- def _get_roles_for_principal (self , user_id , roles_graph_data , app_id_to_role_name ) :
267
+ def _get_roles_for_principal (self , user_id , roles_graph_data , app_id_to_role_name , assignmentType : AssignmentType = AssignmentType . APP_ROLE ) -> List [ AssignedRole ] :
267
268
roles = []
268
269
for role_assignment in roles_graph_data ["value" ]:
269
270
if role_assignment ["principalId" ] == user_id :
270
- roles .append (app_id_to_role_name [role_assignment ["appRoleId" ]])
271
+ roles .append (AssignedRole ( id = role_assignment [ "appRoleId" ], displayName = app_id_to_role_name [role_assignment ["appRoleId" ]], type = assignmentType ) )
271
272
return roles
272
273
273
- def _get_users_inc_groups_from_response (self , users_graph_data , roles_graph_data , app_id_to_role_name ) -> List [User ]:
274
+ def _get_users_inc_groups_from_response (self , users_graph_data , roles_graph_data , app_id_to_role_name ) -> List [AssignedUser ]:
274
275
users = []
275
276
for user_data in users_graph_data ["responses" ]:
276
277
if "users" in user_data ["body" ]["@odata.context" ]:
@@ -284,7 +285,7 @@ def _get_users_inc_groups_from_response(self, users_graph_data, roles_graph_data
284
285
user_roles = self ._get_roles_for_principal (user_id , roles_graph_data , app_id_to_role_name )
285
286
286
287
if not any (user .id == user_id for user in users ):
287
- users .append (User (id = user_id , name = user_name , email = user_email , roles = user_roles ))
288
+ users .append (AssignedUser (id = user_id , displayName = user_name , userPrincipalName = user_email , roles = user_roles ))
288
289
else :
289
290
user = next ((user for user in users if user .id == user_id ), None )
290
291
user .roles = list (set (user .roles + user_roles ))
@@ -297,20 +298,21 @@ def _get_users_inc_groups_from_response(self, users_graph_data, roles_graph_data
297
298
user_name = group_member ["displayName" ]
298
299
user_email = group_member ["userPrincipalName" ]
299
300
300
- group_roles = self ._get_roles_for_principal (group_id , roles_graph_data , app_id_to_role_name )
301
+ group_roles = self ._get_roles_for_principal (group_id , roles_graph_data , app_id_to_role_name , AssignmentType . GROUP )
301
302
302
303
if not any (user .id == user_id for user in users ):
303
- users .append (User (id = user_id , name = user_name , email = user_email , roles = group_roles ))
304
+ users .append (AssignedUser (id = user_id , displayName = user_name , userPrincipalName = user_email , roles = group_roles ))
304
305
else :
305
306
user = next ((user for user in users if user .id == user_id ), None )
306
307
user .roles = list (set (user .roles + group_roles ))
307
308
308
309
return users
309
310
310
- def get_workspace_users (self , workspace : Workspace ) -> List [User ]:
311
+ def get_workspace_users (self , workspace : Workspace ) -> List [AssignedUser ]:
311
312
msgraph_token = self ._get_msgraph_token ()
313
+
312
314
sp_graph_data = self ._get_app_sp_graph_data (workspace .properties ["client_id" ])
313
- app_id_to_role_name = {app_role ["id" ]: app_role ["value" ] for app_role in sp_graph_data ["value" ][0 ]["appRoles" ]}
315
+ app_id_to_role_name = {app_role ["id" ]: ( app_role ["displayName" ]) for app_role in sp_graph_data ["value" ][0 ]["appRoles" ]}
314
316
roles_graph_data = self ._get_user_role_assignments (workspace .properties ["sp_id" ], msgraph_token )
315
317
users_graph_data = self ._get_user_details (roles_graph_data , msgraph_token )
316
318
users_inc_groups = self ._get_users_inc_groups_from_response (users_graph_data , roles_graph_data , app_id_to_role_name )
@@ -327,7 +329,7 @@ def get_assignable_users(self, filter: str = "", maxResultCount: int = 5) -> Lis
327
329
328
330
for user_data in graph_data ["value" ]:
329
331
result .append (
330
- AssignableUser (name = user_data ["displayName" ], email = user_data ["userPrincipalName" ])
332
+ AssignableUser (id = user_data ["id" ], displayName = user_data [ "displayName" ], userPrincipalName = user_data ["userPrincipalName" ])
331
333
)
332
334
333
335
return result
@@ -374,72 +376,67 @@ def get_workspace_role_by_name(self, name: str, workspace: Workspace) -> Role:
374
376
375
377
return None
376
378
377
- def get_user_by_email (self , user_email : str ) -> User :
378
- encoded_email = urllib .parse .quote (user_email )
379
- user_by_email_endpoint = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ encoded_email } "
380
- user_data = self ._ms_graph_query (user_by_email_endpoint , "GET" )
381
-
382
- return User (id = user_data ["id" ][0 ], name = user_data ["displayName" ][0 ], email = user_email , roles = [])
383
-
384
- def assign_workspace_user (self , user : User , workspace : Workspace , role : Role ) -> None :
379
+ def assign_workspace_user (self , user_id : str , workspace : Workspace , role_id : str ) -> None :
385
380
# User already has the role, do nothing
386
- if self ._is_user_in_role (user , role ):
381
+ if self ._is_user_in_role (user_id , role_id ):
387
382
return
388
383
if self ._is_workspace_role_group_in_use (workspace ):
389
- return self ._assign_workspace_user_to_application_group (user , workspace , role )
384
+ return self ._assign_workspace_user_to_application_group (user_id , workspace , role_id )
390
385
else :
391
- return self ._assign_workspace_user_to_application (user , workspace , role )
386
+ return self ._assign_workspace_user_to_application (user_id , workspace , role_id )
392
387
393
- def _is_user_in_role (self , user : User , role : Role ) -> bool :
394
- return any (r for r in user .roles if r == role .value )
388
+ def _is_user_in_role (self , user_id : User , role_id : Role ) -> bool :
389
+ user_app_role_query = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ user_id } /appRoleAssignments"
390
+ user_app_roles = self ._ms_graph_query (user_app_role_query , "GET" )
391
+ return any (r for r in user_app_roles ["value" ] if r ["appRoleId" ] == role_id )
395
392
396
393
def _is_workspace_role_group_in_use (self , workspace : Workspace ) -> bool :
397
394
aad_groups_in_user = workspace .properties ["create_aad_groups" ]
398
395
return aad_groups_in_user
399
396
400
- def _get_workspace_group_name (self , workspace : Workspace , role : Role ) -> tuple :
397
+ def _get_workspace_group_name (self , workspace : Workspace , role_id : str ) -> tuple :
401
398
tre_id = workspace .properties ["tre_id" ]
402
399
workspace_id = workspace .properties ["workspace_id" ]
403
400
group_name = ""
404
401
app_role_id_suffix = ""
405
- if role . value == "WorkspaceResearcher" :
402
+ if workspace . properties [ "app_role_id_workspace_researcher" ] == role_id :
406
403
group_name = "Workspace Researchers"
407
404
app_role_id_suffix = "workspace_researcher"
408
- elif role . value == "WorkspaceOwner" :
405
+ elif workspace . properties [ "app_role_id_workspace_owner" ] == role_id :
409
406
group_name = "Workspace Owners"
410
407
app_role_id_suffix = "workspace_owner"
411
- elif role . value == "AirlockManager" :
408
+ elif workspace . properties [ "app_role_id_workspace_airlock_manager" ] == role_id :
412
409
group_name = "Airlock Managers"
413
410
app_role_id_suffix = "workspace_airlock_manager"
414
411
else :
415
- raise UserRoleAssignmentError (f"Unknown role: { role . value } " )
412
+ raise UserRoleAssignmentError (f"Unknown role: { role_id } " )
416
413
417
414
return (f"{ tre_id } -ws-{ workspace_id } { group_name } " , f"app_role_id_{ app_role_id_suffix } " )
418
415
419
- def _assign_workspace_user_to_application_group (self , user : User , workspace : Workspace , role : Role ):
416
+ def _assign_workspace_user_to_application_group (self , user_id : str , workspace : Workspace , role_id : str ):
420
417
msgraph_token = self ._get_msgraph_token ()
421
418
roles_graph_data = self ._get_user_role_assignments (workspace .properties ["sp_id" ], msgraph_token )
422
- group_details = self ._get_workspace_group_name (workspace , role )
419
+ group_details = self ._get_workspace_group_name (workspace , role_id )
423
420
group_name = group_details [0 ]
424
421
workspace_app_role_field = group_details [1 ]
425
422
426
423
for group in [item for item in roles_graph_data ["value" ] if item ["principalType" ] == PrincipalType .Group .value ]:
427
424
if group .get ("principalDisplayName" ) == group_name and group .get ("appRoleId" ) == workspace .properties [workspace_app_role_field ]:
428
- self ._add_user_to_group (user . id , group ["principalId" ])
425
+ self ._add_user_to_group (user_id , group ["principalId" ])
429
426
return
430
427
431
- raise UserRoleAssignmentError (f"Unable to assign user to group with role: { role . value } " )
428
+ raise UserRoleAssignmentError (f"Unable to assign user to group with role: { role_id } " )
432
429
433
- def _remove_workspace_user_from_application_group (self , user : User , workspace : Workspace , role : Role ):
430
+ def _remove_workspace_user_from_application_group (self , user_id : str , workspace : Workspace , role_id : str ):
434
431
msgraph_token = self ._get_msgraph_token ()
435
432
roles_graph_data = self ._get_user_role_assignments (workspace .properties ["sp_id" ], msgraph_token )
436
- group_details = self ._get_workspace_group_name (workspace , role )
433
+ group_details = self ._get_workspace_group_name (workspace , role_id )
437
434
group_name = group_details [0 ]
438
435
workspace_app_role_field = group_details [1 ]
439
436
440
437
for group in [item for item in roles_graph_data ["value" ] if item ["principalType" ] == PrincipalType .Group .value ]:
441
438
if group .get ("principalDisplayName" ) == group_name and group .get ("appRoleId" ) == workspace .properties [workspace_app_role_field ]:
442
- self ._remove_user_from_group (user . id , group ["principalId" ])
439
+ self ._remove_user_from_group (user_id , group ["principalId" ])
443
440
return
444
441
raise UserRoleAssignmentError (f"Unable to assign user to group with role: { role .value } " )
445
442
@@ -459,15 +456,15 @@ def _remove_user_from_group(self, user_id: str, group_id: str):
459
456
response = requests .delete (url , headers = self ._get_auth_header (msgraph_token ))
460
457
return response
461
458
462
- def _assign_workspace_user_to_application (self , user : User , workspace : Workspace , role : Role ):
459
+ def _assign_workspace_user_to_application (self , user_id : str , workspace : Workspace , role_id : str ):
463
460
msgraph_token = self ._get_msgraph_token ()
464
- url = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ user . id } /appRoleAssignments"
461
+ url = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ user_id } /appRoleAssignments"
465
462
application_id = workspace .properties ["sp_id" ]
466
463
467
464
body = {
468
- "principalId" : user . id ,
465
+ "principalId" : user_id ,
469
466
"resourceId" : application_id ,
470
- "appRoleId" : role . id ,
467
+ "appRoleId" : role_id ,
471
468
}
472
469
473
470
response = requests .post (url , json = body , headers = self ._get_auth_header (msgraph_token ))
@@ -479,20 +476,22 @@ def _get_role_assignment_for_user(self, user_id: str, role_id: str) -> dict:
479
476
if role ["appRoleId" ] == role_id :
480
477
return role
481
478
482
- def remove_workspace_role_user_assignment (self , user : User ,
483
- role : Role ,
484
- workspace : Workspace ) -> None :
485
- # Get the role assignment id for the role we want to remove
486
- role_assignment = self . _get_role_assignment_for_user ( user . id , role . id )
487
-
488
- if self . _is_workspace_role_group_in_use ( workspace ) :
489
- self ._remove_workspace_user_from_application_group ( user , workspace , role )
479
+ def remove_workspace_role_user_assignment (self ,
480
+ user_id : str ,
481
+ role_id : str ,
482
+ workspace : Workspace ,
483
+ assignmentType : AssignmentType = AssignmentType . APP_ROLE
484
+ ) -> None :
485
+ if assignmentType == AssignmentType . APP_ROLE :
486
+ self ._remove_workspace_user_from_application ( user_id , role_id )
490
487
else :
491
- self ._remove_workspace_user_from_application (user , role_assignment )
488
+ self ._remove_workspace_user_from_application_group (user_id , workspace , role_id )
489
+
490
+ def _remove_workspace_user_from_application (self , user_id : str , role_id : str ) -> requests .Response :
491
+ role_assignment = self ._get_role_assignment_for_user (user_id , role_id )
492
492
493
- def _remove_workspace_user_from_application (self , user : User , role_assignment : dict ) -> requests .Response :
494
493
msgraph_token = self ._get_msgraph_token ()
495
- url = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ user . id } /appRoleAssignments/{ role_assignment ['id' ]} "
494
+ url = f"{ MICROSOFT_GRAPH_URL } /v1.0/users/{ user_id } /appRoleAssignments/{ role_assignment ['id' ]} "
496
495
response = requests .delete (url , headers = self ._get_auth_header (msgraph_token ))
497
496
return response
498
497
0 commit comments