From 5b5f16fe87e1902e863800cc9741233548091d98 Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Wed, 25 Sep 2019 18:10:38 +0200 Subject: Migrate hidden warnings to notes https://github.com/python-discord/site/issues/260 We have added a new "note" type to the Infraction model, meaning that we can now decouple notes and warnings completely. However, notes made prior to this change are still registered as "hidden warnings". This commit adds a data migration that sets the type field of "hidden warning" infractions to "note". This commit implements the first part of #260 --- .../0043_infraction_hidden_warnings_to_notes.py | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0043_infraction_hidden_warnings_to_notes.py (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/migrations/0043_infraction_hidden_warnings_to_notes.py b/pydis_site/apps/api/migrations/0043_infraction_hidden_warnings_to_notes.py new file mode 100644 index 00000000..7c751f5d --- /dev/null +++ b/pydis_site/apps/api/migrations/0043_infraction_hidden_warnings_to_notes.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.5 on 2019-09-25 08:41 + +from django.db import migrations + + +def migrate_hidden_warnings_to_notes(apps, schema_editor): + """Migrates hidden warnings to note.""" + Infraction = apps.get_model('api', 'Infraction') + + for infraction in Infraction.objects.filter(type="warning", hidden=True): + infraction.type = "note" + infraction.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0042_infraction_add_default_ordering'), + ] + + operations = [ + migrations.RunPython(migrate_hidden_warnings_to_notes), + ] -- cgit v1.2.3 From ce22f1e0a67f47aca48b5c548d7d1a544b9fe71d Mon Sep 17 00:00:00 2001 From: Sebastiaan Zeeff <33516116+SebastiaanZ@users.noreply.github.com> Date: Thu, 26 Sep 2019 16:30:12 +0200 Subject: Reject unhidden note or hidden warning infraction https://github.com/python-discord/site/issues/260 This commit adds validation steps to the InfractionSerializer to make sure that `"warning"` infractions can never be set with `hidden=True` and note infractions can never be set with `hidden=False` usng the API. This is the final step in decoupling "note" infractions and "warning" infractions. This commit implements the final part of and closes #260 --- pydis_site/apps/api/serializers.py | 5 ++- pydis_site/apps/api/tests/test_infractions.py | 48 +++++++++++++++++++-------- 2 files changed, 38 insertions(+), 15 deletions(-) (limited to 'pydis_site/apps/api') diff --git a/pydis_site/apps/api/serializers.py b/pydis_site/apps/api/serializers.py index 5466b06b..326e20e1 100644 --- a/pydis_site/apps/api/serializers.py +++ b/pydis_site/apps/api/serializers.py @@ -115,9 +115,12 @@ class InfractionSerializer(ModelSerializer): raise ValidationError({'expires_at': [f'{infr_type} infractions cannot expire.']}) hidden = attrs.get('hidden') - if hidden and infr_type in ('superstar',): + if hidden and infr_type in ('superstar', 'warning'): raise ValidationError({'hidden': [f'{infr_type} infractions cannot be hidden.']}) + if not hidden and infr_type in ('note', ): + raise ValidationError({'hidden': [f'{infr_type} infractions must be hidden.']}) + return attrs diff --git a/pydis_site/apps/api/tests/test_infractions.py b/pydis_site/apps/api/tests/test_infractions.py index 0092d355..c58c32e2 100644 --- a/pydis_site/apps/api/tests/test_infractions.py +++ b/pydis_site/apps/api/tests/test_infractions.py @@ -257,32 +257,52 @@ class CreationTests(APISubdomainTestCase): def test_returns_400_for_expiring_non_expirable_type(self): url = reverse('bot:infraction-list', host='api') - data = { - 'user': self.user.id, - 'actor': self.user.id, - 'type': 'kick', - 'expires_at': '5018-11-20T15:52:00+00:00' - } - response = self.client.post(url, data=data) - self.assertEqual(response.status_code, 400) - self.assertEqual(response.json(), { - 'expires_at': [f'{data["type"]} infractions cannot expire.'] - }) + for infraction_type in ('kick', 'warning'): + data = { + 'user': self.user.id, + 'actor': self.user.id, + 'type': infraction_type, + 'expires_at': '5018-11-20T15:52:00+00:00' + } + + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + 'expires_at': [f'{data["type"]} infractions cannot expire.'] + }) def test_returns_400_for_hidden_non_hideable_type(self): url = reverse('bot:infraction-list', host='api') + + for infraction_type in ('superstar', 'warning'): + data = { + 'user': self.user.id, + 'actor': self.user.id, + 'type': infraction_type, + 'hidden': True + } + + response = self.client.post(url, data=data) + self.assertEqual(response.status_code, 400) + self.assertEqual(response.json(), { + 'hidden': [f'{data["type"]} infractions cannot be hidden.'] + }) + + def test_returns_400_for_non_hidden_required_hidden_type(self): + url = reverse('bot:infraction-list', host='api') + data = { 'user': self.user.id, 'actor': self.user.id, - 'type': 'superstar', - 'hidden': True + 'type': 'note', + 'hidden': False, } response = self.client.post(url, data=data) self.assertEqual(response.status_code, 400) self.assertEqual(response.json(), { - 'hidden': [f'{data["type"]} infractions cannot be hidden.'] + 'hidden': [f'{data["type"]} infractions must be hidden.'] }) -- cgit v1.2.3