Noot! Domains working

master
Sebastian Lohff 7 years ago
parent 69abba4d36
commit aa6313b464

@ -32,12 +32,12 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'dncore',
'whoisdb',
@ -46,31 +46,31 @@ INSTALLED_APPS = [
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'dnmgmt.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates/")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, "templates/")],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'dnmgmt.wsgi.application'
@ -80,10 +80,10 @@ WSGI_APPLICATION = 'dnmgmt.wsgi.application'
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
@ -91,18 +91,18 @@ DATABASES = {
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
@ -126,14 +126,13 @@ USE_TZ = True
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "cstatic")
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
os.path.join(BASE_DIR, "static"),
]
CRISPY_TEMPLATE_PACK = 'bootstrap3'
MESSAGE_TAGS = {
messages.ERROR: 'danger',
messages.ERROR: 'danger',
}
AUTH_USER_MODEL = 'dncore.User'
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/'
LOGIN_URL = '/user/login/'

@ -17,28 +17,35 @@ class DomainForm(MntFormMixin, forms.ModelForm):
super(DomainForm, self).__init__(*args, **kwargs)
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
if not self._create:
self.fields['name'].disabled = True
def clean_name(self):
name = self.cleaned_data['name'].lower()
if not name.endswith("."):
name += "."
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 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 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")
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
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:
@ -50,6 +57,9 @@ class NameserverForm(MntFormMixin, forms.ModelForm):
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("."):
@ -62,8 +72,14 @@ class NameserverForm(MntFormMixin, forms.ModelForm):
mnts = self._user.maintainer_set.all()
domains = Domain.objects.filter(mnt_by__in=mnts)
found = False
for domain in domains:
if domain.endswith(name)
if domain.name == zone:
found = True
break
if not found:
raise forms.ValidationError("This nameserver is not under a domain you control.")
return name

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-13 11:18
# Generated by Django 1.10.5 on 2017-03-14 21:04
from __future__ import unicode_literals
from django.db import migrations, models
@ -35,7 +35,7 @@ class Migration(migrations.Migration):
('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)),
('name', models.CharField(max_length=256, unique=True)),
('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')),
@ -45,38 +45,16 @@ class Migration(migrations.Migration):
'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')),
('nameservers', models.ManyToManyField(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',

@ -6,6 +6,7 @@ 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
@ -24,6 +25,7 @@ class Nameserver(MntdObject):
def __str__(self):
return self.name
class Domain(MntdObject):
handle = None
handleSuffix = "DOM"
@ -38,18 +40,29 @@ class Domain(MntdObject):
def __str__(self):
return self.name
def getNoDeleteReasons(self):
reasons = []
nameservers = Nameserver.objects.filter(name__endswith="." + self.name)
for ns in nameservers:
reasons.append("Nameserver %s depends on this domain" % ns.name)
return reasons
#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')
nameservers = models.ManyToManyField(Nameserver)
#class NameserverReverseZoneAssignment(models.Model):
# reversezone = models.ForeignKey(ReverseZone)

@ -6,8 +6,12 @@ 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'domain/show/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainDetail.as_view(), name='domain-show'),
url(r'domain/edit/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainEdit.as_view(), name='domain-edit'),
url(r'domain/delete/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainDelete.as_view(), name='domain-delete'),
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'),
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/delete/(?P<domain>[a-z0-9.-]+)/$', domains_views.NameserverDelete.as_view(), name='nameserver-delete'),
]

@ -1,13 +1,15 @@
from django.shortcuts import render
from django.urls import reverse_lazy
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 whoisdb.generic import MntGenericMixin, DeleteCheckView
from .models import Domain, Nameserver
from .forms import DomainForm, NameserverForm
@login_required
def overview(request):
mnts = request.user.maintainer_set.all()
@ -18,6 +20,7 @@ def overview(request):
return render(request, "domains/overview.html", {"domains": domains, "nameservers": nameservers})
class DomainCreate(LoginRequiredMixin, CreateView):
template_name = "domains/obj_create.html"
form_class = DomainForm
@ -28,13 +31,33 @@ class DomainCreate(LoginRequiredMixin, CreateView):
return kwargs
class DomainDetail(LoginRequiredMixin, DetailView):
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "domain"
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
template_name = "domain"
model = Domain
form_class = DomainForm
slug_field = "name"
slug_url_kwarg = "domain"
template_name = "domains/obj_edit.html"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(DomainEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
class DomainDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "domains/obj_delete.html"
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
success_url = reverse_lazy("domains:overview")
class NameserverCreate(LoginRequiredMixin, CreateView):
@ -47,8 +70,30 @@ class NameserverCreate(LoginRequiredMixin, CreateView):
return kwargs
class NameserverDetail(LoginRequiredMixin, DetailView):
model = Nameserver
#slug_field = "name"
#slug_url_kwarg = "domain"
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "nameserver"
class NameserverEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
model = Nameserver
form_class = NameserverForm
slug_field = "name"
slug_url_kwarg = "domain"
template_name = "domains/obj_edit.html"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(NameserverEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
class NameserverDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "domains/obj_delete.html"
model = Nameserver
slug_field = "name"
slug_url_kwarg = "domain"
success_url = reverse_lazy("domains:overview")

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% 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">
{{ domain.name }}
</div>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,15 @@
{% extends "base.html" %}
{% 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">
{{ nameserver.name }}
</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-{% if reasons %}danger{%else%}default{%endif%}">
<div class="panel-heading">Header</div>
<div class="panel-body">
{% if reasons %}
<p>
You cannot delete this object, as other objects in the database depend on it!
</p>
<p>
<ul>
{% for reason in reasons %}
<li>{{ reason }}</li>
{% endfor %}
</ul>
{% else %}
{{ obj }}
<form method="post" action="#">
{% csrf_token %}
<button type="submit" class="btn btn-primary">Delete</button>
</form>
{% endif %}
</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">Update</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

@ -8,15 +8,46 @@
<div class="panel-body">
<p>
Your nameservers (<a href="{% url "domains:nameserver-create" %}">New nameserver</a>)
<table class="table">
<tr>
<th>Nameserver</th>
<th>Glue IPv4</th>
<th>Glue IPv6</th>
<th>MNTs</th>
<th></th>
</tr>
{% for nameserver in nameservers %}
{{ nameserver }}<br />
<tr>
<td><a href="{% url "domains:nameserver-show" nameserver.name %}">{{ nameserver.name }}</a></td>
<td></td>
<td></td>
<td></td>
<td><a href="{% url "domains:nameserver-edit" nameserver.name %}">Edit</a> <a href="{% url "domains:nameserver-delete" nameserver.name %}">Delete</a></td>
</tr>
{% endfor %}
</table>
</p>
<p>
Your domains (<a href="{% url "domains:domain-create" %}">New domain</a>)
<table class="table">
<tr>
<th>Domain</th>
<th>Nameserver</th>
<th>Glue IPv6</th>
<th>MNTs</th>
<th></th>
</tr>
{% for domain in domains %}
<tr>
<td><a href="{% url "domains:domain-show" domain.name %}">{{ domain.name }}</a></td>
<td></td>
<td></td>
<td></td>
<td><a href="{% url "domains:domain-edit" domain.name %}">Edit</a> <a href="{% url "domains:domain-delete" domain.name %}">Delete</a></td>
</tr>
{{ domain }}<br />
{% endfor %}
</table>
</div>
</div>
</div>

Loading…
Cancel
Save