Merge progress from production system

master
Sebastian Lohff 4 years ago
commit a3b6209e0a

@ -11,121 +11,121 @@ import dns.resolver
# FIXME: DNS timeouts
def compareRecords(rrset, expected):
result = {
"nameMissing": [],
"rrMissing": [],
"rrExtra": [],
}
result = {
"nameMissing": [],
"rrMissing": [],
"rrExtra": [],
}
for domain, rrtype, content in expected:
for rrrec in rrset:
if domain == rrrec.name.to_text() and dns.rdatatype.from_text(rrtype) == rrrec.rdtype:
for name in content:
if name not in map(lambda _x: _x.to_text(), rrrec.items):
# record missing
result["rrMissing"].append((domain, rrtype, name))
for domain, rrtype, content in expected:
for rrrec in rrset:
if domain == rrrec.name.to_text() and dns.rdatatype.from_text(rrtype) == rrrec.rdtype:
for name in content:
if name not in map(lambda _x: _x.to_text(), rrrec.items):
# record missing
result["rrMissing"].append((domain, rrtype, name))
for item in rrrec.items:
if item.to_text() not in content:
# superfluous record
result["rrExtra"].append((domain, rrtype, item.to_text()))
for item in rrrec.items:
if item.to_text() not in content:
# superfluous record
result["rrExtra"].append((domain, rrtype, item.to_text()))
break
else:
# domain + rr nicht in nameserver
result["nameMissing"].append((domain, rrtype))
break
else:
# domain + rr nicht in nameserver
result["nameMissing"].append((domain, rrtype))
success = not any(len(_x) > 0 for _x in result.values())
success = not any(len(_x) > 0 for _x in result.values())
return success, result
return success, result
def dnsQuery(domain, rrType, nameserverIp):
dname = dns.name.from_text(domain)
req = dns.message.make_query(dname, dns.rdatatype.from_text(rrType))
resp = dns.query.udp(req, nameserverIp, timeout=2.0)
dname = dns.name.from_text(domain)
req = dns.message.make_query(dname, dns.rdatatype.from_text(rrType))
resp = dns.query.udp(req, nameserverIp, timeout=2.0)
if resp.rcode() != dns.rcode.NXDOMAIN:
rrset = resp.answer + resp.authority + resp.additional
return True, rrset
else:
return False, []
if resp.rcode() != dns.rcode.NXDOMAIN:
rrset = resp.answer + resp.authority + resp.additional
return True, rrset
else:
return False, []
def checkDomain(domain, tldNameserver, nameservers):
result = []
if nameservers.count() == 0:
return [("err", "Domain %s has no nameservers attached to it, nothing to check" % domain)]
# build record set
nsRecords = [(domain, "NS", list(ns.name for ns in nameservers))]
glueRecords = []
for ns in nameservers:
if ns.name.endswith("." + domain):
if ns.glueIPv4 or ns.glueIPv6:
if ns.glueIPv4:
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
else:
result.append(("err", "Nameserver %s is under domain %s, but has no glue entries." % (ns.name, domain)))
# 1. TLD nameserver
try:
found, rrset = dnsQuery(domain, "ANY", tldNameserver)
if found:
success, errors = compareRecords(rrset, nsRecords + glueRecords)
if success:
result.append(("succ", "All records present in TLD nameserver"))
else:
result.append(("err", "Record mismatch between TLD nameserver and WHOIS database", errors))
else:
result.append(("err", "Domain %s not found in TLD nameserver" % (domain,)))
except (dns.exception.Timeout, OSError):
result.append(("err", "TLD nameserver is currently not reachable"))
# find other records...
# 2. your nameservers
for ns in nameservers:
addr = None
if ns.glueIPv4:
addr = ns.glueIPv4
elif ns.glueIPv6:
addr = ns.glueIPv6
else:
for rrType in ("A", "AAAA"):
try:
r = dns.resolver.Resolver()
r.timeout = 2.0
q = r.query(ns.name, rdtype=dns.rdatatype.from_text(rrType))
addr = q.response.answer[0].items[0].address
except (dns.exception.DNSException, OSError):
pass
if addr:
err = False
errDict = {"nameMissing": [], "rrMissing": [], "rrExtra": []}
try:
for rec in (nsRecords + glueRecords):
found, rrset = dnsQuery(rec[0], rec[1], addr)
#success, errors = compareRecords(rrset, nsRecords + glueRecords)
success, errors = compareRecords(rrset, [rec])
if not success:
err = True
for k in errors.keys():
errDict[k].extend(errors[k])
if not err:
result.append(("succ", "Nameserver %s is configured correctly" % ns.name))
else:
result.append(("err", "Nameserver %s (via %s) recordset does not match the database" % (ns.name, addr), errDict))
except (dns.exception.DNSException, OSError):
result.append(("err", "Nameserver %s is not reachable (via %s)" % (ns.name, addr)))
else:
result.append(("err", "Can't resolv an ip address for nameserver %s" % ns.name))
return result
result = []
if nameservers.count() == 0:
return [("err", "Domain %s has no nameservers attached to it, nothing to check" % domain)]
# build record set
nsRecords = [(domain, "NS", list(ns.name for ns in nameservers))]
glueRecords = []
for ns in nameservers:
if ns.name.endswith("." + domain):
if ns.glueIPv4 or ns.glueIPv6:
if ns.glueIPv4:
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
else:
result.append(("err", "Nameserver %s is under domain %s, but has no glue entries." % (ns.name, domain)))
# 1. TLD nameserver
try:
found, rrset = dnsQuery(domain, "ANY", tldNameserver)
if found:
success, errors = compareRecords(rrset, nsRecords + glueRecords)
if success:
result.append(("succ", "All records present in TLD nameserver"))
else:
result.append(("err", "Record mismatch between TLD nameserver and WHOIS database", errors))
else:
result.append(("err", "Domain %s not found in TLD nameserver" % (domain,)))
except (dns.exception.Timeout, OSError):
result.append(("err", "TLD nameserver is currently not reachable"))
# find other records...
# 2. your nameservers
for ns in nameservers:
addr = None
if ns.glueIPv4:
addr = ns.glueIPv4
elif ns.glueIPv6:
addr = ns.glueIPv6
else:
for rrType in ("A", "AAAA"):
try:
r = dns.resolver.Resolver()
r.timeout = 2.0
q = r.query(ns.name, rdtype=dns.rdatatype.from_text(rrType))
addr = q.response.answer[0].items[0].address
except (dns.exception.DNSException, OSError):
pass
if addr:
err = False
errDict = {"nameMissing": [], "rrMissing": [], "rrExtra": []}
try:
for rec in (nsRecords + glueRecords):
found, rrset = dnsQuery(rec[0], rec[1], addr)
#success, errors = compareRecords(rrset, nsRecords + glueRecords)
success, errors = compareRecords(rrset, [rec])
if not success:
err = True
for k in errors.keys():
errDict[k].extend(errors[k])
if not err:
result.append(("succ", "Nameserver %s is configured correctly" % ns.name))
else:
result.append(("err", "Nameserver %s (via %s) recordset does not match the database" % (ns.name, addr), errDict))
except (dns.exception.DNSException, OSError):
result.append(("err", "Nameserver %s is not reachable (via %s)" % (ns.name, addr)))
else:
result.append(("err", "Can't resolv an ip address for nameserver %s" % ns.name))
return result

@ -7,13 +7,13 @@ from django.conf.urls import url
from . import views as api_views
urlpatterns = [
url(r'asblock/free-as/$', api_views.asblockFreeAS, name='asblock-free-as'),
url(r'asblock/free-subnet/$', api_views.freeSubnet, name='inetnum-free-subnet'),
url(r'inetnum/get-subnet/$', api_views.getSubnet, name='inetnum-get-subnet'),
url(r'asblock/free-as/$', api_views.asblockFreeAS, name='asblock-free-as'),
url(r'asblock/free-subnet/$', api_views.freeSubnet, name='inetnum-free-subnet'),
url(r'inetnum/get-subnet/$', api_views.getSubnet, name='inetnum-get-subnet'),
url(r'domain/check/$', api_views.checkDomain, name='domain-check'),
url(r'rzone/check/$', api_views.checkRzone, name='reversezone-check'),
url(r'domain/check/$', api_views.checkDomain, name='domain-check'),
url(r'rzone/check/$', api_views.checkRzone, name='reversezone-check'),
url(r'roa/$', api_views.getROA, name='get-roa'),
url(r'roa/$', api_views.getROA, name='get-roa'),
]

@ -19,219 +19,219 @@ import ipaddress
@login_required
def asblockFreeAS(request):
ret = {
"success": False,
"errorMsg": None,
"number": -1,
}
try:
blockName = request.GET.get('block', None)
if not blockName:
raise ValidationError("No block given")
try:
mnts = request.user.maintainer_set.all()
block = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=blockName)
if block.asblock_set.count() > 0:
raise ValidationError("AS Block already has sub AS Blocks")
if block.asnumber_set.count() > 0:
num = block.asnumber_set.order_by("-number")[0].number + 1
if num > block.asEnd:
num = None
for n in range(block.asBegin, block.asEnd + 1):
try:
ASNumber.objects.get(number=n)
except ASNumber.DoesNotExist:
num = n
break
if not num:
raise ValidationError("No free AS Number in block")
ret["number"] = num
else:
ret["number"] = block.asBegin
except ASBlock.DoesNotExist:
raise ValidationError("Could not get AS Block")
ret["success"] = True
except ValidationError as e:
ret["errorMsg"] = e.message
return JsonResponse(ret)
ret = {
"success": False,
"errorMsg": None,
"number": -1,
}
try:
blockName = request.GET.get('block', None)
if not blockName:
raise ValidationError("No block given")
try:
mnts = request.user.maintainer_set.all()
block = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=blockName)
if block.asblock_set.count() > 0:
raise ValidationError("AS Block already has sub AS Blocks")
if block.asnumber_set.count() > 0:
num = block.asnumber_set.order_by("-number")[0].number + 1
if num > block.asEnd:
num = None
for n in range(block.asBegin, block.asEnd + 1):
try:
ASNumber.objects.get(number=n)
except ASNumber.DoesNotExist:
num = n
break
if not num:
raise ValidationError("No free AS Number in block")
ret["number"] = num
else:
ret["number"] = block.asBegin
except ASBlock.DoesNotExist:
raise ValidationError("Could not get AS Block")
ret["success"] = True
except ValidationError as e:
ret["errorMsg"] = e.message
return JsonResponse(ret)
@login_required
def freeSubnet(request):
ret = {
"success": False,
"errorMsg": None,
"network": None,
}
try:
parentRangeName = request.GET.get('parentRange', None)
if not parentRangeName:
raise ValidationError("No subnet given")
parentRange = None
try:
mnts = request.user.maintainer_set.all()
parentRange = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=parentRangeName)
except InetNum.DoesNotExist:
raise ValidationError("Parent range does not exist / is not maintained by you")
prefixLen = 0
try:
prefixLen = request.GET.get("prefixLen", None)
if not prefixLen:
if parentRange.protocol == InetNum.IPv4:
prefixLen = 27
else:
prefixLen = 60
prefixLen = int(prefixLen)
if prefixLen < 8 or \
(parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \
(parentRange.protocol == InetNum.IPv6 and prefixLen > 128):
raise ValidationError("Given prefix length is out of range")
except ValueError:
raise ValidationError("PrefixLen is not a number")
usableNet = None
# FIXME: use first biggest usable netblock...
#biggestNet = parentRange.inetnum_set.order_by("-address")
#if biggestNet
# candidateNet =
# and (biggestNet.getNetwork().broadcast_address.:
# try using next network in range
# ordering does not work, as order_by sorts alphabetically
# ==> the set is short, we can iterate through all. no sense in unpacking the SQL magic
#biggestNets = parentRange.inetnum_set.order_by("-address")
biggestNet = None
for ipRange in parentRange.inetnum_set.all():
if not biggestNet or ipRange.getNetwork() > biggestNet:
biggestNet = ipRange.getNetwork()
if biggestNet:
candidateNet = ipaddress.ip_network("%s/%s" % (biggestNet.broadcast_address + 1, biggestNet.prefixlen))
print("biggest net", biggestNet, "candidate", candidateNet)
if candidateNet.network_address in parentRange.getNetwork():
usableNet = candidateNet
# check if there are still networks left in range
if not usableNet:
# search for free network
nets = list(parentRange.getNetwork().subnets())
for subRange in parentRange.inetnum_set.all():
newNet = None
for net in nets:
if subRange.getNetwork().network_address in net:
newNet = net
if not newNet:
# critical error, we want a 500 here
raise ValueError("Subnet not in range")
nets.remove(newNet)
nets.extend(newNet.address_exclude(subRange.getNetwork()))
nets = sorted(nets)
for net in nets:
if net.prefixlen <= prefixLen:
usableNet = net
break
if not usableNet:
raise ValidationError("No space left in given range")
ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen)
ret["success"] = True
except ValidationError as e:
ret["errorMsg"] = e.message
return JsonResponse(ret)
ret = {
"success": False,
"errorMsg": None,
"network": None,
}
try:
parentRangeName = request.GET.get('parentRange', None)
if not parentRangeName:
raise ValidationError("No subnet given")
parentRange = None
try:
mnts = request.user.maintainer_set.all()
parentRange = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=parentRangeName)
except InetNum.DoesNotExist:
raise ValidationError("Parent range does not exist / is not maintained by you")
prefixLen = 0
try:
prefixLen = request.GET.get("prefixLen", None)
if not prefixLen:
if parentRange.protocol == InetNum.IPv4:
prefixLen = 27
else:
prefixLen = 60
prefixLen = int(prefixLen)
if prefixLen < 8 or \
(parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \
(parentRange.protocol == InetNum.IPv6 and prefixLen > 128):
raise ValidationError("Given prefix length is out of range")
except ValueError:
raise ValidationError("PrefixLen is not a number")
usableNet = None
# FIXME: use first biggest usable netblock...
#biggestNet = parentRange.inetnum_set.order_by("-address")
#if biggestNet
# candidateNet =
# and (biggestNet.getNetwork().broadcast_address.:
# try using next network in range
# ordering does not work, as order_by sorts alphabetically
# ==> the set is short, we can iterate through all. no sense in unpacking the SQL magic
#biggestNets = parentRange.inetnum_set.order_by("-address")
biggestNet = None
for ipRange in parentRange.inetnum_set.all():
if not biggestNet or ipRange.getNetwork() > biggestNet:
biggestNet = ipRange.getNetwork()
if biggestNet:
candidateNet = ipaddress.ip_network("%s/%s" % (biggestNet.broadcast_address + 1, biggestNet.prefixlen))
print("biggest net", biggestNet, "candidate", candidateNet)
if candidateNet.network_address in parentRange.getNetwork():
usableNet = candidateNet
# check if there are still networks left in range
if not usableNet:
# search for free network
nets = list(parentRange.getNetwork().subnets())
for subRange in parentRange.inetnum_set.all():
newNet = None
for net in nets:
if subRange.getNetwork().network_address in net:
newNet = net
if not newNet:
# critical error, we want a 500 here
raise ValueError("Subnet not in range")
nets.remove(newNet)
nets.extend(newNet.address_exclude(subRange.getNetwork()))
nets = sorted(nets)
for net in nets:
if net.prefixlen <= prefixLen:
usableNet = net
break
if not usableNet:
raise ValidationError("No space left in given range")
ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen)
ret["success"] = True
except ValidationError as e:
ret["errorMsg"] = e.message
return JsonResponse(ret)
@login_required
def getSubnet(request):
ret = {
"success": False,
"errorMsg": None,
"network": None,
}
ret = {
"success": False,
"errorMsg": None,
"network": None,
}
try:
netName = request.GET.get('net', None)
mnts = request.user.maintainer_set.all()
nets = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
net = nets.get(handle=netName)
try:
netName = request.GET.get('net', None)
mnts = request.user.maintainer_set.all()
nets = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
net = nets.get(handle=netName)
ret["success"] = True
ret["network"] = net.prefix()
except InetNum.DoesNotExist:
ret["errorMsg"] = "Chosen network does not exist"
ret["success"] = True
ret["network"] = net.prefix()
except InetNum.DoesNotExist:
ret["errorMsg"] = "Chosen network does not exist"
return JsonResponse(ret)
return JsonResponse(ret)
@login_required
def checkDomain(request):
ret = {
"success": False,
"errorMsg": None,
"domain": None,
"result": None,
}
ret = {
"success": False,
"errorMsg": None,
"domain": None,
"result": None,
}
try:
domainName = Domain.fixName(request.GET.get('domain', ''))
domain = Domain.objects.get(name=domainName)
#if not domain.canEdit(request.user):
# raise Domain.DoesNotExist()
try:
domainName = Domain.fixName(request.GET.get('domain', ''))
domain = Domain.objects.get(name=domainName)
#if not domain.canEdit(request.user):
# raise Domain.DoesNotExist()
ret["success"] = True
ret["domain"] = domain.name
# FIXME: change this if we ever have more than one...
ret["result"] = helperCheckDomain(domain.name, TLD_NAMESERVERS[0], domain.nameservers.all())
except Domain.DoesNotExist:
ret["errorMsg"] = "Domain does not exist"
ret["success"] = True
ret["domain"] = domain.name
# FIXME: change this if we ever have more than one...
ret["result"] = helperCheckDomain(domain.name, TLD_NAMESERVERS[0], domain.nameservers.all())
except Domain.DoesNotExist:
ret["errorMsg"] = "Domain does not exist"
return JsonResponse(ret)
return JsonResponse(ret)
@login_required
def checkRzone(request):
ret = {
"success": False,
"errorMsg": None,
"domain": None,
"result": None,
}
ret = {
"success": False,
"errorMsg": None,
"domain": None,
"result": None,
}
try:
rzonePk = int(request.GET.get('domain', ''))
rzone = ReverseZone.objects.get(pk=rzonePk)
#if not rzone.canEdit(request.user):
# raise ReverseZone.DoesNotExist()
try:
rzonePk = int(request.GET.get('domain', ''))
rzone = ReverseZone.objects.get(pk=rzonePk)
#if not rzone.canEdit(request.user):
# raise ReverseZone.DoesNotExist()
ret["success"] = True
# FIXME: change this if we ever have more than one...
ret["result"] = helperCheckDomain(rzone.getZone(), TLD_NAMESERVERS[0], rzone.nameservers.all())
except (ReverseZone.DoesNotExist, ValueError):
ret["errorMsg"] = "ReverseZone does not exist"
ret["success"] = True
# FIXME: change this if we ever have more than one...
ret["result"] = helperCheckDomain(rzone.getZone(), TLD_NAMESERVERS[0], rzone.nameservers.all())
except (ReverseZone.DoesNotExist, ValueError):
ret["errorMsg"] = "ReverseZone does not exist"
return JsonResponse(ret)
return JsonResponse(ret)
def getROA(request):
roa = {}
for asn in ASNumber.objects.all():
nets = []
for net in asn.inetnum_set.all():
nets.append(net.prefix())
roa = {}
for asn in ASNumber.objects.all():
nets = []
for net in asn.inetnum_set.all():
nets.append(net.prefix())
if nets:
roa[asn.number] = nets
if nets:
roa[asn.number] = nets
return JsonResponse(roa)
return JsonResponse(roa)

