Skip to content

Commit

Permalink
✨(backend) allow to filter member on team access endpoint
Browse files Browse the repository at this point in the history
Filter member by name...
  • Loading branch information
sdemagny committed Jul 18, 2024
1 parent e0000ca commit 9200fa9
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/backend/core/api/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,23 @@ def get_queryset(self):
queryset = queryset.filter(team=self.kwargs["team_id"])

if self.action in {"list", "retrieve"}:
if query := self.request.GET.get("q", ""):
similarity = Max(
TrigramSimilarity(
Coalesce(Func("user__email", function="unaccent"), Value("")),
Func(Value(query), function="unaccent"),
)
+ TrigramSimilarity(
Coalesce(Func("user__name", function="unaccent"), Value("")),
Func(Value(query), function="unaccent"),
)
)
queryset = (
queryset.annotate(similarity=similarity)
.filter(similarity__gte=SIMILARITY_THRESHOLD)
.order_by("-similarity")
)

# Determine which role the logged-in user has in the team
user_role_query = models.TeamAccess.objects.filter(
user=self.request.user, team=self.kwargs["team_id"]
Expand Down
129 changes: 129 additions & 0 deletions src/backend/core/tests/team_accesses/test_api_team_accesses_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,135 @@ def test_api_team_accesses_list_authenticated_related():
)


def test_api_team_accesses_list_find_members(django_assert_num_queries):
"""
Authenticated users should be able to search users access with a case-insensitive and
partial query on the name.
"""
factories.UserFactory(email="tester@ministry.fr", name="john doe")

dave = factories.UserFactory(name="dave bowman", email=None)
frank = factories.UserFactory(name="frank poole", email=None)
mary = factories.UserFactory(name="mary poole", email=None)
nicole = factories.UserFactory(name="nicole foole", email=None)
factories.UserFactory(name="heywood floyd", email=None)
factories.UserFactory(name="Andrei Smyslov", email=None)
factories.TeamFactory.create_batch(10)

# Add Mary, Nicole and Dave in the same team
team = factories.TeamFactory(
name="Odyssey",
users=[
(mary, models.RoleChoices.OWNER),
(nicole, models.RoleChoices.ADMIN),
(dave, models.RoleChoices.MEMBER),
],
)
factories.TeamFactory(users=[(frank, models.RoleChoices.MEMBER)])

# Search users in the team Odyssey
client = APIClient()
client.force_login(mary)

# 5 queries are needed here:
# - user authenticated
# - search user query
# - TeamAccess
# - Team
# - Count TeamAccess current team with role owner
with django_assert_num_queries(5):
response = client.get(
f"/api/v1.0/teams/{team.id!s}/accesses/",
)
assert response.status_code == HTTP_200_OK
assert response.json()["count"] == 3

# We can find David Bowman
# 3 queries are needed here:
# - user authenticated
# - search user query
# - TeamAccess
with django_assert_num_queries(3):
response = client.get(
f"/api/v1.0/teams/{team.id!s}/accesses/?q=bowman",
)
assert response.status_code == HTTP_200_OK
assert response.json()["count"] == 1
dave_access = dave.accesses.get(team=team)
assert response.json()["results"][0]["id"] == str(dave_access.id)

# We can only find Nicole and Mary
# 5 queries are needed here:
# - user authenticated
# - search user query
# - TeamAccess
# - Team
# - Count TeamAccess current team with role owner
with django_assert_num_queries(5):
response = client.get(
f"/api/v1.0/teams/{team.id!s}/accesses/?q=ool",
)
assert response.status_code == HTTP_200_OK
assert response.json()["count"] == 2
user_access_ids = sorted([user["id"] for user in response.json()["results"]])
mary_access = mary.accesses.get(team=team)
nicole_access = nicole.accesses.get(team=team)
assert sorted([str(mary_access.id), str(nicole_access.id)]) == user_access_ids

# We can only find Nicole and Mary
# 5 queries are needed here:
# - user authenticated
# - search user query
# - TeamAccess
# - Team
# - Count TeamAccess current team with role owner
with django_assert_num_queries(5):
response = client.get(
f"/api/v1.0/teams/{team.id!s}/accesses/?q=ool",
)
assert response.status_code == HTTP_200_OK
assert response.json()["count"] == 2
user_access_ids = sorted([user["id"] for user in response.json()["results"]])
mary_access = mary.accesses.get(team=team)
nicole_access = nicole.accesses.get(team=team)
assert sorted([str(mary_access.id), str(nicole_access.id)]) == user_access_ids


def test_api_team_accesses__list_find_members_by_email():
"""
Authenticated users should be able to search users access with a case-insensitive and
partial query on the email.
"""
user = factories.UserFactory(name=None)

# set all names to None to match only on emails
colleague1 = factories.UserFactory(name=None, email="prudence_crandall@edu.us")
colleague2 = factories.UserFactory(name=None, email="reinebrunehaut@gouv.fr")
colleague3 = factories.UserFactory(name=None, email="artemisia.gentileschi@arte.it")

# Add Mary, Nicole and Dave in the same team
team = factories.TeamFactory(
users=[
(user, models.RoleChoices.ADMIN),
(colleague1, models.RoleChoices.OWNER),
(colleague2, models.RoleChoices.ADMIN),
(colleague3, models.RoleChoices.MEMBER),
],
)
factories.TeamAccessFactory.create_batch(4)

# Search users in the team Odyssey
client = APIClient()
client.force_login(user)

response = client.get(
f"/api/v1.0/teams/{team.id!s}/accesses/?q=BRUNE",
)
assert response.status_code == HTTP_200_OK
assert response.json()["count"] == 1
assert response.json()["results"][0]["user"]["email"] == "reinebrunehaut@gouv.fr"


def test_api_team_accesses_list_authenticated_constant_numqueries(
django_assert_num_queries,
):
Expand Down

0 comments on commit 9200fa9

Please sign in to comment.