Niitt
This commit is contained in:
		
							parent
							
								
									814a8b62cb
								
							
						
					
					
						commit
						f9b98a03f5
					
				|  | @ -0,0 +1,16 @@ | |||
| {% 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"> | ||||
| 				{{ inetnum }} | ||||
| 				{{ inetnum.address }}/{{ inetnum.netmask }} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {% endblock %} | ||||
| 
 | ||||
|  | @ -48,7 +48,7 @@ | |||
| 								{% include "whoisdb/handle_table_row.html" with obj=asnumber objType="AS Number" prefix="contact" %} | ||||
| 							{% endfor %} | ||||
| 							{% for netblock in netblocks %} | ||||
| 								{% include "whoisdb/handle_table_row.html" with obj=netblock objType="IP Netblock" prefix="contact" %} | ||||
| 								{% include "whoisdb/handle_table_row.html" with obj=netblock objType="IP Netblock" prefix="inetnum" %} | ||||
| 							{% endfor %} | ||||
| 						</tbody> | ||||
| 					</table> | ||||
|  |  | |||
|  | @ -6,6 +6,10 @@ from django import forms | |||
| 
 | ||||
| from .models import Maintainer, Contact, InetNum | ||||
| 
 | ||||
| import re | ||||
| import ipaddress | ||||
| 
 | ||||
| 
 | ||||
| class WhoisObjectMixin(object): | ||||
| 	def __init__(self, user, *args, **kwargs): | ||||
| 		super(WhoisObjectMixin, self).__init__(*args, **kwargs) | ||||
|  | @ -24,9 +28,12 @@ class WhoisObjectMixin(object): | |||
| 
 | ||||
| 	def clean(self): | ||||
| 		cleaned_data = super(WhoisObjectMixin, self).clean() | ||||
| 		if cleaned_data.get("handle") == "AUTO": | ||||
| 		if cleaned_data.get("handle") == "AUTO" and not self.errors: | ||||
| 			cleaned_data['handle'] = self._meta.model.genGenericHandle(cleaned_data.get("name")) | ||||
| 
 | ||||
| 		return cleaned_data | ||||
| 
 | ||||
| 
 | ||||
| class MntForm(forms.ModelForm): | ||||
| 	class Meta: | ||||
| 		model = Maintainer | ||||
|  | @ -38,11 +45,13 @@ class MntForm(forms.ModelForm): | |||
| 		if 'admin_c' in self.fields: | ||||
| 			self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by=user.maintainer_set.all()) | ||||
| 
 | ||||
| 
 | ||||
| class MntInitialForm(MntForm): | ||||
| 	class Meta: | ||||
| 		model = Maintainer | ||||
| 		fields = ['handle', 'description'] | ||||
| 
 | ||||
| 
 | ||||
| class ContactForm(WhoisObjectMixin, forms.ModelForm): | ||||
| 	class Meta: | ||||
| 		model = Contact | ||||
|  | @ -51,24 +60,76 @@ class ContactForm(WhoisObjectMixin, forms.ModelForm): | |||
| 	def __init__(self, *args, **kwargs): | ||||
| 		super(ContactForm, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
| 
 | ||||
| class ContactInitialForm(ContactForm): | ||||
| 	class Meta: | ||||
| 		model = Contact | ||||
| 		fields = ['handle', 'name'] | ||||
| 
 | ||||
| 
 | ||||
| class InetNumForm(WhoisObjectMixin, forms.ModelForm): | ||||
| 	prefix = forms.CharField() | ||||
| 	protectedFields = ['handle', 'protocol', 'parent_range', 'mnt_by', 'prefix'] | ||||
| 
 | ||||
| 	class Meta: | ||||
| 		model = InetNum | ||||
| 		fields = ['protocol', 'parent_range', 'address', 'description', 'mnt_lower'] | ||||
| 		fields = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'mnt_by', 'mnt_lower'] | ||||
| 
 | ||||
