From f3b5cccf5d9ed8e5d0efce66c7dcff6c2ee930d4 Mon Sep 17 00:00:00 2001 From: Sabrina Demagny Date: Thu, 10 Jul 2025 15:37:17 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(api)=20Allow=20superuser+staff=20to?= =?UTF-8?q?=20view=20all=20mail=20domains=20in=20admin=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add condition in MailDomainAdminViewSet.get_queryset() to return all domains when user is both superuser and staff - Add comprehensive tests covering all user permission combinations: * superuser + staff: can see all domains * superuser only: cannot see all domains (empty list) * staff only: cannot see all domains (empty list) * staff with domain access: can only see accessible domains - Maintain existing behavior for regular users and domain admins This change ensures that superusers with staff privileges have full administrative access to all mail domains through the admin API, while maintaining proper access control for other user types. --- src/backend/core/api/viewsets/maildomain.py | 3 + .../core/tests/api/test_maildomains.py | 76 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/backend/core/api/viewsets/maildomain.py b/src/backend/core/api/viewsets/maildomain.py index ee6f01c1..71c8064f 100644 --- a/src/backend/core/api/viewsets/maildomain.py +++ b/src/backend/core/api/viewsets/maildomain.py @@ -26,6 +26,9 @@ class MailDomainAdminViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): if not user or not user.is_authenticated: return models.MailDomain.objects.none() + if user.is_superuser and user.is_staff: + return models.MailDomain.objects.all().order_by("name") + accessible_maildomain_ids = models.MailDomainAccess.objects.filter( user=user, role=models.MailDomainAccessRoleChoices.ADMIN ).values_list("maildomain_id", flat=True) diff --git a/src/backend/core/tests/api/test_maildomains.py b/src/backend/core/tests/api/test_maildomains.py index 5e1ee52d..7fe7476e 100644 --- a/src/backend/core/tests/api/test_maildomains.py +++ b/src/backend/core/tests/api/test_maildomains.py @@ -160,6 +160,82 @@ class TestMailDomainAdminViewSet: response = api_client.get(self.LIST_DOMAINS_URL) assert response.status_code == status.HTTP_401_UNAUTHORIZED + def test_list_administered_maildomains_superuser_staff( + self, + api_client, + mail_domain1, + mail_domain2, + unmanaged_domain, + ): + """Test that superuser with staff status can list all domains.""" + superuser_staff = factories.UserFactory(is_superuser=True, is_staff=True) + api_client.force_authenticate(user=superuser_staff) + response = api_client.get(self.LIST_DOMAINS_URL) + + assert response.status_code == status.HTTP_200_OK + assert response.data["count"] == 3 + domain_ids = [item["id"] for item in response.data["results"]] + assert str(mail_domain1.id) in domain_ids + assert str(mail_domain2.id) in domain_ids + assert str(unmanaged_domain.id) in domain_ids + + def test_list_administered_maildomains_superuser_not_staff( + self, + api_client, + mail_domain1, + mail_domain2, + unmanaged_domain, + ): + """Test that superuser without staff status cannot list all domains.""" + superuser_not_staff = factories.UserFactory(is_superuser=True, is_staff=False) + api_client.force_authenticate(user=superuser_not_staff) + response = api_client.get(self.LIST_DOMAINS_URL) + + assert response.status_code == status.HTTP_200_OK + assert response.data["count"] == 0 + + def test_list_administered_maildomains_staff_not_superuser( + self, + api_client, + mail_domain1, + mail_domain2, + unmanaged_domain, + ): + """Test that staff without superuser status cannot list all domains.""" + staff_not_superuser = factories.UserFactory(is_superuser=False, is_staff=True) + api_client.force_authenticate(user=staff_not_superuser) + response = api_client.get(self.LIST_DOMAINS_URL) + + assert response.status_code == status.HTTP_200_OK + assert response.data["count"] == 0 + + def test_list_administered_maildomains_staff_not_superuser_with_access( + self, + api_client, + mail_domain1, + mail_domain2, + unmanaged_domain, + ): + """Test that staff without superuser status can only see domains they have access to.""" + staff_not_superuser = factories.UserFactory(is_superuser=False, is_staff=True) + + # Give access to only one domain + models.MailDomainAccess.objects.create( + maildomain=mail_domain1, + user=staff_not_superuser, + role=models.MailDomainAccessRoleChoices.ADMIN, + ) + + api_client.force_authenticate(user=staff_not_superuser) + response = api_client.get(self.LIST_DOMAINS_URL) + + assert response.status_code == status.HTTP_200_OK + assert response.data["count"] == 1 + domain_ids = [item["id"] for item in response.data["results"]] + assert str(mail_domain1.id) in domain_ids + assert str(mail_domain2.id) not in domain_ids + assert str(unmanaged_domain.id) not in domain_ids + class TestMailboxAdminViewSet: """Tests for the MailboxAdminViewSet."""