Pārlūkot izejas kodu

feat(api): check IP address validity on change, closes #23

Peter Thomassen 8 gadi atpakaļ
vecāks
revīzija
f6c2e0cf0a

+ 25 - 0
api/desecapi/migrations/0014_ip_validation.py

@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.3 on 2017-01-11 15:28
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('desecapi', '0013_acme_challenge'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='domain',
+            name='aaaarecord',
+            field=models.GenericIPAddressField(blank=False, null=True, protocol='IPv6'),
+        ),
+        migrations.AlterField(
+            model_name='domain',
+            name='arecord',
+            field=models.GenericIPAddressField(blank=False, null=True, protocol='IPv4'),
+        ),
+    ]

+ 4 - 2
api/desecapi/models.py

@@ -7,6 +7,8 @@ from django.utils import timezone
 from django.core.exceptions import ValidationError
 from desecapi import pdns
 import datetime, time
+import django.core.exceptions
+import rest_framework.exceptions
 
 
 class MyUserManager(BaseUserManager):
@@ -96,8 +98,8 @@ class Domain(models.Model):
     created = models.DateTimeField(auto_now_add=True)
     updated = models.DateTimeField(null=True)
     name = models.CharField(max_length=191, unique=True)
-    arecord = models.CharField(max_length=255, blank=True)
-    aaaarecord = models.CharField(max_length=1024, blank=True)
+    arecord = models.GenericIPAddressField(protocol='IPv4', blank=False, null=True)
+    aaaarecord = models.GenericIPAddressField(protocol='IPv6', blank=False, null=True)
     owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='domains')
     acme_challenge = models.CharField(max_length=255, blank=True)
     _dirtyName = False

+ 1 - 1
api/desecapi/pdns.py

@@ -73,7 +73,7 @@ def _delete_or_replace_rrset(name, type, value, ttl=60):
     """
     Return pdns API json to either replace or delete a record set, depending on whether value is empty or not.
     """
-    if value != "":
+    if value:
         return \
             {
                 "records": [

+ 16 - 11
api/desecapi/tests/testdomains.py

@@ -7,6 +7,7 @@ from desecapi.models import Domain
 from django.core import mail
 import httpretty
 from django.conf import settings
+import json
 
 
 class UnauthenticatedDomainTests(APITestCase):
@@ -95,7 +96,7 @@ class AuthenticatedDomainTests(APITestCase):
         url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
         response = self.client.get(url)
         response.data['arecord'] = '1.2.3.4'
-        response = self.client.put(url, response.data)
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         response = self.client.get(url)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -106,7 +107,9 @@ class AuthenticatedDomainTests(APITestCase):
         response = self.client.get(url)
         newname = utils.generateDomainname()
         response.data['name'] = newname
-        response = self.client.put(url, response.data)
+        response.data['arecord'] = None
+        response.data['aaaarecord'] = None
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
         response = self.client.get(url)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -114,7 +117,7 @@ class AuthenticatedDomainTests(APITestCase):
 
     def testCantPutOtherDomains(self):
         url = reverse('domain-detail', args=(self.otherDomains[1].pk,))
-        response = self.client.put(url, {})
+        response = self.client.put(url, json.dumps({}), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
 
     def testCanPostDomains(self):
@@ -154,7 +157,8 @@ class AuthenticatedDomainTests(APITestCase):
         url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
         response = self.client.get(url)
         response.data['arecord'] = '10.13.3.7'
-        response = self.client.put(url, response.data)
+        response.data['aaaarecord'] = None
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         response = self.client.get(url)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -163,8 +167,9 @@ class AuthenticatedDomainTests(APITestCase):
     def testCanUpdateAAAARecord(self):
         url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
         response = self.client.get(url)
+        response.data['arecord'] = None
         response.data['aaaarecord'] = 'fe80::a11:10ff:fee0:ff77'
-        response = self.client.put(url, response.data)
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         response = self.client.get(url)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -174,7 +179,7 @@ class AuthenticatedDomainTests(APITestCase):
         url = reverse('domain-detail', args=(self.ownedDomains[1].pk,))
         response = self.client.get(url)
         response.data['acme_challenge'] = 'test_challenge'
-        response = self.client.put(url, response.data)
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
         self.assertEqual(response.status_code, status.HTTP_200_OK)
         response = self.client.get(url)
         self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -234,7 +239,7 @@ class AuthenticatedDomainTests(APITestCase):
         httpretty.register_uri(httpretty.PUT, settings.NSLORD_PDNS_API + '/zones/' + response.data['name'] + './notify')
 
         response.data['arecord'] = '10.13.3.7'
-        response = self.client.put(url, response.data)
+        self.client.put(url, json.dumps(response.data), content_type='application/json')
 
         self.assertTrue('10.13.3.7' in httpretty.httpretty.latest_requests[-2].parsed_body)
 
@@ -247,7 +252,7 @@ class AuthenticatedDomainTests(APITestCase):
         httpretty.register_uri(httpretty.PUT, settings.NSLORD_PDNS_API + '/zones/' + response.data['name'] + './notify')
 
         response.data['arecord'] = '10.13.3.10'
-        response = self.client.put(url, response.data)
+        response = self.client.put(url, json.dumps(response.data), content_type='application/json')
 
         self.assertEqual(httpretty.httpretty.latest_requests[-2].method, 'PATCH')
         self.assertTrue('10.13.3.10' in httpretty.httpretty.latest_requests[-2].parsed_body)
@@ -298,9 +303,9 @@ class AuthenticatedDynDomainTests(APITestCase):
         self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
         self.assertEqual(httpretty.last_request().method, 'PATCH')
         self.assertEqual(httpretty.last_request().headers['Host'], 'nslord:8081')
-        self.assertTrue('"NS"' in httpretty.last_request().parsed_body
-                        and '"' + self.ownedDomains[1].name + '."' in httpretty.last_request().parsed_body
-                        and '"DELETE"' in httpretty.last_request().parsed_body)
+        self.assertTrue('"NS"' in httpretty.last_request().parsed_body)
+        self.assertTrue('"' + self.ownedDomains[1].name + '."' in httpretty.last_request().parsed_body)
+        self.assertTrue('"DELETE"' in httpretty.last_request().parsed_body)
 
         httpretty.reset()
         httpretty.register_uri(httpretty.DELETE, settings.NSLORD_PDNS_API + '/zones/' + self.ownedDomains[1].name + '.')