From f6a1259d64a2e8560b0ea909913c2a38a42609e6 Mon Sep 17 00:00:00 2001 From: Vincent Cai <72774400+vcai122@users.noreply.github.com> Date: Sun, 10 Nov 2024 15:57:12 -0500 Subject: [PATCH 1/2] Fix Portal Staff Email Typo (#321) --- backend/portal/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/portal/models.py b/backend/portal/models.py index b15aeee1..7f58e493 100644 --- a/backend/portal/models.py +++ b/backend/portal/models.py @@ -63,7 +63,7 @@ def _on_create(self): self._get_email_subject(), get_backend_manager_emails(), ( - f"A new {self.__class__._meta.model_name} for {self.club_code}" + f"A new {self.__class__._meta.model_name} for {self.club_code} " f"has been created by {self.creator}." ), ) From 44965e94b0461335991ea46e8347d8631643eb98 Mon Sep 17 00:00:00 2001 From: Vincent Cai <72774400+vcai122@users.noreply.github.com> Date: Mon, 11 Nov 2024 22:16:27 -0500 Subject: [PATCH 2/2] Remove Me Groups (#323) --- backend/gsr_booking/serializers.py | 31 ----------- backend/gsr_booking/urls.py | 4 +- backend/gsr_booking/views.py | 53 ++++--------------- backend/tests/gsr_booking/test_gsr_booking.py | 33 ++++++------ backend/tests/user/test_notifs.py | 3 +- backend/user/models.py | 2 - 6 files changed, 27 insertions(+), 99 deletions(-) diff --git a/backend/gsr_booking/serializers.py b/backend/gsr_booking/serializers.py index 1c94873e..76bf5cca 100644 --- a/backend/gsr_booking/serializers.py +++ b/backend/gsr_booking/serializers.py @@ -20,21 +20,13 @@ def get_is_wharton(self, obj): return obj["lid"] == 1 -class MiniUserSerializer(serializers.ModelSerializer): - class Meta: - model = User - fields = ["username", "first_name", "last_name"] - - class GroupMembershipSerializer(serializers.ModelSerializer): - user = MiniUserSerializer(read_only=True) group = serializers.SlugRelatedField(slug_field="name", queryset=Group.objects.all()) color = serializers.SlugRelatedField(slug_field="color", read_only=True, source="group") class Meta: model = GroupMembership fields = [ - "user", "group", "type", "pennkey_allow", @@ -73,29 +65,6 @@ def to_internal_value(self, data): return None # TODO: If you want to update based on BookingField, implement this. -class UserSerializer(serializers.ModelSerializer): - booking_groups = serializers.SerializerMethodField() - - def get_booking_groups(self, obj): - result = [] - for membership in GroupMembership.objects.filter(accepted=True, user=obj): - result.append( - { - "name": membership.group.name, - "id": membership.group.id, - "color": membership.group.color, - "pennkey_allow": membership.pennkey_allow, - "notifications": membership.notifications, - } - ) - - return result - - class Meta: - model = User - fields = ["username", "booking_groups"] - - class GSRSerializer(serializers.ModelSerializer): class Meta: model = GSR diff --git a/backend/gsr_booking/urls.py b/backend/gsr_booking/urls.py index 7f6e2b01..a54a1e12 100644 --- a/backend/gsr_booking/urls.py +++ b/backend/gsr_booking/urls.py @@ -10,16 +10,16 @@ GroupMembershipViewSet, GroupViewSet, Locations, + MyMembershipViewSet, RecentGSRs, ReservationsView, - UserViewSet, ) from utils.cache import Cache router = routers.DefaultRouter() -router.register(r"users", UserViewSet) +router.register(r"mymemberships", MyMembershipViewSet, "mymemberships") router.register(r"membership", GroupMembershipViewSet) router.register(r"groups", GroupViewSet) diff --git a/backend/gsr_booking/views.py b/backend/gsr_booking/views.py index 9bf6aa3f..e4b9eac5 100644 --- a/backend/gsr_booking/views.py +++ b/backend/gsr_booking/views.py @@ -11,66 +11,31 @@ from gsr_booking.api_wrapper import APIError, GSRBooker, WhartonGSRBooker from gsr_booking.models import GSR, Group, GroupMembership, GSRBooking -from gsr_booking.serializers import ( - GroupMembershipSerializer, - GroupSerializer, - GSRSerializer, - UserSerializer, -) +from gsr_booking.serializers import GroupMembershipSerializer, GroupSerializer, GSRSerializer from pennmobile.analytics import Metric, record_analytics User = get_user_model() -class UserViewSet(viewsets.ReadOnlyModelViewSet): - """ - Can specify `me` instead of the `username` to retrieve details on the current user. - """ - - queryset = User.objects.all().prefetch_related( - Prefetch("booking_groups", Group.objects.filter(memberships__accepted=True)) - ) +class MyMembershipViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] - serializer_class = UserSerializer - lookup_field = "username" - filter_backends = [DjangoFilterBackend] - filterset_fields = ["username", "first_name", "last_name"] - - def get_object(self): - lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field - param = self.kwargs[lookup_url_kwarg] - if param == "me": - return self.request.user - else: - return super().get_object() + serializer_class = GroupMembershipSerializer def get_queryset(self): - if not self.request.user.is_authenticated: - return User.objects.none() + return GroupMembership.objects.filter(user=self.request.user, accepted=True) - queryset = User.objects.all() - queryset = queryset.prefetch_related( - Prefetch( - "memberships", - GroupMembership.objects.filter( - group__in=self.request.user.booking_groups.all(), accepted=True - ), - ) - ) - return queryset - - @action(detail=True, methods=["get"]) - def invites(self, request, username=None): + @action(detail=False, methods=["get"]) + def invites(self, request): """ Retrieve all invites for a given user. """ - - user = get_object_or_404(User, username=username) return Response( GroupMembershipSerializer( GroupMembership.objects.filter( - user=user, accepted=False, group__in=self.request.user.booking_groups.all() + user=request.user, + accepted=False, + group__in=self.request.user.booking_groups.all(), ), many=True, ).data diff --git a/backend/tests/gsr_booking/test_gsr_booking.py b/backend/tests/gsr_booking/test_gsr_booking.py index 1559dbbd..7965e35f 100644 --- a/backend/tests/gsr_booking/test_gsr_booking.py +++ b/backend/tests/gsr_booking/test_gsr_booking.py @@ -8,7 +8,7 @@ User = get_user_model() -class UserViewTestCase(TestCase): +class MyMembershipViewTestCase(TestCase): def setUp(self): self.user1 = User.objects.create_user( username="user1", password="password", first_name="user", last_name="one" @@ -17,28 +17,25 @@ def setUp(self): username="user2", password="password", first_name="user", last_name="two" ) - self.group = Group.objects.create(owner=self.user1, name="g1", color="blue") - self.group.members.add(self.user1) - memship = self.group.memberships.all()[0] - memship.accepted = True - memship.save() + Group.objects.create( + owner=self.user1, name="g1", color="blue" + ) # creating group also adds user + group2 = Group.objects.create(owner=self.user2, name="g2", color="blue") + GroupMembership.objects.create(user=self.user1, group=group2, accepted=True) + group3 = Group.objects.create(owner=self.user2, name="g3", color="blue") + GroupMembership.objects.create(user=self.user1, group=group3) self.client = APIClient() self.client.login(username="user1", password="password") - def test_user_list(self): - response = self.client.get("/gsr/users/") + def test_user_memberships(self): + response = self.client.get("/gsr/mymemberships/") self.assertTrue(200, response.status_code) self.assertEqual(2, len(response.data)) - def test_user_detail_in_group(self): - response = self.client.get("/gsr/users/user1/") - self.assertTrue(200, response.status_code) - self.assertEqual(2, len(response.data["booking_groups"])) - - def test_me_user_detail_in_group(self): - response = self.client.get("/gsr/users/me/") + def test_user_invites(self): + response = self.client.get("/gsr/mymemberships/invites/") self.assertTrue(200, response.status_code) - self.assertEqual(2, len(response.data["booking_groups"])) + self.assertEqual(1, len(response.data)) class MembershipViewTestCase(TestCase): @@ -159,7 +156,7 @@ def setUp(self): def test_get_groups(self): response = self.client.get("/gsr/groups/") self.assertEqual(200, response.status_code) - self.assertEqual(2, len(response.data)) + self.assertEqual(1, len(response.data)) def test_get_groups_includes_invites(self): GroupMembership.objects.create(user=self.user1, group=self.group2, accepted=False) @@ -173,7 +170,7 @@ def test_get_group_not_involved_fails(self): def test_make_group(self): response = self.client.post("/gsr/groups/", {"name": "gx", "color": "blue"}) self.assertEqual(201, response.status_code, response.data) - self.assertEqual(5, Group.objects.count()) + self.assertEqual(3, Group.objects.count()) self.assertEqual("user1", Group.objects.get(name="gx").owner.username) def test_only_accepted_memberships(self): diff --git a/backend/tests/user/test_notifs.py b/backend/tests/user/test_notifs.py index 512b271a..cbeb8075 100644 --- a/backend/tests/user/test_notifs.py +++ b/backend/tests/user/test_notifs.py @@ -9,7 +9,7 @@ from identity.identity import attest, container, get_platform_jwks from rest_framework.test import APIClient -from gsr_booking.models import GSR, Group, GSRBooking, Reservation +from gsr_booking.models import GSR, GSRBooking, Reservation from user.models import NotificationSetting, NotificationToken @@ -350,7 +350,6 @@ def setUp(self): start=g.start, end=g.end, creator=self.test_user, - group=Group.objects.get(owner=self.test_user), ) g.reservation = r diff --git a/backend/user/models.py b/backend/user/models.py index deb3714b..dc71b5c3 100644 --- a/backend/user/models.py +++ b/backend/user/models.py @@ -3,7 +3,6 @@ from django.db.models.signals import post_save from django.dispatch import receiver -from gsr_booking.models import Group from laundry.models import LaundryRoom from penndata.models import FitnessRoom @@ -71,7 +70,6 @@ def create_or_update_user_profile(sender, instance, created, **kwargs): object exists for that User, it will create one """ Profile.objects.get_or_create(user=instance) - Group.objects.get_or_create(owner=instance, name="Me", color="#14f7d1") # notifications token, _ = NotificationToken.objects.get_or_create(user=instance)