1- from typing import TYPE_CHECKING , Dict , List , Optional , Union
1+ from typing import TYPE_CHECKING , Dict , List , Set , Optional , Union
22
33from lbox .exceptions import LabelboxError
44
2222 ProjectRole ,
2323 Role ,
2424 User ,
25+ UserGroupRole ,
2526 )
2627
2728
@@ -65,6 +66,7 @@ def invite_user(
6566 email : str ,
6667 role : "Role" ,
6768 project_roles : Optional [List ["ProjectRole" ]] = None ,
69+ user_group_roles : Optional [List ["UserGroupRole" ]] = None ,
6870 ) -> "Invite" :
6971 """
7072 Invite a new member to the org. This will send the user an email invite
@@ -88,6 +90,40 @@ def invite_user(
8890 f"Project roles cannot be set for a user with organization level permissions. Found role name `{ role .name } `, expected `NONE`"
8991 )
9092
93+ if user_group_roles and role .name != "NONE" :
94+ raise ValueError (
95+ f"User Group roles cannot be set for a user with organization level permissions. Found role name `{ role .name } `, expected `NONE`"
96+ )
97+
98+ if user_group_roles :
99+ # The backend can 500 if the same groupId appears more than once.
100+ # We dedupe exact duplicates (same groupId+roleId), but reject
101+ # conflicting assignments (same groupId with different roleId).
102+
103+ deduped_user_group_roles : Dict [str , "UserGroupRole" ] = {}
104+ conflicting_user_group_ids : Set [str ] = set ()
105+
106+ for user_group_role in user_group_roles :
107+ user_group_id = user_group_role .user_group .id
108+ role_id = user_group_role .role .uid
109+
110+ existing = deduped_user_group_roles .get (user_group_id )
111+ if existing is None :
112+ deduped_user_group_roles [user_group_id ] = user_group_role
113+ else :
114+ if existing .role .uid != role_id :
115+ conflicting_user_group_ids .add (user_group_id )
116+
117+ if conflicting_user_group_ids :
118+ conflicts_str = ", " .join (sorted (conflicting_user_group_ids ))
119+ raise ValueError (
120+ "user_group_roles contains conflicting role assignments for "
121+ "the same UserGroup. Each UserGroup may only appear once. "
122+ f"Conflicting user_group.id values: { conflicts_str } "
123+ )
124+
125+ user_group_roles = list (deduped_user_group_roles .values ())
126+
91127 data_param = "data"
92128 query_str = """mutation createInvitesPyApi($%s: [CreateInviteInput!]){
93129 createInvites(data: $%s){ invite { id createdAt organizationRoleName inviteeEmail inviter { %s } }}}""" % (
@@ -104,6 +140,19 @@ def invite_user(
104140 for project_role in project_roles or []
105141 ]
106142
143+ user_group_ids = [
144+ user_group_role .user_group .id
145+ for user_group_role in user_group_roles or []
146+ ]
147+
148+ user_group_with_role_ids = [
149+ {
150+ "groupId" : user_group_role .user_group .id ,
151+ "roleId" : user_group_role .role .uid ,
152+ }
153+ for user_group_role in user_group_roles or []
154+ ]
155+
107156 res = self .client .execute (
108157 query_str ,
109158 {
@@ -114,6 +163,8 @@ def invite_user(
114163 "organizationId" : self .uid ,
115164 "organizationRoleId" : role .uid ,
116165 "projects" : projects ,
166+ "userGroupIds" : user_group_ids ,
167+ "userGroupWithRoleIds" : user_group_with_role_ids ,
117168 }
118169 ]
119170 },
0 commit comments