🐛(api) return best matching identity only
Use best matching identity to order results.
This commit is contained in:
committed by
Marie
parent
3aba9a4419
commit
a4ac5304d7
@@ -1,6 +1,6 @@
|
|||||||
"""API endpoints"""
|
"""API endpoints"""
|
||||||
from django.contrib.postgres.search import TrigramSimilarity
|
from django.contrib.postgres.search import TrigramSimilarity
|
||||||
from django.db.models import Func, OuterRef, Q, Subquery, Value
|
from django.db.models import Func, Max, OuterRef, Q, Subquery, Value
|
||||||
|
|
||||||
from rest_framework import (
|
from rest_framework import (
|
||||||
decorators,
|
decorators,
|
||||||
@@ -202,9 +202,11 @@ class UserViewSet(
|
|||||||
|
|
||||||
# Search by case-insensitive and accent-insensitive trigram similarity
|
# Search by case-insensitive and accent-insensitive trigram similarity
|
||||||
if query := self.request.GET.get("q", ""):
|
if query := self.request.GET.get("q", ""):
|
||||||
similarity = TrigramSimilarity(
|
similarity = Max(
|
||||||
Func("identities__email", function="unaccent"),
|
TrigramSimilarity(
|
||||||
Func(Value(query), function="unaccent"),
|
Func("identities__email", function="unaccent"),
|
||||||
|
Func(Value(query), function="unaccent"),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
queryset = (
|
queryset = (
|
||||||
queryset.annotate(similarity=similarity)
|
queryset.annotate(similarity=similarity)
|
||||||
|
|||||||
@@ -100,10 +100,9 @@ def test_api_users_authenticated_list_by_email():
|
|||||||
assert user_ids == [str(nicole.user.id), str(frank.user.id)]
|
assert user_ids == [str(nicole.user.id), str(frank.user.id)]
|
||||||
|
|
||||||
|
|
||||||
def test_api_users_authenticated_list_multiplie_identities_user():
|
def test_api_users_authenticated_list_multiple_identities_single_user():
|
||||||
"""
|
"""
|
||||||
Authenticated users should be able to search users with a case-insensitive and
|
User with multiple identities should appear only once in results.
|
||||||
partial query on the email.
|
|
||||||
"""
|
"""
|
||||||
user = factories.UserFactory(email="tester@ministry.fr")
|
user = factories.UserFactory(email="tester@ministry.fr")
|
||||||
factories.IdentityFactory(user=user, email=user.email)
|
factories.IdentityFactory(user=user, email=user.email)
|
||||||
@@ -122,8 +121,36 @@ def test_api_users_authenticated_list_multiplie_identities_user():
|
|||||||
assert response.status_code == HTTP_200_OK
|
assert response.status_code == HTTP_200_OK
|
||||||
# A single user is returned, despite similarity matching both emails
|
# A single user is returned, despite similarity matching both emails
|
||||||
assert response.json()["count"] == 1
|
assert response.json()["count"] == 1
|
||||||
|
assert response.json()["results"][0]["id"] == str(dave.id)
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_users_authenticated_list_multiple_identities_best_result():
|
||||||
|
"""
|
||||||
|
User with multiple identities should be ranked
|
||||||
|
on their best matching identities.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory(email="tester@ministry.fr")
|
||||||
|
factories.IdentityFactory(user=user, email=user.email)
|
||||||
|
jwt_token = OIDCToken.for_user(user)
|
||||||
|
|
||||||
|
dave = factories.UserFactory()
|
||||||
|
davina = factories.UserFactory()
|
||||||
|
prudence = factories.UserFactory()
|
||||||
|
factories.IdentityFactory(user=dave, email="david.bowman@work.com")
|
||||||
|
factories.IdentityFactory(user=dave, email="babibou@ehehe.com")
|
||||||
|
factories.IdentityFactory(user=davina, email="davina.bowan@work.com")
|
||||||
|
factories.IdentityFactory(user=prudence, email="prudence.crandall@work.com")
|
||||||
|
|
||||||
|
# Full query should work
|
||||||
|
response = APIClient().get(
|
||||||
|
"/api/v1.0/users/?q=david.bowman@work.com",
|
||||||
|
HTTP_AUTHORIZATION=f"Bearer {jwt_token}",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == HTTP_200_OK
|
||||||
|
assert response.json()["count"] == 3
|
||||||
user_ids = [user["id"] for user in response.json()["results"]]
|
user_ids = [user["id"] for user in response.json()["results"]]
|
||||||
assert user_ids[0] == str(dave.id)
|
assert user_ids == [str(dave.id), str(davina.id), str(prudence.id)]
|
||||||
|
|
||||||
|
|
||||||
def test_api_users_authenticated_list_uppercase_content():
|
def test_api_users_authenticated_list_uppercase_content():
|
||||||
|
|||||||
Reference in New Issue
Block a user