Skip to content

Commit b9f2589

Browse files
committed
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
1 parent e3696a3 commit b9f2589

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

pydis_site/apps/api/tests/test_infractions.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,20 @@ def test_filter_before_invalid(self):
177177
self.assertEqual(response.status_code, 400)
178178
self.assertEqual(list(response.json())[0], "expires_before")
179179

180+
def test_after_before_before_invalid(self):
181+
url = reverse('bot:infraction-list', host='api')
182+
target_time = datetime.datetime.utcnow() + datetime.timedelta(hours=5)
183+
target_time_late = datetime.datetime.utcnow() + datetime.timedelta(hours=9)
184+
response = self.client.get(
185+
f'{url}?expires_before={target_time_late.isoformat()}'
186+
f'&expires_after={target_time.isoformat()}'
187+
)
188+
189+
self.assertEqual(response.status_code, 400)
190+
errors = list(response.json())
191+
self.assertIn("expires_before", errors)
192+
self.assertIn("expires_after", errors)
193+
180194
def test_filter_manytypes(self):
181195
url = reverse('bot:infraction-list', host='api')
182196
response = self.client.get(f'{url}?types=mute,ban')
@@ -185,6 +199,14 @@ def test_filter_manytypes(self):
185199
infractions = response.json()
186200
self.assertEqual(len(infractions), 3)
187201

202+
def test_types_type_invalid(self):
203+
url = reverse('bot:infraction-list', host='api')
204+
response = self.client.get(f'{url}?types=mute,ban&type=superstar')
205+
206+
self.assertEqual(response.status_code, 400)
207+
errors = list(response.json())
208+
self.assertEqual("types", errors[0])
209+
188210
def test_sort_expiresby(self):
189211
url = reverse('bot:infraction-list', host='api')
190212
response = self.client.get(f'{url}?ordering=expires_at&permanent=false')

pydis_site/apps/api/viewsets/bot/infraction.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class InfractionViewSet(
5454
- **expires_before** `isodatetime`: the latest expires_at time to return infractions for
5555
5656
Invalid query parameters are ignored.
57+
Only one of `type` and `types` may be provided. If both `expires_before` and `expires_after`
58+
are provided, `expires_after` must come after `expires_before`.
5759
5860
#### Response format
5961
Response is paginated but the result is returned without any pagination metadata.
@@ -192,8 +194,19 @@ def get_queryset(self) -> QuerySet:
192194
except ValueError:
193195
raise ValidationError({'expires_before': ['failed to convert to datetime']})
194196

197+
if 'expires_at__lte' in additional_filters and 'expires_at__gte' in additional_filters:
198+
if additional_filters['expires_at__gte'] < additional_filters['expires_at__lte']:
199+
raise ValidationError({
200+
'expires_before': ['cannot be after expires_after'],
201+
'expires_after': ['cannot be before expires_before'],
202+
})
203+
195204
filter_types = self.request.query_params.get('types')
196205
if filter_types:
206+
if self.request.query_params.get('type'):
207+
raise ValidationError({
208+
'types': ['you must provide only one of "type" or "types"'],
209+
})
197210
additional_filters['type__in'] = [i.strip() for i in filter_types.split(",")]
198211

199212
return self.queryset.filter(**additional_filters)

0 commit comments

Comments
 (0)