From 02c6048d2cc630d949063284073b0222f01dcf1b Mon Sep 17 00:00:00 2001 From: Sabrina Demagny Date: Tue, 26 Nov 2024 12:26:54 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(mailbox)=20allow=20to=20activate=20ma?= =?UTF-8?q?ilbox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We send a request to dimail API and change mailbox status to enabled. --- CHANGELOG.md | 1 + .../mailbox_manager/api/client/viewsets.py | 13 +++ .../mailboxes/test_api_mailboxes_enable.py | 99 +++++++++++++++++++ src/backend/mailbox_manager/utils/dimail.py | 19 ++++ 4 files changed, 132 insertions(+) create mode 100644 src/backend/mailbox_manager/tests/api/mailboxes/test_api_mailboxes_enable.py diff --git a/CHANGELOG.md b/CHANGELOG.md index b0a726d..c64564b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to ### Added +- ✨(mailbox) allow to activate mailbox - ✨(mailbox) allow to disable mailbox - ✨(backend) add ServiceProvider #522 - 💄(admin) allow header color customization #552 diff --git a/src/backend/mailbox_manager/api/client/viewsets.py b/src/backend/mailbox_manager/api/client/viewsets.py index 5b32c67..a6b12a0 100644 --- a/src/backend/mailbox_manager/api/client/viewsets.py +++ b/src/backend/mailbox_manager/api/client/viewsets.py @@ -201,6 +201,9 @@ class MailBoxViewSet( POST /api//mail-domains//mailboxes//disable/ Send a request to dimail to disable mailbox and change status of the mailbox in our DB + + POST /api//mail-domains//mailboxes//enable/ + Send a request to dimail to enable mailbox and change status of the mailbox in our DB """ permission_classes = [permissions.MailBoxPermission] @@ -234,3 +237,13 @@ class MailBoxViewSet( mailbox.status = enums.MailboxStatusChoices.DISABLED mailbox.save() return Response(serializers.MailboxSerializer(mailbox).data) + + @action(detail=True, methods=["post"]) + def enable(self, request, domain_slug, pk=None): # pylint: disable=unused-argument + """Enable mailbox. Send a request to dimail and change status in our DB""" + mailbox = self.get_object() + client = DimailAPIClient() + client.enable_mailbox(mailbox, request.user.sub) + mailbox.status = enums.MailboxStatusChoices.ENABLED + mailbox.save() + return Response(serializers.MailboxSerializer(mailbox).data) diff --git a/src/backend/mailbox_manager/tests/api/mailboxes/test_api_mailboxes_enable.py b/src/backend/mailbox_manager/tests/api/mailboxes/test_api_mailboxes_enable.py new file mode 100644 index 0000000..3c27c7e --- /dev/null +++ b/src/backend/mailbox_manager/tests/api/mailboxes/test_api_mailboxes_enable.py @@ -0,0 +1,99 @@ +""" +Unit tests for the mailbox API +""" + +import re + +import pytest +import responses +from rest_framework import status +from rest_framework.test import APIClient + +from core import factories as core_factories + +from mailbox_manager import enums, factories, models + +pytestmark = pytest.mark.django_db + + +def test_api_mailboxes__enable_anonymous_forbidden(): + """Anonymous users should not be able to enable a mailbox via the API.""" + mailbox = factories.MailboxFactory(status=enums.MailboxStatusChoices.DISABLED) + response = APIClient().post( + f"/api/v1.0/mail-domains/{mailbox.domain.slug}/mailboxes/{mailbox.pk}/enable/", + ) + assert response.status_code == status.HTTP_401_UNAUTHORIZED + assert models.Mailbox.objects.get().status == enums.MailboxStatusChoices.DISABLED + + +def test_api_mailboxes__enable_authenticated_failure(): + """Authenticated users should not be able to enable mailbox + without specific role on mail domain.""" + user = core_factories.UserFactory() + + client = APIClient() + client.force_login(user) + + mailbox = factories.MailboxFactory(status=enums.MailboxStatusChoices.DISABLED) + response = client.post( + f"/api/v1.0/mail-domains/{mailbox.domain.slug}/mailboxes/{mailbox.pk}/enable/", + ) + + assert response.status_code == status.HTTP_403_FORBIDDEN + assert models.Mailbox.objects.get().status == enums.MailboxStatusChoices.DISABLED + + +def test_api_mailboxes__enable_viewer_failure(): + """Users with viewer role should not be able to enable mailbox on the mail domain.""" + mailbox = factories.MailboxFactory(status=enums.MailboxStatusChoices.DISABLED) + access = factories.MailDomainAccessFactory( + role=enums.MailDomainRoleChoices.VIEWER, domain=mailbox.domain + ) + + client = APIClient() + client.force_login(access.user) + + response = client.post( + f"/api/v1.0/mail-domains/{mailbox.domain.slug}/mailboxes/{mailbox.pk}/enable/", + ) + + assert response.status_code == status.HTTP_403_FORBIDDEN + assert models.Mailbox.objects.get().status == enums.MailboxStatusChoices.DISABLED + + +@pytest.mark.parametrize( + "role", + [enums.MailDomainRoleChoices.OWNER, enums.MailDomainRoleChoices.ADMIN], +) +def test_api_mailboxes__enable_roles_success(role): + """Users with owner or admin role should be able to enable mailbox on the mail domain.""" + mailbox = factories.MailboxFactory(status=enums.MailboxStatusChoices.DISABLED) + access = factories.MailDomainAccessFactory(role=role, domain=mailbox.domain) + + client = APIClient() + client.force_login(access.user) + + with responses.RequestsMock() as rsps: + # Ensure successful response using "responses": + rsps.add( + rsps.GET, + re.compile(r".*/token/"), + body='{"access_token": "domain_owner_token"}', + status=status.HTTP_200_OK, + content_type="application/json", + ) + rsps.add( + rsps.PATCH, + re.compile( + rf".*/domains/{mailbox.domain.name}/mailboxes/{mailbox.local_part}" + ), + status=status.HTTP_200_OK, + content_type="application/json", + ) + response = client.post( + f"/api/v1.0/mail-domains/{mailbox.domain.slug}/mailboxes/{mailbox.pk}/enable/", + ) + assert response.status_code == status.HTTP_200_OK + mailbox = models.Mailbox.objects.get() + + assert mailbox.status == enums.MailboxStatusChoices.ENABLED diff --git a/src/backend/mailbox_manager/utils/dimail.py b/src/backend/mailbox_manager/utils/dimail.py index 3323684..5291a3c 100644 --- a/src/backend/mailbox_manager/utils/dimail.py +++ b/src/backend/mailbox_manager/utils/dimail.py @@ -291,3 +291,22 @@ class DimailAPIClient: ) return response return self.raise_exception_for_unexpected_response(response) + + def enable_mailbox(self, mailbox, user_sub=None): + """Send a request to enable a mailbox to dimail API""" + response = session.patch( + f"{self.API_URL}/domains/{mailbox.domain.name}/mailboxes/{mailbox.local_part}", + json={"active": "yes"}, + headers=self.get_headers(user_sub), + verify=True, + timeout=10, + ) + if response.status_code == status.HTTP_200_OK: + logger.info( + "Mailbox %s successfully enabled on domain %s by user %s", + str(mailbox), + str(mailbox.domain), + user_sub, + ) + return response + return self.raise_exception_for_unexpected_response(response)