From f093907393b4f479f62409286831b938ba65c558 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 16:27:18 +0200 Subject: Create a signal to unassign roles from user when deleted Add a signal to the api app that automatically unassigns deleted roles from users that have them --- pydis_site/apps/api/__init__.py | 1 + pydis_site/apps/api/apps.py | 10 +++++++++- pydis_site/apps/api/signals.py | 12 ++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 pydis_site/apps/api/signals.py diff --git a/pydis_site/apps/api/__init__.py b/pydis_site/apps/api/__init__.py index e69de29b..afa5b4d5 100644 --- a/pydis_site/apps/api/__init__.py +++ b/pydis_site/apps/api/__init__.py @@ -0,0 +1 @@ +default_app_config = 'pydis_site.apps.api.apps.ApiConfig' diff --git a/pydis_site/apps/api/apps.py b/pydis_site/apps/api/apps.py index 76810b2e..18eda9e3 100644 --- a/pydis_site/apps/api/apps.py +++ b/pydis_site/apps/api/apps.py @@ -4,4 +4,12 @@ from django.apps import AppConfig class ApiConfig(AppConfig): """Django AppConfig for the API app.""" - name = 'api' + name = 'pydis_site.apps.api' + + def ready(self) -> None: + """ + Gets called as soon as the registry is fully populated. + + https://docs.djangoproject.com/en/3.2/ref/applications/#django.apps.AppConfig.ready + """ + import pydis_site.apps.api.signals # noqa: F401 diff --git a/pydis_site/apps/api/signals.py b/pydis_site/apps/api/signals.py new file mode 100644 index 00000000..c69704b1 --- /dev/null +++ b/pydis_site/apps/api/signals.py @@ -0,0 +1,12 @@ +from django.db.models.signals import pre_delete +from django.dispatch import receiver + +from pydis_site.apps.api.models.bot import Role, User + + +@receiver(signal=pre_delete, sender=Role) +def delete_role_from_user(sender: Role, instance: Role, **kwargs) -> None: + """Unassigns the Role (instance) that is being deleted from every user that has it.""" + for user in User.objects.filter(roles__contains=[instance.id]): + del user.roles[user.roles.index(instance.id)] + user.save() -- cgit v1.2.3 From 0f24bdcd0ba261da045ac73e8567239eb63c6fc6 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 17:54:39 +0200 Subject: Add test to check role unassignment Create a test that checks if a role gets deleted it will also get unassigned from the user --- pydis_site/apps/api/tests/test_roles.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index d39cea4d..7c968852 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -1,7 +1,8 @@ from django.urls import reverse from .base import AuthenticatedAPITestCase -from ..models import Role +from ..models import Role, User + class CreationTests(AuthenticatedAPITestCase): @@ -35,6 +36,20 @@ class CreationTests(AuthenticatedAPITestCase): permissions=6, position=0, ) + cls.role_to_delete = Role.objects.create( + id=7, + name="role to delete", + colour=7, + permissions=7, + position=0, + ) + cls.role_unassigned_test_user = User.objects.create( + id=8, + name="role_unassigned_test_user", + discriminator="0000", + roles=[cls.role_to_delete.id], + in_guild=True + ) def _validate_roledict(self, role_dict: dict) -> None: """Helper method to validate a dict representing a role.""" @@ -181,6 +196,11 @@ class CreationTests(AuthenticatedAPITestCase): response = self.client.delete(url) self.assertEqual(response.status_code, 204) + def test_role_delete_unassigned(self): + """Tests if the deleted Role gets unassigned from the user.""" + self.role_to_delete.delete() + self.assertEqual(self.role_unassigned_test_user.roles, []) + def test_role_detail_404_all_methods(self): """Tests detail view with non-existing ID.""" url = reverse('api:bot:role-detail', args=(20190815,)) -- cgit v1.2.3 From 9d255dcf3daafde71071ad75b000077a861da659 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 18:49:21 +0200 Subject: Patch roles test to use fresh instance from the DB --- pydis_site/apps/api/tests/test_roles.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index 7c968852..88c0256b 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -199,6 +199,7 @@ class CreationTests(AuthenticatedAPITestCase): def test_role_delete_unassigned(self): """Tests if the deleted Role gets unassigned from the user.""" self.role_to_delete.delete() + self.role_unassigned_test_user.refresh_from_db() self.assertEqual(self.role_unassigned_test_user.roles, []) def test_role_detail_404_all_methods(self): -- cgit v1.2.3 From f34a52016bd5a7d50c1146d6fbd213ce889f58c7 Mon Sep 17 00:00:00 2001 From: D0rs4n <41237606+D0rs4n@users.noreply.github.com> Date: Tue, 31 Aug 2021 19:21:36 +0200 Subject: Patch signals to use post_delete, instead of pre_delete From now on the signal will only get executed after the Role has been deleted The commit also introduces minor changes in the tests of roles --- pydis_site/apps/api/signals.py | 4 ++-- pydis_site/apps/api/tests/test_roles.py | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pydis_site/apps/api/signals.py b/pydis_site/apps/api/signals.py index c69704b1..5c26bfb6 100644 --- a/pydis_site/apps/api/signals.py +++ b/pydis_site/apps/api/signals.py @@ -1,10 +1,10 @@ -from django.db.models.signals import pre_delete +from django.db.models.signals import post_delete from django.dispatch import receiver from pydis_site.apps.api.models.bot import Role, User -@receiver(signal=pre_delete, sender=Role) +@receiver(signal=post_delete, sender=Role) def delete_role_from_user(sender: Role, instance: Role, **kwargs) -> None: """Unassigns the Role (instance) that is being deleted from every user that has it.""" for user in User.objects.filter(roles__contains=[instance.id]): diff --git a/pydis_site/apps/api/tests/test_roles.py b/pydis_site/apps/api/tests/test_roles.py index 88c0256b..73c80c77 100644 --- a/pydis_site/apps/api/tests/test_roles.py +++ b/pydis_site/apps/api/tests/test_roles.py @@ -4,7 +4,6 @@ from .base import AuthenticatedAPITestCase from ..models import Role, User - class CreationTests(AuthenticatedAPITestCase): @classmethod def setUpTestData(cls): @@ -96,11 +95,11 @@ class CreationTests(AuthenticatedAPITestCase): url = reverse('api:bot:role-list') response = self.client.get(url) - self.assertContains(response, text="id", count=4, status_code=200) + self.assertContains(response, text="id", count=5, status_code=200) roles = response.json() self.assertIsInstance(roles, list) - self.assertEqual(len(roles), 4) + self.assertEqual(len(roles), 5) for role in roles: self._validate_roledict(role) -- cgit v1.2.3