| 	def __init__(self, lower=False, *args, **kwargs): | ||||
| 		super(MntForm, self).__init__(*args, **kwargs) | ||||
| 		super(InetNumForm, self).__init__(*args, **kwargs) | ||||
| 		print("args", args, kwargs) | ||||
| 		self._editLower = lower | ||||
| 		if 'admin_c' in self.fields: | ||||
| 			self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by=self.user.maintainer_set.all()) | ||||
| 			self.fields['admin_c'].queryset = Contact.objects.filter(mnt_by__in=self.user.maintainer_set.all()) | ||||
| 
 | ||||
| 		if self._editLower: | ||||
| 			for key in self.protectedFields: | ||||
| 				self.fields[key].disabled = True | ||||
| 				self.fields[key].widget.attrs['readonly'] = False | ||||
| 
 | ||||
| 	def clean_prefix(self): | ||||
| 		# make sure this is a subnet we're getting | ||||
| 		print("HALLO") | ||||
| 		net = self.cleaned_data['prefix'] | ||||
| 		if not re.match(r"[0-9:.]+/[0-9]+", net): | ||||
| 			raise forms.ValidationError("Address needs to be a subnet in the format of ip/cidr") | ||||
| 		try: | ||||
| 			net = ipaddress.ip_network(net) | ||||
| 		except ValueError as e: | ||||
| 			raise forms.ValidationError(str(e)) | ||||
| 
 | ||||
| 		return net | ||||
| 
 | ||||
| 	def clean(self): | ||||
| 		# FIXME: Reset certain field sto instance: | ||||
| 		pass | ||||
| 		cleaned_data = super(InetNumForm, self).clean() | ||||
| 		if self._editLower: | ||||
| 			# reset some fields, just in case | ||||
| 			#for key in self.protectedFields: | ||||
| 			#	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'] | ||||
| 				parent = cleaned_data['parent_range'] | ||||
| 				parentNet = parent.getNetwork() | ||||
| 
 | ||||
| 				if cleaned_data['protocol'] != parent.protocol: | ||||
| 					raise forms.ValidationError("Protocol type for prefix must be same as parent network") | ||||
| 
 | ||||
| 				# check if in parent block | ||||
| 				if prefix.network_address not in parentNet or prefix.prefixlen < parentNet.prefixlen: | ||||
| 					raise forms.ValidationError("Prefix must be inside parent network range") | ||||
| 
 | ||||
| 				# check if parent block has net that overlaps with us | ||||
| 				for otherNet in parent.inetnum_set.all(): | ||||
| 					if self.instance and self.instance.pk == otherNet.pk: | ||||
| 						continue | ||||
| 
 | ||||
| 					if otherNet.getNetwork().overlaps(prefix): | ||||
| 						raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle) | ||||
| 
 | ||||
| 				self.instance.address = str(prefix.network_address) | ||||
| 				self.instance.netmask = prefix.prefixlen | ||||
| 
 | ||||
| 		return cleaned_data | ||||
|  |  | |||
|  | @ -0,0 +1,26 @@ | |||
| # -*- coding: utf-8 -*- | ||||
| # Generated by Django 1.10.5 on 2017-03-01 00:03 | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('whoisdb', '0007_asblock_mnt_lower'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='inetnum', | ||||
|             name='name', | ||||
|             field=models.CharField(default='', max_length=64), | ||||
|             preserve_default=False, | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='inetnum', | ||||
|             name='protocol', | ||||
|             field=models.CharField(choices=[('ipv4', 'IPv4'), ('ipv6', 'IPv6')], max_length=4), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -4,6 +4,8 @@ from django.urls import reverse | |||
| from dncore.models import User | ||||
| from .validators import HandleValidator, HandleValidatorWithSuffix | ||||
| 
 | ||||
| import ipaddress | ||||
| 
 | ||||
| 
 | ||||
