Zwischencommit
This commit is contained in:
parent
3826078d75
commit
69abba4d36
12
README
12
README
|
@ -7,3 +7,15 @@ FIXME
|
||||||
contact soll nur einen mnt_by haben
|
contact soll nur einen mnt_by haben
|
||||||
mnt_by ==> mnt_by_in in filter statements
|
mnt_by ==> mnt_by_in in filter statements
|
||||||
admin_c für welche objekte?
|
admin_c für welche objekte?
|
||||||
|
|
||||||
|
mnt_by von Contact auf ForeignKey droppen?
|
||||||
|
last-changed has to be changed by forms
|
||||||
|
|
||||||
|
|
||||||
|
Visibility of resources
|
||||||
|
MNT: Everywhere
|
||||||
|
ASBlocks: ASBlock, ASNumber
|
||||||
|
|
||||||
|
|
||||||
|
FIXME: Allow Maintainers to have multiple auth foo
|
||||||
|
multiple select without revealing everything?
|
||||||
|
|
|
@ -39,9 +39,10 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'taggit',
|
|
||||||
'dncore',
|
'dncore',
|
||||||
'whoisdb',
|
'whoisdb',
|
||||||
|
'rrequests',
|
||||||
|
'domains',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
|
|
@ -19,6 +19,8 @@ from django.contrib import admin
|
||||||
import dncore.urls
|
import dncore.urls
|
||||||
import dncore.views
|
import dncore.views
|
||||||
import whoisdb.urls
|
import whoisdb.urls
|
||||||
|
import rrequests.urls
|
||||||
|
import domains.urls
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
@ -28,4 +30,6 @@ urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
url(r'^user/', include(dncore.urls, namespace='user')),
|
url(r'^user/', include(dncore.urls, namespace='user')),
|
||||||
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
|
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
|
||||||
|
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
|
||||||
|
url(r'^domains/', include(domains.urls, namespace='domains')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from .models import Nameserver, Domain, ReverseZone
|
||||||
|
|
||||||
|
admin.site.register(Nameserver)
|
||||||
|
admin.site.register(Domain)
|
||||||
|
admin.site.register(ReverseZone)
|
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DomainsConfig(AppConfig):
|
||||||
|
name = 'domains'
|
|
@ -0,0 +1,73 @@
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
from whoisdb.forms import MntFormMixin
|
||||||
|
|
||||||
|
from .models import Domain, Nameserver
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def clean_name(self):
|
||||||
|
name = self.cleaned_data['name'].lower()
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
for domain in domains:
|
||||||
|
if domain.endswith(name)
|
||||||
|
|
||||||
|
return name
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super(NameserverForm, self).clean()
|
||||||
|
|
||||||
|
return cleaned_data
|
|
@ -0,0 +1,85 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-13 11:18
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('whoisdb', '0013_auto_20170303_1206'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Domain',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('last_modified', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('name', models.CharField(db_index=True, max_length=67, unique=True)),
|
||||||
|
('admin_c', models.ManyToManyField(to='whoisdb.Contact')),
|
||||||
|
('mnt_by', models.ManyToManyField(to='whoisdb.Maintainer')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Nameserver',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('last_modified', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('name', models.CharField(max_length=256)),
|
||||||
|
('glueIPv4', models.GenericIPAddressField(blank=True, null=True, protocol='IPv4')),
|
||||||
|
('glueIPv6', models.GenericIPAddressField(blank=True, null=True, protocol='IPv6')),
|
||||||
|
('admin_c', models.ManyToManyField(to='whoisdb.Contact')),
|
||||||
|
('mnt_by', models.ManyToManyField(to='whoisdb.Maintainer')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NameserverDomainAssignment',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('order', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='domains.Domain')),
|
||||||
|
('nameserver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='domains.Nameserver')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='NameserverReverseZoneAssignment',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('order', models.PositiveSmallIntegerField()),
|
||||||
|
('nameserver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='domains.Nameserver')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ReverseZone',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('address', models.GenericIPAddressField(db_index=True)),
|
||||||
|
('netmask', models.PositiveIntegerField()),
|
||||||
|
('nameservers', models.ManyToManyField(through='domains.NameserverReverseZoneAssignment', to='domains.Nameserver')),
|
||||||
|
('parentNet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='whoisdb.InetNum')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='nameserverreversezoneassignment',
|
||||||
|
name='reversezone',
|
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='domains.ReverseZone'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='domain',
|
||||||
|
name='nameservers',
|
||||||
|
field=models.ManyToManyField(blank=True, to='domains.Nameserver'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,58 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from whoisdb.models import MntdObject, Contact, InetNum
|
||||||
|
|
||||||
|
# generally allow domains for .dn to be created
|
||||||
|
# allow owners of a subnet to create reverse dns record?
|
||||||
|
|
||||||
|
class Nameserver(MntdObject):
|
||||||
|
handleSuffix = "NS"
|
||||||
|
# dns name
|
||||||
|
# ip address, if glue
|
||||||
|
# ipv4/ipv6 address?
|
||||||
|
handle = None
|
||||||
|
name = models.CharField(max_length=256, unique=True)
|
||||||
|
glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True)
|
||||||
|
glueIPv6 = models.GenericIPAddressField(protocol='IPv6', blank=True, null=True)
|
||||||
|
|
||||||
|
admin_c = models.ManyToManyField(Contact)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("domains:nameserver-show", args=(self.name,))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Domain(MntdObject):
|
||||||
|
handle = None
|
||||||
|
handleSuffix = "DOM"
|
||||||
|
name = models.CharField(max_length=67, unique=True, db_index=True)
|
||||||
|
|
||||||
|
nameservers = models.ManyToManyField(Nameserver, blank=True)
|
||||||
|
admin_c = models.ManyToManyField(Contact)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("domains:domain-show", args=(self.name,))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
#class NameserverDomainAssignment(models.Model):
|
||||||
|
# domain = models.ForeignKey(Domain)
|
||||||
|
# nameserver = models.ForeignKey(Nameserver)
|
||||||
|
#
|
||||||
|
# order = models.PositiveSmallIntegerField(default=0)
|
||||||
|
|
||||||
|
class ReverseZone(models.Model):
|
||||||
|
parentNet = models.ForeignKey(InetNum)
|
||||||
|
address = models.GenericIPAddressField(db_index=True)
|
||||||
|
netmask = models.PositiveIntegerField()
|
||||||
|
|
||||||
|
nameservers = models.ManyToManyField(Nameserver, through='NameserverReverseZoneAssignment')
|
||||||
|
|
||||||
|
#class NameserverReverseZoneAssignment(models.Model):
|
||||||
|
# reversezone = models.ForeignKey(ReverseZone)
|
||||||
|
# nameserver = models.ForeignKey(Nameserver)
|
||||||
|
#
|
||||||
|
# order = models.PositiveSmallIntegerField()
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,13 @@
|
||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from . import views as domains_views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', domains_views.overview, name='overview'),
|
||||||
|
|
||||||
|
url(r'domain/create/$', domains_views.DomainCreate.as_view(), name='domain-create'),
|
||||||
|
url(r'show/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainDetail, name='domain-show'),
|
||||||
|
|
||||||
|
url(r'nameserver/create/$', domains_views.NameserverCreate.as_view(), name='nameserver-create'),
|
||||||
|
url(r'nameserver/show/(?P<pk>\d+)/$', domains_views.NameserverDetail, name='nameserver-show'),
|
||||||
|
]
|
|
@ -0,0 +1,54 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.views.generic import DetailView, CreateView, UpdateView
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
|
||||||
|
from whoisdb.generic import MntGenericMixin
|
||||||
|
|
||||||
|
from .models import Domain, Nameserver
|
||||||
|
from .forms import DomainForm, NameserverForm
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def overview(request):
|
||||||
|
mnts = request.user.maintainer_set.all()
|
||||||
|
|
||||||
|
# get all domains and nameservers
|
||||||
|
domains = Domain.objects.filter(mnt_by__in=mnts)
|
||||||
|
nameservers = Nameserver.objects.filter(mnt_by__in=mnts)
|
||||||
|
|
||||||
|
return render(request, "domains/overview.html", {"domains": domains, "nameservers": nameservers})
|
||||||
|
|
||||||
|
class DomainCreate(LoginRequiredMixin, CreateView):
|
||||||
|
template_name = "domains/obj_create.html"
|
||||||
|
form_class = DomainForm
|
||||||
|
|
||||||
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
kwargs = super(DomainCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
class DomainDetail(LoginRequiredMixin, DetailView):
|
||||||
|
model = Domain
|
||||||
|
slug_field = "name"
|
||||||
|
slug_url_kwarg = "domain"
|
||||||
|
|
||||||
|
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
|
template_name = "domain"
|
||||||
|
|
||||||
|
|
||||||
|
class NameserverCreate(LoginRequiredMixin, CreateView):
|
||||||
|
template_name = "domains/obj_create.html"
|
||||||
|
form_class = NameserverForm
|
||||||
|
|
||||||
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
kwargs = super(NameserverCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
class NameserverDetail(LoginRequiredMixin, DetailView):
|
||||||
|
model = Nameserver
|
||||||
|
#slug_field = "name"
|
||||||
|
#slug_url_kwarg = "domain"
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from .models import Request, RequestMessage
|
||||||
|
|
||||||
|
admin.site.register(Request)
|
||||||
|
admin.site.register(RequestMessage)
|
|
@ -0,0 +1,5 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class RrequestsConfig(AppConfig):
|
||||||
|
name = 'rrequests'
|
|
@ -0,0 +1,55 @@
|
||||||
|
from django import forms
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
|
from .models import Request
|
||||||
|
from whoisdb.models import Maintainer
|
||||||
|
|
||||||
|
class RequestForm(forms.Form):
|
||||||
|
RESOURCES = map(lambda _x: (_x, _x), [
|
||||||
|
"AS Number (16bit)", "IPv4 /27", "IPv4 > /27", "IPv6", "other"
|
||||||
|
])
|
||||||
|
|
||||||
|
applicant = forms.ModelChoiceField(Maintainer.objects.none(), label="Applicant (you)", help_text="Maintainer you want to request resources for")
|
||||||
|
provider = forms.ModelChoiceField(Maintainer.objects.none(), label="Provider", help_text="LIR/RIR you want to request resources from")
|
||||||
|
|
||||||
|
subject = forms.CharField(label="Subject")
|
||||||
|
resources = forms.CheckboxSelectMultiple(choices=RESOURCES)
|
||||||
|
message = forms.CharField(widget=forms.Textarea, help_text="Describe shortly what resources you need and what for you need them")
|
||||||
|
|
||||||
|
def __init__(self, user, *args, **kwargs):
|
||||||
|
super(RequestForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self._user = user
|
||||||
|
self.fields['applicant'].queryset = self._user.maintainer_set.all()
|
||||||
|
self.fields['provider'].queryset = Maintainer.objects.filter(Q(rir=True) | Q(lir=True))
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super(RequestForm, self).clean()
|
||||||
|
|
||||||
|
if not forms.errors:
|
||||||
|
mnts = self._user.maintainer_set.all()
|
||||||
|
if cleaned_data['applicant'] in mnts and cleaned_data['provider'] in mnts:
|
||||||
|
raise forms.ValidationError("You could request resources from yourself, but this would actually not make that much sense.")
|
||||||
|
|
||||||
|
class ResponseForm(forms.Form):
|
||||||
|
new_status = forms.ChoiceField(choices=[("KEEP", "----", )] + list(Request.STATES), initial="KEEP", help_text="Only set this if you want to change the status of this request")
|
||||||
|
message = forms.CharField(widget=forms.Textarea)
|
||||||
|
|
||||||
|
def __init__(self, request, user, *args, **kwargs):
|
||||||
|
super(ResponseForm, self).__init__(*args, **kwargs)
|
||||||
|
self._request = request
|
||||||
|
self._user = user
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
cleaned_data = super(ResponseForm, self).clean()
|
||||||
|
|
||||||
|
if not self.errors:
|
||||||
|
if cleaned_data['new_status'] == self._request.status:
|
||||||
|
raise forms.ValidationError("Status changed to same as ticket")
|
||||||
|
if self._request.status in (Request.STATE_RESOLVED, Request.STATE_REJECTED) and \
|
||||||
|
cleaned_data['new_status'] not in (Request.STATE_OPEN,):
|
||||||
|
raise forms.ValidationError("Please put this ticket in an open state before adding messages")
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseForm(ResponseForm):
|
||||||
|
createdResources = forms.CharField(label="Created resources", help_text="If you have created resources for this request, please enter their handles here", required=False)
|
|
@ -0,0 +1,39 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-03 12:21
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('whoisdb', '0013_auto_20170303_1206'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Request',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('title', models.CharField(max_length=200)),
|
||||||
|
('state', models.CharField(choices=[('Open', 'OPEN'), ('Resolved', 'RESOLVED'), ('Rejected', 'REJECTED')], max_length=16)),
|
||||||
|
('requestResources', models.TextField()),
|
||||||
|
('grantedResources', models.TextField()),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('lastAction', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('requestedFrom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='requestfrom_set', to='whoisdb.Maintainer')),
|
||||||
|
('requestedTo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='whoisdb.Maintainer')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='RequestMessage',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('message', models.TextField()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,45 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-05 04:36
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('whoisdb', '0013_auto_20170303_1206'),
|
||||||
|
('rrequests', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='request',
|
||||||
|
old_name='requestedTo',
|
||||||
|
new_name='applicant',
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='request',
|
||||||
|
old_name='requestedFrom',
|
||||||
|
new_name='provider',
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='request',
|
||||||
|
old_name='title',
|
||||||
|
new_name='subject',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='requestmessage',
|
||||||
|
name='created',
|
||||||
|
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='requestmessage',
|
||||||
|
name='creator',
|
||||||
|
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='whoisdb.Maintainer'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-06 02:04
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('rrequests', '0002_auto_20170305_0436'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='requestmessage',
|
||||||
|
name='request',
|
||||||
|
field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to='rrequests.Request'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-06 11:36
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('rrequests', '0003_requestmessage_request'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='requestmessage',
|
||||||
|
name='statusChanged',
|
||||||
|
field=models.CharField(blank=True, choices=[('Open', 'OPEN'), ('Resolved', 'RESOLVED'), ('Rejected', 'REJECTED')], default=None, max_length=16, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,30 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-06 11:53
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('rrequests', '0004_requestmessage_statuschanged'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='request',
|
||||||
|
name='state',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='request',
|
||||||
|
name='status',
|
||||||
|
field=models.CharField(choices=[('OPEN', 'Open'), ('RESOLVED', 'Resolved'), ('REJECTED', 'Rejected')], default='OPEN', max_length=16),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='requestmessage',
|
||||||
|
name='statusChanged',
|
||||||
|
field=models.CharField(blank=True, choices=[('OPEN', 'Open'), ('RESOLVED', 'Resolved'), ('REJECTED', 'Rejected')], default=None, max_length=16, null=True),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,44 @@
|
||||||
|
from django.db import models
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from whoisdb.models import Maintainer
|
||||||
|
|
||||||
|
class Request(models.Model):
|
||||||
|
STATE_OPEN = "OPEN"
|
||||||
|
STATE_RESOLVED = "RESOLVED"
|
||||||
|
STATE_REJECTED = "REJECTED"
|
||||||
|
STATES = (
|
||||||
|
(STATE_OPEN, 'Open'),
|
||||||
|
(STATE_RESOLVED, 'Resolved'),
|
||||||
|
(STATE_REJECTED, 'Rejected'),
|
||||||
|
)
|
||||||
|
|
||||||
|
# request goes to mnt?
|
||||||
|
subject = models.CharField(max_length=200)
|
||||||
|
|
||||||
|
status = models.CharField(max_length=16, choices=STATES)
|
||||||
|
|
||||||
|
applicant = models.ForeignKey(Maintainer)
|
||||||
|
provider = models.ForeignKey(Maintainer, related_name='requestfrom_set')
|
||||||
|
|
||||||
|
requestResources = models.TextField()
|
||||||
|
grantedResources = models.TextField()
|
||||||
|
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
lastAction = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse("rrequests:show", args=(self.pk,))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "(%s -> %s) [%s] %s" % (self.applicant, self.provider, self.state, self.subject)
|
||||||
|
|
||||||
|
|
||||||
|
class RequestMessage(models.Model):
|
||||||
|
request = models.ForeignKey(Request)
|
||||||
|
|
||||||
|
statusChanged = models.CharField(max_length=16, choices=Request.STATES, default=None, null=True, blank=True)
|
||||||
|
|
||||||
|
creator = models.ForeignKey(Maintainer)
|
||||||
|
message = models.TextField()
|
||||||
|
created = models.DateTimeField(auto_now_add=True)
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
|
@ -0,0 +1,10 @@
|
||||||
|
from django.conf.urls import url
|
||||||
|
|
||||||
|
from . import views as rrequests_views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', rrequests_views.listRequests, name='dashboard'),
|
||||||
|
|
||||||
|
url(r'create/$', rrequests_views.RrequestCreate.as_view(), name='create'),
|
||||||
|
url(r'show/(?P<pk>\d+)/$', rrequests_views.rrequestDetail, name='show'),
|
||||||
|
]
|
|
@ -0,0 +1,91 @@
|
||||||
|
from django.shortcuts import render, get_object_or_404
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.views.generic import FormView
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from .models import Request, RequestMessage
|
||||||
|
from .forms import RequestForm, ResponseForm, ProviderResponseForm
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def listRequests(request):
|
||||||
|
mnts = request.user.maintainer_set.all()
|
||||||
|
requestedFromMe = Request.objects.filter(applicant=mnts)
|
||||||
|
requestedToMe = Request.objects.filter(provider__in=mnts)
|
||||||
|
|
||||||
|
return render(request, "rrequests/list.html", {"requestedFromMe": requestedFromMe, "requestedToMe": requestedToMe})
|
||||||
|
|
||||||
|
|
||||||
|
class RrequestCreate(LoginRequiredMixin, FormView):
|
||||||
|
template_name = "rrequests/request_create.html"
|
||||||
|
form_class = RequestForm
|
||||||
|
|
||||||
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
kwargs = super(RrequestCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
kwargs['user'] = self.request.user
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
formData = form.cleaned_data
|
||||||
|
print(formData)
|
||||||
|
request = Request(
|
||||||
|
subject=formData['subject'],
|
||||||
|
status=Request.STATE_OPEN,
|
||||||
|
applicant=formData['applicant'],
|
||||||
|
provider=formData['provider'],
|
||||||
|
)
|
||||||
|
request.save()
|
||||||
|
|
||||||
|
requestMsg = RequestMessage(
|
||||||
|
request=request,
|
||||||
|
|
||||||
|
creator=formData['applicant'],
|
||||||
|
message=formData['message'],
|
||||||
|
)
|
||||||
|
requestMsg.save()
|
||||||
|
|
||||||
|
return HttpResponseRedirect(request.get_absolute_url())
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def rrequestDetail(request, pk):
|
||||||
|
reqObj = get_object_or_404(Request, pk=pk)
|
||||||
|
|
||||||
|
mnts = request.user.maintainer_set.all()
|
||||||
|
formClass = None
|
||||||
|
provider = None
|
||||||
|
if reqObj.provider in mnts:
|
||||||
|
provider = True
|
||||||
|
formClass = ProviderResponseForm
|
||||||
|
else:
|
||||||
|
provider = False
|
||||||
|
formClass = ResponseForm
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
form = formClass(request=reqObj, user=request.user, data=request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
# create message object
|
||||||
|
msg = RequestMessage(
|
||||||
|
request=reqObj,
|
||||||
|
creator=reqObj.provider if provider else reqObj.applicant,
|
||||||
|
message=form.cleaned_data['message']
|
||||||
|
)
|
||||||
|
if form.cleaned_data['new_status'] != "KEEP":
|
||||||
|
msg.statusChanged = form.cleaned_data['new_status']
|
||||||
|
reqObj.status = msg.statusChanged
|
||||||
|
|
||||||
|
msg.save()
|
||||||
|
|
||||||
|
reqObj.lastAction = timezone.now()
|
||||||
|
reqObj.save()
|
||||||
|
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse("rrequests:show", args=(pk,)))
|
||||||
|
else:
|
||||||
|
form = formClass(request=reqObj, user=request.user)
|
||||||
|
|
||||||
|
return render(request, "rrequests/request_detail.html", {"request": reqObj, "form": form})
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Whois DB <span class="caret"></span></a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Whois DB <span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="{% url "whoisdb:dashboard" %}">Overview</a></li>
|
<li><a href="{% url "whoisdb:dashboard" %}">Overview</a></li>
|
||||||
|
<li><a href="{% url "domains:overview" %}">Domains</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Header</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form method="post" action="#">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form | crispy }}
|
||||||
|
<button type="submit" class="btn btn-primary">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Resource Requests</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<p>
|
||||||
|
Your nameservers (<a href="{% url "domains:nameserver-create" %}">New nameserver</a>)
|
||||||
|
{% for nameserver in nameservers %}
|
||||||
|
{{ nameserver }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Your domains (<a href="{% url "domains:domain-create" %}">New domain</a>)
|
||||||
|
{% for domain in domains %}
|
||||||
|
{{ domain }}<br />
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Resource Requests</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<p>
|
||||||
|
<a href="{% url "rrequests:create" %}">Create resource request</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Requests to you
|
||||||
|
<ul>
|
||||||
|
{% for r in requestedFromMe %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
{% for r in requestedToMe %}
|
||||||
|
<li><a href="{% url "rrequests:show" r.pk %}">{{ r.subject }} {{ r.created }} {{ r.applicant }} {{ r.provider }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Header</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form method="post" action="#">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form | crispy }}
|
||||||
|
<button type="submit" class="btn btn-primary">Create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">Header</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<h2>{{ request.subject }}</h2>
|
||||||
|
<p>
|
||||||
|
{% for message in request.requestmessage_set.all %}
|
||||||
|
<h4>{{ message.creator }} {{ message.created }}</h4>
|
||||||
|
{{ message.message | linebreaks }}
|
||||||
|
|
||||||
|
{% if message.statusChanged %}
|
||||||
|
Status changed to {{ message.statusChanged }}.
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</p>
|
||||||
|
<h4>Add / change</h4>
|
||||||
|
<form method="post" action="#">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form | crispy }}
|
||||||
|
<button class="btn btn-primary">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{% url "whoisdb:mnt-create" %}">Create new Maintainer</a></li>
|
<li><a href="{% url "whoisdb:mnt-create" %}">Create new Maintainer</a></li>
|
||||||
<li><a href="{% url "whoisdb:contact-create" %}">Create new Role/Person</a></li>
|
<li><a href="{% url "whoisdb:contact-create" %}">Create new Role/Person</a></li>
|
||||||
<li><a href="">Request resources</a></li>
|
<li><a href="{% url "rrequests:dashboard" %}">Request resources</a></li>
|
||||||
{% if netblocks %}
|
{% if netblocks %}
|
||||||
<li><a href="{% url "whoisdb:inetnum-create" %}">Create Subnet</a></li>
|
<li><a href="{% url "whoisdb:inetnum-create" %}">Create Subnet</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import re
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
class WhoisObjectMixin(object):
|
class WhoisObjectFormMixin(object):
|
||||||
def __init__(self, user, *args, **kwargs):
|
def __init__(self, user, *args, **kwargs):
|
||||||
super(WhoisObjectMixin, self).__init__(*args, **kwargs)
|
super(WhoisObjectFormMixin, self).__init__(*args, **kwargs)
|
||||||
self._user = user
|
self._user = user
|
||||||
|
|
||||||
instance = getattr(self, 'instance', None)
|
instance = getattr(self, 'instance', None)
|
||||||
|
@ -30,7 +30,7 @@ class WhoisObjectMixin(object):
|
||||||
return self.cleaned_data['handle']
|
return self.cleaned_data['handle']
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(WhoisObjectMixin, self).clean()
|
cleaned_data = super(WhoisObjectFormMixin, self).clean()
|
||||||
if cleaned_data.get("handle") == "AUTO" and not self.errors:
|
if cleaned_data.get("handle") == "AUTO" and not self.errors:
|
||||||
cleaned_data['handle'] = self._meta.model.genGenericHandle(cleaned_data.get("name"))
|
cleaned_data['handle'] = self._meta.model.genGenericHandle(cleaned_data.get("name"))
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ class MntFormMixin(object):
|
||||||
mntWhens.append(When(handle__in=instance.mnt_by.all().values_list("handle"), then=1))
|
mntWhens.append(When(handle__in=instance.mnt_by.all().values_list("handle"), then=1))
|
||||||
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
|
||||||
print(mntQs.query)
|
|
||||||
|
|
||||||
class MntForm(forms.ModelForm):
|
class MntForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -75,14 +74,16 @@ class MntInitialForm(MntForm):
|
||||||
fields = ['handle', 'description']
|
fields = ['handle', 'description']
|
||||||
|
|
||||||
|
|
||||||
class ContactForm(WhoisObjectMixin, forms.ModelForm):
|
class ContactForm(WhoisObjectFormMixin, forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contact
|
model = Contact
|
||||||
fields = ['type', 'handle', 'name', 'mnt_by']
|
fields = ['handle', 'name', 'mnt_by']
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
class ContactInitialForm(ContactForm):
|
class ContactInitialForm(ContactForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -90,7 +91,7 @@ class ContactInitialForm(ContactForm):
|
||||||
fields = ['handle', 'name']
|
fields = ['handle', 'name']
|
||||||
|
|
||||||
|
|
||||||
class InetNumForm(MntFormMixin, WhoisObjectMixin, forms.ModelForm):
|
class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
prefix = forms.CharField()
|
prefix = forms.CharField()
|
||||||
protectedFields = ['handle', 'protocol', 'parent_range', 'mnt_by', 'prefix']
|
protectedFields = ['handle', 'protocol', 'parent_range', 'mnt_by', 'prefix']
|
||||||
|
|
||||||
|
@ -123,41 +124,44 @@ class InetNumForm(MntFormMixin, WhoisObjectMixin, forms.ModelForm):
|
||||||
|
|
||||||
return net
|
return net
|
||||||
|
|
||||||
|
def clean_parent_range(self):
|
||||||
|
parent_range = self.cleaned_data.get('parent_range', None)
|
||||||
|
|
||||||
|
# allow parent range to be unset for already present objects
|
||||||
|
if not (self.instance and self.instance.pk) and not parent_range:
|
||||||
|
raise forms.ValidationError("Parent range must be set")
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
# FIXME: Reset certain field sto instance:
|
|
||||||
cleaned_data = super(InetNumForm, self).clean()
|
cleaned_data = super(InetNumForm, self).clean()
|
||||||
if self._editLower:
|
|
||||||
# reset some fields, just in case
|
if not self._editLower:
|
||||||
#for key in self.protectedFields:
|
if not self.errors:
|
||||||
# cleaned_data[key] = getattr(self.instance, key)
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if all(x in cleaned_data for x in ('prefix', 'parent_range', 'protocol')):
|
|
||||||
prefix = cleaned_data['prefix']
|
prefix = cleaned_data['prefix']
|
||||||
parent = cleaned_data['parent_range']
|
parent = cleaned_data['parent_range']
|
||||||
parentNet = parent.getNetwork()
|
if parent:
|
||||||
|
parentNet = parent.getNetwork()
|
||||||
|
|
||||||
if cleaned_data['protocol'] != parent.protocol:
|
if cleaned_data['protocol'] != parent.protocol:
|
||||||
raise forms.ValidationError("Protocol type for prefix must be same as parent network")
|
raise forms.ValidationError("Protocol type for prefix must be same as parent network")
|
||||||
|
|
||||||
# check if in parent block
|
# check if in parent block
|
||||||
if prefix.network_address not in parentNet or prefix.prefixlen < parentNet.prefixlen:
|
if prefix.network_address not in parentNet or prefix.prefixlen < parentNet.prefixlen:
|
||||||
raise forms.ValidationError("Prefix must be inside parent network range")
|
raise forms.ValidationError("Prefix must be inside parent network range")
|
||||||
|
|
||||||
# check if parent block has net that overlaps with us
|
# check if parent block has net that overlaps with us
|
||||||
for otherNet in parent.inetnum_set.all():
|
for otherNet in parent.inetnum_set.all():
|
||||||
if self.instance and self.instance.pk == otherNet.pk:
|
if self.instance and self.instance.pk == otherNet.pk:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if otherNet.getNetwork().overlaps(prefix):
|
if otherNet.getNetwork().overlaps(prefix):
|
||||||
raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle)
|
raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle)
|
||||||
|
|
||||||
self.instance.address = str(prefix.network_address)
|
self.instance.address = str(prefix.network_address)
|
||||||
self.instance.netmask = prefix.prefixlen
|
self.instance.netmask = prefix.prefixlen
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
class ASBlockForm(MntFormMixin, WhoisObjectMixin, forms.ModelForm):
|
class ASBlockForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
protectedFields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'mnt_by']
|
protectedFields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'mnt_by']
|
||||||
|
|
||||||
# FIXME: Filter blocks
|
# FIXME: Filter blocks
|
||||||
|
@ -205,13 +209,12 @@ class ASBlockForm(MntFormMixin, WhoisObjectMixin, forms.ModelForm):
|
||||||
|
|
||||||
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
|
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
|
||||||
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
|
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
|
||||||
print("AS OVERLAP TEST", parent.asBegin, parent.asEnd, asBegin, asEnd)
|
|
||||||
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
|
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
|
||||||
|
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
class ASNumberForm(MntFormMixin, WhoisObjectMixin, forms.ModelForm):
|
class ASNumberForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
protectedFields = ['handle', 'asblock', 'number', 'mnt_by']
|
protectedFields = ['handle', 'asblock', 'number', 'mnt_by']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-03-03 12:06
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('whoisdb', '0012_auto_20170302_0314'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='maintainer',
|
||||||
|
name='lir',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='maintainer',
|
||||||
|
name='rir',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='contact',
|
||||||
|
name='type',
|
||||||
|
field=models.CharField(choices=[('person', 'PERSON')], default='PERSON', max_length=10),
|
||||||
|
),
|
||||||
|
]
|
|
@ -68,6 +68,9 @@ class Maintainer(WhoisObject):
|
||||||
|
|
||||||
admin_c = models.ManyToManyField("Contact")
|
admin_c = models.ManyToManyField("Contact")
|
||||||
|
|
||||||
|
rir = models.BooleanField(default=False)
|
||||||
|
lir = models.BooleanField(default=False)
|
||||||
|
|
||||||
# autoInclude = models.BooleanField(default=True)
|
# autoInclude = models.BooleanField(default=True)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
|
@ -100,7 +103,7 @@ class Contact(MntdObject):
|
||||||
TYPE = (('person', TYPE_PERSON),)
|
TYPE = (('person', TYPE_PERSON),)
|
||||||
|
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
type = models.CharField(max_length=10, choices=TYPE)
|
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:contact-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:contact-detail", kwargs={"handle": self.handle})
|
||||||
|
|
|
@ -21,7 +21,6 @@ class HandleValidatorWithSuffix(validators.RegexValidator):
|
||||||
|
|
||||||
def __init__(self, suffix):
|
def __init__(self, suffix):
|
||||||
self.regex = r'^(?:[A-Z]+[0-9]+-%s|AUTO)' % re.escape(suffix)
|
self.regex = r'^(?:[A-Z]+[0-9]+-%s|AUTO)' % re.escape(suffix)
|
||||||
print(self.regex)
|
|
||||||
self.message = _(
|
self.message = _(
|
||||||
'Enter a valid handle with suffix %s (all uppercase)' % suffix
|
'Enter a valid handle with suffix %s (all uppercase)' % suffix
|
||||||
)
|
)
|
||||||
|
|
|
@ -46,8 +46,6 @@ def dbDashboard(request):
|
||||||
mntForm = MntInitialForm(user=request.user, prefix="mnt", initial={'handle': 'AUTO', 'description': 'Primary maintainer of %s' % request.user.username})
|
mntForm = MntInitialForm(user=request.user, prefix="mnt", initial={'handle': 'AUTO', 'description': 'Primary maintainer of %s' % request.user.username})
|
||||||
contactForm = ContactInitialForm(user=request.user, person=True, initial={'handle': 'AUTO', 'name': request.user.username.capitalize()}, prefix='contact')
|
contactForm = ContactInitialForm(user=request.user, person=True, initial={'handle': 'AUTO', 'name': request.user.username.capitalize()}, prefix='contact')
|
||||||
|
|
||||||
print(asnumbers, asblocks, netblocks, mnts)
|
|
||||||
|
|
||||||
return render(request, "whoisdb/overview.html", {"mnts": mnts, "contacts": contacts, "mntForm": mntForm, "contactForm": contactForm, "netblocks": netblocks, "asblocks": asblocks, "asnumbers": asnumbers})
|
return render(request, "whoisdb/overview.html", {"mnts": mnts, "contacts": contacts, "mntForm": mntForm, "contactForm": contactForm, "netblocks": netblocks, "asblocks": asblocks, "asnumbers": asnumbers})
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,6 +154,7 @@ class InetNumCreate(LoginRequiredMixin, CreateView):
|
||||||
form_class = InetNumForm
|
form_class = InetNumForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
|
print("NOOOOOOOOOOOOOOOOOOOOOOOOOOOOT", args, kwargs)
|
||||||
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
|
|
Loading…
Reference in New Issue