Good, good, queryset foo
This commit is contained in:
parent
baa2dcc38b
commit
189ae23b4a
|
@ -1,10 +1,14 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from whoisdb.models import InetNum
|
||||||
from whoisdb.forms import MntFormMixin
|
from whoisdb.forms import MntFormMixin
|
||||||
|
from whoisdb.validators import IP46CIDRValidator
|
||||||
|
|
||||||
from .models import Domain, Nameserver
|
from .models import Domain, Nameserver, ReverseZone
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
class DomainForm(MntFormMixin, forms.ModelForm):
|
class DomainForm(MntFormMixin, forms.ModelForm):
|
||||||
|
@ -17,11 +21,17 @@ class DomainForm(MntFormMixin, forms.ModelForm):
|
||||||
|
|
||||||
super(DomainForm, self).__init__(*args, **kwargs)
|
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)
|
instance = getattr(self, "instance", None)
|
||||||
self._create = not (instance and instance.pk)
|
self._create = not (instance and instance.pk)
|
||||||
|
|
||||||
if not self._create:
|
if not self._create:
|
||||||
self.fields['name'].disabled = True
|
self.fields['name'].disabled = True
|
||||||
|
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
|
||||||
|
|
||||||
|
self.fields['nameservers'].queryset.distinct()
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name'].lower()
|
name = self.cleaned_data['name'].lower()
|
||||||
|
@ -87,3 +97,56 @@ class NameserverForm(MntFormMixin, forms.ModelForm):
|
||||||
cleaned_data = super(NameserverForm, self).clean()
|
cleaned_data = super(NameserverForm, self).clean()
|
||||||
|
|
||||||
return cleaned_data
|
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
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10.5 on 2017-03-14 21:04
|
# Generated by Django 1.10.5 on 2017-03-20 11:31
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
|
@ -3,6 +3,8 @@ from django.urls import reverse
|
||||||
|
|
||||||
from whoisdb.models import MntdObject, Contact, InetNum
|
from whoisdb.models import MntdObject, Contact, InetNum
|
||||||
|
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
# generally allow domains for .dn to be created
|
# generally allow domains for .dn to be created
|
||||||
# allow owners of a subnet to create reverse dns record?
|
# allow owners of a subnet to create reverse dns record?
|
||||||
|
|
||||||
|
@ -49,12 +51,6 @@ class Domain(MntdObject):
|
||||||
|
|
||||||
return reasons
|
return reasons
|
||||||
|
|
||||||
#class NameserverDomainAssignment(models.Model):
|
|
||||||
# domain = models.ForeignKey(Domain)
|
|
||||||
# nameserver = models.ForeignKey(Nameserver)
|
|
||||||
#
|
|
||||||
# order = models.PositiveSmallIntegerField(default=0)
|
|
||||||
|
|
||||||
|
|
||||||
class ReverseZone(models.Model):
|
class ReverseZone(models.Model):
|
||||||
parentNet = models.ForeignKey(InetNum)
|
parentNet = models.ForeignKey(InetNum)
|
||||||
|
@ -63,9 +59,18 @@ class ReverseZone(models.Model):
|
||||||
|
|
||||||
nameservers = models.ManyToManyField(Nameserver)
|
nameservers = models.ManyToManyField(Nameserver)
|
||||||
|
|
||||||
|
def prefix(self):
|
||||||
|
""" Helper function, mainly used in templates """
|
||||||
|
return "%s/%s" % (self.address, self.netmask)
|
||||||
|
|
||||||
#class NameserverReverseZoneAssignment(models.Model):
|
def getNetwork(self):
|
||||||
# reversezone = models.ForeignKey(ReverseZone)
|
return ipaddress.ip_network(self.prefix())
|
||||||
# nameserver = models.ForeignKey(Nameserver)
|
|
||||||
#
|
def get_absolute_url(self):
|
||||||
# order = models.PositiveSmallIntegerField()
|
return reverse("domains:reversezone-show", args=(self.pk,))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "%s @ %s" % (self.prefix(), self.parentNet)
|
||||||
|
|
||||||
|
def getNoDeleteReasons(self):
|
||||||
|
return []
|
||||||
|
|
|
@ -14,4 +14,10 @@ urlpatterns = [
|
||||||
url(r'nameserver/show/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverDetail.as_view(), name='nameserver-show'),
|
url(r'nameserver/show/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverDetail.as_view(), name='nameserver-show'),
|
||||||
url(r'nameserver/edit/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverEdit.as_view(), name='nameserver-edit'),
|
url(r'nameserver/edit/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverEdit.as_view(), name='nameserver-edit'),
|
||||||
url(r'nameserver/delete/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverDelete.as_view(), name='nameserver-delete'),
|
url(r'nameserver/delete/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverDelete.as_view(), name='nameserver-delete'),
|
||||||
|
|
||||||
|
url(r'reversezone/create/$', domains_views.ReverseZoneCreate.as_view(), name='reversezone-create'),
|
||||||
|
url(r'reversezone/show/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDetail.as_view(), name='reversezone-show'),
|
||||||
|
url(r'reversezone/edit/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneEdit.as_view(), name='reversezone-edit'),
|
||||||
|
url(r'reversezone/delete/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDelete.as_view(), name='reversezone-delete'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,11 +3,12 @@ from django.urls import reverse_lazy
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.views.generic import DetailView, CreateView, UpdateView
|
from django.views.generic import DetailView, CreateView, UpdateView
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from whoisdb.generic import MntGenericMixin, DeleteCheckView
|
from whoisdb.generic import MntGenericMixin, DeleteCheckView
|
||||||
|
|
||||||
from .models import Domain, Nameserver
|
from .models import Domain, Nameserver, ReverseZone
|
||||||
from .forms import DomainForm, NameserverForm
|
from .forms import DomainForm, NameserverForm, ReverseZoneForm
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -15,10 +16,11 @@ def overview(request):
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
|
|
||||||
# get all domains and nameservers
|
# get all domains and nameservers
|
||||||
domains = Domain.objects.filter(mnt_by__in=mnts)
|
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
|
||||||
nameservers = Nameserver.objects.filter(mnt_by__in=mnts)
|
nameservers = Nameserver.objects.filter(mnt_by__in=mnts).distinct()
|
||||||
|
reversezones = ReverseZone.objects.filter(parentNet__mnt_by__in=mnts).distinct()
|
||||||
|
|
||||||
return render(request, "domains/overview.html", {"domains": domains, "nameservers": nameservers})
|
return render(request, "domains/overview.html", {"domains": domains, "nameservers": nameservers, 'reversezones': reversezones})
|
||||||
|
|
||||||
|
|
||||||
class DomainCreate(LoginRequiredMixin, CreateView):
|
class DomainCreate(LoginRequiredMixin, CreateView):
|
||||||
|
@ -38,6 +40,8 @@ class DomainDetail(LoginRequiredMixin, DetailView):
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
context_object_name = "domain"
|
context_object_name = "domain"
|
||||||
|
|
||||||
|
template_name = "domains/handle_show.html"
|
||||||
|
|
||||||
|
|
||||||
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Domain
|
model = Domain
|
||||||
|
@ -97,3 +101,55 @@ class NameserverDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
slug_field = "name"
|
slug_field = "name"
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
success_url = reverse_lazy("domains:overview")
|
success_url = reverse_lazy("domains:overview")
|
||||||
|
|
||||||
|
|
||||||
|
class ReverseZoneCreate(LoginRequiredMixin, CreateView):
|
||||||
|
template_name = "domains/obj_create.html"
|
||||||
|
form_class = ReverseZoneForm
|
||||||
|
|
||||||
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
kwargs = super(ReverseZoneCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class ReverseZoneDetail(LoginRequiredMixin, DetailView):
|
||||||
|
model = ReverseZone
|
||||||
|
slug_field = "name"
|
||||||
|
slug_url_kwarg = "domain"
|
||||||
|
context_object_name = "nameserver"
|
||||||
|
|
||||||
|
|
||||||
|
class ReverseZoneEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
|
model = ReverseZone
|
||||||
|
form_class = ReverseZoneForm
|
||||||
|
#slug_field = "name"
|
||||||
|
#slug_url_kwarg = "domain"
|
||||||
|
template_name = "domains/obj_edit.html"
|
||||||
|
|
||||||
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
kwargs = super(ReverseZoneEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
|
if not "initial" in kwargs:
|
||||||
|
kwargs["initial"] = {}
|
||||||
|
|
||||||
|
kwargs["initial"]["prefix"] = self.object.prefix()
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
mnts = self.request.user.maintainer_set.all()
|
||||||
|
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
|
||||||
|
|
||||||
|
|
||||||
|
class ReverseZoneDelete(LoginRequiredMixin, DeleteCheckView):
|
||||||
|
template_name = "domains/obj_delete.html"
|
||||||
|
model = ReverseZone
|
||||||
|
success_url = reverse_lazy("domains:overview")
|
||||||
|
#slug_field = "name"
|
||||||
|
#slug_url_kwarg = "domain"
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
mnts = self.request.user.maintainer_set.all()
|
||||||
|
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load handletags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">{{ object }} <small>({{ object.getClassName }})</small></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<table class="table">
|
||||||
|
{% for field in object|getFields:user %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ field.0 }}</td>
|
||||||
|
<td>{% if field.1.through %}{{ field.1.all|linkObjects|default:"-" }}{% else %}{{ field.1|default:"-" }}{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% if object|userCanEdit:user %}
|
||||||
|
<tr>
|
||||||
|
<td>Actions</td>
|
||||||
|
{% with "domains:"|add:object.getClassName|lower|add:"-edit" as editView %}
|
||||||
|
{% with "domains:"|add:object.getClassName|lower|add:"-delete" as deleteView %}
|
||||||
|
<td><a href="{% url editView object.name %}">Edit object<a/>, <a href="{% url deleteView object.name %}">Delete object</a></td>
|
||||||
|
{% endwith %}
|
||||||
|
{% endwith %}
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="panel panel-{% if reasons %}danger{%else%}default{%endif%}">
|
<div class="panel panel-{% if reasons %}danger{%else%}default{%endif%}">
|
||||||
<div class="panel-heading">Header</div>
|
<div class="panel-heading">Delete {{ object }}?</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{% if reasons %}
|
{% if reasons %}
|
||||||
<p>
|
<p>
|
||||||
|
@ -19,10 +19,12 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ obj }}
|
<p>
|
||||||
|
Are you sure you want to delete {{ object }}?
|
||||||
|
</p>
|
||||||
<form method="post" action="#">
|
<form method="post" action="#">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class="btn btn-primary">Delete</button>
|
<button type="submit" class="btn btn-primary">Delete {{ object }}</button>
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load handletags %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">Resource Requests</div>
|
<div class="panel-heading">DNS Overview</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p>
|
<h4>Your Nameservers (<a href="{% url "domains:nameserver-create" %}">New nameserver</a>)</h4>
|
||||||
Your nameservers (<a href="{% url "domains:nameserver-create" %}">New nameserver</a>)
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Nameserver</th>
|
<th>Nameserver</th>
|
||||||
|
@ -19,35 +20,62 @@
|
||||||
{% for nameserver in nameservers %}
|
{% for nameserver in nameservers %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{% url "domains:nameserver-show" nameserver.name %}">{{ nameserver.name }}</a></td>
|
<td><a href="{% url "domains:nameserver-show" nameserver.name %}">{{ nameserver.name }}</a></td>
|
||||||
<td></td>
|
<td>{{ nameserver.glueIPv4|default:"-" }}</td>
|
||||||
<td></td>
|
<td>{{ nameserver.glueIPv6|default:"-" }}</td>
|
||||||
<td></td>
|
<td>{{ nameserver.mnt_by.all|linkObjects }}</td>
|
||||||
<td><a href="{% url "domains:nameserver-edit" nameserver.name %}">Edit</a> <a href="{% url "domains:nameserver-delete" nameserver.name %}">Delete</a></td>
|
<td><a href="{% url "domains:nameserver-edit" nameserver.name %}">Edit</a> <a href="{% url "domains:nameserver-delete" nameserver.name %}">Delete</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</p>
|
|
||||||
<p>
|
<h4>Your Domains (<a href="{% url "domains:domain-create" %}">New domain</a>)</h4>
|
||||||
Your domains (<a href="{% url "domains:domain-create" %}">New domain</a>)
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Domain</th>
|
<th>Domain</th>
|
||||||
<th>Nameserver</th>
|
<th>Nameserver</th>
|
||||||
<th>Glue IPv6</th>
|
|
||||||
<th>MNTs</th>
|
<th>MNTs</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for domain in domains %}
|
{% for domain in domains %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{% url "domains:domain-show" domain.name %}">{{ domain.name }}</a></td>
|
<td><a href="{% url "domains:domain-show" domain.name %}">{{ domain.name }}</a></td>
|
||||||
<td></td>
|
<td>
|
||||||
<td></td>
|
<ul>
|
||||||
<td></td>
|
{% for nameserver in domain.nameservers.all %}
|
||||||
|
<li>{{ nameserver|linkObject }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>{{ domain.mnt_by.all|linkObjects }}</td>
|
||||||
<td><a href="{% url "domains:domain-edit" domain.name %}">Edit</a> <a href="{% url "domains:domain-delete" domain.name %}">Delete</a></td>
|
<td><a href="{% url "domains:domain-edit" domain.name %}">Edit</a> <a href="{% url "domains:domain-delete" domain.name %}">Delete</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ domain }}<br />
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<h4>Your Reverse Zones (<a href="{% url "domains:reversezone-create" %}">New reverse zone</a>)</h4>
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th>Zone</th>
|
||||||
|
<th>Network</th>
|
||||||
|
<th>Nameserver</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
{% for reversezone in reversezones %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url "domains:reversezone-show" reversezone.pk %}">{{ reversezone.prefix }}</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
{% for nameserver in domain.nameservers.all %}
|
||||||
|
<li>{{ nameserver|linkObject }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td><a href="{% url "domains:reversezone-edit" reversezone.pk %}">Edit</a> <a href="{% url "domains:reversezone-delete" reversezone.pk %}">Delete</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,18 +14,19 @@ class WhoisObjectFormMixin(object):
|
||||||
|
|
||||||
instance = getattr(self, 'instance', None)
|
instance = getattr(self, 'instance', None)
|
||||||
if instance and instance.pk:
|
if instance and instance.pk:
|
||||||
|
self._create = False
|
||||||
self.fields['handle'].widget.attrs['readonly'] = True
|
self.fields['handle'].widget.attrs['readonly'] = True
|
||||||
|
else:
|
||||||
|
self._create = True
|
||||||
|
|
||||||
# only show users contacts and already present contacts
|
# only show users contacts and already present contacts
|
||||||
|
mnts = self._user.maintainer_set.all()
|
||||||
if 'admin_c' in self.fields:
|
if 'admin_c' in self.fields:
|
||||||
self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by__in=self._user.maintainer_set.all())
|
self.fields['admin_c'].queryset = Contact.getMntQueryset(mnts, self.instance, "admin_c")
|
||||||
if instance and instance.pk:
|
|
||||||
self.fields['admin_c'].queryset |= instance.admin_c.all()
|
|
||||||
|
|
||||||
def clean_handle(self):
|
def clean_handle(self):
|
||||||
instance = getattr(self, 'instance', None)
|
if not self._create:
|
||||||
if instance and instance.pk:
|
return self.instance.handle
|
||||||
return instance.handle
|
|
||||||
else:
|
else:
|
||||||
return self.cleaned_data['handle']
|
return self.cleaned_data['handle']
|
||||||
|
|
||||||
|
@ -56,17 +57,14 @@ class MntFormMixin(object):
|
||||||
mntQs = Maintainer.objects.annotate(card=Case(*mntWhens, default=0, output_field=IntegerField())).order_by("-card")
|
mntQs = Maintainer.objects.annotate(card=Case(*mntWhens, default=0, output_field=IntegerField())).order_by("-card")
|
||||||
self.fields["mnt_by"].queryset = mntQs
|
self.fields["mnt_by"].queryset = mntQs
|
||||||
|
|
||||||
class MntForm(forms.ModelForm):
|
if "mnt_lower" in self.fields:
|
||||||
|
self.fields["mnt_lower"].queryset = mntQs
|
||||||
|
|
||||||
|
class MntForm(WhoisObjectFormMixin, forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
fields = ['handle', 'description', 'admin_c']
|
fields = ['handle', 'description', 'admin_c']
|
||||||
|
|
||||||
def __init__(self, user, *args, **kwargs):
|
|
||||||
super(MntForm, self).__init__(*args, **kwargs)
|
|
||||||
self._user = user
|
|
||||||
if 'admin_c' in self.fields:
|
|
||||||
self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by=user.maintainer_set.all())
|
|
||||||
|
|
||||||
|
|
||||||
class MntInitialForm(MntForm):
|
class MntInitialForm(MntForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -82,7 +80,7 @@ class ContactForm(WhoisObjectFormMixin, forms.ModelForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ContactForm, self).__init__(*args, **kwargs)
|
super(ContactForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user)
|
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user).distinct()
|
||||||
|
|
||||||
|
|
||||||
class ContactInitialForm(ContactForm):
|
class ContactInitialForm(ContactForm):
|
||||||
|
@ -101,16 +99,18 @@ class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(InetNumForm, self).__init__(*args, **kwargs)
|
super(InetNumForm, self).__init__(*args, **kwargs)
|
||||||
if 'admin_c' in self.fields:
|
|
||||||
self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by__in=self.user.maintainer_set.all())
|
|
||||||
instance = getattr(self, "instance", None)
|
|
||||||
if instance and instance.pk:
|
|
||||||
self.fields['admin_c'].queryset |= instance.admin_c.all()
|
|
||||||
|
|
||||||
if self._editLower:
|
if self._editLower:
|
||||||
for key in self.protectedFields:
|
for key in self.protectedFields:
|
||||||
self.fields[key].disabled = True
|
self.fields[key].disabled = True
|
||||||
self.fields[key].widget.attrs['readonly'] = False
|
|
||||||
|
mnts = self._user.maintainer_set.all()
|
||||||
|
#self.fields['parent_range'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts))
|
||||||
|
#if not self._create:
|
||||||
|
# self.fields['parent_range'].queryset |= InetNum.objects.filter(pk=self.instance.pk)
|
||||||
|
|
||||||
|
#self.fields['parent_range'].queryset = self.fields['parent_range'].queryset.distinct()
|
||||||
|
self.fields['parent_range'].queryset = InetNum.getMntQueryset(mnts, self.instance, "parent_range")
|
||||||
|
|
||||||
def clean_prefix(self):
|
def clean_prefix(self):
|
||||||
# make sure this is a subnet we're getting
|
# make sure this is a subnet we're getting
|
||||||
|
@ -128,9 +128,19 @@ class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
parent_range = self.cleaned_data.get('parent_range', None)
|
parent_range = self.cleaned_data.get('parent_range', None)
|
||||||
|
|
||||||
# allow parent range to be unset for already present objects
|
# allow parent range to be unset for already present objects
|
||||||
if not (self.instance and self.instance.pk) and not parent_range:
|
if not parent_range and (self._create or not self._create and self.instance.parent_range):
|
||||||
raise forms.ValidationError("Parent range must be set")
|
raise forms.ValidationError("Parent range must be set")
|
||||||
|
|
||||||
|
if not self._create and parent_range:
|
||||||
|
# make sure we don't have circular dependencies
|
||||||
|
obj = parent_range
|
||||||
|
while obj.parent_range:
|
||||||
|
if obj.pk == self.instance.pk:
|
||||||
|
raise forms.ValidationError("No circular dependencies allowed")
|
||||||
|
obj = obj.parent_range
|
||||||
|
|
||||||
|
return parent_range
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(InetNumForm, self).clean()
|
cleaned_data = super(InetNumForm, self).clean()
|
||||||
|
|
||||||
|
@ -177,6 +187,9 @@ class ASBlockForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
if self.instance and self.instance.pk:
|
if self.instance and self.instance.pk:
|
||||||
self.fields["parent_block"].disabled = True
|
self.fields["parent_block"].disabled = True
|
||||||
|
|
||||||
|
mnts = self._user.maintainer_set.all()
|
||||||
|
self.fields['parent_block'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "parent_block")
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ASBlockForm, self).clean()
|
cleaned_data = super(ASBlockForm, self).clean()
|
||||||
|
|
||||||
|
@ -229,6 +242,9 @@ class ASNumberForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
else:
|
else:
|
||||||
self.fields["asblock"].disabled = True
|
self.fields["asblock"].disabled = True
|
||||||
|
|
||||||
|
mnts = self._user.maintainer_set.all()
|
||||||
|
self.fields['asblock'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "asblock")
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ASNumberForm, self).clean()
|
cleaned_data = super(ASNumberForm, self).clean()
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import whoisdb.models
|
import whoisdb.models
|
||||||
|
import domains.models
|
||||||
|
|
||||||
def _addFields(fields, obj, fieldNames):
|
def _addFields(fields, obj, fieldNames):
|
||||||
for fieldName in fieldNames:
|
for fieldName in fieldNames:
|
||||||
fields.append((fieldName.capitalize(), getattr(obj, fieldName)))
|
fields.append((fieldName.capitalize().replace("_", " "), getattr(obj, fieldName)))
|
||||||
|
|
||||||
|
|
||||||
def getWhoisObjectFields(obj, owner):
|
def getWhoisObjectFields(obj, owner):
|
||||||
|
@ -27,7 +28,15 @@ def getWhoisObjectFields(obj, owner):
|
||||||
elif c == whoisdb.models.InetNum:
|
elif c == whoisdb.models.InetNum:
|
||||||
_addFields(fields, obj, ["name"])
|
_addFields(fields, obj, ["name"])
|
||||||
fields.append(("Address CIDR", obj.prefix()))
|
fields.append(("Address CIDR", obj.prefix()))
|
||||||
_addFields(fields, obj, ["description", "mnt_by", "mnt_lower", "admin_c"])
|
_addFields(fields, obj, ["description", "parent_range", "mnt_by", "mnt_lower", "admin_c"])
|
||||||
|
elif c == domains.models.Domain:
|
||||||
|
_addFields(fields, obj, ["name", "nameservers", "mnt_by", "admin_c"])
|
||||||
|
elif c == domains.models.Nameserver:
|
||||||
|
_addFields(fields, obj, ["name", "glueIPv4", "glueIPv6", "mnt_by", "admin_c"])
|
||||||
|
elif c == domains.models.ReverseZone:
|
||||||
|
_addFields(fields, obj, ["name"])
|
||||||
|
fields.append(("Address CIDR", obj.prefix()))
|
||||||
|
_addFields(fields, obj, ["parentNet", "nameservers"])
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from dncore.models import User
|
from dncore.models import User
|
||||||
|
@ -111,6 +112,20 @@ class MntdObject(WhoisObject):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getMntQueryset(clazz, mnts, instance, attr=None):
|
||||||
|
mntQ = Q(mnt_by__in=mnts)
|
||||||
|
if hasattr(clazz, "mnt_lower"):
|
||||||
|
mntQ |= Q(mnt_lower__in=mnts)
|
||||||
|
|
||||||
|
qs = clazz.objects.filter(mntQ)
|
||||||
|
if attr and instance and instance.pk:
|
||||||
|
if type(getattr(instance, attr)) == models.ManyToManyField:
|
||||||
|
qs |= getattr(instance, attr).all()
|
||||||
|
else:
|
||||||
|
qs |= clazz.objects.filter(pk=instance.pk)
|
||||||
|
|
||||||
|
return qs.distinct()
|
||||||
|
|
||||||
class Contact(MntdObject):
|
class Contact(MntdObject):
|
||||||
handleSuffix = "DN"
|
handleSuffix = "DN"
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deconstruct import deconstructible
|
from django.utils.deconstruct import deconstructible
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
@deconstructible
|
@deconstructible
|
||||||
|
@ -26,3 +28,12 @@ class HandleValidatorWithSuffix(validators.RegexValidator):
|
||||||
)
|
)
|
||||||
|
|
||||||
super(HandleValidatorWithSuffix, self).__init__()
|
super(HandleValidatorWithSuffix, self).__init__()
|
||||||
|
|
||||||
|
def IP46CIDRValidator(value):
|
||||||
|
if not re.match(r"[0-9:.]+/[0-9]+", value):
|
||||||
|
raise ValidationError("Address needs to be a subnet in the format of ip/cidr")
|
||||||
|
|
||||||
|
try:
|
||||||
|
ipaddress.ip_network(value)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValidationError(str(e))
|
||||||
|
|
Loading…
Reference in New Issue