83 lines
3 KiB
Python
83 lines
3 KiB
Python
|
from django.core.exceptions import ValidationError
|
||
|
from django.utils.translation import gettext_lazy as _
|
||
|
from rest_framework import serializers
|
||
|
|
||
|
from orchestra.api.serializers import HyperlinkedModelSerializer
|
||
|
from orchestra.contrib.accounts.serializers import AccountSerializerMixin
|
||
|
|
||
|
from .helpers import domain_for_validation
|
||
|
from .models import Domain, Record
|
||
|
from . import validators
|
||
|
|
||
|
|
||
|
class RecordSerializer(serializers.ModelSerializer):
|
||
|
class Meta:
|
||
|
model = Record
|
||
|
fields = ('type', 'value')
|
||
|
|
||
|
def get_identity(self, data):
|
||
|
return data.get('value')
|
||
|
|
||
|
|
||
|
class DomainSerializer(AccountSerializerMixin, HyperlinkedModelSerializer):
|
||
|
""" Validates if this zone generates a correct zone file """
|
||
|
records = RecordSerializer(required=False, many=True)
|
||
|
|
||
|
class Meta:
|
||
|
model = Domain
|
||
|
fields = ('url', 'id', 'name', 'records')
|
||
|
postonly_fields = ('name',)
|
||
|
|
||
|
def clean_name(self, attrs, source):
|
||
|
""" prevent users creating subdomains of other users domains """
|
||
|
name = attrs[source]
|
||
|
parent = Domain.objects.get_parent(name)
|
||
|
if parent and parent.account != self.account:
|
||
|
raise ValidationError(_("Can not create subdomains of other users domains"))
|
||
|
return attrs
|
||
|
|
||
|
def validate(self, data):
|
||
|
""" Checks if everything is consistent """
|
||
|
data = super(DomainSerializer, self).validate(data)
|
||
|
name = data.get('name')
|
||
|
if name:
|
||
|
instance = self.instance
|
||
|
if instance is None:
|
||
|
instance = Domain(name=name, account=self.account)
|
||
|
records = data['records']
|
||
|
domain = domain_for_validation(instance, records)
|
||
|
validators.validate_zone(domain.render_zone())
|
||
|
return data
|
||
|
|
||
|
def create(self, validated_data):
|
||
|
records = validated_data.pop('records')
|
||
|
domain = super(DomainSerializer, self).create(validated_data)
|
||
|
for record in records:
|
||
|
domain.records.create(type=record['type'], value=record['value'])
|
||
|
return domain
|
||
|
|
||
|
def update(self, instance, validated_data):
|
||
|
precords = validated_data.pop('records')
|
||
|
domain = super(DomainSerializer, self).update(instance, validated_data)
|
||
|
to_delete = []
|
||
|
for erecord in domain.records.all():
|
||
|
match = False
|
||
|
for ix, precord in enumerate(precords):
|
||
|
if erecord.type == precord['type'] and erecord.value == precord['value']:
|
||
|
match = True
|
||
|
break
|
||
|
if match:
|
||
|
precords.pop(ix)
|
||
|
else:
|
||
|
to_delete.append(erecord)
|
||
|
for precord in precords:
|
||
|
try:
|
||
|
recycled = to_delete.pop()
|
||
|
except IndexError:
|
||
|
domain.records.create(type=precord['type'], value=precord['value'])
|
||
|
else:
|
||
|
recycled.type = precord['type']
|
||
|
recycled.value = precord['value']
|
||
|
recycled.save()
|
||
|
return domain
|