浏览代码

feat(api): command for changing minimum TTL and domains limits

Nils Wisiol 3 年之前
父节点
当前提交
69bfb7aa97
共有 2 个文件被更改,包括 72 次插入0 次删除
  1. 38 0
      api/desecapi/management/commands/limit.py
  2. 34 0
      api/desecapi/tests/test_limit.py

+ 38 - 0
api/desecapi/management/commands/limit.py

@@ -0,0 +1,38 @@
+from django.core.management import BaseCommand, CommandError
+from django.db.models import Q
+
+from api import settings
+from desecapi.models import RRset, Domain, User
+from desecapi.pdns_change_tracker import PDNSChangeTracker
+
+
+class Command(BaseCommand):
+    help = 'Sets/updates limits for users and domains.'
+
+    def add_arguments(self, parser):
+        parser.add_argument('kind',
+                            help='Identifies which limit should be updated. Possible values: domains, ttl')
+        parser.add_argument('id',
+                            help='Identifies the entity to be updated. Users are identified by email address; '
+                                 'domains by their name.')
+        parser.add_argument('new_limit', help='New value for the limit.')
+
+    def handle(self, *args, **options):
+        if options['kind'] == 'domains':
+            try:
+                user = User.objects.get(email=options['id'])
+            except User.DoesNotExist:
+                raise CommandError(f'User with email address "{options["id"]}" could not be found.')
+            user.limit_domains = options['new_limit']
+            user.save()
+            print(f'Updated {user.email}: set max number of domains to {user.limit_domains}.')
+        elif options['kind'] == 'ttl':
+            try:
+                domain = Domain.objects.get(name=options['id'])
+            except Domain.DoesNotExist:
+                raise CommandError(f'Domain with name "{options["id"]}" could not be found.')
+            domain.minimum_ttl = options['new_limit']
+            domain.save()
+            print(f'Updated {domain.name}: set minimum TTL to {domain.minimum_ttl}.')
+        else:
+            raise CommandError(f'Unknown limit "{options["kind"]}" specified.')

+ 34 - 0
api/desecapi/tests/test_limit.py

@@ -0,0 +1,34 @@
+from django.core import management
+from django.db.models import Min
+
+from desecapi.models import Domain, RRset
+from desecapi.tests.base import DomainOwnerTestCase
+
+
+class LimitCommandTest(DomainOwnerTestCase):
+
+    def test_update_domains(self):
+        management.call_command('limit', 'domains', self.owner.email, '123')
+        self.owner.refresh_from_db()
+        self.assertEqual(self.owner.limit_domains, 123)
+        management.call_command('limit', 'domains', self.owner.email, 567)
+        self.owner.refresh_from_db()
+        self.assertEqual(self.owner.limit_domains, 567)
+        management.call_command('limit', 'domains', self.owner.email, '1')  # below the actual number of domains
+        self.owner.refresh_from_db()
+        self.assertEqual(self.owner.limit_domains, 1)
+        # did not delete domains below limit:
+        self.assertEqual(Domain.objects.filter(owner_id=self.owner.id).count(), 2)
+
+    def test_update_minimum_ttl(self):
+        management.call_command('limit', 'ttl', self.my_domain.name, '123')
+        self.my_domain.refresh_from_db()
+        self.assertEqual(self.my_domain.minimum_ttl, 123)
+        management.call_command('limit', 'ttl', self.my_domain.name, 567)
+        self.my_domain.refresh_from_db()
+        self.assertEqual(self.my_domain.minimum_ttl, 567)
+        management.call_command('limit', 'ttl', self.my_domain.name, '10000')  # above the currently used ttl
+        self.my_domain.refresh_from_db()
+        self.assertEqual(self.my_domain.minimum_ttl, 10000)
+        # did not change existing TTLs in violation of minimum TTL:
+        self.assertLess(RRset.objects.filter(domain_id=self.my_domain.id).aggregate(Min('ttl'))['ttl__min'], 10000)