from django import forms #from crispy_forms.helper import FormHelper #from crispy_forms.layout import Submit, Layout #from django.urls import reverse 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) self._user = user instance = getattr(self, 'instance', None) if instance and instance.pk: self.fields['handle'].widget.attrs['readonly'] = True def clean_handle(self): instance = getattr(self, 'instance', None) if instance and instance.pk: return instance.handle else: return self.cleaned_data['handle'] def clean(self): cleaned_data = super(WhoisObjectMixin, self).clean() 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 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 Meta: model = Maintainer fields = ['handle', 'description'] class ContactForm(WhoisObjectMixin, forms.ModelForm): class Meta: model = Contact fields = ['type', 'handle', 'name', 'mnt_by'] 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 = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'mnt_by', 'mnt_lower'] def __init__(self, lower=False, *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__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: 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