| class WhoisObject(models.Model): | ||||
| 	class Meta: | ||||
|  | @ -79,9 +81,8 @@ class Maintainer(WhoisObject): | |||
| 			candidates = mntable.objects.filter(mnt_by=self).annotate(mntCount=models.Count('mnt_by')).filter(mntCount__lte=1) | ||||
| 			for candidate in candidates: | ||||
| 				reasons.append("Object %s would have no maintainers left." % candidate.handle) | ||||
| 				 | ||||
| 		return reasons | ||||
| 
 | ||||
| 		return reasons | ||||
| 
 | ||||
| 
 | ||||
| class MntdObject(WhoisObject): | ||||
|  | @ -112,9 +113,10 @@ class Contact(MntdObject): | |||
| 			candidates = contactable.objects.filter(admin_c=self).annotate(contactCount=models.Count('admin_c')).filter(contactCount__lte=1) | ||||
| 			for candidate in candidates: | ||||
| 				reasons.append("Object %s would have no contact left." % candidate.handle) | ||||
| 				 | ||||
| 
 | ||||
| 		return reasons | ||||
| 
 | ||||
| 
 | ||||
| class ASBlock(MntdObject): | ||||
| 	handleSuffix = "ASB" | ||||
| 
 | ||||
|  | @ -123,6 +125,7 @@ class ASBlock(MntdObject): | |||
| 
 | ||||
| 	mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asblock_set', blank=True) | ||||
| 
 | ||||
| 
 | ||||
| class ASNumber(MntdObject): | ||||
| 	handleSuffix = "AS" | ||||
| 
 | ||||
|  | @ -145,6 +148,20 @@ class InetNum(MntdObject): | |||
| 	address = models.GenericIPAddressField(db_index=True) | ||||
| 	netmask = models.PositiveIntegerField() | ||||
| 	parent_range = models.ForeignKey("InetNum", models.CASCADE, null=True, blank=True, default=None) | ||||
| 	name = models.CharField(max_length=64) | ||||
| 	description = models.CharField(max_length=64, blank=True) | ||||
| 
 | ||||
| 	mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_inetnum_set', blank=True) | ||||
| 
 | ||||
| 	def getNetwork(self): | ||||
| 		return ipaddress.ip_network("%s/%s" % (self.address, self.netmask)) | ||||
| 
 | ||||
| 	def get_absolute_url(self): | ||||
| 		return reverse("whoisdb:inetnum-detail", kwargs={"handle": self.handle}) | ||||
| 
 | ||||
| 	def getNoDeleteReasons(self): | ||||
| 		reasons = [] | ||||
| 		if self.inetnum_set.all().count() > 0: | ||||
| 			reasons.append("The following networks depend on this network: %s" % ", ".join(map(lambda _x: _x.handle, self.inetnum_set.all()))) | ||||
| 
 | ||||
