Skip to content

Commit 2936d7e

Browse files
committed
Restrict pool updates to active pools
1 parent 7801052 commit 2936d7e

File tree

4 files changed

+76
-17
lines changed

4 files changed

+76
-17
lines changed

lego/apps/events/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,9 @@ def decrement(self) -> Pool:
849849
self.save(update_fields=["counter"])
850850
return self
851851

852+
def permission_group_ids(self) -> set[int]:
853+
return set(self.permission_groups.values_list("id", flat=True))
854+
852855
@abakus_cached_property
853856
def all_permission_groups(self):
854857
groups = self.permission_groups.all()

lego/apps/events/serializers/events.py

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -454,24 +454,43 @@ def update(self, instance, validated_data):
454454
pools[0]["capacity"] = 0
455455
with transaction.atomic():
456456
if pools is not None:
457-
existing_pools = list(instance.pools.all().values_list("id", flat=True))
457+
existing_ids = set(instance.pools.values_list("id", flat=True))
458458
for pool in pools:
459459
pool_id = pool.get("id", None)
460-
if pool_id in existing_pools:
461-
existing_pools.remove(pool_id)
462460
permission_groups = pool.pop("permission_groups")
463-
created_pool = Pool.objects.update_or_create(
464-
event=instance,
465-
id=pool_id,
466-
defaults={
467-
"name": pool.get("name"),
468-
"capacity": pool.get("capacity", 0),
469-
"activation_date": pool.get("activation_date"),
470-
},
471-
)[0]
472-
created_pool.permission_groups.set(permission_groups)
473-
for pool_id in existing_pools:
474-
Pool.objects.get(id=pool_id).delete()
461+
perm_ids = [getattr(g, "id", g) for g in permission_groups]
462+
pool_instance = None
463+
if pool_id:
464+
pool_instance = (
465+
Pool.objects.filter(id=pool_id, event=instance)
466+
.select_for_update()
467+
.first()
468+
)
469+
existing_ids.discard(pool_id)
470+
pool_data = {
471+
"name": pool.get("name", getattr(pool_instance, "name", None)),
472+
"capacity": pool.get(
473+
"capacity", getattr(pool_instance, "capacity", 0)
474+
),
475+
"activation_date": pool.get(
476+
"activation_date",
477+
getattr(pool_instance, "activation_date", None),
478+
),
479+
"permission_groups": perm_ids,
480+
}
481+
ser = PoolCreateAndUpdateSerializer(
482+
instance=pool_instance,
483+
data=pool_data,
484+
context={**self.context, "event": instance},
485+
partial=True,
486+
)
487+
ser.is_valid(raise_exception=True)
488+
ser.save()
489+
if existing_ids:
490+
for p in Pool.objects.filter(
491+
event=instance, id__in=existing_ids
492+
).iterator():
493+
p.delete()
475494
return super().update(instance, validated_data)
476495

477496

lego/apps/events/serializers/pools.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,29 @@ class Meta:
9090
"registrations": {"read_only": True},
9191
}
9292

93+
def validate(self, attrs):
94+
instance = getattr(self, "instance", None)
95+
if not instance:
96+
return attrs
97+
if "permission_groups" in attrs and instance.is_activated:
98+
new_ids = {getattr(g, "id", g) for g in attrs["permission_groups"]}
99+
old_ids = instance.permission_group_ids()
100+
if new_ids != old_ids:
101+
raise serializers.ValidationError(
102+
{
103+
"permission_groups": "Permission control is disabled for active pools."
104+
}
105+
)
106+
if "activation_date" in attrs and instance.is_activated:
107+
if attrs["activation_date"] != instance.activation_date:
108+
raise serializers.ValidationError(
109+
{"activation_date": "Time travel is disabled for active pools."}
110+
)
111+
return attrs
112+
93113
def create(self, validated_data):
94-
event = Event.objects.get(pk=self.context["view"].kwargs["event_pk"])
114+
event = validated_data.pop("event", None) or self.context.get("event")
95115
permission_groups = validated_data.pop("permission_groups")
96116
pool = Pool.objects.create(event=event, **validated_data)
97117
pool.permission_groups.set(permission_groups)
98-
99118
return pool

lego/apps/events/tests/test_events_api.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,24 @@ def test_event_partial_update_pool_deletion(self):
798798
self.assertEqual(0, event.can_view_groups.count())
799799
self.assertEqual(res_event["pools"], [])
800800

801+
def test_event_update_pool_permission_groups_after_activation(self):
802+
"""Test updating permission group after pool activation is not allowed"""
803+
event = self.client.get(_get_detail_url(self.event_id)).json()
804+
permission_group = AbakusGroup.objects.get(name="Abakus").id
805+
pool = event["pools"][0]
806+
pool["permissionGroups"] = [permission_group]
807+
event_update_response = self.client.put(_get_detail_url(self.event_id), event)
808+
self.assertEqual(event_update_response.status_code, status.HTTP_400_BAD_REQUEST)
809+
810+
def test_event_update_pool_activation_date_after_activation(self):
811+
"""Test updating date after pool activation is not allowed"""
812+
event = self.client.get(_get_detail_url(self.event_id)).json()
813+
activation_date = timezone.now() + timedelta(days=2)
814+
pool = event["pools"][0]
815+
pool["activationDate"] = activation_date.isoformat()
816+
event_update_response = self.client.put(_get_detail_url(self.event_id), event)
817+
self.assertEqual(event_update_response.status_code, status.HTTP_400_BAD_REQUEST)
818+
801819
def test_event_correct_youtube_url(self):
802820
test_event = _test_event_data[0].copy()
803821
test_event["youtubeUrl"] = "https://www.youtube.com/watch?v=KrzIaRwAMvc"

0 commit comments

Comments
 (0)