Skip to content

Commit 2aa2bb6

Browse files
authored
Add ability to resend invitations (#494)
1 parent 1ab4cb4 commit 2aa2bb6

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

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"))

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)