From b8a64da2493c5f37a2d61c8fab6d8db4bf7a723c Mon Sep 17 00:00:00 2001 From: Jonatan Norbye Date: Wed, 20 Mar 2024 14:40:03 +1300 Subject: [PATCH] Extend email-user filter to add boards and ordained --- lego/apps/email/filters.py | 24 ++++++++----- lego/apps/email/tests/test_views.py | 36 +++++++++++++++++-- lego/apps/users/constants.py | 2 ++ lego/apps/users/filters.py | 2 ++ .../migrations/0043_alter_abakusgroup_type.py | 30 ++++++++++++++++ lego/apps/users/tests/test_abakusgroup_api.py | 11 +++++- 6 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 lego/apps/users/migrations/0043_alter_abakusgroup_type.py diff --git a/lego/apps/email/filters.py b/lego/apps/email/filters.py index 7666a142b..beb7703cb 100644 --- a/lego/apps/email/filters.py +++ b/lego/apps/email/filters.py @@ -3,7 +3,13 @@ from django_filters.rest_framework import BooleanFilter, CharFilter, FilterSet from lego.apps.email.models import EmailList -from lego.apps.users.constants import GROUP_COMMITTEE, GROUP_GRADE +from lego.apps.users.constants import ( + GROUP_BOARD, + GROUP_COMMITTEE, + GROUP_GRADE, + GROUP_ORDAINED, +) +from lego.apps.users.filters import CharInFilter from lego.apps.users.models import User @@ -21,8 +27,8 @@ class EmailUserFilterSet(FilterSet): email = CharFilter(field_name="internal_email__email", lookup_expr="icontains") userUsername = CharFilter(field_name="username", lookup_expr="icontains") userFullname = CharFilter(field_name="userFullname", method="fullname") - userCommittee = CharFilter(field_name="userCommitee", method="commitee") userGrade = CharFilter(field_name="abakus_groups", method="grade") + userGroups = CharInFilter(field_name="userGroups", method="groups") enabled = BooleanFilter(field_name="internal_email_enabled") def grade(self, queryset, name, value): @@ -34,13 +40,15 @@ def grade(self, queryset, name, value): ) return queryset - def commitee(self, queryset, name, value): - if value == "-": - return queryset.exclude(abakus_groups__type=GROUP_COMMITTEE) + def groups(self, queryset, name, value): + if value == ["-"]: + return queryset.exclude( + abakus_groups__type__in=[GROUP_COMMITTEE, GROUP_BOARD, GROUP_ORDAINED] + ) if value: return queryset.filter( - abakus_groups__name__icontains=value, - abakus_groups__type=GROUP_COMMITTEE, + abakus_groups__name__in=value, + abakus_groups__type__in=[GROUP_COMMITTEE, GROUP_BOARD, GROUP_ORDAINED], ) return queryset @@ -59,5 +67,5 @@ class Meta: "userUsername", "userFullname", "userGrade", - "userCommittee", + "userGroups", ) diff --git a/lego/apps/email/tests/test_views.py b/lego/apps/email/tests/test_views.py index 61562740d..6750e96e2 100644 --- a/lego/apps/email/tests/test_views.py +++ b/lego/apps/email/tests/test_views.py @@ -1,7 +1,7 @@ from rest_framework import status -from lego.apps.email.models import EmailList -from lego.apps.users.models import AbakusGroup, User +from lego.apps.email.models import EmailAddress, EmailList +from lego.apps.users.models import AbakusGroup, Membership, User from lego.utils.test_utils import BaseAPITestCase @@ -150,7 +150,7 @@ def test_change_assigned_email(self): self.assertEqual("address", EmailList.objects.get(id=1).email_id) def test_delete_endpoint_not_available(self): - """The delete endpoint is'nt available.""" + """The delete endpoint isn't available.""" response = self.client.delete(f"{self.url}1/") self.assertEqual(status.HTTP_403_FORBIDDEN, response.status_code) @@ -178,6 +178,36 @@ def test_list(self): response = self.client.get(self.url) self.assertEqual(status.HTTP_200_OK, response.status_code) + def test_list_filter_groups(self): + """The list endpoint can be filtered by group memberships""" + webkom = AbakusGroup.objects.get(name="Webkom") + webber = User.objects.create( + username="Webber", + email="webber", + internal_email=EmailAddress.objects.create(email="webber"), + ) + Membership.objects.create(abakus_group=webkom, user=webber) + User.objects.create( + username="Pleb", + email="pleb", + internal_email=EmailAddress.objects.create(email="pleb"), + ) + response = self.client.get(self.url) + self.assertEqual(status.HTTP_200_OK, response.status_code) + self.assertEqual(3, len(response.json()["results"])) + + response = self.client.get(f"{self.url}?userGroups=Webkom") + self.assertEqual(status.HTTP_200_OK, response.status_code) + self.assertEqual(1, len(response.json()["results"])) + + response = self.client.get(f"{self.url}?userGroups=Webkom,EmailAdminTest") + self.assertEqual(status.HTTP_200_OK, response.status_code) + self.assertEqual(1, len(response.json()["results"])) + + response = self.client.get(f"{self.url}?userGroups=-") + self.assertEqual(status.HTTP_200_OK, response.status_code) + self.assertEqual(2, len(response.json()["results"])) + def test_retrieve(self): """It is possible to retrieve the user""" response = self.client.get(f"{self.url}1/") diff --git a/lego/apps/users/constants.py b/lego/apps/users/constants.py index c32db7448..899ff7242 100644 --- a/lego/apps/users/constants.py +++ b/lego/apps/users/constants.py @@ -102,6 +102,7 @@ def values(cls) -> list[str]: GROUP_BOARD = "styre" GROUP_REVUE = "revy" GROUP_SUB = "under" +GROUP_ORDAINED = "ordenen" GROUP_GRADE = "klasse" GROUP_OTHER = "annen" GROUP_TYPES = ( @@ -112,6 +113,7 @@ def values(cls) -> list[str]: (GROUP_GRADE, GROUP_GRADE), (GROUP_OTHER, GROUP_OTHER), (GROUP_SUB, GROUP_SUB), + (GROUP_ORDAINED, GROUP_ORDAINED), ) OPEN_GROUPS = (GROUP_INTEREST,) diff --git a/lego/apps/users/filters.py b/lego/apps/users/filters.py index 0435a1379..575224c08 100644 --- a/lego/apps/users/filters.py +++ b/lego/apps/users/filters.py @@ -37,6 +37,8 @@ def user__fullname(self, queryset, name, value): class AbakusGroupFilterSet(FilterSet): + type = CharInFilter(field_name="type", lookup_expr="in") + class Meta: model = AbakusGroup fields = ("type",) diff --git a/lego/apps/users/migrations/0043_alter_abakusgroup_type.py b/lego/apps/users/migrations/0043_alter_abakusgroup_type.py new file mode 100644 index 000000000..bbb5ca237 --- /dev/null +++ b/lego/apps/users/migrations/0043_alter_abakusgroup_type.py @@ -0,0 +1,30 @@ +# Generated by Django 4.0.10 on 2024-03-20 00:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("users", "0042_penalty_type"), + ] + + operations = [ + migrations.AlterField( + model_name="abakusgroup", + name="type", + field=models.CharField( + choices=[ + ("komite", "komite"), + ("interesse", "interesse"), + ("styre", "styre"), + ("revy", "revy"), + ("klasse", "klasse"), + ("annen", "annen"), + ("under", "under"), + ("ordenen", "ordenen"), + ], + default="annen", + max_length=10, + ), + ), + ] diff --git a/lego/apps/users/tests/test_abakusgroup_api.py b/lego/apps/users/tests/test_abakusgroup_api.py index aedd5272a..f5db93824 100644 --- a/lego/apps/users/tests/test_abakusgroup_api.py +++ b/lego/apps/users/tests/test_abakusgroup_api.py @@ -2,7 +2,7 @@ from rest_framework import status from lego.apps.users import constants -from lego.apps.users.constants import LEADER +from lego.apps.users.constants import GROUP_COMMITTEE, GROUP_INTEREST, LEADER from lego.apps.users.models import AbakusGroup, User from lego.apps.users.serializers.abakus_groups import PublicAbakusGroupSerializer from lego.utils.test_utils import BaseAPITestCase @@ -67,6 +67,15 @@ def test_without_auth(self): def test_with_auth(self): self.successful_list(self.user) + def test_with_filter_type(self): + """Groups can be filtered on multiple types""" + self.client.force_authenticate(self.user) + response = self.client.get( + f"{_get_list_url()}?type={GROUP_COMMITTEE},{GROUP_INTEREST}" + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(7, len(response.json()["results"])) + class RetrieveAbakusGroupAPITestCase(BaseAPITestCase): fixtures = ["test_abakus_groups.yaml", "test_users.yaml"]