1212from lib .core .entities import FolderEntity
1313from lib .core .entities import ProjectEntity
1414from lib .core .entities import ProjectSettingEntity
15+ from lib .core .entities import TeamEntity
1516from lib .core .entities import WorkflowEntity
1617from lib .core .exceptions import AppException
1718from lib .core .exceptions import AppValidationException
@@ -915,31 +916,6 @@ def execute(self):
915916 return self ._response
916917
917918
918- class InviteContributorUseCase (BaseUseCase ):
919- def __init__ (
920- self ,
921- backend_service_provider : SuerannotateServiceProvider ,
922- email : str ,
923- team_id : int ,
924- is_admin : bool = False ,
925- ):
926- super ().__init__ ()
927- self ._backend_service = backend_service_provider
928- self ._email = email
929- self ._team_id = team_id
930- self ._is_admin = is_admin
931-
932- def execute (self ):
933- role = (
934- constances .UserRole .ADMIN .value
935- if self ._is_admin
936- else constances .UserRole .ANNOTATOR .value
937- )
938- self ._backend_service .invite_contributor (
939- team_id = self ._team_id , email = self ._email , user_role = role
940- )
941-
942-
943919class SearchContributorsUseCase (BaseUseCase ):
944920 def __init__ (
945921 self ,
@@ -963,3 +939,122 @@ def execute(self):
963939 )
964940 self ._response .data = res
965941 return self ._response
942+
943+
944+ class AddContributorsToProject (BaseReportableUseCae ):
945+ """
946+ Returns tuple of lists (added, skipped)
947+ """
948+
949+ def __init__ (
950+ self ,
951+ reporter : Reporter ,
952+ team : TeamEntity ,
953+ project : ProjectEntity ,
954+ emails : list ,
955+ role : str ,
956+ service : SuerannotateServiceProvider ,
957+ ):
958+ super ().__init__ (reporter )
959+ self ._team = team
960+ self ._project = project
961+ self ._emails = emails
962+ self ._role = role
963+ self ._service = service
964+
965+ @property
966+ def user_role (self ):
967+ return constances .UserRole .get_value (self ._role )
968+
969+ def execute (self ):
970+ team_users = set ()
971+ project_users = {user ["user_id" ] for user in self ._project .users }
972+ for user in self ._team .users :
973+ if user .user_role > constances .UserRole .ADMIN .value :
974+ team_users .add (user .email )
975+ # collecting pending team users which is not admin
976+ for user in self ._team .pending_invitations :
977+ if user ["user_role" ] > constances .UserRole .ADMIN .value :
978+ team_users .add (user ["email" ])
979+ # collecting pending project users which is not admin
980+ for user in self ._project .unverified_users :
981+ if user ["user_role" ] > constances .UserRole .ADMIN .value :
982+ project_users .add (user ["email" ])
983+
984+ to_add = team_users .intersection (self ._emails ) - project_users
985+ to_skip = set (self ._emails ).difference (to_add )
986+
987+ if to_skip :
988+ self .reporter .log_warning (
989+ f"Skipped { len (to_skip )} /{ len (self ._emails )} "
990+ "contributors that are out of the team scope or already have access to the project."
991+ )
992+ if to_add :
993+ response = self ._service .share_project_bulk (
994+ team_id = self ._team .uuid ,
995+ project_id = self ._project .uuid ,
996+ users = [
997+ dict (user_id = user_id , user_role = self .user_role )
998+ for user_id in to_add
999+ ],
1000+ )
1001+ if response and not response .get ("invalidUsers" ):
1002+ self ._response .data = to_add , to_skip
1003+ self .reporter .log_info (
1004+ f"Added { len (to_add )} /{ len (self ._emails )} "
1005+ "contributors to the project <project_name> with the <role> role."
1006+ )
1007+ return self ._response
1008+
1009+
1010+ class InviteContributorsToTeam (BaseReportableUseCae ):
1011+ """
1012+ Returns tuple of lists (added, skipped)
1013+ """
1014+
1015+ def __init__ (
1016+ self ,
1017+ reporter : Reporter ,
1018+ team : TeamEntity ,
1019+ emails : list ,
1020+ set_admin : bool ,
1021+ service : SuerannotateServiceProvider ,
1022+ ):
1023+ super ().__init__ (reporter )
1024+ self ._team = team
1025+ self ._emails = emails
1026+ self ._set_admin = set_admin
1027+ self ._service = service
1028+
1029+ def execute (self ):
1030+ team_users = set ()
1031+ for user in self ._team .users :
1032+ if user .user_role > constances .UserRole .ADMIN .value :
1033+ team_users .add (user .email )
1034+ # collecting pending team users which is not admin
1035+ for user in self ._team .pending_invitations :
1036+ if user ["user_role" ] > constances .UserRole .ADMIN .value :
1037+ team_users .add (user ["email" ])
1038+
1039+ emails = set (self ._emails )
1040+
1041+ to_skip = emails .intersection (team_users )
1042+ to_add = emails .difference (to_skip )
1043+
1044+ if to_skip :
1045+ self .reporter .log_warning (
1046+ f"Found { len (to_skip )} /{ len (self ._emails )} existing members of the team."
1047+ )
1048+ if to_add :
1049+ response = self ._service .invite_contributors (
1050+ team_id = self ._team .uuid ,
1051+ # REMINDER UserRole.VIEWER is the contributor for the teams
1052+ team_role = constances .UserRole .ADMIN .value if self ._set_admin else constances .UserRole .VIEWER .value ,
1053+ emails = to_add
1054+ )
1055+ if response :
1056+ self ._response .data = to_add , to_skip
1057+ self .reporter .log_info (
1058+ f"Sent team <admin/contributor> invitations to { len (to_add )} /{ len (self ._emails )} ."
1059+ )
1060+ return self ._response
0 commit comments