✨(backend) domain accesses list API
Add an endpoint to list all accesses created for a domain Return all roles available to set for each access depending to the authenticated user.
This commit is contained in:
@@ -8,6 +8,9 @@ and this project adheres to
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
✨(domains) add endpoint API to list all accesses created for a domain
|
||||||
|
|
||||||
|
|
||||||
## [1.1.0] - 2024-09-10
|
## [1.1.0] - 2024-09-10
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from mailbox_manager import models
|
from core.api.serializers import UserSerializer
|
||||||
|
|
||||||
|
from mailbox_manager import enums, models
|
||||||
|
|
||||||
|
|
||||||
class MailboxSerializer(serializers.ModelSerializer):
|
class MailboxSerializer(serializers.ModelSerializer):
|
||||||
@@ -50,7 +52,10 @@ class MailDomainSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class MailDomainAccessSerializer(serializers.ModelSerializer):
|
class MailDomainAccessSerializer(serializers.ModelSerializer):
|
||||||
"""Serialize mail domain accesses."""
|
"""Serialize mail domain access."""
|
||||||
|
|
||||||
|
user = UserSerializer(read_only=True, fields=["id", "name", "email"])
|
||||||
|
can_set_role_to = serializers.SerializerMethodField(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.MailDomainAccess
|
model = models.MailDomainAccess
|
||||||
@@ -58,7 +63,44 @@ class MailDomainAccessSerializer(serializers.ModelSerializer):
|
|||||||
"id",
|
"id",
|
||||||
"user",
|
"user",
|
||||||
"role",
|
"role",
|
||||||
"created_at",
|
"can_set_role_to",
|
||||||
"updated_at",
|
]
|
||||||
|
read_only_fields = ["id", "user", "can_set_role_to"]
|
||||||
|
|
||||||
|
def get_can_set_role_to(self, access):
|
||||||
|
"""Return roles available to set"""
|
||||||
|
roles = list(enums.MailDomainRoleChoices)
|
||||||
|
# get role of authenticated user
|
||||||
|
authenticated_user_role = access.user_role
|
||||||
|
if authenticated_user_role != enums.MailDomainRoleChoices.OWNER:
|
||||||
|
roles.remove(enums.MailDomainRoleChoices.OWNER)
|
||||||
|
# if the user authenticated is a viewer, they can't modify role
|
||||||
|
# and only an owner can change role of an owner
|
||||||
|
if authenticated_user_role == enums.MailDomainRoleChoices.VIEWER or (
|
||||||
|
authenticated_user_role != enums.MailDomainRoleChoices.OWNER
|
||||||
|
and access.role == enums.MailDomainRoleChoices.OWNER
|
||||||
|
):
|
||||||
|
return []
|
||||||
|
# we only want to return other roles available to change,
|
||||||
|
# so we remove the current role of current access.
|
||||||
|
roles.remove(access.role)
|
||||||
|
return sorted(roles)
|
||||||
|
|
||||||
|
|
||||||
|
class MailDomainAccessReadOnlySerializer(MailDomainAccessSerializer):
|
||||||
|
"""Serialize mail domain access for list and retrieve actions."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.MailDomainAccess
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"user",
|
||||||
|
"role",
|
||||||
|
"can_set_role_to",
|
||||||
|
]
|
||||||
|
read_only_fields = [
|
||||||
|
"id",
|
||||||
|
"user",
|
||||||
|
"role",
|
||||||
|
"can_set_role_to",
|
||||||
]
|
]
|
||||||
read_only_fields = ["id"]
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
"""API endpoints"""
|
"""API endpoints"""
|
||||||
|
|
||||||
|
from django.db.models import Subquery
|
||||||
|
|
||||||
from rest_framework import filters, mixins, viewsets
|
from rest_framework import filters, mixins, viewsets
|
||||||
from rest_framework import permissions as drf_permissions
|
from rest_framework import permissions as drf_permissions
|
||||||
|
|
||||||
@@ -54,19 +56,67 @@ class MailDomainViewSet(
|
|||||||
|
|
||||||
# pylint: disable=too-many-ancestors
|
# pylint: disable=too-many-ancestors
|
||||||
class MailDomainAccessViewSet(
|
class MailDomainAccessViewSet(
|
||||||
mixins.ListModelMixin,
|
|
||||||
viewsets.GenericViewSet,
|
viewsets.GenericViewSet,
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
MailDomainAccess viewset.
|
API ViewSet for all interactions with mail domain accesses.
|
||||||
|
|
||||||
|
GET /api/v1.0/mail-domains/<domain_slug>/accesses/:<domain_access_id>
|
||||||
|
Return list of all domain accesses related to the logged-in user and one
|
||||||
|
domain access if an id is provided.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
permission_classes = [drf_permissions.IsAuthenticated]
|
permission_classes = [drf_permissions.IsAuthenticated]
|
||||||
serializer_class = serializers.MailDomainAccessSerializer
|
serializer_class = serializers.MailDomainAccessSerializer
|
||||||
filter_backends = [filters.OrderingFilter]
|
filter_backends = [filters.OrderingFilter]
|
||||||
ordering_fields = ["created_at", "user", "domain", "role"]
|
ordering_fields = ["role", "user__email", "user__name"]
|
||||||
ordering = ["-created_at"]
|
ordering = ["-created_at"]
|
||||||
queryset = models.MailDomainAccess.objects.all()
|
queryset = (
|
||||||
|
models.MailDomainAccess.objects.all()
|
||||||
|
.select_related("user")
|
||||||
|
.order_by("-created_at")
|
||||||
|
)
|
||||||
|
list_serializer_class = serializers.MailDomainAccessReadOnlySerializer
|
||||||
|
detail_serializer_class = serializers.MailDomainAccessSerializer
|
||||||
|
|
||||||
|
def get_serializer_class(self):
|
||||||
|
if self.action in {"list", "retrieve"}:
|
||||||
|
return self.list_serializer_class
|
||||||
|
return self.detail_serializer_class
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
"""Extra context provided to the serializer class."""
|
||||||
|
context = super().get_serializer_context()
|
||||||
|
context["domain_slug"] = self.kwargs["domain_slug"]
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
"""Return the queryset according to the action."""
|
||||||
|
queryset = super().get_queryset()
|
||||||
|
queryset = queryset.filter(domain__slug=self.kwargs["domain_slug"])
|
||||||
|
|
||||||
|
if self.action in {"list", "retrieve"}:
|
||||||
|
# Determine which role the logged-in user has in the domain
|
||||||
|
user_role_query = models.MailDomainAccess.objects.filter(
|
||||||
|
user=self.request.user, domain__slug=self.kwargs["domain_slug"]
|
||||||
|
).values("role")[:1]
|
||||||
|
|
||||||
|
queryset = (
|
||||||
|
# The logged-in user should be part of a domain to see its accesses
|
||||||
|
queryset.filter(
|
||||||
|
domain__accesses__user=self.request.user,
|
||||||
|
)
|
||||||
|
# Abilities are computed based on logged-in user's role and
|
||||||
|
# the user role on each domain access
|
||||||
|
.annotate(
|
||||||
|
user_role=Subquery(user_role_query),
|
||||||
|
)
|
||||||
|
.select_related("user")
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class MailBoxViewSet(
|
class MailBoxViewSet(
|
||||||
|
|||||||
@@ -0,0 +1,260 @@
|
|||||||
|
"""
|
||||||
|
Test for mail_domain accesses API endpoints in People's core app : list
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
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_mail_domain__accesses_list_anonymous():
|
||||||
|
"""Anonymous users should not be allowed to list mail_domain accesses."""
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
factories.MailDomainAccessFactory.create_batch(2, domain=mail_domain)
|
||||||
|
|
||||||
|
response = APIClient().get(f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/")
|
||||||
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "Authentication credentials were not provided."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_list_authenticated_unrelated():
|
||||||
|
"""
|
||||||
|
Authenticated users should not be allowed to list mail_domain accesses for a mail_domain
|
||||||
|
to which they are not related.
|
||||||
|
"""
|
||||||
|
user = core_factories.UserFactory()
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
factories.MailDomainAccessFactory.create_batch(3, domain=mail_domain)
|
||||||
|
|
||||||
|
# Accesses for other mail_domains to which the user is related should not be listed either
|
||||||
|
other_access = factories.MailDomainAccessFactory(user=user)
|
||||||
|
factories.MailDomainAccessFactory(domain=other_access.domain)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 0,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_list_for_authenticated_user_related_to_domain():
|
||||||
|
"""
|
||||||
|
Authenticated users should be able to list mail_domain accesses for a mail_domain
|
||||||
|
to which they are related, with a given role.
|
||||||
|
"""
|
||||||
|
viewer, administrator, owner = core_factories.UserFactory.create_batch(3)
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
|
||||||
|
owner_access = factories.MailDomainAccessFactory.create(
|
||||||
|
domain=mail_domain, user=owner, role=enums.MailDomainRoleChoices.OWNER
|
||||||
|
)
|
||||||
|
admin_access = factories.MailDomainAccessFactory.create(
|
||||||
|
domain=mail_domain, user=administrator, role=enums.MailDomainRoleChoices.ADMIN
|
||||||
|
)
|
||||||
|
viewer_access = models.MailDomainAccess.objects.create(
|
||||||
|
domain=mail_domain, user=viewer, role=enums.MailDomainRoleChoices.VIEWER
|
||||||
|
)
|
||||||
|
|
||||||
|
admin_expected_data = {
|
||||||
|
"id": str(admin_access.id),
|
||||||
|
"user": {
|
||||||
|
"id": str(administrator.id),
|
||||||
|
"email": str(administrator.email),
|
||||||
|
"name": str(administrator.name),
|
||||||
|
},
|
||||||
|
"role": str(admin_access.role),
|
||||||
|
}
|
||||||
|
viewer_expected_data = {
|
||||||
|
"id": str(viewer_access.id),
|
||||||
|
"user": {
|
||||||
|
"id": str(viewer.id),
|
||||||
|
"email": str(viewer.email),
|
||||||
|
"name": str(viewer.name),
|
||||||
|
},
|
||||||
|
"role": str(viewer_access.role),
|
||||||
|
}
|
||||||
|
owner_expected_data = {
|
||||||
|
"id": str(owner_access.id),
|
||||||
|
"user": {
|
||||||
|
"id": str(owner.id),
|
||||||
|
"email": str(owner.email),
|
||||||
|
"name": str(owner.name),
|
||||||
|
},
|
||||||
|
"role": str(owner_access.role),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Grant other mail_domain accesses to the user, they should not be listed either
|
||||||
|
other_access = factories.MailDomainAccessFactory(user=viewer)
|
||||||
|
factories.MailDomainAccessFactory(domain=other_access.domain)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(viewer)
|
||||||
|
# viewer can see accesses but no action is available
|
||||||
|
admin_expected_data["can_set_role_to"] = []
|
||||||
|
viewer_expected_data["can_set_role_to"] = []
|
||||||
|
owner_expected_data["can_set_role_to"] = []
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json()["count"] == 3
|
||||||
|
expected = sorted(
|
||||||
|
[admin_expected_data, viewer_expected_data, owner_expected_data],
|
||||||
|
key=lambda x: x["role"],
|
||||||
|
)
|
||||||
|
assert sorted(response.json()["results"], key=lambda x: x["role"]) == expected
|
||||||
|
|
||||||
|
client.force_login(administrator)
|
||||||
|
# administrator can see and give new role but not an OWNER role
|
||||||
|
admin_expected_data["can_set_role_to"] = [enums.MailDomainRoleChoices.VIEWER]
|
||||||
|
viewer_expected_data["can_set_role_to"] = [enums.MailDomainRoleChoices.ADMIN]
|
||||||
|
owner_expected_data["can_set_role_to"] = []
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json()["count"] == 3
|
||||||
|
expected = sorted(
|
||||||
|
[admin_expected_data, viewer_expected_data, owner_expected_data],
|
||||||
|
key=lambda x: x["role"],
|
||||||
|
)
|
||||||
|
assert sorted(response.json()["results"], key=lambda x: x["role"]) == expected
|
||||||
|
|
||||||
|
client.force_login(owner)
|
||||||
|
# owner can do everything
|
||||||
|
admin_expected_data["can_set_role_to"] = [
|
||||||
|
enums.MailDomainRoleChoices.OWNER,
|
||||||
|
enums.MailDomainRoleChoices.VIEWER,
|
||||||
|
]
|
||||||
|
viewer_expected_data["can_set_role_to"] = [
|
||||||
|
enums.MailDomainRoleChoices.ADMIN,
|
||||||
|
enums.MailDomainRoleChoices.OWNER,
|
||||||
|
]
|
||||||
|
owner_expected_data["can_set_role_to"] = [
|
||||||
|
enums.MailDomainRoleChoices.ADMIN,
|
||||||
|
enums.MailDomainRoleChoices.VIEWER,
|
||||||
|
]
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json()["count"] == 3
|
||||||
|
|
||||||
|
expected = sorted(
|
||||||
|
[admin_expected_data, viewer_expected_data, owner_expected_data],
|
||||||
|
key=lambda x: x["role"],
|
||||||
|
)
|
||||||
|
assert sorted(response.json()["results"], key=lambda x: x["role"]) == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_list_authenticated_constant_numqueries(
|
||||||
|
django_assert_num_queries,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
The number of queries should not depend on the amount of fetched accesses.
|
||||||
|
"""
|
||||||
|
user = core_factories.UserFactory()
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
models.MailDomainAccess.objects.create(domain=mail_domain, user=user) # random role
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
# Only 3 queries are needed to efficiently fetch mail_domain accesses,
|
||||||
|
# related users :
|
||||||
|
# - query retrieving logged-in user for user_role annotation
|
||||||
|
# - count from pagination
|
||||||
|
# - distinct from viewset
|
||||||
|
with django_assert_num_queries(3):
|
||||||
|
client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
|
||||||
|
# create 20 new mail_domain accesses
|
||||||
|
for _ in range(20):
|
||||||
|
factories.MailDomainAccessFactory(domain=mail_domain)
|
||||||
|
|
||||||
|
# num queries should still be the same
|
||||||
|
with django_assert_num_queries(3):
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json()["count"] == 21
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_list_authenticated_ordering():
|
||||||
|
"""MailDomain accesses can be ordered by "role"."""
|
||||||
|
|
||||||
|
user = core_factories.UserFactory()
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
models.MailDomainAccess.objects.create(domain=mail_domain, user=user)
|
||||||
|
|
||||||
|
# create 20 new mail_domain accesses
|
||||||
|
for _ in range(20):
|
||||||
|
factories.MailDomainAccessFactory(domain=mail_domain)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/?ordering=role",
|
||||||
|
)
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json()["count"] == 21
|
||||||
|
|
||||||
|
results = [access["role"] for access in response.json()["results"]]
|
||||||
|
assert sorted(results) == results
|
||||||
|
|
||||||
|
# check results when we change ordering
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/?ordering=-role",
|
||||||
|
)
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json()["count"] == 21
|
||||||
|
|
||||||
|
results = [access["role"] for access in response.json()["results"]]
|
||||||
|
assert sorted(results, reverse=True) == results
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("ordering_field", ["email", "name"])
|
||||||
|
def test_api_mail_domain__accesses_list_authenticated_ordering_user(ordering_field):
|
||||||
|
"""Mail domain accesses can be ordered by user's fields."""
|
||||||
|
|
||||||
|
user = core_factories.UserFactory()
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
models.MailDomainAccess.objects.create(domain=mail_domain, user=user)
|
||||||
|
|
||||||
|
for _ in range(20):
|
||||||
|
factories.MailDomainAccessFactory(domain=mail_domain)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/?ordering=user__{ordering_field}",
|
||||||
|
)
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json()["count"] == 21
|
||||||
|
|
||||||
|
def normalize(x):
|
||||||
|
"""Mimic Django order_by, which is case-insensitive and space-insensitive"""
|
||||||
|
return x.casefold().replace(" ", "")
|
||||||
|
|
||||||
|
results = [access["user"][ordering_field] for access in response.json()["results"]]
|
||||||
|
assert sorted(results, key=normalize) == results
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
"""
|
||||||
|
Test for mail_domain accesses API endpoints in People's core app : retrieve
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
from core import factories as core_factories
|
||||||
|
|
||||||
|
from mailbox_manager import enums, factories
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_retrieve_anonymous():
|
||||||
|
"""
|
||||||
|
Anonymous users should not be allowed to retrieve a mail_domain access.
|
||||||
|
"""
|
||||||
|
access = factories.MailDomainAccessFactory()
|
||||||
|
|
||||||
|
response = APIClient().get(
|
||||||
|
f"/api/v1.0/mail-domains/{access.domain.slug}/accesses/{access.id!s}/",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "Authentication credentials were not provided."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_retrieve_authenticated_unrelated():
|
||||||
|
"""
|
||||||
|
Authenticated users should not be allowed to retrieve a mail_domain access for
|
||||||
|
a mail_domain to which they are not related.
|
||||||
|
"""
|
||||||
|
user = core_factories.UserFactory()
|
||||||
|
access = factories.MailDomainAccessFactory(domain=factories.MailDomainFactory())
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{access.domain.slug}/accesses/{access.id!s}/",
|
||||||
|
)
|
||||||
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||||
|
assert response.json() == {"detail": "No MailDomainAccess matches the given query."}
|
||||||
|
|
||||||
|
# Accesses related to another mail_domain should be excluded even if the user is related to it
|
||||||
|
for other_access in [
|
||||||
|
factories.MailDomainAccessFactory(),
|
||||||
|
factories.MailDomainAccessFactory(user=user),
|
||||||
|
]:
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{access.domain.slug}/accesses/{other_access.id!s}/",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "No MailDomainAccess matches the given query."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_mail_domain__accesses_retrieve_authenticated_related():
|
||||||
|
"""
|
||||||
|
A user who is related to a mail_domain should be allowed to retrieve the
|
||||||
|
associated mail_domain user accesses.
|
||||||
|
"""
|
||||||
|
owner = core_factories.UserFactory()
|
||||||
|
mail_domain = factories.MailDomainFactory()
|
||||||
|
access = factories.MailDomainAccessFactory(
|
||||||
|
domain=mail_domain, user=owner, role=enums.MailDomainRoleChoices.OWNER
|
||||||
|
)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(owner)
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/{access.id!s}/",
|
||||||
|
)
|
||||||
|
|
||||||
|
results = {
|
||||||
|
"id": str(access.id),
|
||||||
|
"user": {
|
||||||
|
"id": str(access.user.id),
|
||||||
|
"email": str(owner.email),
|
||||||
|
"name": str(owner.name),
|
||||||
|
},
|
||||||
|
"role": str(access.role),
|
||||||
|
"can_set_role_to": [
|
||||||
|
enums.MailDomainRoleChoices.ADMIN,
|
||||||
|
enums.MailDomainRoleChoices.VIEWER,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json() == results
|
||||||
|
|
||||||
|
admin = factories.MailDomainAccessFactory(
|
||||||
|
domain=mail_domain, role=enums.MailDomainRoleChoices.ADMIN
|
||||||
|
).user
|
||||||
|
client.force_login(admin)
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/{access.id!s}/",
|
||||||
|
)
|
||||||
|
# admin can't change role of an owner
|
||||||
|
results["can_set_role_to"] = []
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json() == results
|
||||||
|
|
||||||
|
viewer = factories.MailDomainAccessFactory(
|
||||||
|
domain=mail_domain, role=enums.MailDomainRoleChoices.VIEWER
|
||||||
|
).user
|
||||||
|
client.force_login(viewer)
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/mail-domains/{mail_domain.slug}/accesses/{access.id!s}/",
|
||||||
|
)
|
||||||
|
# viewer can't change anyone's role
|
||||||
|
results["can_set_role_to"] = []
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json() == results
|
||||||
Reference in New Issue
Block a user