@ -25,179 +25,181 @@ __VERSION__ = '0.1'
def _parser():
parser = argparse.ArgumentParser(
#prog='foo',
#description='do some awesome foo',
)
parser = argparse.ArgumentParser()
parser.add_argument("--pdns-host", default="127.0.0.1", help="PDNS host")
parser.add_argument("--pdns-port", default=8081, help="PDNS port")
parser.add_argument("-c", "--config", default=None, type=argparse.FileType("r"), help="Path to config file (default path: ./dns-sync.conf, /etc/dns-sync.conf)")
parser.add_argument("--api-key", default=None, help="PDNS API key")
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
parser.add_argument("--pdns-host", default="127.0.0.1", help="PDNS host")
parser.add_argument("--pdns-port", default=8081, help="PDNS port")
parser.add_argument("-c", "--config", default=None, type=argparse.FileType("r"), help="Path to config file (default path: ./dns-sync.conf, /etc/dns-sync.conf)")
parser.add_argument("--api-key", default=None, help="PDNS API key")
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
return parser
return parser
def mergeDomains(zoneData, pdnsData):
rrAdd = []
rrData = pdnsData['rrsets']
for domain, rrType, records in zoneData:
found = False
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
if len(pdnsDom) > 0:
rrSet = set(_x['content'] for _x in pdnsDom[0]['records'])
if rrSet == set(records):
found = True
if not found:
# new domain!
rrAdd.append({
"name": domain,
"type": rrType,
"ttl": 60*60,
"changetype": "REPLACE",
"records": [{"content": record, "disabled": False} for record in records],
})
return rrAdd
rrAdd = []
rrData = pdnsData['rrsets']
for domain, rrType, records in zoneData:
found = False
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
if len(pdnsDom) > 0:
rrSet = set(_x['content'].lower() for _x in pdnsDom[0]['records'])
if rrSet == set(record.lower() for record in records):
found = True
if not found:
# new domain!
rrAdd.append({
"name": domain,
"type": rrType,
"ttl": 60*60,
"changetype": "REPLACE",
"records": [{"content": record, "disabled": False} for record in records],
})
return rrAdd
def removeOldDomains(zoneData, pdnsData):
rrDel = []
#print("zone data", zoneData)
#print("pdnsData", pdnsData)
for entry in pdnsData['rrsets']:
# search for name/type in domain dict. if non-existtant mark for deletion
# this could be much more efficient with a dict! name: [rrset...]
if not any(entry['name'] == _x[0] and entry['type'] == _x[1] for _x in zoneData):
rrDel.append({
"changetype": "DELETE",
"name": entry["name"],
"type": entry["type"],
})
return rrDel
rrDel = []
#print("zone data", zoneData)
#print("pdnsData", pdnsData)
for entry in pdnsData['rrsets']:
# search for name/type in domain dict. if non-existtant mark for deletion
# this could be much more efficient with a dict! name: [rrset...]
if not any(entry['name'] == _x[0] and entry['type'] == _x[1] for _x in zoneData):
rrDel.append({
"changetype": "DELETE",
"name": entry["name"],
"type": entry["type"],
})
return rrDel
def handleNameserver(ns, servers, usedNameservers, domains):
servers.append(ns.name)
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
usedNameservers.append(ns.name)
if ns.glueIPv4:
domains.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
usedNameservers.append(ns.name)
if ns.glueIPv4:
domains.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers, v4reverse=False):
for domain in qs:
servers = []
for ns in domain.nameservers.all():
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
usedNameservers.append(ns.name)
if ns.glueIPv4:
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
zone.append((domain.getZone(), "NS", servers))
if v4reverse:
# for ipv4 reverse we have to do some extra work in case of classless delegations
# see RFC2317
net = domain.parentNet.getNetwork()
if net.prefixlen % 8 != 0:
revZone = domain.getZone()
parts = str(net.network_address).split(".")
baseZone = ".".join(reversed(parts[:net.prefixlen // 8])) + ".in-addr.arpa."
startNo = int(parts[net.prefixlen // 8])
lenExp = 8 - (net.prefixlen % 8)
for i in range(2 ** lenExp):
no = startNo + i
zone.append(("%d.%s" % (no, baseZone), "CNAME", ["%d.%s" % (no, revZone)]))
for domain in qs:
servers = []
for ns in domain.nameservers.all():
servers.append(ns.name)
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
usedNameservers.append(ns.name)
if ns.glueIPv4:
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
if ns.glueIPv6:
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
zone.append((domain.getZone(), "NS", servers))
if domain.ds_records:
zone.append((domain.getZone(), "DS", domain.ds_records.split("\n")))
if v4reverse:
# for ipv4 reverse we have to do some extra work in case of classless delegations
# see RFC2317
net = domain.parentNet.getNetwork()
if net.prefixlen % 8 != 0:
revZone = domain.getZone()
parts = str(net.network_address).split(".")
baseZone = ".".join(reversed(parts[:net.prefixlen // 8])) + ".in-addr.arpa."
startNo = int(parts[net.prefixlen // 8])
lenExp = 8 - (net.prefixlen % 8)
for i in range(2 ** lenExp):
no = startNo + i
zone.append(("%d.%s" % (no, baseZone), "CNAME", ["%d.%s" % (no, revZone)]))
def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
url = "http://%s:%s/api/v1/servers/localhost/zones/%s" % (args.pdns_host, args.pdns_port, zone,)
pdnsData = s.get(url).json()
url = "http://%s:%s/api/v1/servers/localhost/zones/%s" % (args.pdns_host, args.pdns_port, zone,)
pdnsData = s.get(url).json()
baseProtectedRecords = [
(zone, "NS", []),
(zone, "SOA", []),
]
baseProtectedRecords = [
(zone, "NS", []),
(zone, "SOA", []),
]
# add dn. (NS + glue Nameservers)
newDomains = mergeDomains(zoneData, pdnsData)
print("Add/replace", newDomains)
# add dn. (NS + glue Nameservers)
newDomains = mergeDomains(zoneData, pdnsData)
print("Add/replace", newDomains)
if len(newDomains) > 0:
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
if len(newDomains) > 0:
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
delDomains = removeOldDomains(zoneData + protectedRecords + baseProtectedRecords, pdnsData)
print("Del", delDomains)
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
delDomains = removeOldDomains(zoneData + protectedRecords + baseProtectedRecords, pdnsData)
print("Del", delDomains)
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
if r.status_code != 204:
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
def main():
parser = _parser()
args = parser.parse_args()
config = configparser.ConfigParser()
if args.config:
config.read_file(args.config)
else:
config.read([os.path.join(os.path.abspath(__file__), "dns-sync.conf"), "/etc/dns-sync.conf"])
#print(config)
#print(config.get("DEFAULT", "api-key"))
#print(config.has_section("DEFAULT"), config.has_option("DEFAULT", "api-key"))
if args.api_key:
config["DEFAULT"]["api-key"] = args.api_key
if not config.has_option("DEFAULT", "api-key"):
print("Error: Could not find api-key (not present in config under [DEFAULT]; not given via command line)", file=sys.stderr)
sys.exit(2)
s = requests.Session()
s.headers = {
'X-API-Key': config.get("DEFAULT", "api-key"),
'Accept': 'application/json'
}
domains = []
rzone4 = []
rzone6 = []
usedNameservers = []
# assenble domain data
# dn.
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
getDomainsFromQueryset(qs, domains, domains, usedNameservers)
# reverse zones
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers, v4reverse=True)
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
#print("dn.", domains)
#print("v4", rzone4)
#print("v6", rzone6)
mergeDomainsWithPdns(s, args, "dn.", domains)
mergeDomainsWithPdns(s, args, "10.in-addr.arpa.", rzone4)
mergeDomainsWithPdns(s, args, "3.2.7.c.3.a.d.f.ip6.arpa.", rzone6)
parser = _parser()
args = parser.parse_args()
config = configparser.ConfigParser()
if args.config:
config.read_file(args.config)
else:
config.read([os.path.join(os.path.abspath(__file__), "dns-sync.conf"), "/etc/dns-sync.conf"])
#print(config)
#print(config.get("DEFAULT", "api-key"))
#print(config.has_section("DEFAULT"), config.has_option("DEFAULT", "api-key"))
if args.api_key:
config["DEFAULT"]["api-key"] = args.api_key
if not config.has_option("DEFAULT", "api-key"):
print("Error: Could not find api-key (not present in config under [DEFAULT]; not given via command line)", file=sys.stderr)
sys.exit(2)
s = requests.Session()
s.headers = {
'X-API-Key': config.get("DEFAULT", "api-key"),
'Accept': 'application/json'
}
domains = []
rzone4 = []
rzone6 = []
usedNameservers = []
# assenble domain data
# dn.
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
getDomainsFromQueryset(qs, domains, domains, usedNameservers)
# reverse zones
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers, v4reverse=True)
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
#print("dn.", domains)
#print("v4", rzone4)
#print("v6", rzone6)
mergeDomainsWithPdns(s, args, "dn.", domains)
mergeDomainsWithPdns(s, args, "10.in-addr.arpa.", rzone4)
mergeDomainsWithPdns(s, args, "3.2.7.c.3.a.d.f.ip6.arpa.", rzone6)
if __name__ == '__main__':
main()
main()

@ -24,107 +24,107 @@ from whoisdb.models import ASBlock, ASNumber, Contact, Maintainer, InetNum
__VERSION__ = '0.1'
def _parser():
parser = argparse.ArgumentParser(
#prog='foo',
#description='do some awesome foo',
)
parser = argparse.ArgumentParser(
#prog='foo',
#description='do some awesome foo',
)
#parser.add_argument("-p", "--port", default=2323, type=int, help="Your port")
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
parser.add_argument("-j", "--json", type=argparse.FileType('r'), required=True, help="Path to json file")
#parser.add_argument("-p", "--port", default=2323, type=int, help="Your port")
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
parser.add_argument("-j", "--json", type=argparse.FileType('r'), required=True, help="Path to json file")
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
return parser
return parser
def main():
parser = _parser()
args = parser.parse_args()
defContact = Contact.objects.get(handle="UNKNOWN-DN")
defMnt = Maintainer.objects.get(handle="DARKNET-MNT")
blocks = [
ASBlock.objects.get(handle="TRA1-ASB"),
ASBlock.objects.get(handle="UAB1-ASB")
]
ranges = [
InetNum.objects.get(handle="TRA1-NET"),
InetNum.objects.get(handle="DEF4-NET"),
InetNum.objects.get(handle="DEF6-NET"),
InetNum.objects.get(handle="MISC6-NET"),
InetNum.objects.get(handle="LTRA1-NET"),
InetNum.objects.get(handle="MAIN4-NET"),
]
data = json.load(args.json)
print(data.keys())
for k, v in data["handles"].items():
print(k, v["person"])
for asn in data["as"]:
print(asn)
if ASNumber.objects.filter(number=asn["number"]).count() > 0:
continue
obj = ASNumber(number=asn["number"])
block = None
for block in blocks:
if obj.number >= block.asBegin and obj.number <= block.asEnd:
obj.asblock = block
break
else:
raise ValueError("AS %d does not fit a block" % asn["number"])
if len(asn['admin_c']) >= 1:
name = data["handles"][asn["admin_c"][0]]["person"]
obj.name = "Imported AS of %s" % name
obj.handle = ASNumber.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
else:
obj.name = "Imported AS without admin info"
obj.handle = ASNumber.genGenericHandle("Unknown Imported AS")
obj.description = "Object has been imported from old DB and has not yet been edited"
obj.save()
obj.mnt_by.add(defMnt)
obj.admin_c.add(defContact)
obj.save()
for net in data["network"]:
print(net)
network = ipaddress.ip_network(net["prefix"])
if InetNum.objects.filter(address=str(network.network_address), netmask=network.prefixlen).count() > 0:
continue
origin = None
if net["origin"]:
origin = ASNumber.objects.get(number=net["origin"])
obj = InetNum(address=str(network.network_address), netmask=network.prefixlen)
obj.protocol = InetNum.IPv4 if network.version == 4 else InetNum.IPv6
x = list(filter(lambda _x: _x['number'] == net["origin"], data["as"]))
if len(x) > 0 and x[0]["admin_c"]:
name = data["handles"][x[0]["admin_c"][0]]["person"]
obj.name = "Imported Network of %s" % name
obj.handle = InetNum.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
else:
obj.name = "Imported Network without admin info"
obj.handle = InetNum.genGenericHandle("Unknown Imported Network")
obj.description = "Object has been imported from old DB and has not yet been edited"
for r in ranges:
if network.network_address in r.getNetwork():
obj.parent_range = r
break
else:
raise ValueError("%s did not fit in any netblock" % network)
obj.save()
obj.mnt_by.add(defMnt)
obj.admin_c.add(defContact)
if origin:
obj.origin_as.add(origin)
obj.save()
parser = _parser()
args = parser.parse_args()
defContact = Contact.objects.get(handle="UNKNOWN-DN")
defMnt = Maintainer.objects.get(handle="DARKNET-MNT")
blocks = [
ASBlock.objects.get(handle="TRA1-ASB"),
ASBlock.objects.get(handle="UAB1-ASB")
]
ranges = [
InetNum.objects.get(handle="TRA1-NET"),
InetNum.objects.get(handle="DEF4-NET"),
InetNum.objects.get(handle="DEF6-NET"),
InetNum.objects.get(handle="MISC6-NET"),
InetNum.objects.get(handle="LTRA1-NET"),
InetNum.objects.get(handle="MAIN4-NET"),
]
data = json.load(args.json)
print(data.keys())
for k, v in data["handles"].items():
print(k, v["person"])
for asn in data["as"]:
print(asn)
if ASNumber.objects.filter(number=asn["number"]).count() > 0:
continue
obj = ASNumber(number=asn["number"])
block = None
for block in blocks:
if obj.number >= block.asBegin and obj.number <= block.asEnd:
obj.asblock = block
break
else:
raise ValueError("AS %d does not fit a block" % asn["number"])
if len(asn['admin_c']) >= 1:
name = data["handles"][asn["admin_c"][0]]["person"]
obj.name = "Imported AS of %s" % name
obj.handle = ASNumber.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
else:
obj.name = "Imported AS without admin info"
obj.handle = ASNumber.genGenericHandle("Unknown Imported AS")
obj.description = "Object has been imported from old DB and has not yet been edited"
obj.save()
obj.mnt_by.add(defMnt)
obj.admin_c.add(defContact)
obj.save()
for net in data["network"]:
print(net)
network = ipaddress.ip_network(net["prefix"])
if InetNum.objects.filter(address=str(network.network_address), netmask=network.prefixlen).count() > 0:
continue
origin = None
if net["origin"]:
origin = ASNumber.objects.get(number=net["origin"])
obj = InetNum(address=str(network.network_address), netmask=network.prefixlen)
obj.protocol = InetNum.IPv4 if network.version == 4 else InetNum.IPv6
x = list(filter(lambda _x: _x['number'] == net["origin"], data["as"]))
if len(x) > 0 and x[0]["admin_c"]:
name = data["handles"][x[0]["admin_c"][0]]["person"]
obj.name = "Imported Network of %s" % name
obj.handle = InetNum.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
else:
obj.name = "Imported Network without admin info"
obj.handle = InetNum.genGenericHandle("Unknown Imported Network")
obj.description = "Object has been imported from old DB and has not yet been edited"
for r in ranges:
if network.network_address in r.getNetwork():
obj.parent_range = r
break
else:
raise ValueError("%s did not fit in any netblock" % network)
obj.save()
obj.mnt_by.add(defMnt)
obj.admin_c.add(defContact)
if origin:
obj.origin_as.add(origin)
obj.save()
if __name__ == '__main__':
main()
main()

@ -12,11 +12,11 @@ import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
files = [
("templates/help/faq.md", "templates/help/faq.html"),
("templates/help/faq.md", "templates/help/faq.html"),
]
for srcFile, dstFile in files:
srcFile = os.path.join(BASE_DIR, srcFile)
dstFile = os.path.join(BASE_DIR, dstFile)
markdown.markdownFromFile(open(srcFile, "rb"), open(dstFile, "wb"), extensions=[TocExtension(baselevel=1, permalink=True)])
srcFile = os.path.join(BASE_DIR, srcFile)
dstFile = os.path.join(BASE_DIR, dstFile)
markdown.markdownFromFile(open(srcFile, "rb"), open(dstFile, "wb"), extensions=[TocExtension(baselevel=1, permalink=True)])

@ -22,26 +22,26 @@ from whoisdb.models import ASNumber
__VERSION__ = '0.1'
def _parser():
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser()
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
return parser
return parser
def main():
parser = _parser()
parser.parse_args()
parser = _parser()
parser.parse_args()
roa = {}
for asn in ASNumber.objects.all():
nets = []
for net in asn.inetnum_set.all():
nets.append(net.prefix())
roa = {}
for asn in ASNumber.objects.all():
nets = []
for net in asn.inetnum_set.all():
nets.append(net.prefix())
if nets:
roa[asn.number] = nets
if nets:
roa[asn.number] = nets
print(json.dumps(roa))
print(json.dumps(roa))
if __name__ == '__main__':
main()
main()

@ -24,84 +24,84 @@ log = logging.getLogger("whoisd")
__VERSION__ = '0.1'
class WhoisHandler(socketserver.BaseRequestHandler):
header = "% This is the DARKNET database query service.\n" \
"% The objects should be in something like RPSL format.\n" \
"%\n" \
"% The DARKNET database is subject to terms and conditions.\n" \
"% Mostly these are \"be nice\" and \"don't knowingly break things\".\n" \
"\n"
def handle(self):
self.request.sendall(self.header.encode())
line = self.request.recv(1024)
line = line.split(b"\n", 2)[0].strip()
print("Request object is %s" % line)
log.info("Request by %s for %s" % (self.request.getpeername()[0], line))
self.request.send(b"\n")
objs = findInDatabase(line.decode())
if len(objs) > 0:
self.request.sendall(("%% %d result%s\n" % (len(objs), "" if len(objs)==1 else "s")).encode())
for obj in objs:
self.sendObject(obj)
else:
self.request.sendall(b"%% NOT FOUND\n\n")
def sendObject(self, obj):
result = [
"",
"%% Object %s (%s)" % (obj, obj.getClassName()),
""
]
for field, value in getWhoisObjectFields(obj, False):
fieldName = field.lower().replace(" ", "-") + ":"
if not value:
value = ""
if hasattr(value, "through"):
for v in value.all():
result.append("%-16s %s" % (fieldName, v))
else:
result.append("%-16s %s" % (fieldName, value))
result.extend(["", ""])
self.request.sendall("\n".join(result).encode())
header = "% This is the DARKNET database query service.\n" \
"% The objects should be in something like RPSL format.\n" \
"%\n" \
"% The DARKNET database is subject to terms and conditions.\n" \
"% Mostly these are \"be nice\" and \"don't knowingly break things\".\n" \
"\n"
def handle(self):
self.request.sendall(self.header.encode())
line = self.request.recv(1024)
line = line.split(b"\n", 2)[0].strip()
print("Request object is %s" % line)
log.info("Request by %s for %s" % (self.request.getpeername()[0], line))
self.request.send(b"\n")
objs = findInDatabase(line.decode())
if len(objs) > 0:
self.request.sendall(("%% %d result%s\n" % (len(objs), "" if len(objs)==1 else "s")).encode())
for obj in objs:
self.sendObject(obj)
else:
self.request.sendall(b"%% NOT FOUND\n\n")
def sendObject(self, obj):
result = [
"",
"%% Object %s (%s)" % (obj, obj.getClassName()),
""
]
for field, value in getWhoisObjectFields(obj, False):
fieldName = field.lower().replace(" ", "-") + ":"
if not value:
value = ""
if hasattr(value, "through"):
for v in value.all():
result.append("%-16s %s" % (fieldName, v))
else:
result.append("%-16s %s" % (fieldName, value))
result.extend(["", ""])
self.request.sendall("\n".join(result).encode())
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True
allow_reuse_address = True
def _parser():
parser = argparse.ArgumentParser(
#prog='foo',
#description='do some awesome foo',
)
parser = argparse.ArgumentParser(
#prog='foo',
#description='do some awesome foo',
)
parser.add_argument("-p", "--port", default=43, type=int, help="whoisd port")
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
parser.add_argument("-p", "--port", default=43, type=int, help="whoisd port")
#parser.add_argument("-v", "--verbose", default=False, action="store_true", help="Be more verbose")
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
parser.add_argument("--version", action="version", version="%(prog)s " + __VERSION__)
return parser
return parser
def main():
parser = _parser()
args = parser.parse_args()
parser = _parser()
args = parser.parse_args()
server = ThreadedTCPServer(('', args.port), WhoisHandler)
server = ThreadedTCPServer(('', args.port), WhoisHandler)
while True:
try:
server.serve_forever()
except select.error as e:
log.exception(e)
except KeyboardInterrupt:
log.info("^c hit, quitting.")
break
while True:
try:
server.serve_forever()
except select.error as e:
log.exception(e)
except KeyboardInterrupt:
log.info("^c hit, quitting.")
break
server.server_close()
server.server_close()
if __name__ == '__main__':
main()
main()

@ -7,6 +7,6 @@ from .models import User
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ("username",)
class Meta:
model = User
fields = ("username",)

@ -7,4 +7,4 @@ from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
pass

@ -8,10 +8,10 @@ from django.contrib.auth import views as auth_views
from . import views as dncore_views
urlpatterns = [
url(r'^$', dncore_views.dashboard, name='dashboard'),
url(r'^$', dncore_views.dashboard, name='dashboard'),
url(r'^login/$', auth_views.login, name='login'),
url(r'^register/$', dncore_views.RegisterUser.as_view(), name='register'),
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
url(r'^profile/$', dncore_views.profile, name='profile'),
url(r'^login/$', auth_views.login, name='login'),
url(r'^register/$', dncore_views.RegisterUser.as_view(), name='register'),
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
url(r'^profile/$', dncore_views.profile, name='profile'),
]

@ -22,54 +22,54 @@ from .forms import CustomUserCreationForm
@login_required
def profile(request):
pwForm = None
pwForm = None
if request.method == "POST":
if request.POST.get("submit", None) == "pwchange":
pwForm = PasswordChangeForm(user=request.user, data=request.POST)
if pwForm.is_valid():
pwForm.save()
auth_login(request, pwForm.user)
messages.success(request, "Password changed")
if request.method == "POST":
if request.POST.get("submit", None) == "pwchange":
pwForm = PasswordChangeForm(user=request.user, data=request.POST)
if pwForm.is_valid():
pwForm.save()
auth_login(request, pwForm.user)
messages.success(request, "Password changed")
return HttpResponseRedirect(reverse("user:profile"))
return HttpResponseRedirect(reverse("user:profile"))
if not pwForm:
pwForm = PasswordChangeForm(user=request.user)
if not pwForm:
pwForm = PasswordChangeForm(user=request.user)
return render(request, "registration/profile.html", {'pwForm': pwForm})
return render(request, "registration/profile.html", {'pwForm': pwForm})
@login_required
def dashboard(request):
mnts = request.user.maintainer_set.all()
ownMnts = request.user.maintainer_set.filter(rir=False, lir=False).all().distinct()
# if account only has rir/lir objects, show them
if ownMnts.count() == 0:
ownMnts = mnts
mnts = request.user.maintainer_set.all()
ownMnts = request.user.maintainer_set.filter(rir=False, lir=False).all().distinct()
# if account only has rir/lir objects, show them
if ownMnts.count() == 0:
ownMnts = mnts
asns = ASNumber.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).distinct()
inetnums = InetNum.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).distinct()
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
rrequests = Request.objects.filter((Q(provider__in=mnts) | Q(applicant__in=mnts)) & Q(status=Request.STATE_OPEN)).distinct()
asns = ASNumber.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).distinct()
inetnums = InetNum.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).distinct()
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
rrequests = Request.objects.filter((Q(provider__in=mnts) | Q(applicant__in=mnts)) & Q(status=Request.STATE_OPEN)).distinct()
return render(request, "dncore/dashboard.html", {"asns": asns, "inetnums": inetnums, "domains": domains, 'rrequests': rrequests})
return render(request, "dncore/dashboard.html", {"asns": asns, "inetnums": inetnums, "domains": domains, 'rrequests': rrequests})
def index(request):
if request.user.is_authenticated():
return HttpResponseRedirect(reverse("dashboard"))
if request.user.is_authenticated():
return HttpResponseRedirect(reverse("dashboard"))
return render(request, "index.html", {})
return render(request, "index.html", {})
class RegisterUser(CreateView):
template_name = "dncore/registration.html"
form_class = CustomUserCreationForm
success_url = reverse_lazy("user:login")
template_name = "dncore/registration.html"
form_class = CustomUserCreationForm
success_url = reverse_lazy("user:login")
def form_valid(self, form):
ret = super(RegisterUser, self).form_valid(form)
messages.success(self.request, "You successfully registered as user %s and can now log in!" % form.instance.username)
def form_valid(self, form):
ret = super(RegisterUser, self).form_valid(form)
messages.success(self.request, "You successfully registered as user %s and can now log in!" % form.instance.username)
return ret
return ret

@ -21,7 +21,7 @@ from django.contrib import messages
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TLD_NAMESERVERS = [
'10.100.100.100',
'10.100.100.100',
]
DATETIME_FORMAT = "Y-m-d H:i:s"
@ -42,47 +42,47 @@ ALLOWED_HOSTS = ["*"]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'formtools',
'dncore',
'whoisdb',
'rrequests',
'domains',
'api',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'formtools',
'dncore',
'whoisdb',
'rrequests',
'domains',
'api',
]
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'
@ -92,10 +92,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'),
}
}
@ -103,18 +103,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',
},
]
@ -139,11 +139,11 @@ 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'

@ -30,15 +30,15 @@ import api.urls
urlpatterns = [
url(r'^$', dncore.views.index, name='index'),
url(r'^dashboard/$', dncore.views.dashboard, name='dashboard'),
url(r'^$', dncore.views.index, name='index'),
url(r'^dashboard/$', dncore.views.dashboard, name='dashboard'),
url(r'^admin/', admin.site.urls),
url(r'^user/', include(dncore.urls, namespace='user')),
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
url(r'^domains/', include(domains.urls, namespace='domains')),
url(r'^api/', include(api.urls, namespace='api')),
url(r'^user/', include(dncore.urls, namespace='user')),
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
url(r'^domains/', include(domains.urls, namespace='domains')),
url(r'^api/', include(api.urls, namespace='api')),
url(r'^help/$', TemplateView.as_view(template_name='help/help.html'), name='help'),
url(r'^help/$', TemplateView.as_view(template_name='help/help.html'), name='help'),
]

@ -15,229 +15,260 @@ import re
import ipaddress
class DomainForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
class Meta:
model = Domain
fields = ['name', 'nameservers', 'mnt_by', 'admin_c']
class DSRecordMixin(object):
ds_re = re.compile(r"^(?P<id>\d+)\s+(?P<crypto>\d+)\s+(?P<hashtype>\d+)\s+(?P<hash>[0-9a-fA-F]+)$")
HASH_SUPPORTED = (1, 2)
CRYPTO_SUPPORTED = (3, 5, 6, 8, 10, 13, 15)
def __init__(self, *args, **kwargs):
super(DomainForm, self).__init__(*args, **kwargs)
def clean_ds_records(self):
ds_records = self.cleaned_data['ds_records'].strip()
result = []
mnts = self._user.maintainer_set.all()
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
if not ds_records:
return ''
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
for n, rec in enumerate(ds_records.split("\n"), 1):
rec = rec.strip()
m = self.ds_re.match(rec)
if not m:
raise forms.ValidationError("Could not parse records {} - needs to be in format "
"'<id> <crypto> <hashtype> <hash>'".format(n))
if not self._create:
self.fields['name'].disabled = True
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
if int(m.group('hashtype')) not in self.HASH_SUPPORTED:
raise forms.ValidationError("Record {} has an invalid hashtype of {}, supported are {}"
"".format(n, m.group('hashtype'), " ".join(map(str, self.HASH_SUPPORTED))))
if int(m.group('crypto')) not in self.CRYPTO_SUPPORTED:
raise forms.ValidationError("Record {} has unsupported crypto {}, supported are {}"
"".format(n, m.group('crypto'), " ".join(map(str, self.CRYPTO_SUPPORTED))))
self.fields['nameservers'].queryset = self.fields['nameservers'].queryset.distinct()
result.append("{id} {crypto} {hashtype} {hash}".format(**m.groupdict()))
def clean_name(self):
name = self.cleaned_data['name'].lower()
if self._create:
if not name.endswith("."):
name += "."
return "\n".join(result)
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")
class DomainForm(MntFormMixin, WhoisObjectFormMixin, DSRecordMixin, forms.ModelForm):
class Meta:
model = Domain
fields = ['name', 'nameservers', 'mnt_by', 'admin_c', 'ds_records']
if not re.match("^[a-z0-9.-]+$", name):
raise forms.ValidationError("Only a-z, 0-9 and - are allowed inside the domain name")
def __init__(self, *args, **kwargs):
super(DomainForm, self).__init__(*args, **kwargs)
try:
Domain.objects.get(name=name)
raise forms.ValidationError("Domain already exists")
except Domain.DoesNotExist:
pass
mnts = self._user.maintainer_set.all()
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
return name
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
if not self._create:
self.fields['name'].disabled = True
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
self.fields['nameservers'].queryset = self.fields['nameservers'].queryset.distinct()
def clean_name(self):
name = self.cleaned_data['name'].lower()
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 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")
try:
Domain.objects.get(name=name)
raise forms.ValidationError("Domain already exists")
except Domain.DoesNotExist:
pass
return name
class NameserverForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
class Meta:
model = Nameserver
fields = ['name', 'glueIPv4', 'glueIPv6', 'mnt_by', 'admin_c']
help_texts = {
"glueIPv4": "Note: You can only set a glue record if the base domain of this nameserver belongs to you!"
}
def __init__(self, *args, **kwargs):
super(NameserverForm, self).__init__(*args, **kwargs)
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
def cleanNetwork(self, glue):
ip = ipaddress.ip_address(glue)
proto = InetNum.IPv4 if ip.version == 4 else InetNum.IPv6
nets = InetNum.objects.filter(parent_range=None, protocol=proto)
if len(nets) == 0:
raise forms.ValidationError("No range has been registered for IPv%s in the whois interface" % ip.version)
for net in nets:
if ip in net.getNetwork():
break
else:
raise forms.ValidationError("Glue record address is not inside DarkNet (subnet %s)" % ", ".join(map(lambda _x: _x.prefix(), nets)))
def clean_glueIPv4(self):
glue = self.cleaned_data['glueIPv4']
if glue:
self.cleanNetwork(glue)
return glue
def clean_glueIPv6(self):
glue = self.cleaned_data['glueIPv6']
class Meta:
model = Nameserver
fields = ['name', 'glueIPv4', 'glueIPv6', 'mnt_by', 'admin_c']
help_texts = {
"glueIPv4": "Note: You can only set a glue record if the base domain of this nameserver belongs to you!"
}
def __init__(self, *args, **kwargs):
super(NameserverForm, self).__init__(*args, **kwargs)
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
def cleanNetwork(self, glue):
ip = ipaddress.ip_address(glue)
proto = InetNum.IPv4 if ip.version == 4 else InetNum.IPv6
nets = InetNum.objects.filter(parent_range=None, protocol=proto)
if len(nets) == 0:
raise forms.ValidationError("No range has been registered for IPv%s in the whois interface" % ip.version)
for net in nets:
if ip in net.getNetwork():
break
else:
raise forms.ValidationError("Glue record address is not inside DarkNet (subnet %s)" % ", ".join(map(lambda _x: _x.prefix(), nets)))
def clean_glueIPv4(self):
glue = self.cleaned_data['glueIPv4']
if glue:
self.cleanNetwork(glue)
return glue
def clean_glueIPv6(self):
glue = self.cleaned_data['glueIPv6']
if glue:
self.cleanNetwork(glue)
if glue:
self.cleanNetwork(glue)
return glue
return glue
def clean_name(self):
name = self.cleaned_data['name'].lower().strip()
if not name.endswith("."):
name += "."
def clean_name(self):
name = self.cleaned_data['name'].lower().strip()
if not name.endswith("."):
name += "."
# allow name to stay if it did not change
if not self._create and self.instance.name == name:
return name
# allow name to stay if it did not change
if not self._create and self.instance.name == name:
return name
if name.count(".") <= 2:
raise forms.ValidationError("Nameserver must be inside a domain (e.g. ns1.noot.dn.)")
if name.count(".") <= 2:
raise forms.ValidationError("Nameserver must be inside a domain (e.g. ns1.noot.dn.)")
mnts = self._user.maintainer_set.all()
try:
obj = Nameserver.objects.get(name=name, mnt_by__in=mnts)
if self._create or not self._create and obj.pk != self.instance.pk:
raise forms.ValidationError("You already have a nameserver with this name under your control")
except Nameserver.DoesNotExist:
pass
except Nameserver.MultipleObjectsReturned:
pass
mnts = self._user.maintainer_set.all()
try:
obj = Nameserver.objects.get(name=name, mnt_by__in=mnts)
if self._create or not self._create and obj.pk != self.instance.pk:
raise forms.ValidationError("You already have a nameserver with this name under your control")
except Nameserver.DoesNotExist:
pass
except Nameserver.MultipleObjectsReturned:
pass
return name
return name
def clean(self):
cleaned_data = super(NameserverForm, self).clean()
def clean(self):
cleaned_data = super(NameserverForm, self).clean()
if not self.errors:
name = cleaned_data.get("name")
mntBy = cleaned_data.get("mnt_by")
zone = ".".join(name.split(".")[-3:])
ipv4 = cleaned_data.get("glueIPv4", None)
ipv6 = cleaned_data.get("glueIPv6", None)
if not self.errors:
name = cleaned_data.get("name")
mntBy = cleaned_data.get("mnt_by")
zone = ".".join(name.split(".")[-3:])
ipv4 = cleaned_data.get("glueIPv4", None)
ipv6 = cleaned_data.get("glueIPv6", None)
if not ipv4:
ipv4 = None
if not ipv6:
ipv6 = None
if not ipv4:
ipv4 = None
if not ipv6:
ipv6 = None
if self._create and (ipv4 or ipv6) or not self._create and not (self.instance.glueIPv4 == ipv4 and self.instance.glueIPv6 == ipv6):
mnts = self._user.maintainer_set.all()
domains = Domain.objects.filter(mnt_by__in=mnts)
found = False
for domain in domains:
if domain.name == zone:
found = True
break
if self._create and (ipv4 or ipv6) or not self._create and not (self.instance.glueIPv4 == ipv4 and self.instance.glueIPv6 == ipv6):
mnts = self._user.maintainer_set.all()
domains = Domain.objects.filter(mnt_by__in=mnts)
found = False
for domain in domains:
if domain.name == zone:
found = True
break
if not found:
raise forms.ValidationError("You have glue IPs set, but this domain is not under a domain you control.")
if not found:
raise forms.ValidationError("You have glue IPs set, but this domain is not under a domain you control.")
if ipv4 or ipv6:
try:
ns = Nameserver.objects.get(Q(name=name) & (Q(glueIPv4__isnull=False) | Q(glueIPv6__isnull=False)))
if self._create or ns.pk != self.instance.pk:
nsMnts = ", ".join(n.handle for n in ns.mnt_by.all())
if ipv4 or ipv6:
try:
ns = Nameserver.objects.get(Q(name=name) & (Q(glueIPv4__isnull=False) | Q(glueIPv6__isnull=False)))
if self._create or ns.pk != self.instance.pk:
nsMnts = ", ".join(n.handle for n in ns.mnt_by.all())
raise forms.ValidationError("Only one nameserver for this domain can have glue records and one already exists (maintained by %s)" % nsMnts)
except Nameserver.DoesNotExist:
pass
raise forms.ValidationError("Only one nameserver for this domain can have glue records and one already exists (maintained by %s)" % nsMnts)
except Nameserver.DoesNotExist:
pass
failedMnts = set()
for ns in Nameserver.objects.filter(name=name, mnt_by__in=mntBy):
if self._create or self.instance.pk != ns.pk:
for mnt in ns.mnt_by.all():
if mnt in mntBy:
failedMnts.add(mnt.handle)
failedMnts = set()
for ns in Nameserver.objects.filter(name=name, mnt_by__in=mntBy):
if self._create or self.instance.pk != ns.pk:
for mnt in ns.mnt_by.all():
if mnt in mntBy:
failedMnts.add(mnt.handle)
if len(failedMnts) > 0:
raise forms.ValidationError("The following maintainer objects already have this nameservers: %s" % ", ".join(failedMnts))
return cleaned_data
if len(failedMnts) > 0:
raise forms.ValidationError("The following maintainer objects already have this nameservers: %s" % ", ".join(failedMnts))
return cleaned_data
class ReverseZoneForm(forms.ModelForm):
prefix = forms.CharField(validators=[IP46CIDRValidator])
class ReverseZoneForm(DSRecordMixin, forms.ModelForm):
prefix = forms.CharField(validators=[IP46CIDRValidator])
class Meta:
model = ReverseZone
fields = ['parentNet', 'nameservers']
class Meta:
model = ReverseZone
fields = ['parentNet', 'nameservers']
help_texts = {
"prefix": "The prefix in CIDR form for which this object is responsible",
}
help_texts = {
"prefix": "The prefix in CIDR form for which this object is responsible",
}
def __init__(self, user, *args, **kwargs):
self._user = user
def __init__(self, user, *args, **kwargs):
self._user = user
super(ReverseZoneForm, self).__init__(*args, **kwargs)
super(ReverseZoneForm, self).__init__(*args, **kwargs)
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
instance = getattr(self, "instance", None)
self._create = not (instance and instance.pk)
mnts = self._user.maintainer_set.all()
self.fields['parentNet'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
mnts = self._user.maintainer_set.all()
self.fields['parentNet'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
if not self._create:
self.fields['prefix'].disabled = True
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
if not self._create:
self.fields['prefix'].disabled = True
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
self.fields['nameservers'].queryset = self.fields['nameservers'].queryset.distinct()
self.fields['nameservers'].queryset = self.fields['nameservers'].queryset.distinct()
def clean_prefix(self):
prefix = self.cleaned_data['prefix']
def clean_prefix(self):
prefix = self.cleaned_data['prefix']
net = ipaddress.ip_network(prefix)
if net.version == 6 and net.prefixlen % 4 != 0:
raise forms.ValidationError("IPv6 reverse zone prefix length has to be a multiple of 4")
net = ipaddress.ip_network(prefix)
if net.version == 6 and net.prefixlen % 4 != 0:
raise forms.ValidationError("IPv6 reverse zone prefix length has to be a multiple of 4")
return prefix
return prefix
def clean(self):
cleaned_data = super(ReverseZoneForm, self).clean()
def clean(self):
cleaned_data = super(ReverseZoneForm, self).clean()
if not self.errors:
if self._create:
net = ipaddress.ip_network(cleaned_data['prefix'])
parentNet = cleaned_data['parentNet'].getNetwork()
if not self.errors:
if self._create:
net = ipaddress.ip_network(cleaned_data['prefix'])
parentNet = cleaned_data['parentNet'].getNetwork()
if net.network_address not in parentNet:
raise forms.ValidationError("Given prefix %s is not inside of parent netblock %s" % (net, parentNet))
if net.network_address not in parentNet:
raise forms.ValidationError("Given prefix %s is not inside of parent netblock %s" % (net, parentNet))
# For now just check all the zones...
#zones = ReverseZone.objects.filter(parentNet=cleaned_data['parentNet'])
zones = ReverseZone.objects.all()
for zone in zones:
if net.network_address in zone.parentNet.getNetwork():
raise forms.ValidationError("Given prefix already has a reverse zone object associated to it: %s" % zone)
# For now just check all the zones...
#zones = ReverseZone.objects.filter(parentNet=cleaned_data['parentNet'])
zones = ReverseZone.objects.all()
for zone in zones:
if net.network_address in zone.parentNet.getNetwork():
raise forms.ValidationError("Given prefix already has a reverse zone object associated to it: %s" % zone)
self.instance.address = str(net.network_address)
self.instance.netmask = net.prefixlen
self.instance.address = str(net.network_address)
self.instance.netmask = net.prefixlen
return cleaned_data
return cleaned_data

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-04-03 05:33
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('domains', '0003_auto_20170322_1801'),
]
operations = [
migrations.AlterField(
model_name='domain',
name='mnt_by',
field=models.ManyToManyField(help_text='You can select multiple maintainers here', to='whoisdb.Maintainer'),
),
migrations.AlterField(
model_name='nameserver',
name='mnt_by',
field=models.ManyToManyField(help_text='You can select multiple maintainers here', to='whoisdb.Maintainer'),
),
]

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2019-05-30 21:18
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('domains', '0004_auto_20170403_0533'),
]
operations = [
migrations.AddField(
model_name='domain',
name='ds_records',
field=models.TextField(blank=True),
),
]

@ -13,139 +13,146 @@ import ipaddress
# allow owners of a subnet to create reverse dns record?
class DSRecordModelMixin(models.Model):
class Meta:
abstract = True
ds_records = models.TextField(blank=True, verbose_name='DS Records',
help_text='DS Records in the format of [id] [crypto-algo] [hash-algo] [hash]')
class Nameserver(MntdObject):
handleSuffix = "NS"
# dns name
# ip address, if glue
# ipv4/ipv6 address?
handle = None
name = models.CharField(max_length=256)
glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True)
glueIPv6 = models.GenericIPAddressField(protocol='IPv6', blank=True, null=True)
handleSuffix = "NS"
# dns name
# ip address, if glue
# ipv4/ipv6 address?
handle = None
name = models.CharField(max_length=256)
glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True)
glueIPv6 = models.GenericIPAddressField(protocol='IPv6', blank=True, null=True)
admin_c = models.ManyToManyField(Contact)
admin_c = models.ManyToManyField(Contact)
def getPK(self):
return self.pk
def get_absolute_url(self):
return reverse("domains:nameserver-show", args=(self.pk,))
def __str__(self):
return self.name
def getAppName(self):
return "domains"
def getPK(self):
return self.pk
def get_absolute_url(self):
return reverse("domains:nameserver-show", args=(self.pk,))
def __str__(self):
return self.name
def getAppName(self):
return "domains"
def getNoDeleteReasons(self):
# nameservers can always be deleted
return []
def getNoDeleteReasons(self):
# nameservers can always be deleted
return []
class Domain(MntdObject):
handle = None
handleSuffix = "DOM"
name = models.CharField(max_length=67, unique=True, db_index=True)
class Domain(DSRecordModelMixin, MntdObject):
handle = None
handleSuffix = "DOM"
name = models.CharField(max_length=67, unique=True, db_index=True)
nameservers = models.ManyToManyField(Nameserver, blank=True)
admin_c = models.ManyToManyField(Contact)
nameservers = models.ManyToManyField(Nameserver, blank=True)
admin_c = models.ManyToManyField(Contact)
def getPK(self):
return self.name
def getPK(self):
return self.name
def getZone(self):
return self.name
def getZone(self):
return self.name
def get_absolute_url(self):
return reverse("domains:domain-show", args=(self.name,))
def get_absolute_url(self):
return reverse("domains:domain-show", args=(self.name,))
def __str__(self):
return self.name
def __str__(self):
return self.name
def getAppName(self):
return "domains"
def getAppName(self):
return "domains"
def getNoDeleteReasons(self):
reasons = []
def getNoDeleteReasons(self):
reasons = []
nameservers = Nameserver.objects.filter(name__endswith="." + self.name)
for ns in nameservers:
# FIXME: check if the nameserver has a glue record.... and also if it is maintained by us
reasons.append("Nameserver %s depends on this domain" % ns.name)
nameservers = Nameserver.objects.filter(name__endswith="." + self.name)
for ns in nameservers:
# FIXME: check if the nameserver has a glue record.... and also if it is maintained by us
reasons.append("Nameserver %s depends on this domain" % ns.name)
return reasons
return reasons
@classmethod
def fixName(clazz, name):
if not name.endswith("."):
name += "."
return name.lower()
@classmethod
def fixName(clazz, name):
if not name.endswith("."):
name += "."
return name.lower()
class ReverseZone(WhoisObject):
handle = None
class ReverseZone(DSRecordModelMixin, WhoisObject):
handle = None
parentNet = models.ForeignKey(InetNum)
address = models.GenericIPAddressField(db_index=True)
netmask = models.PositiveIntegerField()
parentNet = models.ForeignKey(InetNum)
address = models.GenericIPAddressField(db_index=True)
netmask = models.PositiveIntegerField()
nameservers = models.ManyToManyField(Nameserver)
nameservers = models.ManyToManyField(Nameserver)
def getPK(self):
return self.pk
def getPK(self):
return self.pk
def prefix(self):
""" Helper function, mainly used in templates """
return "%s/%s" % (self.address, self.netmask)
def prefix(self):
""" Helper function, mainly used in templates """
return "%s/%s" % (self.address, self.netmask)
def getNetwork(self):
return ipaddress.ip_network(self.prefix())
def getNetwork(self):
return ipaddress.ip_network(self.prefix())
def getZone(self):
net = self.parentNet.getNetwork()
if net.version == 4:
# does not work with python3.4
## for these we delegate the full domain
#if 0 < net.prefixlen < 32 and net.prefixlen % 8 == 0:
# zoneParts = net.reverse_pointer.split(".")
def getZone(self):
net = self.parentNet.getNetwork()
if net.version == 4:
# does not work with python3.4
## for these we delegate the full domain
#if 0 < net.prefixlen < 32 and net.prefixlen % 8 == 0:
# zoneParts = net.reverse_pointer.split(".")
# return ".".join(zoneParts[1:])
#else:
# # return RFC2317 compliant zone
# return net.reverse_pointer
parts = list(reversed(str(net.network_address).split(".")))
domain = ".".join(parts[4 - net.prefixlen // 8:]) + ".in-addr.arpa."
if net.prefixlen % 8 == 0:
# clean cut!
return domain
else:
# RFC2317 compliant!
rfc2317Domain = "%s/%s.%s" % (parts[4 - net.prefixlen // 8 - 1], net.prefixlen, domain)
return rfc2317Domain
else:
## does not work with python3.4
## ipv6
## thefuck ipaddress lib... _the_ _fuck_
#zoneParts = net.reverse_pointer.split(".")[-2 - net.prefixlen // 4:]
#return ".".join(zoneParts)
# return ".".join(zoneParts[1:])
#else:
# # return RFC2317 compliant zone
# return net.reverse_pointer
parts = list(reversed(str(net.network_address).split(".")))
domain = ".".join(parts[4 - net.prefixlen // 8:]) + ".in-addr.arpa."
if net.prefixlen % 8 == 0:
# clean cut!
return domain
else:
# RFC2317 compliant!
rfc2317Domain = "%s/%s.%s" % (parts[4 - net.prefixlen // 8 - 1], net.prefixlen, domain)
return rfc2317Domain
else:
## does not work with python3.4
## ipv6
## thefuck ipaddress lib... _the_ _fuck_
#zoneParts = net.reverse_pointer.split(".")[-2 - net.prefixlen // 4:]
#return ".".join(zoneParts)
parts = list(reversed(net.exploded.split("/")[0].replace(":", "")))[32 - net.prefixlen // 4:]
return ".".join(parts) + ".ip6.arpa."
parts = list(reversed(net.exploded.split("/")[0].replace(":", "")))[32 - net.prefixlen // 4:]
return ".".join(parts) + ".ip6.arpa."
def get_absolute_url(self):
return reverse("domains:reversezone-show", args=(self.pk,))
def get_absolute_url(self):
return reverse("domains:reversezone-show", args=(self.pk,))
def getAppName(self):
return "domains"
def __str__(self):
return "%s @ %s" % (self.prefix(), self.parentNet)
def getAppName(self):
return "domains"
def __str__(self):
return "%s @ %s" % (self.prefix(), self.parentNet)
def getNoDeleteReasons(self):
return []
def canEdit(self, user):
if self.parentNet:
return self.parentNet.canEdit(user)
else:
return False
def getNoDeleteReasons(self):
return []
def canEdit(self, user):
if self.parentNet:
return self.parentNet.canEdit(user)
else:
return False

@ -7,23 +7,23 @@ from django.conf.urls import url
from . import views as domains_views
urlpatterns = [
url(r'^$', domains_views.overview, name='overview'),
url(r'^$', domains_views.overview, name='overview'),
url(r'domain/create/$', domains_views.DomainCreate.as_view(), name='domain-create'),
url(r'domain/check/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainCheck.as_view(), name='domain-check'),
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'domain/create/$', domains_views.DomainCreate.as_view(), name='domain-create'),
url(r'domain/check/(?P<domain>[a-z0-9.-]+)/$', domains_views.DomainCheck.as_view(), name='domain-check'),
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>[0-9]+)/$', domains_views.NameserverDetail.as_view(), name='nameserver-show'),
url(r'nameserver/edit/(?P<pk>[0-9]+)/$', domains_views.NameserverEdit.as_view(), name='nameserver-edit'),
url(r'nameserver/delete/(?P<pk>[0-9]+)/$', domains_views.NameserverDelete.as_view(), name='nameserver-delete'),
url(r'nameserver/create/$', domains_views.NameserverCreate.as_view(), name='nameserver-create'),
url(r'nameserver/show/(?P<pk>[0-9]+)/$', domains_views.NameserverDetail.as_view(), name='nameserver-show'),
url(r'nameserver/edit/(?P<pk>[0-9]+)/$', domains_views.NameserverEdit.as_view(), name='nameserver-edit'),
url(r'nameserver/delete/(?P<pk>[0-9]+)/$', domains_views.NameserverDelete.as_view(), name='nameserver-delete'),
url(r'reversezone/create/$', domains_views.ReverseZoneCreate.as_view(), name='reversezone-create'),
url(r'reversezone/show/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDetail.as_view(), name='reversezone-show'),
url(r'reversezone/check/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneCheck.as_view(), name='reversezone-check'),
url(r'reversezone/edit/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneEdit.as_view(), name='reversezone-edit'),
url(r'reversezone/delete/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDelete.as_view(), name='reversezone-delete'),
url(r'reversezone/create/$', domains_views.ReverseZoneCreate.as_view(), name='reversezone-create'),
url(r'reversezone/show/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDetail.as_view(), name='reversezone-show'),
url(r'reversezone/check/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneCheck.as_view(), name='reversezone-check'),
url(r'reversezone/edit/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneEdit.as_view(), name='reversezone-edit'),
url(r'reversezone/delete/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDelete.as_view(), name='reversezone-delete'),
]

@ -17,157 +17,157 @@ from .forms import DomainForm, NameserverForm, ReverseZoneForm
@login_required
def overview(request):
mnts = request.user.maintainer_set.all()
mnts = request.user.maintainer_set.all()
# get all domains and nameservers
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
nameservers = Nameserver.objects.filter(mnt_by__in=mnts).distinct()
reversezones = ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
# get all domains and nameservers
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
nameservers = Nameserver.objects.filter(mnt_by__in=mnts).distinct()
reversezones = ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
return render(request, "domains/overview.html", {"mnts": mnts, "domains": domains, "nameservers": nameservers, 'reversezones': reversezones})
return render(request, "domains/overview.html", {"mnts": mnts, "domains": domains, "nameservers": nameservers, 'reversezones': reversezones})
class DomainCreate(LoginRequiredMixin, CreateView):
template_name = "domains/obj_create.html"
form_class = DomainForm
template_name = "domains/obj_create.html"
form_class = DomainForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(DomainCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(DomainCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
return kwargs
class DomainCheck(LoginRequiredMixin, DetailView):
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "domain"
template_name = "domains/dns_check.html"
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "domain"
template_name = "domains/dns_check.html"
def get_context_data(self, **kwargs):
ctx = super(DomainCheck, self).get_context_data(**kwargs)
ctx["key"] = self.object.name
ctx["apiUrl"] = reverse("api:domain-check")
def get_context_data(self, **kwargs):
ctx = super(DomainCheck, self).get_context_data(**kwargs)
ctx["key"] = self.object.name
ctx["apiUrl"] = reverse("api:domain-check")
return ctx
return ctx
class DomainDetail(LoginRequiredMixin, DetailView):
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "domain"
model = Domain
slug_field = "name"
slug_url_kwarg = "domain"
context_object_name = "domain"
template_name = "whoisdb/handle_show.html"
template_name = "whoisdb/handle_show.html"
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
model = Domain
form_class = DomainForm
slug_field = "name"
slug_url_kwarg = "domain"
template_name = "domains/obj_edit.html"
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
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")
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):
template_name = "domains/obj_create.html"
form_class = NameserverForm
template_name = "domains/obj_create.html"
form_class = NameserverForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(NameserverCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(NameserverCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
return kwargs
class NameserverDetail(LoginRequiredMixin, DetailView):
model = Nameserver
template_name = "whoisdb/handle_show.html"
model = Nameserver
template_name = "whoisdb/handle_show.html"
class NameserverEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
model = Nameserver
form_class = NameserverForm
template_name = "domains/obj_edit.html"
model = Nameserver
form_class = NameserverForm
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
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
success_url = reverse_lazy("domains:overview")
template_name = "domains/obj_delete.html"
model = Nameserver
success_url = reverse_lazy("domains:overview")
class ReverseZoneCreate(LoginRequiredMixin, CreateView):
template_name = "domains/obj_create.html"
form_class = ReverseZoneForm
template_name = "domains/obj_create.html"
form_class = ReverseZoneForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ReverseZoneCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ReverseZoneCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
return kwargs
class ReverseZoneCheck(LoginRequiredMixin, DetailView):
model = ReverseZone
template_name = "domains/dns_check.html"
model = ReverseZone
template_name = "domains/dns_check.html"
def get_context_data(self, **kwargs):
ctx = super(ReverseZoneCheck, self).get_context_data(**kwargs)
ctx["key"] = self.object.id
ctx["apiUrl"] = reverse("api:reversezone-check")
def get_context_data(self, **kwargs):
ctx = super(ReverseZoneCheck, self).get_context_data(**kwargs)
ctx["key"] = self.object.id
ctx["apiUrl"] = reverse("api:reversezone-check")
return ctx
return ctx
class ReverseZoneDetail(LoginRequiredMixin, DetailView):
model = ReverseZone
template_name = "whoisdb/handle_show.html"
model = ReverseZone
template_name = "whoisdb/handle_show.html"
class ReverseZoneEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
model = ReverseZone
form_class = ReverseZoneForm
template_name = "domains/obj_edit.html"
model = ReverseZone
form_class = ReverseZoneForm
template_name = "domains/obj_edit.html"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ReverseZoneEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ReverseZoneEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
if "initial" not in kwargs:
kwargs["initial"] = {}
if "initial" not in kwargs:
kwargs["initial"] = {}
kwargs["initial"]["prefix"] = self.object.prefix()
return kwargs
kwargs["initial"]["prefix"] = self.object.prefix()
return kwargs
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
class ReverseZoneDelete(LoginRequiredMixin, DeleteCheckView):
template_name = "domains/obj_delete.html"
model = ReverseZone
success_url = reverse_lazy("domains:overview")
template_name = "domains/obj_delete.html"
model = ReverseZone
success_url = reverse_lazy("domains:overview")
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()

@ -9,51 +9,51 @@ from .models import Request
from whoisdb.models import Maintainer
class RequestForm(forms.Form):
RESOURCES = map(lambda _x: (_x, _x), [
"AS Number (16bit)", "IPv4 /27", "IPv4 > /27", "IPv6", "other"
])
RESOURCES = map(lambda _x: (_x, _x), [
"AS Number (16bit)", "IPv4 /27", "IPv4 > /27", "IPv6", "other"
])
applicant = forms.ModelChoiceField(Maintainer.objects.none(), label="Applicant (you)", help_text="Maintainer you want to request resources for")
provider = forms.ModelChoiceField(Maintainer.objects.none(), label="Provider", help_text="LIR/RIR you want to request resources from")
applicant = forms.ModelChoiceField(Maintainer.objects.none(), label="Applicant (you)", help_text="Maintainer you want to request resources for")
provider = forms.ModelChoiceField(Maintainer.objects.none(), label="Provider", help_text="LIR/RIR you want to request resources from")
subject = forms.CharField(label="Subject")
resources = forms.CheckboxSelectMultiple(choices=RESOURCES)
message = forms.CharField(widget=forms.Textarea, help_text="Describe shortly what resources you need and what you need them for")
subject = forms.CharField(label="Subject")
resources = forms.CheckboxSelectMultiple(choices=RESOURCES)
message = forms.CharField(widget=forms.Textarea, help_text="Describe shortly what resources you need and what you need them for")
def __init__(self, user, *args, **kwargs):
super(RequestForm, self).__init__(*args, **kwargs)
def __init__(self, user, *args, **kwargs):
super(RequestForm, self).__init__(*args, **kwargs)
self._user = user
self.fields['applicant'].queryset = self._user.maintainer_set.all()
self.fields['provider'].queryset = Maintainer.objects.filter(Q(rir=True) | Q(lir=True))
self._user = user
self.fields['applicant'].queryset = self._user.maintainer_set.all()
self.fields['provider'].queryset = Maintainer.objects.filter(Q(rir=True) | Q(lir=True))
def clean(self):
cleaned_data = super(RequestForm, self).clean()
def clean(self):
cleaned_data = super(RequestForm, self).clean()
if not self.errors:
mnts = self._user.maintainer_set.all()
if cleaned_data['applicant'] in mnts and cleaned_data['provider'] in mnts:
raise forms.ValidationError("You could request resources from yourself, but this would actually not make that much sense.")
if not self.errors:
mnts = self._user.maintainer_set.all()
if cleaned_data['applicant'] in mnts and cleaned_data['provider'] in mnts:
raise forms.ValidationError("You could request resources from yourself, but this would actually not make that much sense.")
class ResponseForm(forms.Form):
new_status = forms.ChoiceField(choices=[("KEEP", "----", )] + list(Request.STATES), initial="KEEP", help_text="Only set this if you want to change the status of this request")
message = forms.CharField(widget=forms.Textarea)
new_status = forms.ChoiceField(choices=[("KEEP", "----", )] + list(Request.STATES), initial="KEEP", help_text="Only set this if you want to change the status of this request")
message = forms.CharField(widget=forms.Textarea)
def __init__(self, request, user, *args, **kwargs):
super(ResponseForm, self).__init__(*args, **kwargs)
self._request = request
self._user = user
def __init__(self, request, user, *args, **kwargs):
super(ResponseForm, self).__init__(*args, **kwargs)
self._request = request
self._user = user
def clean(self):
cleaned_data = super(ResponseForm, self).clean()
def clean(self):
cleaned_data = super(ResponseForm, self).clean()
if not self.errors:
if cleaned_data['new_status'] == self._request.status:
raise forms.ValidationError("Status changed to same as ticket")
if self._request.status in (Request.STATE_RESOLVED, Request.STATE_REJECTED) and \
cleaned_data['new_status'] not in (Request.STATE_OPEN,):
raise forms.ValidationError("Please put this ticket in an open state before adding messages")
if not self.errors:
if cleaned_data['new_status'] == self._request.status:
raise forms.ValidationError("Status changed to same as ticket")
if self._request.status in (Request.STATE_RESOLVED, Request.STATE_REJECTED) and \
cleaned_data['new_status'] not in (Request.STATE_OPEN,):
raise forms.ValidationError("Please put this ticket in an open state before adding messages")
class ProviderResponseForm(ResponseForm):
createdResources = forms.CharField(label="Created resources", help_text="If you have created resources for this request, please enter their handles here", required=False)
createdResources = forms.CharField(label="Created resources", help_text="If you have created resources for this request, please enter their handles here", required=False)

@ -8,49 +8,49 @@ from django.urls import reverse
from whoisdb.models import Maintainer
class Request(models.Model):
STATE_OPEN = "OPEN"
STATE_RESOLVED = "RESOLVED"
STATE_REJECTED = "REJECTED"
STATES = (
(STATE_OPEN, 'Open'),
(STATE_RESOLVED, 'Resolved'),
(STATE_REJECTED, 'Rejected'),
)
STATE_OPEN = "OPEN"
STATE_RESOLVED = "RESOLVED"
STATE_REJECTED = "REJECTED"
STATES = (
(STATE_OPEN, 'Open'),
(STATE_RESOLVED, 'Resolved'),
(STATE_REJECTED, 'Rejected'),
)
# request goes to mnt?
subject = models.CharField(max_length=200)
# request goes to mnt?
subject = models.CharField(max_length=200)
status = models.CharField(max_length=16, choices=STATES)
status = models.CharField(max_length=16, choices=STATES)
applicant = models.ForeignKey(Maintainer)
provider = models.ForeignKey(Maintainer, related_name='requestfrom_set')
applicant = models.ForeignKey(Maintainer)
provider = models.ForeignKey(Maintainer, related_name='requestfrom_set')
requestResources = models.TextField()
grantedResources = models.TextField()
requestResources = models.TextField()
grantedResources = models.TextField()
created = models.DateTimeField(auto_now_add=True)
lastAction = models.DateTimeField(auto_now_add=True)
created = models.DateTimeField(auto_now_add=True)
lastAction = models.DateTimeField(auto_now_add=True)
def get_absolute_url(self):
return reverse("rrequests:show", args=(self.pk,))
def get_absolute_url(self):
return reverse("rrequests:show", args=(self.pk,))
def __str__(self):
return "(%s -> %s) [%s] %s" % (self.applicant, self.provider, self.status, self.subject)
def __str__(self):
return "(%s -> %s) [%s] %s" % (self.applicant, self.provider, self.status, self.subject)
def getLastActionBy(self):
msgs = self.requestmessage_set.order_by("-created")
def getLastActionBy(self):
msgs = self.requestmessage_set.order_by("-created")
if msgs.count() > 0:
return msgs[0].creator
else:
return None
if msgs.count() > 0:
return msgs[0].creator
else:
return None
class RequestMessage(models.Model):
request = models.ForeignKey(Request)
request = models.ForeignKey(Request)
statusChanged = models.CharField(max_length=16, choices=Request.STATES, default=None, null=True, blank=True)
statusChanged = models.CharField(max_length=16, choices=Request.STATES, default=None, null=True, blank=True)
creator = models.ForeignKey(Maintainer)
message = models.TextField()
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(Maintainer)
message = models.TextField()
created = models.DateTimeField(auto_now_add=True)

@ -7,8 +7,8 @@ from django.conf.urls import url
from . import views as rrequests_views
urlpatterns = [
url(r'^$', rrequests_views.listRequests, name='dashboard'),
url(r'^$', rrequests_views.listRequests, name='dashboard'),
url(r'create/$', rrequests_views.RrequestCreate.as_view(), name='create'),
url(r'show/(?P<pk>\d+)/$', rrequests_views.rrequestDetail, name='show'),
url(r'create/$', rrequests_views.RrequestCreate.as_view(), name='create'),
url(r'show/(?P<pk>\d+)/$', rrequests_views.rrequestDetail, name='show'),
]

@ -17,88 +17,88 @@ from .forms import RequestForm, ResponseForm, ProviderResponseForm
@login_required
def listRequests(request):
mnts = request.user.maintainer_set.all()
requestedFromMe = Request.objects.filter(applicant__in=mnts)
requestedToMe = Request.objects.filter(provider__in=mnts)
requests = (requestedFromMe | requestedToMe).order_by("-lastAction")
mnts = request.user.maintainer_set.all()
requestedFromMe = Request.objects.filter(applicant__in=mnts)
requestedToMe = Request.objects.filter(provider__in=mnts)
requests = (requestedFromMe | requestedToMe).order_by("-lastAction")
return render(request, "rrequests/list.html", {"mnts": mnts, "requests": requests, "requestedFromMe": requestedFromMe, "requestedToMe": requestedToMe})
return render(request, "rrequests/list.html", {"mnts": mnts, "requests": requests, "requestedFromMe": requestedFromMe, "requestedToMe": requestedToMe})
class RrequestCreate(LoginRequiredMixin, FormView):
template_name = "rrequests/request_create.html"
form_class = RequestForm
template_name = "rrequests/request_create.html"
form_class = RequestForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(RrequestCreate, self).get_form_kwargs(*args, **kwargs)
kwargs['user'] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(RrequestCreate, self).get_form_kwargs(*args, **kwargs)
kwargs['user'] = self.request.user
return kwargs
return kwargs
def form_valid(self, form):
formData = form.cleaned_data
print(formData)
request = Request(
subject=formData['subject'],
status=Request.STATE_OPEN,
applicant=formData['applicant'],
provider=formData['provider'],
)
request.save()
def form_valid(self, form):
formData = form.cleaned_data
print(formData)
request = Request(
subject=formData['subject'],
status=Request.STATE_OPEN,
applicant=formData['applicant'],
provider=formData['provider'],
)
request.save()
requestMsg = RequestMessage(
request=request,
requestMsg = RequestMessage(
request=request,
creator=formData['applicant'],
message=formData['message'],
)
requestMsg.save()
creator=formData['applicant'],
message=formData['message'],
)
requestMsg.save()
return HttpResponseRedirect(request.get_absolute_url())
return HttpResponseRedirect(request.get_absolute_url())
@login_required
def rrequestDetail(request, pk):
mnts = request.user.maintainer_set.all()
reqObj = get_object_or_404(Request.objects.filter(Q(provider__in=mnts) | Q(applicant__in=mnts)), pk=pk)
mnts = request.user.maintainer_set.all()
formClass = None
provider = None
initialFormData = {}
if reqObj.provider in mnts:
provider = True
formClass = ProviderResponseForm
initialFormData["createdResources"] = reqObj.grantedResources
else:
provider = False
formClass = ResponseForm
if request.method == "POST":
form = formClass(request=reqObj, user=request.user, data=request.POST)
if form.is_valid():
# create message object
msg = RequestMessage(
request=reqObj,
creator=reqObj.provider if provider else reqObj.applicant,
message=form.cleaned_data['message']
)
if form.cleaned_data['new_status'] != "KEEP":
msg.statusChanged = form.cleaned_data['new_status']
reqObj.status = msg.statusChanged
msg.save()
if "createdResources" in form.cleaned_data and \
form.cleaned_data['createdResources'].strip() != "":
reqObj.grantedResources = form.cleaned_data["createdResources"].strip()
reqObj.lastAction = timezone.now()
reqObj.save()
return HttpResponseRedirect(reverse("rrequests:show", args=(pk,)))
else:
form = formClass(request=reqObj, user=request.user, initial=initialFormData)
return render(request, "rrequests/request_detail.html", {"request": reqObj, "form": form})
mnts = request.user.maintainer_set.all()
reqObj = get_object_or_404(Request.objects.filter(Q(provider__in=mnts) | Q(applicant__in=mnts)), pk=pk)
mnts = request.user.maintainer_set.all()
formClass = None
provider = None
initialFormData = {}
if reqObj.provider in mnts:
provider = True
formClass = ProviderResponseForm
initialFormData["createdResources"] = reqObj.grantedResources
else:
provider = False
formClass = ResponseForm
if request.method == "POST":
form = formClass(request=reqObj, user=request.user, data=request.POST)
if form.is_valid():
# create message object
msg = RequestMessage(
request=reqObj,
creator=reqObj.provider if provider else reqObj.applicant,
message=form.cleaned_data['message']
)
if form.cleaned_data['new_status'] != "KEEP":
msg.statusChanged = form.cleaned_data['new_status']
reqObj.status = msg.statusChanged
msg.save()
if "createdResources" in form.cleaned_data and \
form.cleaned_data['createdResources'].strip() != "":
reqObj.grantedResources = form.cleaned_data["createdResources"].strip()
reqObj.lastAction = timezone.now()
reqObj.save()
return HttpResponseRedirect(reverse("rrequests:show", args=(pk,)))
else:
form = formClass(request=reqObj, user=request.user, initial=initialFormData)
return render(request, "rrequests/request_detail.html", {"request": reqObj, "form": form})

@ -6,33 +6,33 @@ from django import forms
class MultiTextInput(forms.widgets.Input):
input_type = "text"
def render(self, name, value, attrs=None):
if value is not None:
selectedOptions = []
for val in value:
for k, v in self.choices:
if val == k:
selectedOptions.append(v)
value = " ".join(selectedOptions)
input_type = "text"
def render(self, name, value, attrs=None):
if value is not None:
selectedOptions = []
for val in value:
for k, v in self.choices:
if val == k:
selectedOptions.append(v)
value = " ".join(selectedOptions)
return super(MultiTextInput, self).render(name, value, attrs)
return super(MultiTextInput, self).render(name, value, attrs)
def value_from_datadict(self, data, files, name):
values = list(filter(bool, map(lambda _x: _x.strip(), data.get(name).split(" "))))
def value_from_datadict(self, data, files, name):
values = list(filter(bool, map(lambda _x: _x.strip(), data.get(name).split(" "))))
result = []
for value in values:
# FIXME: using value here throws a weird error message at some point
# could be handled by overriding the messages in ChoiceField
# or... well, don't know
kId = value
for k, v in self.choices:
if v.lower() == value.lower():
kId = str(k)
break
result.append(kId)
result = []
for value in values:
# FIXME: using value here throws a weird error message at some point
# could be handled by overriding the messages in ChoiceField
# or... well, don't know
kId = value
for k, v in self.choices:
if v.lower() == value.lower():
kId = str(k)
break
result.append(kId)
return result
return result

@ -15,351 +15,351 @@ import ipaddress
class WhoisObjectFormMixin(object):
def __init__(self, user, *args, **kwargs):
super(WhoisObjectFormMixin, self).__init__(*args, **kwargs)
self._user = user
def __init__(self, user, *args, **kwargs):
super(WhoisObjectFormMixin, self).__init__(*args, **kwargs)
self._user = user
instance = getattr(self, 'instance', None)
if instance and instance.pk:
self._create = False
#self.fields['handle'].disabled = True
else:
self._create = True
instance = getattr(self, 'instance', None)
if instance and instance.pk:
self._create = False
#self.fields['handle'].disabled = True
else:
self._create = True
if 'handle' in self.fields:
self.fields['handle'].help_text = "Handle for this object in uppercase with a suffix of -%s" % instance.handleSuffix
if 'handle' in self.fields:
self.fields['handle'].help_text = "Handle for this object in uppercase with a suffix of -%s" % instance.handleSuffix
# only show users contacts and already present contacts
mnts = self._user.maintainer_set.all()
if 'admin_c' in self.fields:
self.fields['admin_c'].queryset = Contact.getMntQueryset(mnts, self.instance, "admin_c")
# only show users contacts and already present contacts
mnts = self._user.maintainer_set.all()
if 'admin_c' in self.fields:
self.fields['admin_c'].queryset = Contact.getMntQueryset(mnts, self.instance, "admin_c")
def clean_handle(self):
HandleValidatorWithSuffix(self.instance.handleSuffix)(self.cleaned_data['handle'])
return self.cleaned_data['handle']
def clean_handle(self):
HandleValidatorWithSuffix(self.instance.handleSuffix)(self.cleaned_data['handle'])
return self.cleaned_data['handle']
def clean(self):
cleaned_data = super(WhoisObjectFormMixin, self).clean()
if cleaned_data.get("handle") == "AUTO" and not self.errors:
name = cleaned_data.get("name")
if name is None:
name = self._user.username
def clean(self):
cleaned_data = super(WhoisObjectFormMixin, self).clean()
if cleaned_data.get("handle") == "AUTO" and not self.errors:
name = cleaned_data.get("name")
if name is None:
name = self._user.username
cleaned_data['handle'] = self._meta.model.genGenericHandle(name)
cleaned_data['handle'] = self._meta.model.genGenericHandle(name)
# XXX: Find a better position to update last_changed
self.instance.last_modified = timezone.now()
# XXX: Find a better position to update last_changed
self.instance.last_modified = timezone.now()
return cleaned_data
return cleaned_data
class MntFormMixin(object):
protectedFields = []
protectedFields = []
def __init__(self, lower=False, *args, **kwargs):
super(MntFormMixin, self).__init__(*args, **kwargs)
def __init__(self, lower=False, *args, **kwargs):
super(MntFormMixin, self).__init__(*args, **kwargs)
self._editLower = lower
self._editLower = lower
if self._editLower:
for key in self.protectedFields:
self.fields[key].disabled = True
if self._editLower:
for key in self.protectedFields:
self.fields[key].disabled = True
instance = getattr(self, "instance", None)
if not hasattr(self, "_create"):
self._create = not (instance and instance.pk)
instance = getattr(self, "instance", None)
if not hasattr(self, "_create"):
self._create = not (instance and instance.pk)
mntQs = orderQueryset(Maintainer.objects.all(), Q(auth=self._user), Q(pk__in=instance.mnt_by.all()) if not self._create else None)
self.fields["mnt_by"].queryset = mntQs
mntQs = orderQueryset(Maintainer.objects.all(), Q(auth=self._user), Q(pk__in=instance.mnt_by.all()) if not self._create else None)
self.fields["mnt_by"].queryset = mntQs
if "mnt_lower" in self.fields:
self.fields["mnt_lower"].queryset = mntQs
if "mnt_lower" in self.fields:
self.fields["mnt_lower"].queryset = mntQs
def clean(self):
cleaned_data = super(MntFormMixin, self).clean()
def clean(self):
cleaned_data = super(MntFormMixin, self).clean()
if not self.errors:
if self._create:
# at least one own mnt on creation
mnts = self._user.maintainer_set.all()
if not self.errors:
if self._create:
# at least one own mnt on creation
mnts = self._user.maintainer_set.all()
for mnt in cleaned_data['mnt_by']:
if mnt in mnts:
break
else:
raise forms.ValidationError("On object creation at least one maintainer needs to be under your control")
for mnt in cleaned_data['mnt_by']:
if mnt in mnts:
break
else:
raise forms.ValidationError("On object creation at least one maintainer needs to be under your control")
if cleaned_data['mnt_by'].count() > 5 or "mnt_lower" in self.fields and cleaned_data['mnt_lower'].count() > 5:
raise forms.ValidationError("Currently only 5 MNTs per object allowed. If you need more ask @ irc/rrequest and state your use case")
if cleaned_data['mnt_by'].count() > 5 or "mnt_lower" in self.fields and cleaned_data['mnt_lower'].count() > 5:
raise forms.ValidationError("Currently only 5 MNTs per object allowed. If you need more ask @ irc/rrequest and state your use case")
return cleaned_data
return cleaned_data
class MntForm(WhoisObjectFormMixin, forms.ModelForm):
class Meta:
model = Maintainer
#fields = ['handle', 'description', 'admin_c', 'auth']
fields = ['handle', 'description', 'admin_c']
widgets = {'auth': MultiTextInput()}
class Meta:
model = Maintainer
#fields = ['handle', 'description', 'admin_c', 'auth']
fields = ['handle', 'description', 'admin_c']
widgets = {'auth': MultiTextInput()}
help_texts = {
'auth': 'Enter names of users which can edit this object (space separated; '
'and yes, validation is somewhat broken (values disappear on error - just reload))'
}
help_texts = {
'auth': 'Enter names of users which can edit this object (space separated; '
'and yes, validation is somewhat broken (values disappear on error - just reload))'
}
def __init__(self, *args, **kwargs):
super(MntForm, self).__init__(*args, **kwargs)
print(args, kwargs)
#if self._create:
# self.fields['auth'].text("noot")
def __init__(self, *args, **kwargs):
super(MntForm, self).__init__(*args, **kwargs)
print(args, kwargs)
#if self._create:
# self.fields['auth'].text("noot")
class MntInitialForm(MntForm):
class Meta:
model = Maintainer
fields = ['handle', 'description']
class Meta:
model = Maintainer
fields = ['handle', 'description']
class ContactForm(WhoisObjectFormMixin, forms.ModelForm):
class Meta:
model = Contact
fields = ['handle', 'name', 'mnt_by']
class Meta:
model = Contact
fields = ['handle', 'name', 'mnt_by']
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
if "mnt_by" in self.fields:
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user).distinct()
if "mnt_by" in self.fields:
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user).distinct()
class ContactInitialForm(ContactForm):
class Meta:
model = Contact
fields = ['handle', 'name']
class Meta:
model = Contact
fields = ['handle', 'name']
class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
prefix = forms.CharField()
protectedFields = ['protocol', 'parent_range', 'mnt_by', 'prefix']
prefix = forms.CharField()
protectedFields = ['protocol', 'parent_range', 'mnt_by', 'prefix']
class Meta:
model = InetNum
fields = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'origin_as', 'mnt_by', 'mnt_lower', 'admin_c']
class Meta:
model = InetNum
fields = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'origin_as', 'mnt_by', 'mnt_lower', 'admin_c']
def __init__(self, *args, **kwargs):
super(InetNumForm, self).__init__(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(InetNumForm, self).__init__(*args, **kwargs)
if self._editLower:
for key in self.protectedFields:
self.fields[key].disabled = True
if self._editLower:
for key in self.protectedFields:
self.fields[key].disabled = True
mnts = self._user.maintainer_set.all()
#self.fields['parent_range'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts))
#if not self._create:
# self.fields['parent_range'].queryset |= InetNum.objects.filter(pk=self.instance.pk)
mnts = self._user.maintainer_set.all()
#self.fields['parent_range'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts))
#if not self._create:
# self.fields['parent_range'].queryset |= InetNum.objects.filter(pk=self.instance.pk)
#self.fields['parent_range'].queryset = self.fields['parent_range'].queryset.distinct()
self.fields['parent_range'].queryset = InetNum.getMntQueryset(mnts, self.instance, "parent_range")
self.fields['origin_as'].queryset = ASNumber.getMntQueryset(mnts, self.instance, "origin_as")
#self.fields['parent_range'].queryset = self.fields['parent_range'].queryset.distinct()
self.fields['parent_range'].queryset = InetNum.getMntQueryset(mnts, self.instance, "parent_range")
self.fields['origin_as'].queryset = ASNumber.getMntQueryset(mnts, self.instance, "origin_as")
def clean_prefix(self):
# make sure this is a subnet we're getting
net = self.cleaned_data['prefix'].lower()
IP46CIDRValidator(net)
def clean_prefix(self):
# make sure this is a subnet we're getting
net = self.cleaned_data['prefix'].lower()
IP46CIDRValidator(net)
try:
net = ipaddress.ip_network(net)
except ValueError as e:
raise forms.ValidationError(str(e))
try:
net = ipaddress.ip_network(net)
except ValueError as e:
raise forms.ValidationError(str(e))
return net
return net
def clean_parent_range(self):
parent_range = self.cleaned_data.get('parent_range', None)
def clean_parent_range(self):
parent_range = self.cleaned_data.get('parent_range', None)
# allow parent range to be unset for already present objects
if not parent_range and (self._create or not self._create and self.instance.parent_range):
raise forms.ValidationError("Parent range must be set")
# allow parent range to be unset for already present objects
if not parent_range and (self._create or not self._create and self.instance.parent_range):
raise forms.ValidationError("Parent range must be set")
if not self._create and parent_range:
# make sure we don't have circular dependencies
obj = parent_range
while obj.parent_range:
if obj.pk == self.instance.pk:
raise forms.ValidationError("No circular dependencies allowed")
obj = obj.parent_range
if not self._create and parent_range:
# make sure we don't have circular dependencies
obj = parent_range
while obj.parent_range:
if obj.pk == self.instance.pk:
raise forms.ValidationError("No circular dependencies allowed")
obj = obj.parent_range
if parent_range.origin_as.count() > 0:
raise forms.ValidationError("Parent range has origin as set")
if parent_range.origin_as.count() > 0:
raise forms.ValidationError("Parent range has origin as set")
return parent_range
return parent_range
def clean(self):
cleaned_data = super(InetNumForm, self).clean()
def clean(self):
cleaned_data = super(InetNumForm, self).clean()
if not self._editLower:
if not self.errors:
if not self._create and self.cleaned_data['origin_as']:
if self.instance.inetnum_set.count() > 0:
ranges = ", ".join(map(str, self.instance.inetnum_set.all()))
raise forms.ValidationError("You cannot set an origin as if there are already existing subranges (%s)" % (ranges))
if not self._editLower:
if not self.errors:
if not self._create and self.cleaned_data['origin_as']:
if self.instance.inetnum_set.count() > 0:
ranges = ", ".join(map(str, self.instance.inetnum_set.all()))
raise forms.ValidationError("You cannot set an origin as if there are already existing subranges (%s)" % (ranges))
prefix = cleaned_data['prefix']
parent = cleaned_data['parent_range']
if parent:
parentNet = parent.getNetwork()
prefix = cleaned_data['prefix']
parent = cleaned_data['parent_range']
if parent:
parentNet = parent.getNetwork()
if cleaned_data['protocol'] != parent.protocol:
raise forms.ValidationError("Protocol type for prefix must be same as parent network")
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 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
# 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)
if otherNet.getNetwork().overlaps(prefix):
raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle)
# check if subnets to this subnet are (still) in current network
if not self._create:
for subnet in self.instance.inetnum_set.all():
if subnet.getNetwork().network_address not in self.instance.getNetwork():
raise forms.ValidationError("Subnet %s with %s is not in block anymore" % (subnet, subnet.getNetwork()))
# check if subnets to this subnet are (still) in current network
if not self._create:
for subnet in self.instance.inetnum_set.all():
if subnet.getNetwork().network_address not in self.instance.getNetwork():
raise forms.ValidationError("Subnet %s with %s is not in block anymore" % (subnet, subnet.getNetwork()))
self.instance.address = str(prefix.network_address)
self.instance.netmask = prefix.prefixlen
self.instance.address = str(prefix.network_address)
self.instance.netmask = prefix.prefixlen
return cleaned_data
return cleaned_data
class ASBlockForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
protectedFields = ['parent_block', 'asBegin', 'asEnd', 'mnt_by']
protectedFields = ['parent_block', 'asBegin', 'asEnd', 'mnt_by']
# FIXME: Filter blocks
class Meta:
model = ASBlock
fields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
# FIXME: Filter blocks
class Meta:
model = ASBlock
fields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
def __init__(self, *args, **kwargs):
super(ASBlockForm, self).__init__(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(ASBlockForm, self).__init__(*args, **kwargs)
if not self.instance or self.instance and self.instance and self.instance.parent_block:
self.fields["parent_block"].required = True
if self.instance and self.instance.pk:
self.fields["parent_block"].disabled = True
if not self.instance or self.instance and self.instance and self.instance.parent_block:
self.fields["parent_block"].required = True
if self.instance and self.instance.pk:
self.fields["parent_block"].disabled = True
mnts = self._user.maintainer_set.all()
self.fields['parent_block'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "parent_block")
mnts = self._user.maintainer_set.all()
self.fields['parent_block'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "parent_block")
def clean_parent_block(self):
parent_block = self.cleaned_data.get('parent_block', None)
def clean_parent_block(self):
parent_block = self.cleaned_data.get('parent_block', None)
# allow parent range to be unset for already present objects
if not parent_block and (self._create or not self._create and self.instance.parent_block):
raise forms.ValidationError("Parent block must be set")
# allow parent range to be unset for already present objects
if not parent_block and (self._create or not self._create and self.instance.parent_block):
raise forms.ValidationError("Parent block must be set")
if not self._create and parent_block:
# make sure we don't have circular dependencies
obj = parent_block
while obj.parent_block:
if obj.pk == self.instance.pk:
raise forms.ValidationError("No circular dependencies allowed")
obj = obj.parent_block
if not self._create and parent_block:
# make sure we don't have circular dependencies
obj = parent_block
while obj.parent_block:
if obj.pk == self.instance.pk:
raise forms.ValidationError("No circular dependencies allowed")
obj = obj.parent_block
return parent_block
return parent_block
def clean(self):
cleaned_data = super(ASBlockForm, self).clean()
def clean(self):
cleaned_data = super(ASBlockForm, self).clean()
if not self.errors:
asBegin = cleaned_data['asBegin']
asEnd = cleaned_data['asEnd']
parent = cleaned_data['parent_block']
# check if somebody is already using this block
if not self.errors:
asBegin = cleaned_data['asBegin']
asEnd = cleaned_data['asEnd']
parent = cleaned_data['parent_block']
# check if somebody is already using this block
# check if in range
if asBegin > asEnd:
raise forms.ValidationError("AS beginning must be smaller or equal to AS end")
# check if in range
if asBegin > asEnd:
raise forms.ValidationError("AS beginning must be smaller or equal to AS end")
if parent:
if parent.asnumber_set.count() > 0:
raise forms.ValidationError("The parent AS block is already references by following AS number objects: %s" % (", ".join(map(lambda _x: _x.handle, parent.asnumber_set.all())),))
if parent:
if parent.asnumber_set.count() > 0:
raise forms.ValidationError("The parent AS block is already references by following AS number objects: %s" % (", ".join(map(lambda _x: _x.handle, parent.asnumber_set.all())),))
# check if same range
if not (asBegin >= parent.asBegin and asEnd <= parent.asEnd):
raise forms.ValidationError("AS beginning and end must be inside the range of the parent AS block")
# check if same range
if not (asBegin >= parent.asBegin and asEnd <= parent.asEnd):
raise forms.ValidationError("AS beginning and end must be inside the range of the parent AS block")
if parent.asBegin == asBegin and parent.asEnd == asEnd:
raise forms.ValidationError("The range of this block cannot be the same range AS the parent AS block")
if parent.asBegin == asBegin and parent.asEnd == asEnd:
raise forms.ValidationError("The range of this block cannot be the same range AS the parent AS block")
# check for overlap with other asblocks
for block in parent.asblock_set.all():
if self.instance and self.instance.pk and block.pk == self.instance.pk:
continue
# check for overlap with other asblocks
for block in parent.asblock_set.all():
if self.instance and self.instance.pk and block.pk == self.instance.pk:
continue
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
if not self._create:
# check if subblocks are still in range
for subblock in self.instance.asblock_set.all():
if not (asBegin <= subblock.asBegin <= asEnd and asBegin <= subblock.asEnd <= asEnd):
raise forms.ValidationError("Subblock %s (%s - %s) is not contained in this block anymore" % (subblock, subblock.asBegin, subblock.asEnd))
if not self._create:
# check if subblocks are still in range
for subblock in self.instance.asblock_set.all():
if not (asBegin <= subblock.asBegin <= asEnd and asBegin <= subblock.asEnd <= asEnd):
raise forms.ValidationError("Subblock %s (%s - %s) is not contained in this block anymore" % (subblock, subblock.asBegin, subblock.asEnd))
# check if asnumbers are still in range
for asnumber in self.instance.asnumber_set.all():
if not (asBegin <= asnumber.number <= asEnd):
raise forms.ValidationError("AS %s (%s) is not contained in this block anymore" % (asnumber, asnumber.number))
# check if asnumbers are still in range
for asnumber in self.instance.asnumber_set.all():
if not (asBegin <= asnumber.number <= asEnd):
raise forms.ValidationError("AS %s (%s) is not contained in this block anymore" % (asnumber, asnumber.number))
return cleaned_data
return cleaned_data
class ASNumberForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
protectedFields = ['asblock', 'number', 'mnt_by']
protectedFields = ['asblock', 'number', 'mnt_by']
class Meta:
model = ASNumber
fields = ['handle', 'asblock', 'number', 'volatile', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
class Meta:
model = ASNumber
fields = ['handle', 'asblock', 'number', 'volatile', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
def __init__(self, *args, **kwargs):
super(ASNumberForm, self).__init__(*args, **kwargs)
def __init__(self, *args, **kwargs):
super(ASNumberForm, self).__init__(*args, **kwargs)
if not (self.instance and self.instance.pk):
self.fields["asblock"].required = True
else:
self.fields["asblock"].disabled = True
if not (self.instance and self.instance.pk):
self.fields["asblock"].required = True
else:
self.fields["asblock"].disabled = True
mnts = self._user.maintainer_set.all()
self.fields['asblock'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "asblock")
mnts = self._user.maintainer_set.all()
self.fields['asblock'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "asblock")
def clean(self):
cleaned_data = super(ASNumberForm, self).clean()
def clean(self):
cleaned_data = super(ASNumberForm, self).clean()
if not self.errors:
number = cleaned_data['number']
block = cleaned_data['asblock']
if not self.errors:
number = cleaned_data['number']
block = cleaned_data['asblock']
# belongs to asblock?
if number < block.asBegin or number > block.asEnd:
raise forms.ValidationError("AS number is not inside AS block")
# belongs to asblock?
if number < block.asBegin or number > block.asEnd:
raise forms.ValidationError("AS number is not inside AS block")
# does an entry already exist?
try:
otherAS = ASNumber.objects.get(number=number)
if not (self.instance and self.instance.pk and self.instance.pk == otherAS.pk):
raise forms.ValidationError("This AS number is already represented by %s" % otherAS.handle)
except ASNumber.DoesNotExist:
pass
# does an entry already exist?
try:
otherAS = ASNumber.objects.get(number=number)
if not (self.instance and self.instance.pk and self.instance.pk == otherAS.pk):
raise forms.ValidationError("This AS number is already represented by %s" % otherAS.handle)
except ASNumber.DoesNotExist:
pass
# has already other asblock?
if block.asblock_set.count() > 0:
raise forms.ValidationError("The given AS block is already references by following sub AS blocks: %s" % (", ".join(map(lambda _x: _x.handle, block.asblock_set.all())),))
# has already other asblock?
if block.asblock_set.count() > 0:
raise forms.ValidationError("The given AS block is already references by following sub AS blocks: %s" % (", ".join(map(lambda _x: _x.handle, block.asblock_set.all())),))

@ -9,45 +9,45 @@ from django.db.models import Q
class DeleteCheckView(DeleteView):
""" Check if object actually can be deleted. Provide reasons to template
if not.
"""
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
reasons = self.object.getNoDeleteReasons()
if reasons:
# do not delete, do what get does...
return self.get(request, *args, **kwargs)
else:
self.object.delete()
messages.info(request, "Object %s has been deleted" % str(self.object))
return HttpResponseRedirect(success_url)
def get_context_data(self, **kwargs):
if 'reasons' not in kwargs:
kwargs['reasons'] = self.object.getNoDeleteReasons()
return super(DeleteCheckView, self).get_context_data(**kwargs)
""" Check if object actually can be deleted. Provide reasons to template
if not.
"""
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
success_url = self.get_success_url()
reasons = self.object.getNoDeleteReasons()
if reasons:
# do not delete, do what get does...
return self.get(request, *args, **kwargs)
else:
self.object.delete()
messages.info(request, "Object %s has been deleted" % str(self.object))
return HttpResponseRedirect(success_url)
def get_context_data(self, **kwargs):
if 'reasons' not in kwargs:
kwargs['reasons'] = self.object.getNoDeleteReasons()
return super(DeleteCheckView, self).get_context_data(**kwargs)
class MntGenericMixin(object):
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
def get_queryset(self):
mnts = self.request.user.maintainer_set.all()
q = Q(mnt_by__in=mnts)
if hasattr(self.model, "mnt_lower"):
q |= Q(mnt_lower__in=mnts)
q = Q(mnt_by__in=mnts)
if hasattr(self.model, "mnt_lower"):
q |= Q(mnt_lower__in=mnts)
return self.model.objects.filter(q).distinct()
return self.model.objects.filter(q).distinct()
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MntGenericMixin, self).get_form_kwargs(*args, **kwargs)
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MntGenericMixin, self).get_form_kwargs(*args, **kwargs)
if hasattr(self.model, "mnt_lower"):
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
if hasattr(self.model, "mnt_lower"):
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
return kwargs
return kwargs

@ -11,161 +11,161 @@ import ipaddress
import re
def _addFields(fields, obj, fieldNames):
for fieldName in fieldNames:
fields.append((fieldName.capitalize().replace("_", " "), getattr(obj, fieldName)))
for fieldName in fieldNames:
fields.append((fieldName.capitalize().replace("_", " "), getattr(obj, fieldName)))
def getWhoisObjectFields(obj, owner):
fields = []
if getattr(obj, "handle", None):
_addFields(fields, obj, ["handle"])
c = type(obj)
if c == whoisdb.models.Maintainer:
_addFields(fields, obj, ["description", "admin_c"])
if owner:
_addFields(fields, obj, ["auth"])
elif c == whoisdb.models.Contact:
_addFields(fields, obj, ["name", "mnt_by"])
elif c == whoisdb.models.ASBlock:
_addFields(fields, obj, ["name"])
fields.append(("AS Range", "%s - %s" % (obj.asBegin, obj.asEnd)))
_addFields(fields, obj, ["description", "parent_block", "mnt_by", "mnt_lower", "admin_c"])
elif c == whoisdb.models.ASNumber:
_addFields(fields, obj, ["name", "number", "description", "asblock", "volatile", "mnt_by", "mnt_lower", "admin_c"])
elif c == whoisdb.models.InetNum:
_addFields(fields, obj, ["name"])
fields.append(("Address CIDR", obj.prefix()))
_addFields(fields, obj, ["description", "parent_range", "origin_as", "mnt_by", "mnt_lower", "admin_c"])
elif c == domains.models.Domain:
_addFields(fields, obj, ["name", "nameservers", "mnt_by", "admin_c"])
elif c == domains.models.Nameserver:
_addFields(fields, obj, ["name", "glueIPv4", "glueIPv6", "mnt_by", "admin_c"])
elif c == domains.models.ReverseZone:
#_addFields(fields, obj, ["name"])
fields.append(("Address CIDR", obj.prefix()))
_addFields(fields, obj, ["parentNet", "nameservers"])
_addFields(fields, obj, ["created", "last_modified"])
return fields
fields = []
if getattr(obj, "handle", None):
_addFields(fields, obj, ["handle"])
c = type(obj)
if c == whoisdb.models.Maintainer:
_addFields(fields, obj, ["description", "admin_c"])
if owner:
_addFields(fields, obj, ["auth"])
elif c == whoisdb.models.Contact:
_addFields(fields, obj, ["name", "mnt_by"])
elif c == whoisdb.models.ASBlock:
_addFields(fields, obj, ["name"])
fields.append(("AS Range", "%s - %s" % (obj.asBegin, obj.asEnd)))
_addFields(fields, obj, ["description", "parent_block", "mnt_by", "mnt_lower", "admin_c"])
elif c == whoisdb.models.ASNumber:
_addFields(fields, obj, ["name", "number", "description", "asblock", "volatile", "mnt_by", "mnt_lower", "admin_c"])
elif c == whoisdb.models.InetNum:
_addFields(fields, obj, ["name"])
fields.append(("Address CIDR", obj.prefix()))
_addFields(fields, obj, ["description", "parent_range", "origin_as", "mnt_by", "mnt_lower", "admin_c"])
elif c == domains.models.Domain:
_addFields(fields, obj, ["name", "nameservers", "mnt_by", "admin_c", "ds_records"])
elif c == domains.models.Nameserver:
_addFields(fields, obj, ["name", "glueIPv4", "glueIPv6", "mnt_by", "admin_c"])
elif c == domains.models.ReverseZone:
#_addFields(fields, obj, ["name"])
fields.append(("Address CIDR", obj.prefix()))
_addFields(fields, obj, ["parentNet", "nameservers"])
_addFields(fields, obj, ["created", "last_modified"])
return fields
def guessWhoisObject(self, handle):
# is it a normal handle?
pass
# is it a normal handle?
pass
def findInDatabase(rawValue):
# is this an ip address?
rawValue = rawValue.strip().upper()
value = None
results = []
# try subnetwork
try:
value = ipaddress.ip_network(rawValue, strict=False)
except ValueError:
pass
if value:
# ssubnet
obj = whoisdb.models.InetNum.objects.filter(address=str(value.network_address), netmask=value.prefixlen)
results.extend(obj)
# single ip
value = None
try:
value = ipaddress.ip_address(rawValue)
except ValueError:
pass
if value:
# NOTE: this is only for "small subnets", we could increase this...
baseaddr = None
if value.version == 4:
basenet = ipaddress.ip_network("%s/24" % value, strict=False)
baseaddr = ".".join(str(basenet).split(".")[0:3]) + "."
else:
basenet = ipaddress.ip_network("%s/56" % value.exploded, strict=False)
baseaddr = ":".join(str(basenet).split(":")[0:4])[-2]
nets = whoisdb.models.InetNum.objects.filter(address__startswith=baseaddr).order_by("-netmask")
for net in nets:
if value in net.getNetwork():
results.append(net)
break
# asnumber?
m = re.match("^(?:AS)?(\d+)$", rawValue)
if m:
# asnumber!
num = int(m.group(1))
obj = whoisdb.models.ASNumber.objects.filter(number=num)
results.extend(obj)
# find a matching block
blocks = whoisdb.models.ASBlock.objects.filter(asBegin__lte=num, asEnd__gte=num).annotate(size=F('asEnd')-F('asBegin')).order_by('size')
if blocks.count() > 0:
results.append(blocks[0])
# asblocks? smallest asblock containing the range
# WHEN anotation foo... could also be done in asnumber match
# also look for number - number queries?
# domain?
if rawValue.endswith("DN") or rawValue.endswith("DN."):
value = rawValue.lower()
if not value.endswith("."):
value += "."
obj = domains.models.Domain.objects.filter(name=value)
results.extend(obj)
# contact by name?
# handlenames for Maintainer, Contact, InetNum, ASNumber, ASBlock
handleObjs = [
whoisdb.models.Contact,
whoisdb.models.Maintainer,
whoisdb.models.InetNum,
whoisdb.models.ASBlock,
whoisdb.models.ASNumber,
]
for handleObj in handleObjs:
obj = handleObj.objects.filter(handle=rawValue)
if not obj and len(rawValue) >= 3:
obj = handleObj.objects.filter(handle__startswith=rawValue)
results.extend(obj)
return results
# is this an ip address?
rawValue = rawValue.strip().upper()
value = None
results = []
# try subnetwork
try:
value = ipaddress.ip_network(rawValue, strict=False)
except ValueError:
pass
if value:
# ssubnet
obj = whoisdb.models.InetNum.objects.filter(address=str(value.network_address), netmask=value.prefixlen)
results.extend(obj)
# single ip
value = None
try:
value = ipaddress.ip_address(rawValue)
except ValueError:
pass
if value:
# NOTE: this is only for "small subnets", we could increase this...
baseaddr = None
if value.version == 4:
basenet = ipaddress.ip_network("%s/24" % value, strict=False)
baseaddr = ".".join(str(basenet).split(".")[0:3]) + "."
else:
basenet = ipaddress.ip_network("%s/56" % value.exploded, strict=False)
baseaddr = ":".join(str(basenet).split(":")[0:4])[-2]
nets = whoisdb.models.InetNum.objects.filter(address__startswith=baseaddr).order_by("-netmask")
for net in nets:
if value in net.getNetwork():
results.append(net)
break
# asnumber?
m = re.match("^(?:AS)?(\d+)$", rawValue)
if m:
# asnumber!
num = int(m.group(1))
obj = whoisdb.models.ASNumber.objects.filter(number=num)
results.extend(obj)
# find a matching block
blocks = whoisdb.models.ASBlock.objects.filter(asBegin__lte=num, asEnd__gte=num).annotate(size=F('asEnd')-F('asBegin')).order_by('size')
if blocks.count() > 0:
results.append(blocks[0])
# asblocks? smallest asblock containing the range
# WHEN anotation foo... could also be done in asnumber match
# also look for number - number queries?
# domain?
if rawValue.endswith("DN") or rawValue.endswith("DN."):
value = rawValue.lower()
if not value.endswith("."):
value += "."
obj = domains.models.Domain.objects.filter(name=value)
results.extend(obj)
# contact by name?
# handlenames for Maintainer, Contact, InetNum, ASNumber, ASBlock
handleObjs = [
whoisdb.models.Contact,
whoisdb.models.Maintainer,
whoisdb.models.InetNum,
whoisdb.models.ASBlock,
whoisdb.models.ASNumber,
]
for handleObj in handleObjs:
obj = handleObj.objects.filter(handle=rawValue)
if not obj and len(rawValue) >= 3:
obj = handleObj.objects.filter(handle__startswith=rawValue)
results.extend(obj)
return results
def findHandleFromStr(rawValue):
handleObjs = [
whoisdb.models.Contact,
whoisdb.models.Maintainer,
whoisdb.models.InetNum,
whoisdb.models.ASBlock,
whoisdb.models.ASNumber,
]
handleObjs = [
whoisdb.models.Contact,
whoisdb.models.Maintainer,
whoisdb.models.InetNum,
whoisdb.models.ASBlock,
whoisdb.models.ASNumber,
]
for handleObj in handleObjs:
try:
return handleObj.objects.get(handle=rawValue)
except handleObj.DoesNotExist:
pass
for handleObj in handleObjs:
try:
return handleObj.objects.get(handle=rawValue)
except handleObj.DoesNotExist:
pass
return None
return None
def orderQueryset(qs, userOwned, objOwned):
# when for
whens = [When(userOwned, then=2)]
if objOwned:
# add existing
whens.append(When(objOwned, then=1))
# when for
whens = [When(userOwned, then=2)]
if objOwned:
# add existing
whens.append(When(objOwned, then=1))
qs = qs.annotate(card=Max(Case(*whens, default=0, output_field=IntegerField()))).order_by("-card")
qs = qs.annotate(card=Max(Case(*whens, default=0, output_field=IntegerField()))).order_by("-card")
return qs
return qs

@ -13,269 +13,269 @@ import ipaddress
class WhoisObject(models.Model):
class Meta:
abstract = True
handleSuffix = ""
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)
#def __init__(self, *args, **kwargs):
# super(WhoisObject, self).__init__(*args, **kwargs)
# if getattr(self, "handle"):
# field = self._meta.get_field("handle")
# if HandleValidatorWithSuffix not in map(type, field.validators):
# print(self.handle, "NOOOOT")
# field.validators.append(HandleValidatorWithSuffix(self.handleSuffix))
# else:
# print(self.handle, list(map(type, field.validators)))
def getPK(self):
return self.handle
def __str__(self):
return self.handle
def getAppName(self):
return "whoisdb"
def getClassName(self):
return self._meta.object_name
def genHandle(self, main=None):
if not main:
main = self.name
return self.genGenericHandle(main)
@classmethod
def genGenericHandle(clazz, main):
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
handle = "%s%%d-%s" % (prefix, clazz.handleSuffix)
while True:
try:
prefix
clazz.objects.get(handle=handle % i)
i += 1
except clazz.DoesNotExist:
break
return handle % i
def getNoDeleteReasons(self):
raise NotImplementedError("Delete reason checking is not implemented for this model")
def canBeDeleted(self):
return not bool(self.getNoDeleteReasons())
def handleAuto(self, name=None):
if self.handle == "AUTO":
self.handle = self.genHandle(name)
class Meta:
abstract = True
handleSuffix = ""
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)
#def __init__(self, *args, **kwargs):
# super(WhoisObject, self).__init__(*args, **kwargs)
# if getattr(self, "handle"):
# field = self._meta.get_field("handle")
# if HandleValidatorWithSuffix not in map(type, field.validators):
# print(self.handle, "NOOOOT")
# field.validators.append(HandleValidatorWithSuffix(self.handleSuffix))
# else:
# print(self.handle, list(map(type, field.validators)))
def getPK(self):
return self.handle
def __str__(self):
return self.handle
def getAppName(self):
return "whoisdb"
def getClassName(self):
return self._meta.object_name
def genHandle(self, main=None):
if not main:
main = self.name
return self.genGenericHandle(main)
@classmethod
def genGenericHandle(clazz, main):
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
handle = "%s%%d-%s" % (prefix, clazz.handleSuffix)
while True:
try:
prefix
clazz.objects.get(handle=handle % i)
i += 1
except clazz.DoesNotExist:
break
return handle % i
def getNoDeleteReasons(self):
raise NotImplementedError("Delete reason checking is not implemented for this model")
def canBeDeleted(self):
return not bool(self.getNoDeleteReasons())
def handleAuto(self, name=None):
if self.handle == "AUTO":
self.handle = self.genHandle(name)
class Maintainer(WhoisObject):
handleSuffix = "MNT"
handleSuffix = "MNT"
auth = models.ManyToManyField(User)
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")
auth = models.ManyToManyField(User)
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")
admin_c = models.ManyToManyField("Contact", verbose_name="Administrative Contact")
admin_c = models.ManyToManyField("Contact", verbose_name="Administrative Contact")
rir = models.BooleanField(default=False)
lir = models.BooleanField(default=False)
rir = models.BooleanField(default=False)
lir = models.BooleanField(default=False)
# autoInclude = models.BooleanField(default=True)
# autoInclude = models.BooleanField(default=True)
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
def getNoDeleteReasons(self):
reasons = []
# FIXME: Tempfix for circular dependency problem
import domains.models
# FIXME: Tempfix for circular dependency problem
import domains.models
mntables = [Contact, ASBlock, ASNumber, InetNum, domains.models.Domain, domains.models.Nameserver]
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)
mntables = [Contact, ASBlock, ASNumber, InetNum, domains.models.Domain, domains.models.Nameserver]
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)
return reasons
return reasons
def canEdit(self, user):
return user in self.auth.all()
def canEdit(self, user):
return user in self.auth.all()
class MntdObject(WhoisObject):
class Meta:
abstract = True
class Meta:
abstract = True
mnt_by = models.ManyToManyField(Maintainer, help_text="You can select multiple maintainers here")
mnt_by = models.ManyToManyField(Maintainer, help_text="You can select multiple maintainers here")
def canEdit(self, user):
if not hasattr(user, "maintainer_set"):
return False
def canEdit(self, user):
if not hasattr(user, "maintainer_set"):
return False
mnts = user.maintainer_set.all()
objmnts = self.mnt_by.all()
if hasattr(self, "mnt_lower"):
objmnts |= self.mnt_lower.all()
mnts = user.maintainer_set.all()
objmnts = self.mnt_by.all()
if hasattr(self, "mnt_lower"):
objmnts |= self.mnt_lower.all()
for objmnt in objmnts:
if objmnt in mnts:
return True
return False
for objmnt in objmnts:
if objmnt in mnts:
return True
return False
@classmethod
def getMntQueryset(clazz, mnts, instance, attr=None):
mntQ = Q(mnt_by__in=mnts)
if hasattr(clazz, "mnt_lower"):
mntQ |= Q(mnt_lower__in=mnts)
@classmethod
def getMntQueryset(clazz, mnts, instance, attr=None):
mntQ = Q(mnt_by__in=mnts)
if hasattr(clazz, "mnt_lower"):
mntQ |= Q(mnt_lower__in=mnts)
qs = clazz.objects.filter(mntQ)
if attr and instance and instance.pk:
if type(instance._meta.get_field(attr)) == models.ManyToManyField:
qs |= getattr(instance, attr).all()
elif getattr(instance, attr) is not None:
qs |= clazz.objects.filter(pk=getattr(instance, attr).pk)
qs = clazz.objects.filter(mntQ)
if attr and instance and instance.pk:
if type(instance._meta.get_field(attr)) == models.ManyToManyField:
qs |= getattr(instance, attr).all()
elif getattr(instance, attr) is not None:
qs |= clazz.objects.filter(pk=getattr(instance, attr).pk)
return qs.distinct()
return qs.distinct()
class Contact(MntdObject):
handleSuffix = "DN"
TYPE_PERSON = 'PERSON'
TYPE_ROLE = 'ROLE'
TYPE = (('person', TYPE_PERSON), ('role', TYPE_ROLE))
TYPE = (('person', TYPE_PERSON),)
handleSuffix = "DN"
TYPE_PERSON = 'PERSON'
TYPE_ROLE = 'ROLE'
TYPE = (('person', TYPE_PERSON), ('role', TYPE_ROLE))
TYPE = (('person', TYPE_PERSON),)
name = models.CharField(max_length=128)
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
name = models.CharField(max_length=128)
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
def getNoDeleteReasons(self):
reasons = []
contactables = [Maintainer, ASBlock, ASNumber, InetNum]
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)
contactables = [Maintainer, ASBlock, ASNumber, InetNum]
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)
return reasons
return reasons
class ASBlock(MntdObject):
handleSuffix = "ASB"
handleSuffix = "ASB"
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()
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
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()
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asblock_set', blank=True)
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asblock_set', blank=True)
def contains(self, block):
return self.asBegin <= block.asBegin <= self.asEnd and self.asBegin <= block.asEnd <= self.asEnd
def contains(self, block):
return self.asBegin <= block.asBegin <= self.asEnd and self.asBegin <= block.asEnd <= self.asEnd
def getResource(self):
return "%s - %s" % (self.asBegin, self.asEnd)
def getResource(self):
return "%s - %s" % (self.asBegin, self.asEnd)
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
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.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()))))
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
return reasons
class ASNumber(MntdObject):
handleSuffix = "AS"
handleSuffix = "AS"
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)")
asblock = models.ForeignKey(ASBlock, models.CASCADE)
name = models.CharField(max_length=32)
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
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)")
asblock = models.ForeignKey(ASBlock, models.CASCADE)
name = models.CharField(max_length=32)
description = models.CharField(max_length=64, blank=True)
admin_c = models.ManyToManyField("Contact")
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asnumber_set', blank=True)
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_asnumber_set', blank=True)
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def getNoDeleteReasons(self):
reasons = []
def getNoDeleteReasons(self):
reasons = []
return reasons
return reasons
def getResource(self):
return str(self.number)
def getResource(self):
return str(self.number)
class InetNum(MntdObject):
class Meta:
unique_together = (
("address", "netmask"),
)
class Meta:
unique_together = (
("address", "netmask"),
)
handleSuffix = "NET"
handleSuffix = "NET"
IPv4 = "ipv4"
IPv6 = "ipv6"
IPv4 = "ipv4"
IPv6 = "ipv6"
PROTO = ((IPv4, 'IPv4'), (IPv6, 'IPv6'))
protocol = models.CharField(max_length=4, choices=PROTO)
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)
origin_as = models.ManyToManyField(ASNumber, blank=True)
admin_c = models.ManyToManyField("Contact")
PROTO = ((IPv4, 'IPv4'), (IPv6, 'IPv6'))
protocol = models.CharField(max_length=4, choices=PROTO)
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)
origin_as = models.ManyToManyField(ASNumber, blank=True)
admin_c = models.ManyToManyField("Contact")
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_inetnum_set', blank=True)
mnt_lower = models.ManyToManyField(Maintainer, related_name='lower_inetnum_set', blank=True)
def getResource(self):
return self.prefix()
def getResource(self):
return self.prefix()
def prefix(self):
""" Helper function, mainly used in templates """
return "%s/%s" % (self.address, self.netmask)
def prefix(self):
""" Helper function, mainly used in templates """
return "%s/%s" % (self.address, self.netmask)
def getNetwork(self):
return ipaddress.ip_network(self.prefix())
def getNetwork(self):
return ipaddress.ip_network(self.prefix())
def get_absolute_url(self):
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
def get_absolute_url(self):
return reverse("whoisdb:handle-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())))
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
return reasons

@ -9,44 +9,44 @@ register = template.Library()
@register.filter
def linkObject(value):
return mark_safe('<a href="%s">%s</a>' % (value.get_absolute_url(), str(value)))
return mark_safe('<a href="%s">%s</a>' % (value.get_absolute_url(), str(value)))
@register.filter
def tryLinkHandle(handle):
try:
if not handle:
raise ValueError()
HandleValidator()(str(handle))
obj = findHandleFromStr(handle)
if obj:
return linkObject(obj)
except:
pass
try:
if not handle:
raise ValueError()
HandleValidator()(str(handle))
obj = findHandleFromStr(handle)
if obj:
return linkObject(obj)
except:
pass
return handle
return handle
@register.filter
def linkObjects(value):
links = []
for obj in value:
if hasattr(obj, "get_absolute_url"):
links.append('<a href="%s">%s</a>' % (obj.get_absolute_url(), str(obj)))
else:
links.append(str(obj))
links = []
for obj in value:
if hasattr(obj, "get_absolute_url"):
links.append('<a href="%s">%s</a>' % (obj.get_absolute_url(), str(obj)))
else:
links.append(str(obj))
return mark_safe(", ".join(links))
return mark_safe(", ".join(links))
@register.filter
def getFields(value, user):
owner = value.canEdit(user)
owner = value.canEdit(user)
return getWhoisObjectFields(value, owner)
return getWhoisObjectFields(value, owner)
@register.filter
def userCanEdit(value, user):
if hasattr(value, "canEdit"):
return value.canEdit(user)
return False
if hasattr(value, "canEdit"):
return value.canEdit(user)
return False

@ -7,40 +7,40 @@ from django.conf.urls import url
from . import views as whoisdb_views
urlpatterns = [
url(r'^$', whoisdb_views.dbDashboard, name='dashboard'),
url(r'^$', whoisdb_views.dbDashboard, name='dashboard'),
url(r'^search/$', whoisdb_views.searchObject, name='search'),
url(r'^search/$', whoisdb_views.searchObject, name='search'),
url(r'^create/$', whoisdb_views.createObjectOverview, name='createObjectOverview'),
url(r'^handle/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.showHandle, name='showhandle'),
url(r'^handle/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.showHandle, name='handle-detail'),
url(r'^create/$', whoisdb_views.createObjectOverview, name='createObjectOverview'),
url(r'^handle/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.showHandle, name='showhandle'),
url(r'^handle/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.showHandle, name='handle-detail'),
url(r'^mnt/create/$', whoisdb_views.MaintainerCreate.as_view(), name='maintainer-create'),
url(r'^mnt/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerDetail.as_view(), name='maintainer-detail'),
url(r'^mnt/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerEdit.as_view(), name='maintainer-edit'),
url(r'^mnt/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerDelete.as_view(), name='maintainer-delete'),
url(r'^mnt/create/$', whoisdb_views.MaintainerCreate.as_view(), name='maintainer-create'),
url(r'^mnt/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerDetail.as_view(), name='maintainer-detail'),
url(r'^mnt/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerEdit.as_view(), name='maintainer-edit'),
url(r'^mnt/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.MaintainerDelete.as_view(), name='maintainer-delete'),
url(r'^contact/create/$', whoisdb_views.ContactCreate.as_view(), name='contact-create'),
url(r'^contact/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDetail.as_view(), name='contact-detail'),
url(r'^contact/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactEdit.as_view(), name='contact-edit'),
url(r'^contact/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDelete.as_view(), name='contact-delete'),
url(r'^contact/create/$', whoisdb_views.ContactCreate.as_view(), name='contact-create'),
url(r'^contact/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactDetail.as_view(), name='contact-detail'),
url(r'^contact/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ContactEdit.as_view(), name='contact-edit'),
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.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'),
url(r'^inetnum/create/$', whoisdb_views.InetNumCreate.as_view(), name='inetnum-create'),
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'),
url(r'^asblock/create/$', whoisdb_views.ASBlockCreate.as_view(), name='asblock-create'),
url(r'^asblock/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockDetail.as_view(), name='asblock-detail'),
url(r'^asblock/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockEdit.as_view(), name='asblock-edit'),
url(r'^asblock/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockDelete.as_view(), name='asblock-delete'),
url(r'^asblock/create/$', whoisdb_views.ASBlockCreate.as_view(), name='asblock-create'),
url(r'^asblock/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockDetail.as_view(), name='asblock-detail'),
url(r'^asblock/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockEdit.as_view(), name='asblock-edit'),
url(r'^asblock/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASBlockDelete.as_view(), name='asblock-delete'),
url(r'^asnumber/create/$', whoisdb_views.ASNumberCreate.as_view(), name='asnumber-create'),
url(r'^asnumber/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDetail.as_view(), name='asnumber-detail'),
url(r'^asnumber/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberEdit.as_view(), name='asnumber-edit'),
url(r'^asnumber/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDelete.as_view(), name='asnumber-delete'),
url(r'^asnumber/create/$', whoisdb_views.ASNumberCreate.as_view(), name='asnumber-create'),
url(r'^asnumber/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDetail.as_view(), name='asnumber-detail'),
url(r'^asnumber/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberEdit.as_view(), name='asnumber-edit'),
url(r'^asnumber/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDelete.as_view(), name='asnumber-delete'),
url(r'^assubnetset/create/$', whoisdb_views.ASAndSubnetWizard.as_view(), name='asandsubnet-wizard'),
url(r'^assubnetset/create/$', whoisdb_views.ASAndSubnetWizard.as_view(), name='asandsubnet-wizard'),
]

@ -14,31 +14,31 @@ import ipaddress
@deconstructible
class HandleValidator(validators.RegexValidator):
regex = r'^(?:[A-Z]+[0-9]*(-[A-Z]+)|AUTO)$'
message = _(
'Enter a valid handle (all uppercase)'
)
flags = re.ASCII if six.PY3 else 0
regex = r'^(?:[A-Z]+[0-9]*(-[A-Z]+)|AUTO)$'
message = _(
'Enter a valid handle (all uppercase)'
)
flags = re.ASCII if six.PY3 else 0
@deconstructible
class HandleValidatorWithSuffix(validators.RegexValidator):
flags = re.ASCII if six.PY3 else 0
flags = re.ASCII if six.PY3 else 0
def __init__(self, suffix):
self.regex = r'^(?:[A-Z]+[0-9]*-%s|AUTO)$' % re.escape(suffix)
self.message = _(
'Enter a valid handle with suffix %s (all uppercase), e.g. FOO3-%s' % (suffix, suffix)
)
def __init__(self, suffix):
self.regex = r'^(?:[A-Z]+[0-9]*-%s|AUTO)$' % re.escape(suffix)
self.message = _(
'Enter a valid handle with suffix %s (all uppercase), e.g. FOO3-%s' % (suffix, suffix)
)
super(HandleValidatorWithSuffix, self).__init__()
super(HandleValidatorWithSuffix, self).__init__()
def IP46CIDRValidator(value):
if not re.match(r"[0-9a-fA-F:.]+/[0-9]+", value):
raise ValidationError("Address needs to be a subnet in the format of ip/prefix")
if not re.match(r"[0-9a-fA-F:.]+/[0-9]+", value):
raise ValidationError("Address needs to be a subnet in the format of ip/prefix")
try:
ipaddress.ip_network(value)
except ValueError as e:
raise ValidationError(str(e))
try:
ipaddress.ip_network(value)
except ValueError as e:
raise ValidationError(str(e))

@ -20,349 +20,349 @@ from .helpers import findInDatabase
@login_required
def createObjectOverview(request):
mnts = request.user.maintainer_set.filter().all()
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()
mnts = request.user.maintainer_set.filter().all()
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()
return render(request, "whoisdb/create_overview.html", {"netblocks": netblocks, "asblocks": asblocks})
return render(request, "whoisdb/create_overview.html", {"netblocks": netblocks, "asblocks": asblocks})
@login_required
def dbDashboard(request):
mnts = request.user.maintainer_set.filter(rir=False, lir=False).all()
if request.GET.get("delegated", None) or mnts.count() == 0:
# if user wants to see rir/lir objects or only has rir/lir mnts, use all available mnts
mnts = request.user.maintainer_set.all()
showDelegations = True
else:
showDelegations = False
hasDelegations = request.user.maintainer_set.filter(Q(rir=True) | Q(lir=True)).count() > 0
contacts = Contact.objects.filter(mnt_by__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:
mntForm = contactForm = None
if request.method == "POST":
mntForm = MntInitialForm(user=request.user, data=request.POST, prefix="mnt")
contactForm = ContactInitialForm(user=request.user, data=request.POST, prefix="contact")
if mntForm.is_valid() and contactForm.is_valid():
mnt = mntForm.save(commit=False)
mnt.handleAuto(request.user.username)
mnt.save()
contact = contactForm.save(commit=False)
contact.handleAuto()
contact.type = Contact.TYPE_PERSON
contact.save()
contact.mnt_by.add(mnt.id)
contact.save()
mnt.auth.add(request.user.id)
mnt.admin_c.add(contact.id)
mnt.save()
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
else:
mntForm = MntInitialForm(user=request.user, prefix="mnt", initial={'handle': 'AUTO', 'description': 'Primary maintainer of %s' % request.user.username})
contactForm = ContactInitialForm(user=request.user, initial={'handle': 'AUTO', 'name': request.user.username.capitalize()}, prefix='contact')
return render(request, "whoisdb/overview.html", {"mnts": mnts, "contacts": contacts, "mntForm": mntForm, "contactForm": contactForm, "netblocks": netblocks, "asblocks": asblocks, "asnumbers": asnumbers, 'hasDelegations': hasDelegations, "showDelegations": showDelegations})
mnts = request.user.maintainer_set.filter(rir=False, lir=False).all()
if request.GET.get("delegated", None) or mnts.count() == 0:
# if user wants to see rir/lir objects or only has rir/lir mnts, use all available mnts
mnts = request.user.maintainer_set.all()
showDelegations = True
else:
showDelegations = False
hasDelegations = request.user.maintainer_set.filter(Q(rir=True) | Q(lir=True)).count() > 0
contacts = Contact.objects.filter(mnt_by__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:
mntForm = contactForm = None
if request.method == "POST":
mntForm = MntInitialForm(user=request.user, data=request.POST, prefix="mnt")
contactForm = ContactInitialForm(user=request.user, data=request.POST, prefix="contact")
if mntForm.is_valid() and contactForm.is_valid():
mnt = mntForm.save(commit=False)
mnt.handleAuto(request.user.username)
mnt.save()
contact = contactForm.save(commit=False)
contact.handleAuto()
contact.type = Contact.TYPE_PERSON
contact.save()
contact.mnt_by.add(mnt.id)
contact.save()
mnt.auth.add(request.user.id)
mnt.admin_c.add(contact.id)
mnt.save()
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
else:
mntForm = MntInitialForm(user=request.user, prefix="mnt", initial={'handle': 'AUTO', 'description': 'Primary maintainer of %s' % request.user.username})
contactForm = ContactInitialForm(user=request.user, initial={'handle': 'AUTO', 'name': request.user.username.capitalize()}, prefix='contact')
return render(request, "whoisdb/overview.html", {"mnts": mnts, "contacts": contacts, "mntForm": mntForm, "contactForm": contactForm, "netblocks": netblocks, "asblocks": asblocks, "asnumbers": asnumbers, 'hasDelegations': hasDelegations, "showDelegations": showDelegations})
def showHandle(request, handle):
# a) find handle
models = [Contact, Maintainer, ASBlock, ASNumber, InetNum]
obj = None
# a) find handle
models = [Contact, Maintainer, ASBlock, ASNumber, InetNum]
obj = None
for model in models:
if handle.endswith(model.handleSuffix):
obj = get_object_or_404(model, handle=handle)
break
for model in models:
if handle.endswith(model.handleSuffix):
obj = get_object_or_404(model, handle=handle)
break
if not obj:
raise Http404("Handle object not found")
if not obj:
raise Http404("Handle object not found")
return render(request, "whoisdb/handle_show.html", {"object": obj})
return render(request, "whoisdb/handle_show.html", {"object": obj})
def searchObject(request):
results = None
term = request.GET.get("q", None)
if term:
results = findInDatabase(term)
return render(request, "whoisdb/search.html", {"results": results, "term": term})
results = None
term = request.GET.get("q", None)
if term:
results = findInDatabase(term)
return render(request, "whoisdb/search.html", {"results": results, "term": term})
class MaintainerCreate(LoginRequiredMixin, CreateView):
template_name = "whoisdb/obj_create.html"
form_class = MntForm
template_name = "whoisdb/obj_create.html"
form_class = MntForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MaintainerCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
#"auth": self.request.user.username,
}
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MaintainerCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
#"auth": self.request.user.username,
}
return kwargs
return kwargs
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.handleAuto(self.request.user.username)
self.object.save()
self.object.auth.add(self.request.user)
self.object.save()
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.handleAuto(self.request.user.username)
self.object.save()
self.object.auth.add(self.request.user)
self.object.save()
return super(MaintainerCreate, self).form_valid(form)
return super(MaintainerCreate, self).form_valid(form)
class MaintainerEdit(LoginRequiredMixin, UpdateView):
template_name = "whoisdb/obj_edit.html"
model = Maintainer
form_class = MntForm
slug_field = "handle"
slug_url_kwarg = "handle"
template_name = "whoisdb/obj_edit.html"
model = Maintainer
form_class = MntForm
slug_field = "handle"
slug_url_kwarg = "handle"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MaintainerEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(MaintainerEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
def get_queryset(self):
return self.model.objects.filter(auth=self.request.user)
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
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
template_name = "whoisdb/obj_delete.html"
model = Maintainer
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
def get_queryset(self):
return self.model.objects.filter(auth=self.request.user)
def get_queryset(self):
return self.model.objects.filter(auth=self.request.user)
class MaintainerDetail(LoginRequiredMixin, DetailView):
template_name = "whoisdb/handle_show.html"
model = Maintainer
slug_field = "handle"
slug_url_kwarg = "handle"
#context_object_name = "mnt"
template_name = "whoisdb/handle_show.html"
model = Maintainer
slug_field = "handle"
slug_url_kwarg = "handle"
#context_object_name = "mnt"
class ContactDetail(DetailView):
model = Contact
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "contact"
model = Contact
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "contact"
class ContactEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
template_name = "whoisdb/obj_edit.html"
model = Contact
form_class = ContactForm
slug_field = "handle"
slug_url_kwarg = "handle"
template_name = "whoisdb/obj_edit.html"
model = Contact
form_class = ContactForm
slug_field = "handle"
slug_url_kwarg = "handle"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ContactEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ContactEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
class ContactCreate(LoginRequiredMixin, CreateView):
template_name = "whoisdb/obj_create.html"
form_class = ContactForm
template_name = "whoisdb/obj_create.html"
form_class = ContactForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ContactCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
"type": Contact.TYPE_PERSON
}
return kwargs
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ContactCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
"type": Contact.TYPE_PERSON
}
return kwargs
class ContactDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "whoisdb/obj_delete.html"
model = Contact
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
template_name = "whoisdb/obj_delete.html"
model = Contact
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
# InetNum
class InetNumCreate(LoginRequiredMixin, CreateView):
template_name = "whoisdb/obj_create.html"
form_class = InetNumForm
template_name = "whoisdb/obj_create.html"
form_class = InetNumForm
def get_form_kwargs(self, *args, **kwargs):
print("NOOOOOOOOOOOOOOOOOOOOOOOOOOOOT", args, kwargs)
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
def get_form_kwargs(self, *args, **kwargs):
print("NOOOOOOOOOOOOOOOOOOOOOOOOOOOOT", args, kwargs)
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
return kwargs
return kwargs
class InetNumDetail(DetailView):
model = InetNum
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "inetnum"
model = InetNum
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "inetnum"
class InetNumEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
template_name = "whoisdb/obj_edit.html"
model = InetNum
form_class = InetNumForm
slug_field = "handle"
slug_url_kwarg = "handle"
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
kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(InetNumEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
return kwargs
return kwargs
class InetNumDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "whoisdb/obj_delete.html"
model = InetNum
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
template_name = "whoisdb/obj_delete.html"
model = InetNum
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
# asblock
class ASBlockCreate(LoginRequiredMixin, CreateView):
template_name = "whoisdb/obj_create.html"
form_class = ASBlockForm
template_name = "whoisdb/obj_create.html"
form_class = ASBlockForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASBlockCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASBlockCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
return kwargs
return kwargs
class ASBlockDetail(DetailView):
model = ASBlock
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "asblock"
model = ASBlock
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "asblock"
class ASBlockEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
template_name = "whoisdb/obj_edit.html"
model = ASBlock
form_class = ASBlockForm
slug_field = "handle"
slug_url_kwarg = "handle"
template_name = "whoisdb/obj_edit.html"
model = ASBlock
form_class = ASBlockForm
slug_field = "handle"
slug_url_kwarg = "handle"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASBlockEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
#kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASBlockEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
#kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
return kwargs
return kwargs
class ASBlockDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "whoisdb/obj_delete.html"
model = ASBlock
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
template_name = "whoisdb/obj_delete.html"
model = ASBlock
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
# asnumber
class ASNumberCreate(LoginRequiredMixin, CreateView):
template_name = "whoisdb/obj_create.html"
form_class = ASNumberForm
template_name = "whoisdb/obj_create.html"
form_class = ASNumberForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASNumberCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASNumberCreate, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
kwargs["initial"] = {
"handle": "AUTO",
}
return kwargs
return kwargs
class ASNumberDetail(DetailView):
model = ASNumber
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "asnumber"
model = ASNumber
slug_field = "handle"
slug_url_kwarg = "handle"
context_object_name = "asnumber"
class ASNumberEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
template_name = "whoisdb/obj_edit.html"
model = ASNumber
form_class = ASNumberForm
slug_field = "handle"
slug_url_kwarg = "handle"
template_name = "whoisdb/obj_edit.html"
model = ASNumber
form_class = ASNumberForm
slug_field = "handle"
slug_url_kwarg = "handle"
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASNumberEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASNumberEdit, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
return kwargs
class ASNumberDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
template_name = "whoisdb/obj_delete.html"
model = ASNumber
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
template_name = "whoisdb/obj_delete.html"
model = ASNumber
slug_field = "handle"
slug_url_kwarg = "handle"
success_url = reverse_lazy("whoisdb:dashboard")
class ASAndSubnetWizard(LoginRequiredMixin, SessionWizardView):
form_list = [ASNumberForm, InetNumForm]
template_name = "whoisdb/wizard.html"
form_list = [ASNumberForm, InetNumForm]
template_name = "whoisdb/wizard.html"
def get_form_initial(self, step):
return {"handle": "AUTO"}
def get_form_initial(self, step):
return {"handle": "AUTO"}
def done(self, form_list, **kwargs):
fl = list(form_list)
asNum = fl[0].save()
net = fl[1].save()
def done(self, form_list, **kwargs):
fl = list(form_list)
asNum = fl[0].save()
net = fl[1].save()
messages.info(self.request, "The following objects have been created: AS %s %s, Subnet %s %s" % (asNum.handle, asNum.number, net.handle, net.getNetwork()))
messages.info(self.request, "The following objects have been created: AS %s %s, Subnet %s %s" % (asNum.handle, asNum.number, net.handle, net.getNetwork()))
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASAndSubnetWizard, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(ASAndSubnetWizard, self).get_form_kwargs(*args, **kwargs)
kwargs["user"] = self.request.user
return kwargs
return kwargs
def get_context_data(self, *args, **kwargs):
d = super(ASAndSubnetWizard, self).get_context_data(*args, **kwargs)
def get_context_data(self, *args, **kwargs):
d = super(ASAndSubnetWizard, self).get_context_data(*args, **kwargs)
step = d["wizard"]["steps"].step1
if step == 1:
d["message"] = "Create an AS object"
elif step == 2:
d["message"] = "Create a Subnet"
step = d["wizard"]["steps"].step1
if step == 1:
d["message"] = "Create an AS object"
elif step == 2:
d["message"] = "Create a Subnet"
return d
return d

Loading…
Cancel
Save