2017-02-10 02:45:45 +01:00
from django . db import models
2017-02-28 19:44:15 +01:00
from django . urls import reverse
2017-02-10 02:45:45 +01:00
from dncore . models import User
2017-02-24 03:43:59 +01:00
from . validators import HandleValidator , HandleValidatorWithSuffix
2017-02-10 02:45:45 +01:00
2017-03-01 03:21:03 +01:00
import ipaddress
2017-02-15 02:35:46 +01:00
class WhoisObject ( models . Model ) :
2017-02-24 03:43:59 +01:00
class Meta :
abstract = True
handleSuffix = " "
2017-02-15 02:35:46 +01:00
2017-02-23 22:28:06 +01:00
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 )
2017-02-15 02:35:46 +01:00
2017-02-24 03:43:59 +01:00
def __str__ ( self ) :
return self . handle
def genHandle ( self , main = None ) :
if not main :
main = self . name
2017-02-28 19:44:15 +01:00
return self . genGenericHandle ( main )
@classmethod
def genGenericHandle ( clazz , main ) :
2017-02-24 03:43:59 +01:00
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
2017-02-28 19:44:15 +01:00
handle = " %s %% d- %s " % ( prefix , clazz . handleSuffix )
2017-02-24 03:43:59 +01:00
while True :
try :
prefix
2017-02-28 19:44:15 +01:00
clazz . objects . get ( handle = handle % i )
2017-02-24 03:43:59 +01:00
i + = 1
2017-02-28 19:44:15 +01:00
except clazz . DoesNotExist :
2017-02-24 03:43:59 +01:00
break
return handle % i
2017-02-28 19:44:15 +01:00
def getNoDeleteReasons ( self ) :
raise NotImplementedError ( )
def canBeDeleted ( self ) :
return not bool ( self . getNoDeleteReasons ( ) )
2017-02-24 03:43:59 +01:00
def handleAuto ( self , name = None ) :
if self . handle == " AUTO " :
self . handle = self . genHandle ( name )
2017-02-15 02:35:46 +01:00
class Maintainer ( WhoisObject ) :
2017-02-24 03:43:59 +01:00
handleSuffix = " MNT "
2017-02-10 02:45:45 +01:00
auth = models . ManyToManyField ( User )
2017-02-28 19:44:15 +01:00
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 " )
2017-02-15 02:35:46 +01:00
admin_c = models . ManyToManyField ( " Contact " )
2017-02-24 03:43:59 +01:00
# autoInclude = models.BooleanField(default=True)
2017-02-28 19:44:15 +01:00
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 )
2017-03-01 03:21:03 +01:00
return reasons
2017-02-15 02:35:46 +01:00
2017-02-24 03:43:59 +01:00
class MntdObject ( WhoisObject ) :
2017-02-15 02:35:46 +01:00
class Meta :
abstract = True
2017-02-24 03:43:59 +01:00
mnt_by = models . ManyToManyField ( Maintainer )
2017-02-15 02:35:46 +01:00
class Contact ( MntdObject ) :
2017-02-24 03:43:59 +01:00
handleSuffix = " DN "
2017-02-28 19:44:15 +01:00
TYPE_PERSON = ' PERSON '
TYPE_ROLE = ' ROLE '
TYPE = ( ( ' person ' , TYPE_PERSON ) , ( ' role ' , TYPE_ROLE ) )
TYPE = ( ( ' person ' , TYPE_PERSON ) , )
2017-02-15 02:35:46 +01:00
name = models . CharField ( max_length = 128 )
2017-02-28 19:44:15 +01:00
type = models . CharField ( max_length = 10 , choices = TYPE )
def get_absolute_url ( self ) :
return reverse ( " whoisdb:contact-detail " , kwargs = { " handle " : self . handle } )
2017-02-15 02:35:46 +01:00
2017-02-28 19:44:15 +01:00
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 )
2017-03-01 03:21:03 +01:00
2017-02-28 19:44:15 +01:00
return reasons
2017-02-24 03:43:59 +01:00
2017-03-01 03:21:03 +01:00
2017-02-21 20:45:44 +01:00
class ASBlock ( MntdObject ) :
2017-02-24 03:43:59 +01:00
handleSuffix = " ASB "
2017-02-21 20:45:44 +01:00
parent_block = models . ForeignKey ( " ASBlock " , models . CASCADE , null = True , blank = True , default = None )
description = models . CharField ( max_length = 64 , blank = True )
2017-02-15 02:35:46 +01:00
2017-02-28 19:44:15 +01:00
mnt_lower = models . ManyToManyField ( Maintainer , related_name = ' lower_asblock_set ' , blank = True )
2017-02-24 03:43:59 +01:00
2017-03-01 03:21:03 +01:00
2017-02-21 20:45:44 +01:00
class ASNumber ( MntdObject ) :
2017-02-24 03:43:59 +01:00
handleSuffix = " AS "
2017-02-15 02:35:46 +01:00
number = models . PositiveIntegerField ( unique = True , db_index = True )
2017-02-21 20:45:44 +01:00
volatile = models . BooleanField ( default = False )
asblock = models . ForeignKey ( ASBlock , models . CASCADE )
description = models . CharField ( max_length = 64 , blank = True )
2017-02-28 19:44:15 +01:00
mnt_lower = models . ManyToManyField ( Maintainer , related_name = ' lower_asnumber_set ' , blank = True )
2017-02-15 02:35:46 +01:00
2017-02-28 19:44:15 +01:00
class InetNum ( MntdObject ) :
2017-02-24 03:43:59 +01:00
handleSuffix = " NET "
2017-02-28 19:44:15 +01:00
IPv4 = " ipv4 "
IPv6 = " ipv6 "
PROTO = ( ( IPv4 , ' IPv4 ' ) , ( IPv6 , ' IPv6 ' ) )
2017-02-15 02:35:46 +01:00
protocol = models . CharField ( max_length = 4 , choices = PROTO )
2017-02-28 19:44:15 +01:00
address = models . GenericIPAddressField ( db_index = True )
2017-02-15 02:35:46 +01:00
netmask = models . PositiveIntegerField ( )
2017-02-21 20:45:44 +01:00
parent_range = models . ForeignKey ( " InetNum " , models . CASCADE , null = True , blank = True , default = None )
2017-03-01 03:21:03 +01:00
name = models . CharField ( max_length = 64 )
2017-02-21 20:45:44 +01:00
description = models . CharField ( max_length = 64 , blank = True )
2017-02-15 02:35:46 +01:00
2017-02-28 19:44:15 +01:00
mnt_lower = models . ManyToManyField ( Maintainer , related_name = ' lower_inetnum_set ' , blank = True )
2017-03-01 03:21:03 +01:00
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