Skip to content

Commit 246acf2

Browse files
authored
Merge branch 'main' into minor/expose-api-key-validation
2 parents 7610c60 + f9e5359 commit 246acf2

File tree

8 files changed

+88
-1
lines changed

8 files changed

+88
-1
lines changed

tests/test_sso.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def mock_magic_link_profile(self):
3030
first_name=None,
3131
last_name=None,
3232
role=None,
33+
roles=None,
3334
groups=None,
3435
raw_attributes={},
3536
).dict()

tests/test_user_management.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,3 +1194,59 @@ def test_revoke_invitation(
11941194
)
11951195
assert request_kwargs["method"] == "post"
11961196
assert isinstance(invitation, Invitation)
1197+
1198+
def test_resend_invitation(
1199+
self, capture_and_mock_http_client_request, mock_invitation
1200+
):
1201+
request_kwargs = capture_and_mock_http_client_request(
1202+
self.http_client, mock_invitation, 200
1203+
)
1204+
1205+
invitation = syncify(self.user_management.resend_invitation("invitation_ABCDE"))
1206+
1207+
assert request_kwargs["url"].endswith(
1208+
"user_management/invitations/invitation_ABCDE/resend"
1209+
)
1210+
assert request_kwargs["method"] == "post"
1211+
assert isinstance(invitation, Invitation)
1212+
assert invitation.id == "invitation_ABCDE"
1213+
1214+
def test_resend_invitation_not_found(self, capture_and_mock_http_client_request):
1215+
error_response = {
1216+
"message": "Invitation not found",
1217+
"code": "not_found",
1218+
}
1219+
capture_and_mock_http_client_request(self.http_client, error_response, 404)
1220+
1221+
with pytest.raises(Exception):
1222+
syncify(self.user_management.resend_invitation("invitation_nonexistent"))
1223+
1224+
def test_resend_invitation_expired(self, capture_and_mock_http_client_request):
1225+
error_response = {
1226+
"message": "Invite has expired.",
1227+
"code": "invite_expired",
1228+
}
1229+
capture_and_mock_http_client_request(self.http_client, error_response, 400)
1230+
1231+
with pytest.raises(Exception):
1232+
syncify(self.user_management.resend_invitation("invitation_expired"))
1233+
1234+
def test_resend_invitation_revoked(self, capture_and_mock_http_client_request):
1235+
error_response = {
1236+
"message": "Invite has been revoked.",
1237+
"code": "invite_revoked",
1238+
}
1239+
capture_and_mock_http_client_request(self.http_client, error_response, 400)
1240+
1241+
with pytest.raises(Exception):
1242+
syncify(self.user_management.resend_invitation("invitation_revoked"))
1243+
1244+
def test_resend_invitation_accepted(self, capture_and_mock_http_client_request):
1245+
error_response = {
1246+
"message": "Invite has already been accepted.",
1247+
"code": "invite_accepted",
1248+
}
1249+
capture_and_mock_http_client_request(self.http_client, error_response, 400)
1250+
1251+
with pytest.raises(Exception):
1252+
syncify(self.user_management.resend_invitation("invitation_accepted"))

tests/utils/fixtures/mock_directory_user.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,5 @@ def __init__(self, id):
4949
],
5050
},
5151
role=InlineRole(slug="member"),
52+
roles=[InlineRole(slug="member")],
5253
)

tests/utils/fixtures/mock_profile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def __init__(self, id: str):
1111
first_name="WorkOS",
1212
last_name="Demo",
1313
role={"slug": "admin"},
14+
roles=[{"slug": "admin"}],
1415
groups=["Admins", "Developers"],
1516
organization_id="org_01FG53X8636WSNW2WEKB2C31ZB",
1617
connection_id="conn_01EMH8WAK20T42N2NBMNBCYHAG",

workos/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
__package_url__ = "https://github.com/workos-inc/workos-python"
1414

15-
__version__ = "5.32.0"
15+
__version__ = "5.34.1"
1616

1717
__author__ = "WorkOS"
1818

workos/types/directory_sync/directory_user.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class DirectoryUser(WorkOSModel):
3838
created_at: str
3939
updated_at: str
4040
role: Optional[InlineRole] = None
41+
roles: Optional[Sequence[InlineRole]] = None
4142

4243
def primary_email(self) -> Union[DirectoryUserEmail, None]:
4344
return next((email for email in self.emails if email.primary), None)

workos/types/sso/profile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Profile(WorkOSModel):
2222
last_name: Optional[str] = None
2323
idp_id: str
2424
role: Optional[ProfileRole] = None
25+
roles: Optional[Sequence[ProfileRole]] = None
2526
groups: Optional[Sequence[str]] = None
2627
custom_attributes: Optional[Mapping[str, Any]] = None
2728
raw_attributes: Optional[Mapping[str, Any]] = None

workos/user_management.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
INVITATION_DETAIL_PATH = "user_management/invitations/{0}"
9595
INVITATION_DETAIL_BY_TOKEN_PATH = "user_management/invitations/by_token/{0}"
9696
INVITATION_REVOKE_PATH = "user_management/invitations/{0}/revoke"
97+
INVITATION_RESEND_PATH = "user_management/invitations/{0}/resend"
9798
PASSWORD_RESET_PATH = "user_management/password_reset"
9899
PASSWORD_RESET_DETAIL_PATH = "user_management/password_reset/{0}"
99100

@@ -896,6 +897,17 @@ def revoke_invitation(self, invitation_id: str) -> SyncOrAsync[Invitation]:
896897
"""
897898
...
898899

900+
def resend_invitation(self, invitation_id: str) -> SyncOrAsync[Invitation]:
901+
"""Resends an existing Invitation.
902+
903+
Args:
904+
invitation_id (str): The unique ID of the Invitation.
905+
906+
Returns:
907+
Invitation: Invitation response from WorkOS.
908+
"""
909+
...
910+
899911

900912
class UserManagement(UserManagementModule):
901913
_http_client: SyncHTTPClient
@@ -1584,6 +1596,13 @@ def revoke_invitation(self, invitation_id: str) -> Invitation:
15841596

15851597
return Invitation.model_validate(response)
15861598

1599+
def resend_invitation(self, invitation_id: str) -> Invitation:
1600+
response = self._http_client.request(
1601+
INVITATION_RESEND_PATH.format(invitation_id), method=REQUEST_METHOD_POST
1602+
)
1603+
1604+
return Invitation.model_validate(response)
1605+
15871606

15881607
class AsyncUserManagement(UserManagementModule):
15891608
_http_client: AsyncHTTPClient
@@ -2286,3 +2305,10 @@ async def revoke_invitation(self, invitation_id: str) -> Invitation:
22862305
)
22872306

22882307
return Invitation.model_validate(response)
2308+
2309+
async def resend_invitation(self, invitation_id: str) -> Invitation:
2310+
response = await self._http_client.request(
2311+
INVITATION_RESEND_PATH.format(invitation_id), method=REQUEST_METHOD_POST
2312+
)
2313+
2314+
return Invitation.model_validate(response)

0 commit comments

Comments
 (0)