| 		return reasons | ||||
|  |  | |||
|  | @ -16,8 +16,7 @@ urlpatterns = [ | |||
| 	url(r'^contact/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDelete.as_view(), name='contact-delete'), | ||||
| 
 | ||||
| 	url(r'^inetnum/create/$', whoisdb_views.InetNumCreate.as_view(), name='inetnum-create'), | ||||
| 	url(r'^inetnum/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDetail.as_view(), name='inetnum-detail'), | ||||
| 	url(r'^inetnum/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactEdit.as_view(), name='inetnum-edit'), | ||||
| 	url(r'^inetnum/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDelete.as_view(), name='inetnum-delete'), | ||||
| 	url(r'^inetnum/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.InetNumDetail.as_view(), name='inetnum-detail'), | ||||
| 	url(r'^inetnum/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.InetNumEdit.as_view(), name='inetnum-edit'), | ||||
| 	url(r'^inetnum/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.InetNumDelete.as_view(), name='inetnum-delete'), | ||||
| ] | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,13 +10,14 @@ from .models import Maintainer, Contact, InetNum, ASBlock, ASNumber | |||
| from .forms import MntForm, MntInitialForm, ContactForm, ContactInitialForm, InetNumForm | ||||
| from .generic import DeleteCheckView | ||||
| 
 | ||||
| 
 | ||||
| @login_required | ||||
| def dbDashboard(request): | ||||
| 	mnts = request.user.maintainer_set.all() | ||||
| 	contacts = Contact.objects.filter(mnt_by__in=mnts) | ||||
| 	netblocks = InetNum.objects.filter(Q(mnt_by__in=mnts)|Q(mnt_lower__in=mnts)) | ||||
| 	asblocks = ASBlock.objects.filter(Q(mnt_by__in=mnts)|Q(mnt_lower__in=mnts)) | ||||
| 	asnumbers = ASNumber.objects.filter(Q(mnt_by__in=mnts)|Q(mnt_lower__in=mnts)) | ||||
| 	netblocks = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct() | ||||
| 	asblocks = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct() | ||||
| 	asnumbers = ASNumber.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct() | ||||
| 	mntForm = contactForm = None | ||||
| 
 | ||||
| 	if mnts.count() == 0: | ||||
|  | @ -49,6 +50,7 @@ def dbDashboard(request): | |||
| 
 | ||||
| 	return render(request, "whoisdb/overview.html", {"mnts": mnts, "contacts": contacts, "mntForm": mntForm, "contactForm": contactForm, "netblocks": netblocks, "asblocks": asblocks, "asnumbers": asnumbers}) | ||||
| 
 | ||||
| 
 | ||||
| class MaintainerCreate(LoginRequiredMixin, CreateView): | ||||
| 	template_name = "whoisdb/obj_create.html" | ||||
| 	form_class = MntForm | ||||
|  | @ -71,6 +73,7 @@ class MaintainerCreate(LoginRequiredMixin, CreateView): | |||
| 
 | ||||
| 		return super(MaintainerCreate, self).form_valid(form) | ||||
| 
 | ||||
| 
 | ||||
| class MaintainerEdit(LoginRequiredMixin, UpdateView): | ||||
| 	template_name = "whoisdb/maintainer_edit.html" | ||||
| 	model = Maintainer | ||||
|  | @ -86,6 +89,7 @@ class MaintainerEdit(LoginRequiredMixin, UpdateView): | |||
| 	def get_queryset(self): | ||||
| 		return self.model.objects.filter(auth=self.request.user) | ||||
| 
 | ||||
| 
 | ||||
| class MaintainerDelete(LoginRequiredMixin, DeleteCheckView): | ||||
| 	template_name = "whoisdb/obj_delete.html" | ||||
| 	model = Maintainer | ||||
|  | @ -95,7 +99,7 @@ class MaintainerDelete(LoginRequiredMixin, DeleteCheckView): | |||
| 
 | ||||
| 	def get_queryset(self): | ||||
| 		return self.model.objects.filter(auth=self.request.user) | ||||
| 	 | ||||
| 
 | ||||
| 
 | ||||
| class MaintainerDetail(LoginRequiredMixin, DetailView): | ||||
| 	model = Maintainer | ||||
|  | @ -103,12 +107,14 @@ class MaintainerDetail(LoginRequiredMixin, DetailView): | |||
| 	slug_url_kwarg = "handle" | ||||
| 	context_object_name = "mnt" | ||||
| 
 | ||||
| 
 | ||||
| class ContactDetail(DetailView): | ||||
| 	model = Contact | ||||
| 	slug_field = "handle" | ||||
| 	slug_url_kwarg = "handle" | ||||
| 	context_object_name = "contact" | ||||
| 
 | ||||
| 
 | ||||
| class ContactEdit(LoginRequiredMixin, UpdateView): | ||||
| 	template_name = "whoisdb/obj_edit.html" | ||||
| 	model = Contact | ||||
|  | @ -125,6 +131,7 @@ class ContactEdit(LoginRequiredMixin, UpdateView): | |||
| 		# FIXME: we need all maintainers to be available. autofill own maintainers | ||||
| 		return self.model.objects.filter(mnt_by__in=self.request.user.maintainer_set.all()) | ||||
| 
 | ||||
| 
 | ||||
| class ContactCreate(LoginRequiredMixin, CreateView): | ||||
| 	template_name = "whoisdb/obj_create.html" | ||||
| 	form_class = ContactForm | ||||
|  | @ -138,6 +145,7 @@ class ContactCreate(LoginRequiredMixin, CreateView): | |||
| 		} | ||||
| 		return kwargs | ||||
| 
 | ||||
| 
 | ||||
| class ContactDelete(LoginRequiredMixin, DeleteCheckView): | ||||
| 	template_name = "whoisdb/obj_delete.html" | ||||
| 	model = Contact | ||||
|  | @ -148,6 +156,7 @@ class ContactDelete(LoginRequiredMixin, DeleteCheckView): | |||
| 	def get_queryset(self): | ||||
| 		return self.model.objects.filter(mnt_by__in=self.request.user.maintainer_set.all()) | ||||
| 
 | ||||
| 
 | ||||
| # InetNum | ||||
| class InetNumCreate(LoginRequiredMixin, CreateView): | ||||
| 	template_name = "whoisdb/obj_create.html" | ||||
|  | @ -158,7 +167,51 @@ class InetNumCreate(LoginRequiredMixin, CreateView): | |||
| 		kwargs["user"] = self.request.user | ||||
| 		kwargs["initial"] = { | ||||
| 			"handle": "AUTO", | ||||
| 			"type": Contact.TYPE_PERSON | ||||
| 		} | ||||
| 
 | ||||
| 		return kwargs | ||||
| 
 | ||||
| 
 | ||||
| class InetNumDetail(DetailView): | ||||
| 	model = InetNum | ||||
| 	slug_field = "handle" | ||||
| 	slug_url_kwarg = "handle" | ||||
| 	context_object_name = "inetnum" | ||||
| 
 | ||||
| 
 | ||||
| class InetNumEdit(LoginRequiredMixin, UpdateView): | ||||
| 	template_name = "whoisdb/obj_edit.html" | ||||
| 	model = InetNum | ||||
| 	form_class = InetNumForm | ||||
| 	slug_field = "handle" | ||||
| 	slug_url_kwarg = "handle" | ||||
| 
 | ||||
| 	def get_form_kwargs(self, *args, **kwargs): | ||||
| 		kwargs = super(InetNumEdit, self).get_form_kwargs(*args, **kwargs) | ||||
| 		kwargs["user"] = self.request.user | ||||
| 
 | ||||
| 		mnts = self.request.user.maintainer_set.all() | ||||
| 		if not any(mnt in self.object.mnt_by.all() for mnt in mnts): | ||||
| 			# we are in mnt_lower | ||||
| 			kwargs["lower"] = True | ||||
| 
 | ||||
| 		kwargs["initial"] = {'prefix': str(self.object.getNetwork())} | ||||
| 
 | ||||
| 		return kwargs | ||||
| 
 | ||||
| 	def get_queryset(self): | ||||
| 		# FIXME: we need all maintainers to be available. autofill own maintainers | ||||
| 		mnts = self.request.user.maintainer_set.all() | ||||
| 		return self.model.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct() | ||||
| 
 | ||||
| 
 | ||||
| class InetNumDelete(LoginRequiredMixin, DeleteCheckView): | ||||
| 	template_name = "whoisdb/obj_delete.html" | ||||
| 	model = InetNum | ||||
| 	slug_field = "handle" | ||||
| 	slug_url_kwarg = "handle" | ||||
| 	success_url = reverse_lazy("whoisdb:dashboard") | ||||
| 
 | ||||
| 	def get_queryset(self): | ||||
| 		mnts = self.request.user.maintainer_set.all() | ||||
| 		return self.model.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue