Pārlūkot izejas kodu

fix(api): disallow deleting RRset while user is locked

When syncing domains during unlock, we send all known RRsets to pdns.
However, it is difficult to track which RRsets have been deleted while
the user is locked (to request deletion from pdns), so for now, we
disallow RRset deletion in this case.
Peter Thomassen 7 gadi atpakaļ
vecāks
revīzija
c80af3e611
3 mainītis faili ar 24 papildinājumiem un 0 dzēšanām
  1. 1 0
      api/desecapi/models.py
  2. 20 0
      api/desecapi/tests/testrrsets.py
  3. 3 0
      api/desecapi/views.py

+ 1 - 0
api/desecapi/models.py

@@ -433,6 +433,7 @@ class RRset(models.Model, mixins.SetterMixin):
 
 
     @transaction.atomic
     @transaction.atomic
     def delete(self, *args, **kwargs):
     def delete(self, *args, **kwargs):
+        assert not self.domain.owner.captcha_required
         super().delete(*args, **kwargs)
         super().delete(*args, **kwargs)
         pdns.set_rrset(self)
         pdns.set_rrset(self)
         self._dirties = {}
         self._dirties = {}

+ 20 - 0
api/desecapi/tests/testrrsets.py

@@ -379,6 +379,26 @@ class AuthenticatedRRsetTests(APITestCase):
         response = self.client.delete(url)
         response = self.client.delete(url)
         self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
         self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
 
 
+    def testCantDeleteOwnRRsetWhileAccountIsLocked(self):
+        self.owner.captcha_required = True
+        self.owner.save()
+
+        url = reverse('rrsets', args=(self.ownedDomains[1].name,))
+        data = {'records': ['1.2.3.4'], 'ttl': 60, 'type': 'A'}
+        response = self.client.post(url, json.dumps(data), content_type='application/json')
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+
+        url = reverse('rrset', args=(self.ownedDomains[1].name, '', 'A',))
+
+        # Try PATCH with empty records
+        data = {'records': []}
+        response = self.client.patch(url, json.dumps(data), content_type='application/json')
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+        # Try DELETE
+        response = self.client.delete(url)
+        self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
     def testPostCausesPdnsAPICall(self):
     def testPostCausesPdnsAPICall(self):
         httpretty.enable()
         httpretty.enable()
         httpretty.register_uri(httpretty.PATCH, settings.NSLORD_PDNS_API + '/zones/' + self.ownedDomains[1].name + '.')
         httpretty.register_uri(httpretty.PATCH, settings.NSLORD_PDNS_API + '/zones/' + self.ownedDomains[1].name + '.')

+ 3 - 0
api/desecapi/views.py

@@ -137,6 +137,9 @@ class RRsetDetail(generics.RetrieveUpdateDestroyAPIView):
     permission_classes = (permissions.IsAuthenticated, IsDomainOwner,)
     permission_classes = (permissions.IsAuthenticated, IsDomainOwner,)
 
 
     def delete(self, request, *args, **kwargs):
     def delete(self, request, *args, **kwargs):
+        if request.user.captcha_required:
+            detail = "You cannot delete RRset while your account is locked."
+            raise PermissionDenied(detail)
         try:
         try:
             super().delete(request, *args, **kwargs)
             super().delete(request, *args, **kwargs)
         except Http404:
         except Http404: