diff --git a/src/workos/user_management.py b/src/workos/user_management.py index a1324822..b8a72d62 100644 --- a/src/workos/user_management.py +++ b/src/workos/user_management.py @@ -99,6 +99,7 @@ INVITATION_DETAIL_BY_TOKEN_PATH = "user_management/invitations/by_token/{0}" INVITATION_REVOKE_PATH = "user_management/invitations/{0}/revoke" INVITATION_RESEND_PATH = "user_management/invitations/{0}/resend" +INVITATION_ACCEPT_PATH = "user_management/invitations/{0}/accept" PASSWORD_RESET_PATH = "user_management/password_reset" PASSWORD_RESET_DETAIL_PATH = "user_management/password_reset/{0}" USER_FEATURE_FLAGS_PATH = "user_management/users/{0}/feature-flags" @@ -915,6 +916,17 @@ def resend_invitation(self, invitation_id: str) -> SyncOrAsync[Invitation]: """ ... + def accept_invitation(self, invitation_id: str) -> SyncOrAsync[Invitation]: + """Accepts an existing Invitation. + + Args: + invitation_id (str): The unique ID of the Invitation. + + Returns: + Invitation: Invitation response from WorkOS. + """ + ... + def list_feature_flags( self, user_id: str, @@ -1634,6 +1646,13 @@ def resend_invitation(self, invitation_id: str) -> Invitation: return Invitation.model_validate(response) + def accept_invitation(self, invitation_id: str) -> Invitation: + response = self._http_client.request( + INVITATION_ACCEPT_PATH.format(invitation_id), method=REQUEST_METHOD_POST + ) + + return Invitation.model_validate(response) + def list_feature_flags( self, user_id: str, @@ -2373,6 +2392,13 @@ async def resend_invitation(self, invitation_id: str) -> Invitation: return Invitation.model_validate(response) + async def accept_invitation(self, invitation_id: str) -> Invitation: + response = await self._http_client.request( + INVITATION_ACCEPT_PATH.format(invitation_id), method=REQUEST_METHOD_POST + ) + + return Invitation.model_validate(response) + async def list_feature_flags( self, user_id: str, diff --git a/tests/test_user_management.py b/tests/test_user_management.py index dc9267cc..e4dd5b63 100644 --- a/tests/test_user_management.py +++ b/tests/test_user_management.py @@ -1260,6 +1260,44 @@ def test_resend_invitation_accepted(self, capture_and_mock_http_client_request): with pytest.raises(Exception): syncify(self.user_management.resend_invitation("invitation_accepted")) + def test_accept_invitation( + self, capture_and_mock_http_client_request, mock_invitation + ): + request_kwargs = capture_and_mock_http_client_request( + self.http_client, mock_invitation, 200 + ) + + invitation = syncify(self.user_management.accept_invitation("invitation_ABCDE")) + + assert request_kwargs["url"].endswith( + "user_management/invitations/invitation_ABCDE/accept" + ) + assert request_kwargs["method"] == "post" + assert isinstance(invitation, Invitation) + assert invitation.id == "invitation_ABCDE" + + def test_accept_invitation_not_found(self, capture_and_mock_http_client_request): + error_response = { + "message": "Invitation not found", + "code": "not_found", + } + capture_and_mock_http_client_request(self.http_client, error_response, 404) + + with pytest.raises(Exception): + syncify(self.user_management.accept_invitation("invitation_nonexistent")) + + def test_accept_invitation_already_accepted( + self, capture_and_mock_http_client_request + ): + error_response = { + "message": "Invite has already been accepted.", + "code": "invite_accepted", + } + capture_and_mock_http_client_request(self.http_client, error_response, 400) + + with pytest.raises(Exception): + syncify(self.user_management.accept_invitation("invitation_accepted")) + def test_list_feature_flags( self, mock_feature_flags, capture_and_mock_http_client_request ):