Add team filter for users endpoint (#3666)

# What this PR does

Adds `team` filter for `users` endpoint

## Checklist

- [x] Unit, integration, and e2e (if applicable) tests updated
- [x] Documentation added (or `pr:no public docs` PR label added if not
required)
- [x] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
This commit is contained in:
Vadim Stepanov 2024-01-11 15:03:54 +00:00 committed by GitHub
parent 39421f2cc7
commit 8b7ffad598
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 3 deletions

View file

@ -287,6 +287,48 @@ def test_list_users_filtered_by_public_primary_key(
assert returned_user_pks == [user1.public_primary_key]
@pytest.mark.django_db
def test_list_users_filtered_by_team(
make_organization,
make_team,
make_user_for_organization,
make_token_for_organization,
make_user_auth_headers,
):
organization = make_organization()
user1 = make_user_for_organization(organization)
user2 = make_user_for_organization(organization)
team1 = make_team(organization)
team2 = make_team(organization)
team3 = make_team(organization)
user1.teams.add(team1)
user1.teams.add(team2)
user2.teams.add(team2)
_, token = make_token_for_organization(organization)
client = APIClient()
url = reverse("api-internal:user-list")
def _get_user_pks(teams):
response = client.get(
url,
data={"team": [team.public_primary_key for team in teams]}, # these are query params
**make_user_auth_headers(user1, token),
)
assert response.status_code == status.HTTP_200_OK
return [u["pk"] for u in response.json()["results"]]
assert _get_user_pks([team1]) == [user1.public_primary_key]
assert _get_user_pks([team1, team2]) == [user1.public_primary_key, user2.public_primary_key]
assert _get_user_pks([team3]) == []
# check non-existent team returns bad request
response = client.get(f"{url}?team=null", **make_user_auth_headers(user1, token))
assert response.status_code == status.HTTP_400_BAD_REQUEST
@pytest.mark.django_db
def test_notification_chain_verbal(
make_organization,

View file

@ -64,6 +64,7 @@ from apps.telegram.client import TelegramClient
from apps.telegram.models import TelegramVerificationCode
from apps.user_management.models import Team, User
from common.api_helpers.exceptions import Conflict
from common.api_helpers.filters import ByTeamModelFieldFilterMixin, TeamModelMultipleChoiceFilter
from common.api_helpers.mixins import FilterSerializerMixin, PublicPrimaryKeyMixin
from common.api_helpers.paginators import HundredPageSizePaginator
from common.api_helpers.utils import create_engine_url
@ -113,7 +114,7 @@ class CurrentUserView(APIView):
return Response(serializer.data)
class UserFilter(filters.FilterSet):
class UserFilter(ByTeamModelFieldFilterMixin, filters.FilterSet):
"""
https://django-filter.readthedocs.io/en/master/guide/rest_framework.html
"""
@ -122,6 +123,7 @@ class UserFilter(filters.FilterSet):
# TODO: remove "roles" in next version
roles = filters.MultipleChoiceFilter(field_name="role", choices=LegacyAccessControlRole.choices())
permission = filters.ChoiceFilter(method="filter_by_permission", choices=ALL_PERMISSION_CHOICES)
team = TeamModelMultipleChoiceFilter(field_name="teams", null_label=None, null_value=None)
class Meta:
model = User

View file

@ -85,8 +85,7 @@ class ByTeamModelFieldFilterMixin:
if null_team_lookup is not None:
teams_lookup = teams_lookup | null_team_lookup
queryset = queryset.filter(teams_lookup)
return queryset
return queryset.filter(teams_lookup).distinct()
def get_team_queryset(request):