aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar bast <[email protected]>2021-05-30 14:46:27 -0700
committerGravatar bast <[email protected]>2021-05-30 15:42:12 -0700
commitb9f2589c7b2b5f171c47f1a614229ff999341b29 (patch)
tree3c43f7698ad8c86b05a5a1c01647efd2b8f3c72c
parentAdd tests for failure states of `expires_before` and `expires_after` filters (diff)
Raise ValidationError for new bot/infractions filter if the types are invalid
If the before time is after the after time, or if both `type` and `types` are specified
-rw-r--r--pydis_site/apps/api/tests/test_infractions.py22
-rw-r--r--pydis_site/apps/api/viewsets/bot/infraction.py13
2 files changed, 35 insertions, 0 deletions
diff --git a/pydis_site/apps/api/tests/test_infractions.py b/pydis_site/apps/api/tests/test_infractions.py
index 0f9a53c2..f2641492 100644
--- a/pydis_site/apps/api/tests/test_infractions.py
+++ b/pydis_site/apps/api/tests/test_infractions.py
@@ -177,6 +177,20 @@ class InfractionTests(APISubdomainTestCase):
self.assertEqual(response.status_code, 400)
self.assertEqual(list(response.json())[0], "expires_before")
+ def test_after_before_before_invalid(self):
+ url = reverse('bot:infraction-list', host='api')
+ target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5)
+ target_time_late = datetime.datetime.utcnow() + datetime.timedelta(hours=9)
+ response = self.client.get(
+ f'{url}?expires_before={target_time_late.isoformat()}'
+ f'&expires_after={target_time.isoformat()}'
+ )
+
+ self.assertEqual(response.status_code, 400)
+ errors = list(response.json())
+ self.assertIn("expires_before", errors)
+ self.assertIn("expires_after", errors)
+
def test_filter_manytypes(self):
url = reverse('bot:infraction-list', host='api')
response = self.client.get(f'{url}?types=mute,ban')
@@ -185,6 +199,14 @@ class InfractionTests(APISubdomainTestCase):
infractions = response.json()
self.assertEqual(len(infractions), 3)
+ def test_types_type_invalid(self):
+ url = reverse('bot:infraction-list', host='api')
+ response = self.client.get(f'{url}?types=mute,ban&type=superstar')
+
+ self.assertEqual(response.status_code, 400)
+ errors = list(response.json())
+ self.assertEqual("types", errors[0])
+
def test_sort_expiresby(self):
url = reverse('bot:infraction-list', host='api')
response = self.client.get(f'{url}?ordering=expires_at&permanent=false')
diff --git a/pydis_site/apps/api/viewsets/bot/infraction.py b/pydis_site/apps/api/viewsets/bot/infraction.py
index b0c7d332..00dd05b8 100644
--- a/pydis_site/apps/api/viewsets/bot/infraction.py
+++ b/pydis_site/apps/api/viewsets/bot/infraction.py
@@ -54,6 +54,8 @@ class InfractionViewSet(
- **expires_before** `isodatetime`: the latest expires_at time to return infractions for
Invalid query parameters are ignored.
+ Only one of `type` and `types` may be provided. If both `expires_before` and `expires_after`
+ are provided, `expires_after` must come after `expires_before`.
#### Response format
Response is paginated but the result is returned without any pagination metadata.
@@ -192,8 +194,19 @@ class InfractionViewSet(
except ValueError:
raise ValidationError({'expires_before': ['failed to convert to datetime']})
+ if 'expires_at__lte' in additional_filters and 'expires_at__gte' in additional_filters:
+ if additional_filters['expires_at__gte'] < additional_filters['expires_at__lte']:
+ raise ValidationError({
+ 'expires_before': ['cannot be after expires_after'],
+ 'expires_after': ['cannot be before expires_before'],
+ })
+
filter_types = self.request.query_params.get('types')
if filter_types:
+ if self.request.query_params.get('type'):
+ raise ValidationError({
+ 'types': ['you must provide only one of "type" or "types"'],
+ })
additional_filters['type__in'] = [i.strip() for i in filter_types.split(",")]
return self.queryset.filter(**additional_filters)