Skip to content

Commit

Permalink
✨(maildomain_access) add API endpoint to search users
Browse files Browse the repository at this point in the history
  • Loading branch information
sdemagny committed Nov 26, 2024
1 parent 02c6048 commit 23eb00b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to

### Added

- ✨(maildomain_access) Add API endpoint to search users #508
- ✨(mailbox) allow to activate mailbox
- ✨(mailbox) allow to disable mailbox
- ✨(backend) add ServiceProvider #522
Expand Down
26 changes: 25 additions & 1 deletion src/backend/mailbox_manager/api/client/viewsets.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
"""API endpoints"""

from django.db.models import Subquery
from django.db.models import Q, Subquery

from rest_framework import exceptions, filters, mixins, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

from core import models as core_models
from core.api.client.serializers import UserSerializer

from mailbox_manager import enums, models
from mailbox_manager.api import permissions
Expand Down Expand Up @@ -74,6 +75,9 @@ class MailDomainAccessViewSet(
Return list of all domain accesses related to the logged-in user and one
domain access if an id is provided.
GET /api/v1.0/mail-domains/<domain_slug>/accesses/users/
Return list of all users who can have an access to the domain
POST /api/v1.0/mail-domains/<domain_slug>/accesses/ with expected data:
- user: str
- role: str [owner|admin|viewer]
Expand Down Expand Up @@ -181,6 +185,26 @@ def destroy(self, request, *args, **kwargs):

return super().destroy(request, *args, **kwargs)

@action(detail=False, url_path="users", methods=["get"])
def get_available_users(self, request, domain_slug):
"""API endpoint to search user to give them new access.
More filters and permission will be added soon.
"""
queryset = (
core_models.User.objects.all()
.order_by("-created_at")
# exclude inactive contacts
.filter(is_active=True)
# exclude all users with already an access config
.exclude(mail_domain_accesses__domain__slug=domain_slug)
)
# Search by case-insensitive and accent-insensitive
if query := request.GET.get("q", ""):
queryset = queryset.filter(
Q(name__unaccent__icontains=query) | Q(email__unaccent__icontains=query)
)
return Response(UserSerializer(queryset.all(), many=True).data)


class MailBoxViewSet(
mixins.CreateModelMixin,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""
Tests for MailDomains API endpoint in People's mailbox manager app. Focus on "list" action.
"""

import pytest
from rest_framework import status
from rest_framework.test import APIClient

from core import factories as core_factories
from core import models as core_models

from mailbox_manager import enums, factories

pytestmark = pytest.mark.django_db


def test_api_mail_domains__available_users_anonymous():
"""Anonymous users should not be allowed to list users."""

maildomain = factories.MailDomainFactory()

response = APIClient().get(
f"/api/v1.0/mail-domains/{maildomain.slug}/accesses/users/"
)

assert response.status_code == status.HTTP_401_UNAUTHORIZED
assert response.json() == {
"detail": "Authentication credentials were not provided."
}


def test_api_mail_domains__list_available_users__authenticated():
"""Authenticated users should be allowed to list available users for a domain."""
authenticated_user = core_factories.UserFactory()
client = APIClient()
client.force_login(authenticated_user)

dave = core_factories.UserFactory(email="[email protected]", name="David Bowman")
nicole = core_factories.UserFactory(
email="[email protected]", name="Nicole Foole"
)
frank = core_factories.UserFactory(
email="[email protected]", name="Frank Poole"
)
mary = core_factories.UserFactory(email="[email protected]", name="Mary Pol")

expected_ids = {str(user.id) for user in core_models.User.objects.all()}

maildomain = factories.MailDomainFactory()
factories.MailDomainAccessFactory(
user__name="Owen Theowner",
domain=maildomain,
role=enums.MailDomainRoleChoices.OWNER,
)
factories.MailDomainAccessFactory(
user__name="Anna Theadmin",
domain=maildomain,
role=enums.MailDomainRoleChoices.ADMIN,
)
factories.MailDomainAccessFactory(
user__name="Victor Theviewer",
domain=maildomain,
role=enums.MailDomainRoleChoices.VIEWER,
)

response = client.get(f"/api/v1.0/mail-domains/{maildomain.slug}/accesses/users/")
assert response.status_code == status.HTTP_200_OK

results = response.json()
assert len(results) == 5
results_id = {result["id"] for result in results}
assert expected_ids == results_id

# now test filter user
response = client.get(
f"/api/v1.0/mail-domains/{maildomain.slug}/accesses/users/?q=OL"
)
assert response.status_code == status.HTTP_200_OK
expected_ids = {str(user.id) for user in [nicole, frank, mary]}
results = response.json()
assert len(results) == 3
results_id = {result["id"] for result in results}
assert expected_ids == results_id

# filter on email info
response = client.get(
f"/api/v1.0/mail-domains/{maildomain.slug}/accesses/users/?q=bowbow"
)
assert response.status_code == status.HTTP_200_OK
results = response.json()
assert len(results) == 1
assert results[0]["id"] == str(dave.id)

0 comments on commit 23eb00b

Please sign in to comment.