You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
5.9 KiB

7 years ago
from django.db import models
7 years ago
from django.urls import reverse
7 years ago
from dncore.models import User
7 years ago
from .validators import HandleValidator, HandleValidatorWithSuffix
7 years ago
7 years ago
import ipaddress
7 years ago
class WhoisObject(models.Model):
7 years ago
class Meta:
abstract = True
handleSuffix = ""
7 years ago
7 years ago
handle = models.SlugField(max_length=32, unique=True, verbose_name='handle', validators=[HandleValidator()])
created = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now_add=True)
7 years ago
7 years ago
def __str__(self):
return self.handle
def genHandle(self, main=None):
if not main:
main = self.name
7 years ago
return self.genGenericHandle(main)
@classmethod
def genGenericHandle(clazz, main):
7 years ago
prefix = ""
if " " in main:
parts = main.split(" ")
prefix = "".join(map(lambda _x: _x[0], parts))
if len(prefix) < 3 and len(parts[-1]) > 1:
prefix += parts[-1][1:4 - len(prefix)]
else:
prefix = main[0:3]
prefix = prefix.upper()
i = 1
7 years ago
handle = "%s%%d-%s" % (prefix, clazz.handleSuffix)
7 years ago
while True:
try:
prefix
7 years ago
clazz.objects.get(handle=handle % i)
7 years ago
i += 1
7 years ago
except clazz.DoesNotExist:
7 years ago
break
return handle % i
7 years ago
def getNoDeleteReasons(self):
raise NotImplementedError()
def canBeDeleted(self):
return not bool(self.getNoDeleteReasons())
7 years ago
def handleAuto(self, name=None):
if self.handle == "AUTO":
self.handle = self.genHandle(name)
7 years ago
class Maintainer(WhoisObject):
7 years ago
handleSuffix = "MNT"
7 years ago
auth = models.ManyToManyField(User)
7 years ago
handle = models.SlugField(max_length=32, unique=True, verbose_name='handle', validators=[HandleValidatorWithSuffix('MNT')], help_text="Must end with -MNT, eg FOO3-MNT")
description = models.CharField(max_length=64, blank=True, help_text="Short description what this maintainer is for")
7 years ago
admin_c = models.ManyToManyField("Contact")
7 years ago
rir = models.BooleanField(default=False)
lir = models.BooleanField(default=False)
7 years ago
# autoInclude = models.BooleanField(default=True)
7 years ago
def get_absolute_url(self):
return reverse("whoisdb:mnt-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
mntables = [Contact, ASBlock, ASNumber, InetNum]
for mntable in mntables:
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)
7 years ago
return reasons
7 years ago
7 years ago
class MntdObject(WhoisObject):
7 years ago
class Meta:
abstract = True
7 years ago
mnt_by = models.ManyToManyField(Maintainer)
7 years ago
class Contact(MntdObject):
7 years ago
handleSuffix = "DN"
7 years ago
TYPE_PERSON = 'PERSON'
TYPE_ROLE = 'ROLE'
TYPE = (('person', TYPE_PERSON), ('role', TYPE_ROLE))
TYPE = (('person', TYPE_PERSON),)
7 years ago
name = models.CharField(max_length=128)
7 years ago
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
7 years ago
def get_absolute_url(self):
return reverse("whoisdb:contact-detail", kwargs={"handle": self.handle})
7 years ago
7 years ago
def getNoDeleteReasons(self):
reasons = []
contactables = [Maintainer]
for contactable in contactables:
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)
7 years ago
7 years ago
return reasons
7 years ago
7 years ago
7 years ago
class ASBlock(MntdObject):
7 years ago
handleSuffix = "ASB"
7 years ago
parent_block = models.ForeignKey("ASBlock", models.CASCADE, null=True, blank=True, default=None)
name = models.CharField(max_length=32)
asBegin = models.PositiveIntegerField()
asEnd = models.PositiveIntegerField()
7 years ago
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
7 years ago
7 years ago
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asblock_set', blank=True)
7 years ago
def get_absolute_url(self):
return reverse("whoisdb:asblock-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
if self.asblock_set.count() > 0:
reasons.append("The AS block is referenced by the following other blocks: %s" % (", ".join(map(lambda _x: _x.handle, self.asblock_set.all()))))
if self.asnumber_set.count() > 0:
reasons.append("The AS block is referenced by the following as numbers: %s" % (", ".join(map(lambda _x: _x.handle, self.asnumber_set.all()))))
return reasons
7 years ago
7 years ago
class ASNumber(MntdObject):
7 years ago
handleSuffix = "AS"
7 years ago
number = models.PositiveIntegerField(unique=True, db_index=True)
volatile = models.BooleanField(default=False, help_text="Check if this AS is not going to be online 24/7 (for example on a laptop)")
7 years ago
asblock = models.ForeignKey(ASBlock, models.CASCADE)
name = models.CharField(max_length=32)
7 years ago
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
7 years ago
7 years ago
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asnumber_set', blank=True)
7 years ago
def get_absolute_url(self):
return reverse("whoisdb:asnumber-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
return reasons
7 years ago
7 years ago
class InetNum(MntdObject):
7 years ago
handleSuffix = "NET"
7 years ago
IPv4 = "ipv4"
IPv6 = "ipv6"
PROTO = ((IPv4, 'IPv4'), (IPv6, 'IPv6'))
7 years ago
protocol = models.CharField(max_length=4, choices=PROTO)
7 years ago
address = models.GenericIPAddressField(db_index=True)
7 years ago
netmask = models.PositiveIntegerField()
7 years ago
parent_range = models.ForeignKey("InetNum", models.CASCADE, null=True, blank=True, default=None)
7 years ago
name = models.CharField(max_length=64)
7 years ago
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
7 years ago
7 years ago
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_inetnum_set', blank=True)
7 years ago
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