153 lines
4.2 KiB
Python
153 lines
4.2 KiB
Python
from django import forms
|
|
from django.db.models import Q
|
|
|
|
from whoisdb.models import InetNum
|
|
from whoisdb.forms import MntFormMixin
|
|
from whoisdb.validators import IP46CIDRValidator
|
|
|
|
from .models import Domain, Nameserver, ReverseZone
|
|
|
|
import re
|
|
import ipaddress
|
|
|
|
|
|
class DomainForm(MntFormMixin, forms.ModelForm):
|
|
class Meta:
|
|
model = Domain
|
|
fields = ['name', 'nameservers', 'mnt_by', 'admin_c']
|
|
|
|
def __init__(self, user, *args, **kwargs):
|
|
self._user = user
|
|
|
|
super(DomainForm, self).__init__(*args, **kwargs)
|
|
|
|
mnts = self._user.maintainer_set.all()
|
|
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
|
|
|
|
instance = getattr(self, "instance", None)
|
|
self._create = not (instance and instance.pk)
|
|
|
|
if not self._create:
|
|
self.fields['name'].disabled = True
|
|
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
|
|
|
|
self.fields['nameservers'].queryset.distinct()
|
|
|
|
def clean_name(self):
|
|
name = self.cleaned_data['name'].lower()
|
|
if self._create:
|
|
if not name.endswith("."):
|
|
name += "."
|
|
|
|
if not name.endswith("dn."):
|
|
raise forms.ValidationError("Only .dn domains can be registered at this point")
|
|
|
|
if name.count(".") > 2:
|
|
raise forms.ValidationError("No subdomains can be registered")
|
|
|
|
if not re.match("^[a-z0-9.-]+$", name):
|
|
raise forms.ValidationError("Only a-z, 0-9 and - are allowed inside the domain name")
|
|
|
|
try:
|
|
Domain.objects.get(name=name)
|
|
raise forms.ValidationError("Domain already exists")
|
|
except Domain.DoesNotExist:
|
|
pass
|
|
|
|
return name
|
|
|
|
|
|
class NameserverForm(MntFormMixin, forms.ModelForm):
|
|
class Meta:
|
|
model = Nameserver
|
|
fields = ['name', 'glueIPv4', 'glueIPv6', 'mnt_by', 'admin_c']
|
|
|
|
def __init__(self, user, *args, **kwargs):
|
|
self._user = user
|
|
|
|
super(NameserverForm, self).__init__(*args, **kwargs)
|
|
|
|
instance = getattr(self, "instance", None)
|
|
self._create = not (instance and instance.pk)
|
|
|
|
def clean_name(self):
|
|
name = self.cleaned_data['name'].lower().strip()
|
|
if not name.endswith("."):
|
|
name += "."
|
|
|
|
if name.count(".") <= 2:
|
|
raise forms.ValidationError("Nameserver must be inside a domain (e.g. ns1.noot.dn.)")
|
|
|
|
zone = ".".join(name.split(".")[-3:])
|
|
|
|
mnts = self._user.maintainer_set.all()
|
|
domains = Domain.objects.filter(mnt_by__in=mnts)
|
|
found = False
|
|
for domain in domains:
|
|
if domain.name == zone:
|
|
found = True
|
|
break
|
|
|
|
if not found:
|
|
raise forms.ValidationError("This nameserver is not under a domain you control.")
|
|
|
|
return name
|
|
|
|
def clean(self):
|
|
cleaned_data = super(NameserverForm, self).clean()
|
|
|
|
return cleaned_data
|
|
|
|
|
|
class ReverseZoneForm(forms.ModelForm):
|
|
prefix = forms.CharField(validators=[IP46CIDRValidator])
|
|
|
|
class Meta:
|
|
model = ReverseZone
|
|
fields = ['parentNet', 'nameservers']
|
|
|
|
def __init__(self, user, *args, **kwargs):
|
|
self._user = user
|
|
|
|
super(ReverseZoneForm, self).__init__(*args, **kwargs)
|
|
|
|
instance = getattr(self, "instance", None)
|
|
self._create = not (instance and instance.pk)
|
|
|
|
mnts = self._user.maintainer_set.all()
|
|
self.fields['parentNet'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
|
|
|
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
|
|
|
|
if not self._create:
|
|
self.fields['prefix'].disabled = True
|
|
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
|
|
|
|
self.fields['nameservers'].queryset.distinct()
|
|
|
|
|
|
|
|
def clean(self):
|
|
cleaned_data = super(ReverseZoneForm, self).clean()
|
|
|
|
if not self.errors:
|
|
if self._create:
|
|
net = ipaddress.ip_network(cleaned_data['prefix'])
|
|
parentNet = cleaned_data['parentNet'].getNetwork()
|
|
|
|
if net.network_address not in parentNet:
|
|
raise forms.ValidationError("Given prefix %s is not inside of parent netblock %s" % (net, parentNet))
|
|
|
|
# For now just check all the zones...
|
|
#zones = ReverseZone.objects.filter(parentNet=cleaned_data['parentNet'])
|
|
zones = ReverseZone.objects.all()
|
|
for zone in zones:
|
|
if net.network_address in zone.parentNet.getNetwork():
|
|
raise forms.ValidationError("Given prefix already has a reverse zone object associated to it: %s" % zone)
|
|
|
|
self.instance.address = str(net.network_address)
|
|
self.instance.netmask = net.prefixlen
|
|
|
|
|
|
return cleaned_data
|