diff --git a/mockserver/tenants/migrations/0012_tenant_logic_delete.py b/mockserver/tenants/migrations/0012_tenant_logic_delete.py new file mode 100644 index 0000000..e1581f2 --- /dev/null +++ b/mockserver/tenants/migrations/0012_tenant_logic_delete.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.9 on 2021-01-30 23:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenants', '0011_project_slug_name'), + ] + + operations = [ + migrations.AddField( + model_name='tenant', + name='deleted', + field=models.BooleanField(default=False), + ), + ] diff --git a/mockserver/tenants/models.py b/mockserver/tenants/models.py index 1009284..5f5b7a4 100644 --- a/mockserver/tenants/models.py +++ b/mockserver/tenants/models.py @@ -122,7 +122,7 @@ def __str__(self): class Tenant(DateAwareModel, User): - pass + deleted = models.BooleanField(default=False) class OrganizationInvite(DateAwareModel): diff --git a/mockserver/tenants/tests/test_views.py b/mockserver/tenants/tests/test_views.py index c528715..ae6554b 100644 --- a/mockserver/tenants/tests/test_views.py +++ b/mockserver/tenants/tests/test_views.py @@ -248,6 +248,50 @@ def test_authenticated_owner_profile_update_is_allowed(self, patch_serializer): self.assertEqual(response.status_code, 200) + def test_tenants_view_does_not_return_deleted_tenants(self): + self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.tenant.user_ptr.auth_token}') + self.tenant.deleted = True + self.tenant.save() + url = reverse('v1:organization-tenants', kwargs={'pk': self.organization.pk}) + + response = self.client.get(url) + + self.assertEqual(0, len(response.json())) + + +class TenantViewsetTestCase(APIViewSetTestCase): + def setUp(self): + super().setUp() + self.client.credentials(HTTP_AUTHORIZATION=f'Token {self.tenant.user_ptr.auth_token}') + + def test_delete_on_deleted_tenant_returns_not_found(self): + tenant = self.create_bare_minimum_tenant() + tenant.deleted = True + tenant.save() + url = reverse('v1:tenant-detail', kwargs={'pk': tenant.pk}) + + response = self.client.delete(url) + + self.assertEqual(404, response.status_code) + + def test_delete_on_tenant_flags_as_deleted(self): + url = reverse('v1:tenant-detail', kwargs={'pk': self.tenant.pk}) + + response = self.client.delete(url) + self.tenant.refresh_from_db() + + self.assertTrue(self.tenant.deleted) + self.assertEqual(204, response.status_code) + + def test_update_on_deleted_tenant_returns_not_found(self): + tenant = self.create_bare_minimum_tenant() + tenant.deleted = True + tenant.save() + url = reverse('v1:tenant-detail', kwargs={'pk': tenant.pk}) + + response = self.client.put(url) + + self.assertEqual(404, response.status_code) class ProjectViewsetTestCase(APIViewSetTestCase): diff --git a/mockserver/tenants/views.py b/mockserver/tenants/views.py index 2e43fb8..61fa5fb 100644 --- a/mockserver/tenants/views.py +++ b/mockserver/tenants/views.py @@ -11,7 +11,6 @@ from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response -from tenants.filters import TenantFilter from tenants.models import ( Tenant, Organization, @@ -59,15 +58,18 @@ class TenantViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet): - queryset = Tenant.objects.all() + queryset = Tenant.objects.filter(deleted=False) serializer_class = TenantSerializer - filter_class = TenantFilter def get_permissions(self): if self.action == 'create': return (TenantPermission(),) return (IsAuthenticated(), TenantPermission(),) + def perform_destroy(self, instance): + instance.deleted = True + instance.save() + @action(detail=False, methods=['GET', ]) def me(self, request): tenant = request.user.tenant @@ -185,6 +187,6 @@ def profile(self, request, pk=None): @action(detail=True, methods=['GET']) def tenants(self, request, pk=None): organization: Organization = self.get_object() - tenants_ser = TenantSerializer(organization.users.all(), many=True) + tenants_ser = TenantSerializer(organization.users.filter(deleted=False), many=True) return JsonResponse(tenants_ser.data, safe=False)