diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bfd387..5b39ac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to ## [Unreleased] +### Added + +- ✨(invitations) can delete domain invitations + ## [1.22.2] - 2026-01-26 ### Fixed diff --git a/src/backend/mailbox_manager/api/client/viewsets.py b/src/backend/mailbox_manager/api/client/viewsets.py index d992e73..63a8735 100644 --- a/src/backend/mailbox_manager/api/client/viewsets.py +++ b/src/backend/mailbox_manager/api/client/viewsets.py @@ -348,6 +348,7 @@ class MailDomainInvitationViewset( mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, + mixins.DestroyModelMixin, viewsets.GenericViewSet, ): """API ViewSet for user invitations to domain management. @@ -365,6 +366,9 @@ class MailDomainInvitationViewset( PUT / PATCH : Not permitted. Instead of updating your invitation, delete and create a new one. + + DELETE /api//mail-domains//invitations/:/ + Delete targeted invitation """ lookup_field = "id" diff --git a/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_delete.py b/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_delete.py new file mode 100644 index 0000000..c92a83e --- /dev/null +++ b/src/backend/mailbox_manager/tests/api/invitations/test_api_domain_invitations_delete.py @@ -0,0 +1,59 @@ +""" +Tests for MailDomainInvitations API endpoint in People's app mailbox_manager. +Focus on "delete" action. +""" + +import pytest +from rest_framework import status +from rest_framework.test import APIClient + +from mailbox_manager import factories + +pytestmark = pytest.mark.django_db + + +def test_api_domain_invitations__delete__anonymous(): + """Anonymous users should not be able to delete invitations.""" + domain = factories.MailDomainEnabledFactory() + invitation = factories.MailDomainInvitationFactory() + + response = APIClient().delete( + f"/api/v1.0/mail-domains/{domain.slug}/invitations/{invitation.id}/", + ) + assert response.status_code == status.HTTP_401_UNAUTHORIZED + assert response.json() == { + "detail": "Authentication credentials were not provided." + } + + +def test_api_domain_invitations__delete__no_access_not_found(): + """Users should not be permitted to delete invitations + on domains they don't manage.""" + domain = factories.MailDomainEnabledFactory() + invitation = factories.MailDomainInvitationFactory() + + other_access = factories.MailDomainAccessFactory(role="owner") # unrelated access + client = APIClient() + client.force_login(other_access.user) + + response = client.delete( + f"/api/v1.0/mail-domains/{domain.slug}/invitations/{invitation.id}/", + ) + assert response.status_code == status.HTTP_404_NOT_FOUND + + +@pytest.mark.parametrize( + "role", + ["owner", "administrator"], +) +def test_api_domain_invitations__delete_admins_ok(role): + """Domain owners and admins should be able to delete invitations.""" + access = factories.MailDomainAccessFactory(role=role) + invitation = factories.MailDomainInvitationFactory(domain=access.domain) + + client = APIClient() + client.force_login(access.user) + response = client.delete( + f"/api/v1.0/mail-domains/{access.domain.slug}/invitations/{invitation.id}/", + ) + assert response.status_code == status.HTTP_204_NO_CONTENT