Merge progress from production system
This commit is contained in:
commit
a3b6209e0a
194
api/dnshelper.py
194
api/dnshelper.py
|
@ -11,121 +11,121 @@ import dns.resolver
|
||||||
# FIXME: DNS timeouts
|
# FIXME: DNS timeouts
|
||||||
|
|
||||||
def compareRecords(rrset, expected):
|
def compareRecords(rrset, expected):
|
||||||
result = {
|
result = {
|
||||||
"nameMissing": [],
|
"nameMissing": [],
|
||||||
"rrMissing": [],
|
"rrMissing": [],
|
||||||
"rrExtra": [],
|
"rrExtra": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
for domain, rrtype, content in expected:
|
for domain, rrtype, content in expected:
|
||||||
for rrrec in rrset:
|
for rrrec in rrset:
|
||||||
if domain == rrrec.name.to_text() and dns.rdatatype.from_text(rrtype) == rrrec.rdtype:
|
if domain == rrrec.name.to_text() and dns.rdatatype.from_text(rrtype) == rrrec.rdtype:
|
||||||
for name in content:
|
for name in content:
|
||||||
if name not in map(lambda _x: _x.to_text(), rrrec.items):
|
if name not in map(lambda _x: _x.to_text(), rrrec.items):
|
||||||
# record missing
|
# record missing
|
||||||
result["rrMissing"].append((domain, rrtype, name))
|
result["rrMissing"].append((domain, rrtype, name))
|
||||||
|
|
||||||
for item in rrrec.items:
|
for item in rrrec.items:
|
||||||
if item.to_text() not in content:
|
if item.to_text() not in content:
|
||||||
# superfluous record
|
# superfluous record
|
||||||
result["rrExtra"].append((domain, rrtype, item.to_text()))
|
result["rrExtra"].append((domain, rrtype, item.to_text()))
|
||||||
|
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# domain + rr nicht in nameserver
|
# domain + rr nicht in nameserver
|
||||||
result["nameMissing"].append((domain, rrtype))
|
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):
|
def dnsQuery(domain, rrType, nameserverIp):
|
||||||
dname = dns.name.from_text(domain)
|
dname = dns.name.from_text(domain)
|
||||||
req = dns.message.make_query(dname, dns.rdatatype.from_text(rrType))
|
req = dns.message.make_query(dname, dns.rdatatype.from_text(rrType))
|
||||||
resp = dns.query.udp(req, nameserverIp, timeout=2.0)
|
resp = dns.query.udp(req, nameserverIp, timeout=2.0)
|
||||||
|
|
||||||
if resp.rcode() != dns.rcode.NXDOMAIN:
|
if resp.rcode() != dns.rcode.NXDOMAIN:
|
||||||
rrset = resp.answer + resp.authority + resp.additional
|
rrset = resp.answer + resp.authority + resp.additional
|
||||||
return True, rrset
|
return True, rrset
|
||||||
else:
|
else:
|
||||||
return False, []
|
return False, []
|
||||||
|
|
||||||
|
|
||||||
def checkDomain(domain, tldNameserver, nameservers):
|
def checkDomain(domain, tldNameserver, nameservers):
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
if nameservers.count() == 0:
|
if nameservers.count() == 0:
|
||||||
return [("err", "Domain %s has no nameservers attached to it, nothing to check" % domain)]
|
return [("err", "Domain %s has no nameservers attached to it, nothing to check" % domain)]
|
||||||
|
|
||||||
# build record set
|
# build record set
|
||||||
nsRecords = [(domain, "NS", list(ns.name for ns in nameservers))]
|
nsRecords = [(domain, "NS", list(ns.name for ns in nameservers))]
|
||||||
glueRecords = []
|
glueRecords = []
|
||||||
for ns in nameservers:
|
for ns in nameservers:
|
||||||
if ns.name.endswith("." + domain):
|
if ns.name.endswith("." + domain):
|
||||||
if ns.glueIPv4 or ns.glueIPv6:
|
if ns.glueIPv4 or ns.glueIPv6:
|
||||||
if ns.glueIPv4:
|
if ns.glueIPv4:
|
||||||
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
|
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
|
||||||
if ns.glueIPv6:
|
if ns.glueIPv6:
|
||||||
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
|
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
|
||||||
else:
|
else:
|
||||||
result.append(("err", "Nameserver %s is under domain %s, but has no glue entries." % (ns.name, domain)))
|
result.append(("err", "Nameserver %s is under domain %s, but has no glue entries." % (ns.name, domain)))
|
||||||
|
|
||||||
# 1. TLD nameserver
|
# 1. TLD nameserver
|
||||||
try:
|
try:
|
||||||
found, rrset = dnsQuery(domain, "ANY", tldNameserver)
|
found, rrset = dnsQuery(domain, "ANY", tldNameserver)
|
||||||
if found:
|
if found:
|
||||||
success, errors = compareRecords(rrset, nsRecords + glueRecords)
|
success, errors = compareRecords(rrset, nsRecords + glueRecords)
|
||||||
if success:
|
if success:
|
||||||
result.append(("succ", "All records present in TLD nameserver"))
|
result.append(("succ", "All records present in TLD nameserver"))
|
||||||
else:
|
else:
|
||||||
result.append(("err", "Record mismatch between TLD nameserver and WHOIS database", errors))
|
result.append(("err", "Record mismatch between TLD nameserver and WHOIS database", errors))
|
||||||
else:
|
else:
|
||||||
result.append(("err", "Domain %s not found in TLD nameserver" % (domain,)))
|
result.append(("err", "Domain %s not found in TLD nameserver" % (domain,)))
|
||||||
except (dns.exception.Timeout, OSError):
|
except (dns.exception.Timeout, OSError):
|
||||||
result.append(("err", "TLD nameserver is currently not reachable"))
|
result.append(("err", "TLD nameserver is currently not reachable"))
|
||||||
|
|
||||||
# find other records...
|
# find other records...
|
||||||
|
|
||||||
# 2. your nameservers
|
# 2. your nameservers
|
||||||
for ns in nameservers:
|
for ns in nameservers:
|
||||||
addr = None
|
addr = None
|
||||||
if ns.glueIPv4:
|
if ns.glueIPv4:
|
||||||
addr = ns.glueIPv4
|
addr = ns.glueIPv4
|
||||||
elif ns.glueIPv6:
|
elif ns.glueIPv6:
|
||||||
addr = ns.glueIPv6
|
addr = ns.glueIPv6
|
||||||
else:
|
else:
|
||||||
for rrType in ("A", "AAAA"):
|
for rrType in ("A", "AAAA"):
|
||||||
try:
|
try:
|
||||||
r = dns.resolver.Resolver()
|
r = dns.resolver.Resolver()
|
||||||
r.timeout = 2.0
|
r.timeout = 2.0
|
||||||
q = r.query(ns.name, rdtype=dns.rdatatype.from_text(rrType))
|
q = r.query(ns.name, rdtype=dns.rdatatype.from_text(rrType))
|
||||||
addr = q.response.answer[0].items[0].address
|
addr = q.response.answer[0].items[0].address
|
||||||
except (dns.exception.DNSException, OSError):
|
except (dns.exception.DNSException, OSError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if addr:
|
if addr:
|
||||||
err = False
|
err = False
|
||||||
errDict = {"nameMissing": [], "rrMissing": [], "rrExtra": []}
|
errDict = {"nameMissing": [], "rrMissing": [], "rrExtra": []}
|
||||||
try:
|
try:
|
||||||
for rec in (nsRecords + glueRecords):
|
for rec in (nsRecords + glueRecords):
|
||||||
found, rrset = dnsQuery(rec[0], rec[1], addr)
|
found, rrset = dnsQuery(rec[0], rec[1], addr)
|
||||||
|
|
||||||
#success, errors = compareRecords(rrset, nsRecords + glueRecords)
|
#success, errors = compareRecords(rrset, nsRecords + glueRecords)
|
||||||
success, errors = compareRecords(rrset, [rec])
|
success, errors = compareRecords(rrset, [rec])
|
||||||
if not success:
|
if not success:
|
||||||
err = True
|
err = True
|
||||||
for k in errors.keys():
|
for k in errors.keys():
|
||||||
errDict[k].extend(errors[k])
|
errDict[k].extend(errors[k])
|
||||||
|
|
||||||
if not err:
|
if not err:
|
||||||
result.append(("succ", "Nameserver %s is configured correctly" % ns.name))
|
result.append(("succ", "Nameserver %s is configured correctly" % ns.name))
|
||||||
else:
|
else:
|
||||||
result.append(("err", "Nameserver %s (via %s) recordset does not match the database" % (ns.name, addr), errDict))
|
result.append(("err", "Nameserver %s (via %s) recordset does not match the database" % (ns.name, addr), errDict))
|
||||||
except (dns.exception.DNSException, OSError):
|
except (dns.exception.DNSException, OSError):
|
||||||
result.append(("err", "Nameserver %s is not reachable (via %s)" % (ns.name, addr)))
|
result.append(("err", "Nameserver %s is not reachable (via %s)" % (ns.name, addr)))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
result.append(("err", "Can't resolv an ip address for nameserver %s" % ns.name))
|
result.append(("err", "Can't resolv an ip address for nameserver %s" % ns.name))
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
12
api/urls.py
12
api/urls.py
|
@ -7,13 +7,13 @@ from django.conf.urls import url
|
||||||
from . import views as api_views
|
from . import views as api_views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'asblock/free-as/$', api_views.asblockFreeAS, name='asblock-free-as'),
|
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'asblock/free-subnet/$', api_views.freeSubnet, name='inetnum-free-subnet'),
|
||||||
url(r'inetnum/get-subnet/$', api_views.getSubnet, name='inetnum-get-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'domain/check/$', api_views.checkDomain, name='domain-check'),
|
||||||
url(r'rzone/check/$', api_views.checkRzone, name='reversezone-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'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
336
api/views.py
336
api/views.py
|
@ -19,219 +19,219 @@ import ipaddress
|
||||||
@login_required
|
@login_required
|
||||||
def asblockFreeAS(request):
|
def asblockFreeAS(request):
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
"success": False,
|
"success": False,
|
||||||
"errorMsg": None,
|
"errorMsg": None,
|
||||||
"number": -1,
|
"number": -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
blockName = request.GET.get('block', None)
|
blockName = request.GET.get('block', None)
|
||||||
if not blockName:
|
if not blockName:
|
||||||
raise ValidationError("No block given")
|
raise ValidationError("No block given")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
block = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=blockName)
|
block = ASBlock.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=blockName)
|
||||||
if block.asblock_set.count() > 0:
|
if block.asblock_set.count() > 0:
|
||||||
raise ValidationError("AS Block already has sub AS Blocks")
|
raise ValidationError("AS Block already has sub AS Blocks")
|
||||||
if block.asnumber_set.count() > 0:
|
if block.asnumber_set.count() > 0:
|
||||||
num = block.asnumber_set.order_by("-number")[0].number + 1
|
num = block.asnumber_set.order_by("-number")[0].number + 1
|
||||||
if num > block.asEnd:
|
if num > block.asEnd:
|
||||||
num = None
|
num = None
|
||||||
for n in range(block.asBegin, block.asEnd + 1):
|
for n in range(block.asBegin, block.asEnd + 1):
|
||||||
try:
|
try:
|
||||||
ASNumber.objects.get(number=n)
|
ASNumber.objects.get(number=n)
|
||||||
except ASNumber.DoesNotExist:
|
except ASNumber.DoesNotExist:
|
||||||
num = n
|
num = n
|
||||||
break
|
break
|
||||||
if not num:
|
if not num:
|
||||||
raise ValidationError("No free AS Number in block")
|
raise ValidationError("No free AS Number in block")
|
||||||
ret["number"] = num
|
ret["number"] = num
|
||||||
else:
|
else:
|
||||||
ret["number"] = block.asBegin
|
ret["number"] = block.asBegin
|
||||||
except ASBlock.DoesNotExist:
|
except ASBlock.DoesNotExist:
|
||||||
raise ValidationError("Could not get AS Block")
|
raise ValidationError("Could not get AS Block")
|
||||||
|
|
||||||
ret["success"] = True
|
ret["success"] = True
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
ret["errorMsg"] = e.message
|
ret["errorMsg"] = e.message
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def freeSubnet(request):
|
def freeSubnet(request):
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
"success": False,
|
"success": False,
|
||||||
"errorMsg": None,
|
"errorMsg": None,
|
||||||
"network": None,
|
"network": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parentRangeName = request.GET.get('parentRange', None)
|
parentRangeName = request.GET.get('parentRange', None)
|
||||||
if not parentRangeName:
|
if not parentRangeName:
|
||||||
raise ValidationError("No subnet given")
|
raise ValidationError("No subnet given")
|
||||||
|
|
||||||
parentRange = None
|
parentRange = None
|
||||||
try:
|
try:
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
parentRange = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=parentRangeName)
|
parentRange = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct().get(handle=parentRangeName)
|
||||||
except InetNum.DoesNotExist:
|
except InetNum.DoesNotExist:
|
||||||
raise ValidationError("Parent range does not exist / is not maintained by you")
|
raise ValidationError("Parent range does not exist / is not maintained by you")
|
||||||
|
|
||||||
prefixLen = 0
|
prefixLen = 0
|
||||||
try:
|
try:
|
||||||
prefixLen = request.GET.get("prefixLen", None)
|
prefixLen = request.GET.get("prefixLen", None)
|
||||||
if not prefixLen:
|
if not prefixLen:
|
||||||
if parentRange.protocol == InetNum.IPv4:
|
if parentRange.protocol == InetNum.IPv4:
|
||||||
prefixLen = 27
|
prefixLen = 27
|
||||||
else:
|
else:
|
||||||
prefixLen = 60
|
prefixLen = 60
|
||||||
prefixLen = int(prefixLen)
|
prefixLen = int(prefixLen)
|
||||||
|
|
||||||
if prefixLen < 8 or \
|
if prefixLen < 8 or \
|
||||||
(parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \
|
(parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \
|
||||||
(parentRange.protocol == InetNum.IPv6 and prefixLen > 128):
|
(parentRange.protocol == InetNum.IPv6 and prefixLen > 128):
|
||||||
raise ValidationError("Given prefix length is out of range")
|
raise ValidationError("Given prefix length is out of range")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValidationError("PrefixLen is not a number")
|
raise ValidationError("PrefixLen is not a number")
|
||||||
|
|
||||||
usableNet = None
|
usableNet = None
|
||||||
# FIXME: use first biggest usable netblock...
|
# FIXME: use first biggest usable netblock...
|
||||||
#biggestNet = parentRange.inetnum_set.order_by("-address")
|
#biggestNet = parentRange.inetnum_set.order_by("-address")
|
||||||
#if biggestNet
|
#if biggestNet
|
||||||
# candidateNet =
|
# candidateNet =
|
||||||
# and (biggestNet.getNetwork().broadcast_address.:
|
# and (biggestNet.getNetwork().broadcast_address.:
|
||||||
|
|
||||||
# try using next network in range
|
# try using next network in range
|
||||||
# ordering does not work, as order_by sorts alphabetically
|
# 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
|
# ==> the set is short, we can iterate through all. no sense in unpacking the SQL magic
|
||||||
#biggestNets = parentRange.inetnum_set.order_by("-address")
|
#biggestNets = parentRange.inetnum_set.order_by("-address")
|
||||||
biggestNet = None
|
biggestNet = None
|
||||||
for ipRange in parentRange.inetnum_set.all():
|
for ipRange in parentRange.inetnum_set.all():
|
||||||
if not biggestNet or ipRange.getNetwork() > biggestNet:
|
if not biggestNet or ipRange.getNetwork() > biggestNet:
|
||||||
biggestNet = ipRange.getNetwork()
|
biggestNet = ipRange.getNetwork()
|
||||||
|
|
||||||
if biggestNet:
|
if biggestNet:
|
||||||
candidateNet = ipaddress.ip_network("%s/%s" % (biggestNet.broadcast_address + 1, biggestNet.prefixlen))
|
candidateNet = ipaddress.ip_network("%s/%s" % (biggestNet.broadcast_address + 1, biggestNet.prefixlen))
|
||||||
print("biggest net", biggestNet, "candidate", candidateNet)
|
print("biggest net", biggestNet, "candidate", candidateNet)
|
||||||
if candidateNet.network_address in parentRange.getNetwork():
|
if candidateNet.network_address in parentRange.getNetwork():
|
||||||
usableNet = candidateNet
|
usableNet = candidateNet
|
||||||
|
|
||||||
# check if there are still networks left in range
|
# check if there are still networks left in range
|
||||||
if not usableNet:
|
if not usableNet:
|
||||||
# search for free network
|
# search for free network
|
||||||
nets = list(parentRange.getNetwork().subnets())
|
nets = list(parentRange.getNetwork().subnets())
|
||||||
for subRange in parentRange.inetnum_set.all():
|
for subRange in parentRange.inetnum_set.all():
|
||||||
newNet = None
|
newNet = None
|
||||||
for net in nets:
|
for net in nets:
|
||||||
if subRange.getNetwork().network_address in net:
|
if subRange.getNetwork().network_address in net:
|
||||||
newNet = net
|
newNet = net
|
||||||
if not newNet:
|
if not newNet:
|
||||||
# critical error, we want a 500 here
|
# critical error, we want a 500 here
|
||||||
raise ValueError("Subnet not in range")
|
raise ValueError("Subnet not in range")
|
||||||
|
|
||||||
nets.remove(newNet)
|
nets.remove(newNet)
|
||||||
nets.extend(newNet.address_exclude(subRange.getNetwork()))
|
nets.extend(newNet.address_exclude(subRange.getNetwork()))
|
||||||
|
|
||||||
nets = sorted(nets)
|
nets = sorted(nets)
|
||||||
for net in nets:
|
for net in nets:
|
||||||
if net.prefixlen <= prefixLen:
|
if net.prefixlen <= prefixLen:
|
||||||
usableNet = net
|
usableNet = net
|
||||||
break
|
break
|
||||||
|
|
||||||
if not usableNet:
|
if not usableNet:
|
||||||
raise ValidationError("No space left in given range")
|
raise ValidationError("No space left in given range")
|
||||||
|
|
||||||
ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen)
|
ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen)
|
||||||
ret["success"] = True
|
ret["success"] = True
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
ret["errorMsg"] = e.message
|
ret["errorMsg"] = e.message
|
||||||
|
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def getSubnet(request):
|
def getSubnet(request):
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
"success": False,
|
"success": False,
|
||||||
"errorMsg": None,
|
"errorMsg": None,
|
||||||
"network": None,
|
"network": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
netName = request.GET.get('net', None)
|
netName = request.GET.get('net', None)
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
nets = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
nets = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
||||||
net = nets.get(handle=netName)
|
net = nets.get(handle=netName)
|
||||||
|
|
||||||
ret["success"] = True
|
ret["success"] = True
|
||||||
ret["network"] = net.prefix()
|
ret["network"] = net.prefix()
|
||||||
except InetNum.DoesNotExist:
|
except InetNum.DoesNotExist:
|
||||||
ret["errorMsg"] = "Chosen network does not exist"
|
ret["errorMsg"] = "Chosen network does not exist"
|
||||||
|
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def checkDomain(request):
|
def checkDomain(request):
|
||||||
ret = {
|
ret = {
|
||||||
"success": False,
|
"success": False,
|
||||||
"errorMsg": None,
|
"errorMsg": None,
|
||||||
"domain": None,
|
"domain": None,
|
||||||
"result": None,
|
"result": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
domainName = Domain.fixName(request.GET.get('domain', ''))
|
domainName = Domain.fixName(request.GET.get('domain', ''))
|
||||||
domain = Domain.objects.get(name=domainName)
|
domain = Domain.objects.get(name=domainName)
|
||||||
#if not domain.canEdit(request.user):
|
#if not domain.canEdit(request.user):
|
||||||
# raise Domain.DoesNotExist()
|
# raise Domain.DoesNotExist()
|
||||||
|
|
||||||
ret["success"] = True
|
ret["success"] = True
|
||||||
ret["domain"] = domain.name
|
ret["domain"] = domain.name
|
||||||
# FIXME: change this if we ever have more than one...
|
# FIXME: change this if we ever have more than one...
|
||||||
ret["result"] = helperCheckDomain(domain.name, TLD_NAMESERVERS[0], domain.nameservers.all())
|
ret["result"] = helperCheckDomain(domain.name, TLD_NAMESERVERS[0], domain.nameservers.all())
|
||||||
except Domain.DoesNotExist:
|
except Domain.DoesNotExist:
|
||||||
ret["errorMsg"] = "Domain does not exist"
|
ret["errorMsg"] = "Domain does not exist"
|
||||||
|
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def checkRzone(request):
|
def checkRzone(request):
|
||||||
ret = {
|
ret = {
|
||||||
"success": False,
|
"success": False,
|
||||||
"errorMsg": None,
|
"errorMsg": None,
|
||||||
"domain": None,
|
"domain": None,
|
||||||
"result": None,
|
"result": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rzonePk = int(request.GET.get('domain', ''))
|
rzonePk = int(request.GET.get('domain', ''))
|
||||||
rzone = ReverseZone.objects.get(pk=rzonePk)
|
rzone = ReverseZone.objects.get(pk=rzonePk)
|
||||||
#if not rzone.canEdit(request.user):
|
#if not rzone.canEdit(request.user):
|
||||||
# raise ReverseZone.DoesNotExist()
|
# raise ReverseZone.DoesNotExist()
|
||||||
|
|
||||||
ret["success"] = True
|
ret["success"] = True
|
||||||
# FIXME: change this if we ever have more than one...
|
# FIXME: change this if we ever have more than one...
|
||||||
ret["result"] = helperCheckDomain(rzone.getZone(), TLD_NAMESERVERS[0], rzone.nameservers.all())
|
ret["result"] = helperCheckDomain(rzone.getZone(), TLD_NAMESERVERS[0], rzone.nameservers.all())
|
||||||
except (ReverseZone.DoesNotExist, ValueError):
|
except (ReverseZone.DoesNotExist, ValueError):
|
||||||
ret["errorMsg"] = "ReverseZone does not exist"
|
ret["errorMsg"] = "ReverseZone does not exist"
|
||||||
|
|
||||||
return JsonResponse(ret)
|
return JsonResponse(ret)
|
||||||
|
|
||||||
|
|
||||||
def getROA(request):
|
def getROA(request):
|
||||||
roa = {}
|
roa = {}
|
||||||
for asn in ASNumber.objects.all():
|
for asn in ASNumber.objects.all():
|
||||||
nets = []
|
nets = []
|
||||||
for net in asn.inetnum_set.all():
|
for net in asn.inetnum_set.all():
|
||||||
nets.append(net.prefix())
|
nets.append(net.prefix())
|
||||||
|
|
||||||
if nets:
|
if nets:
|
||||||
roa[asn.number] = nets
|
roa[asn.number] = nets
|
||||||
|
|
||||||
return JsonResponse(roa)
|
return JsonResponse(roa)
|
||||||
|
|
268
bin/dns-sync
268
bin/dns-sync
|
@ -25,179 +25,181 @@ __VERSION__ = '0.1'
|
||||||
|
|
||||||
|
|
||||||
def _parser():
|
def _parser():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser()
|
||||||
#prog='foo',
|
|
||||||
#description='do some awesome foo',
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument("--pdns-host", default="127.0.0.1", help="PDNS host")
|
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("--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("-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("--api-key", default=None, help="PDNS API key")
|
||||||
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 mergeDomains(zoneData, pdnsData):
|
def mergeDomains(zoneData, pdnsData):
|
||||||
rrAdd = []
|
rrAdd = []
|
||||||
rrData = pdnsData['rrsets']
|
rrData = pdnsData['rrsets']
|
||||||
|
|
||||||
for domain, rrType, records in zoneData:
|
for domain, rrType, records in zoneData:
|
||||||
found = False
|
found = False
|
||||||
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
|
pdnsDom = list(filter(lambda _x: _x['name'] == domain and _x['type'] == rrType, rrData))
|
||||||
if len(pdnsDom) > 0:
|
if len(pdnsDom) > 0:
|
||||||
rrSet = set(_x['content'] for _x in pdnsDom[0]['records'])
|
rrSet = set(_x['content'].lower() for _x in pdnsDom[0]['records'])
|
||||||
if rrSet == set(records):
|
if rrSet == set(record.lower() for record in records):
|
||||||
found = True
|
found = True
|
||||||
|
|
||||||
if not found:
|
if not found:
|
||||||
# new domain!
|
# new domain!
|
||||||
rrAdd.append({
|
rrAdd.append({
|
||||||
"name": domain,
|
"name": domain,
|
||||||
"type": rrType,
|
"type": rrType,
|
||||||
"ttl": 60*60,
|
"ttl": 60*60,
|
||||||
"changetype": "REPLACE",
|
"changetype": "REPLACE",
|
||||||
"records": [{"content": record, "disabled": False} for record in records],
|
"records": [{"content": record, "disabled": False} for record in records],
|
||||||
})
|
})
|
||||||
|
|
||||||
return rrAdd
|
return rrAdd
|
||||||
|
|
||||||
|
|
||||||
def removeOldDomains(zoneData, pdnsData):
|
def removeOldDomains(zoneData, pdnsData):
|
||||||
rrDel = []
|
rrDel = []
|
||||||
|
|
||||||
#print("zone data", zoneData)
|
#print("zone data", zoneData)
|
||||||
#print("pdnsData", pdnsData)
|
#print("pdnsData", pdnsData)
|
||||||
for entry in pdnsData['rrsets']:
|
for entry in pdnsData['rrsets']:
|
||||||
# search for name/type in domain dict. if non-existtant mark for deletion
|
# search for name/type in domain dict. if non-existtant mark for deletion
|
||||||
# this could be much more efficient with a dict! name: [rrset...]
|
# 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):
|
if not any(entry['name'] == _x[0] and entry['type'] == _x[1] for _x in zoneData):
|
||||||
rrDel.append({
|
rrDel.append({
|
||||||
"changetype": "DELETE",
|
"changetype": "DELETE",
|
||||||
"name": entry["name"],
|
"name": entry["name"],
|
||||||
"type": entry["type"],
|
"type": entry["type"],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return rrDel
|
||||||
|
|
||||||
return rrDel
|
|
||||||
|
|
||||||
def handleNameserver(ns, servers, usedNameservers, domains):
|
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):
|
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
|
||||||
usedNameservers.append(ns.name)
|
usedNameservers.append(ns.name)
|
||||||
if ns.glueIPv4:
|
if ns.glueIPv4:
|
||||||
domains.append((ns.name, "A", [ns.glueIPv4]))
|
domains.append((ns.name, "A", [ns.glueIPv4]))
|
||||||
if ns.glueIPv6:
|
if ns.glueIPv6:
|
||||||
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
|
domains.append((ns.name, "AAAA", [ns.glueIPv6]))
|
||||||
|
|
||||||
|
|
||||||
def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers, v4reverse=False):
|
def getDomainsFromQueryset(qs, zone, glueRecords, usedNameservers, v4reverse=False):
|
||||||
for domain in qs:
|
for domain in qs:
|
||||||
servers = []
|
servers = []
|
||||||
for ns in domain.nameservers.all():
|
for ns in domain.nameservers.all():
|
||||||
servers.append(ns.name)
|
servers.append(ns.name)
|
||||||
|
|
||||||
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
|
if ns.name not in usedNameservers and (ns.glueIPv4 or ns.glueIPv6):
|
||||||
usedNameservers.append(ns.name)
|
usedNameservers.append(ns.name)
|
||||||
if ns.glueIPv4:
|
if ns.glueIPv4:
|
||||||
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
|
glueRecords.append((ns.name, "A", [ns.glueIPv4]))
|
||||||
if ns.glueIPv6:
|
if ns.glueIPv6:
|
||||||
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
|
glueRecords.append((ns.name, "AAAA", [ns.glueIPv6]))
|
||||||
|
|
||||||
zone.append((domain.getZone(), "NS", servers))
|
zone.append((domain.getZone(), "NS", servers))
|
||||||
|
|
||||||
if v4reverse:
|
if domain.ds_records:
|
||||||
# for ipv4 reverse we have to do some extra work in case of classless delegations
|
zone.append((domain.getZone(), "DS", domain.ds_records.split("\n")))
|
||||||
# see RFC2317
|
|
||||||
net = domain.parentNet.getNetwork()
|
if v4reverse:
|
||||||
if net.prefixlen % 8 != 0:
|
# for ipv4 reverse we have to do some extra work in case of classless delegations
|
||||||
revZone = domain.getZone()
|
# see RFC2317
|
||||||
parts = str(net.network_address).split(".")
|
net = domain.parentNet.getNetwork()
|
||||||
baseZone = ".".join(reversed(parts[:net.prefixlen // 8])) + ".in-addr.arpa."
|
if net.prefixlen % 8 != 0:
|
||||||
startNo = int(parts[net.prefixlen // 8])
|
revZone = domain.getZone()
|
||||||
lenExp = 8 - (net.prefixlen % 8)
|
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 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=[]):
|
def mergeDomainsWithPdns(s, args, zone, zoneData, protectedRecords=[]):
|
||||||
url = "http://%s:%s/api/v1/servers/localhost/zones/%s" % (args.pdns_host, args.pdns_port, zone,)
|
url = "http://%s:%s/api/v1/servers/localhost/zones/%s" % (args.pdns_host, args.pdns_port, zone,)
|
||||||
pdnsData = s.get(url).json()
|
pdnsData = s.get(url).json()
|
||||||
|
|
||||||
baseProtectedRecords = [
|
baseProtectedRecords = [
|
||||||
(zone, "NS", []),
|
(zone, "NS", []),
|
||||||
(zone, "SOA", []),
|
(zone, "SOA", []),
|
||||||
]
|
]
|
||||||
|
|
||||||
# add dn. (NS + glue Nameservers)
|
# add dn. (NS + glue Nameservers)
|
||||||
newDomains = mergeDomains(zoneData, pdnsData)
|
newDomains = mergeDomains(zoneData, pdnsData)
|
||||||
print("Add/replace", newDomains)
|
print("Add/replace", newDomains)
|
||||||
|
|
||||||
if len(newDomains) > 0:
|
if len(newDomains) > 0:
|
||||||
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
|
r = s.patch(url, data=json.dumps({'rrsets': newDomains}))
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
||||||
|
|
||||||
delDomains = removeOldDomains(zoneData + protectedRecords + baseProtectedRecords, pdnsData)
|
delDomains = removeOldDomains(zoneData + protectedRecords + baseProtectedRecords, pdnsData)
|
||||||
print("Del", delDomains)
|
print("Del", delDomains)
|
||||||
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
|
r = s.patch(url, data=json.dumps({'rrsets': delDomains}))
|
||||||
if r.status_code != 204:
|
if r.status_code != 204:
|
||||||
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
raise RuntimeError("Could not update records in powerdns, API returned %d" % r.status_code)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = _parser()
|
parser = _parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
if args.config:
|
if args.config:
|
||||||
config.read_file(args.config)
|
config.read_file(args.config)
|
||||||
else:
|
else:
|
||||||
config.read([os.path.join(os.path.abspath(__file__), "dns-sync.conf"), "/etc/dns-sync.conf"])
|
config.read([os.path.join(os.path.abspath(__file__), "dns-sync.conf"), "/etc/dns-sync.conf"])
|
||||||
#print(config)
|
#print(config)
|
||||||
#print(config.get("DEFAULT", "api-key"))
|
#print(config.get("DEFAULT", "api-key"))
|
||||||
#print(config.has_section("DEFAULT"), config.has_option("DEFAULT", "api-key"))
|
#print(config.has_section("DEFAULT"), config.has_option("DEFAULT", "api-key"))
|
||||||
|
|
||||||
if args.api_key:
|
if args.api_key:
|
||||||
config["DEFAULT"]["api-key"] = args.api_key
|
config["DEFAULT"]["api-key"] = args.api_key
|
||||||
|
|
||||||
if not config.has_option("DEFAULT", "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)
|
print("Error: Could not find api-key (not present in config under [DEFAULT]; not given via command line)", file=sys.stderr)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
s = requests.Session()
|
s = requests.Session()
|
||||||
s.headers = {
|
s.headers = {
|
||||||
'X-API-Key': config.get("DEFAULT", "api-key"),
|
'X-API-Key': config.get("DEFAULT", "api-key"),
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
domains = []
|
domains = []
|
||||||
rzone4 = []
|
rzone4 = []
|
||||||
rzone6 = []
|
rzone6 = []
|
||||||
usedNameservers = []
|
usedNameservers = []
|
||||||
|
|
||||||
# assenble domain data
|
# assenble domain data
|
||||||
# dn.
|
# dn.
|
||||||
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
|
qs = Domain.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("name")
|
||||||
getDomainsFromQueryset(qs, domains, domains, usedNameservers)
|
getDomainsFromQueryset(qs, domains, domains, usedNameservers)
|
||||||
|
|
||||||
# reverse zones
|
# reverse zones
|
||||||
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
|
qs = ReverseZone.objects.annotate(nsCount=Count('nameservers')).filter(nsCount__gt=0).order_by("parentNet__address")
|
||||||
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
|
qs4 = filter(lambda _revz: _revz.getNetwork().version == 4, qs)
|
||||||
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
|
qs6 = filter(lambda _revz: _revz.getNetwork().version == 6, qs)
|
||||||
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers, v4reverse=True)
|
getDomainsFromQueryset(qs4, rzone4, domains, usedNameservers, v4reverse=True)
|
||||||
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
|
getDomainsFromQueryset(qs6, rzone6, domains, usedNameservers)
|
||||||
|
|
||||||
#print("dn.", domains)
|
#print("dn.", domains)
|
||||||
#print("v4", rzone4)
|
#print("v4", rzone4)
|
||||||
#print("v6", rzone6)
|
#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)
|
|
||||||
|
|
||||||
|
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__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
170
bin/import-data
170
bin/import-data
|
@ -24,107 +24,107 @@ from whoisdb.models import ASBlock, ASNumber, Contact, Maintainer, InetNum
|
||||||
__VERSION__ = '0.1'
|
__VERSION__ = '0.1'
|
||||||
|
|
||||||
def _parser():
|
def _parser():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
#prog='foo',
|
#prog='foo',
|
||||||
#description='do some awesome foo',
|
#description='do some awesome foo',
|
||||||
)
|
)
|
||||||
|
|
||||||
#parser.add_argument("-p", "--port", default=2323, type=int, help="Your port")
|
#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("-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("-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():
|
def main():
|
||||||
parser = _parser()
|
parser = _parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
defContact = Contact.objects.get(handle="UNKNOWN-DN")
|
defContact = Contact.objects.get(handle="UNKNOWN-DN")
|
||||||
defMnt = Maintainer.objects.get(handle="DARKNET-MNT")
|
defMnt = Maintainer.objects.get(handle="DARKNET-MNT")
|
||||||
blocks = [
|
blocks = [
|
||||||
ASBlock.objects.get(handle="TRA1-ASB"),
|
ASBlock.objects.get(handle="TRA1-ASB"),
|
||||||
ASBlock.objects.get(handle="UAB1-ASB")
|
ASBlock.objects.get(handle="UAB1-ASB")
|
||||||
]
|
]
|
||||||
ranges = [
|
ranges = [
|
||||||
InetNum.objects.get(handle="TRA1-NET"),
|
InetNum.objects.get(handle="TRA1-NET"),
|
||||||
InetNum.objects.get(handle="DEF4-NET"),
|
InetNum.objects.get(handle="DEF4-NET"),
|
||||||
InetNum.objects.get(handle="DEF6-NET"),
|
InetNum.objects.get(handle="DEF6-NET"),
|
||||||
InetNum.objects.get(handle="MISC6-NET"),
|
InetNum.objects.get(handle="MISC6-NET"),
|
||||||
InetNum.objects.get(handle="LTRA1-NET"),
|
InetNum.objects.get(handle="LTRA1-NET"),
|
||||||
InetNum.objects.get(handle="MAIN4-NET"),
|
InetNum.objects.get(handle="MAIN4-NET"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
data = json.load(args.json)
|
data = json.load(args.json)
|
||||||
print(data.keys())
|
print(data.keys())
|
||||||
for k, v in data["handles"].items():
|
for k, v in data["handles"].items():
|
||||||
print(k, v["person"])
|
print(k, v["person"])
|
||||||
for asn in data["as"]:
|
for asn in data["as"]:
|
||||||
print(asn)
|
print(asn)
|
||||||
if ASNumber.objects.filter(number=asn["number"]).count() > 0:
|
if ASNumber.objects.filter(number=asn["number"]).count() > 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
obj = ASNumber(number=asn["number"])
|
obj = ASNumber(number=asn["number"])
|
||||||
block = None
|
block = None
|
||||||
for block in blocks:
|
for block in blocks:
|
||||||
if obj.number >= block.asBegin and obj.number <= block.asEnd:
|
if obj.number >= block.asBegin and obj.number <= block.asEnd:
|
||||||
obj.asblock = block
|
obj.asblock = block
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise ValueError("AS %d does not fit a block" % asn["number"])
|
raise ValueError("AS %d does not fit a block" % asn["number"])
|
||||||
|
|
||||||
if len(asn['admin_c']) >= 1:
|
if len(asn['admin_c']) >= 1:
|
||||||
name = data["handles"][asn["admin_c"][0]]["person"]
|
name = data["handles"][asn["admin_c"][0]]["person"]
|
||||||
obj.name = "Imported AS of %s" % name
|
obj.name = "Imported AS of %s" % name
|
||||||
obj.handle = ASNumber.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
|
obj.handle = ASNumber.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
|
||||||
else:
|
else:
|
||||||
obj.name = "Imported AS without admin info"
|
obj.name = "Imported AS without admin info"
|
||||||
obj.handle = ASNumber.genGenericHandle("Unknown Imported AS")
|
obj.handle = ASNumber.genGenericHandle("Unknown Imported AS")
|
||||||
obj.description = "Object has been imported from old DB and has not yet been edited"
|
obj.description = "Object has been imported from old DB and has not yet been edited"
|
||||||
obj.save()
|
obj.save()
|
||||||
obj.mnt_by.add(defMnt)
|
obj.mnt_by.add(defMnt)
|
||||||
obj.admin_c.add(defContact)
|
obj.admin_c.add(defContact)
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
for net in data["network"]:
|
for net in data["network"]:
|
||||||
print(net)
|
print(net)
|
||||||
network = ipaddress.ip_network(net["prefix"])
|
network = ipaddress.ip_network(net["prefix"])
|
||||||
|
|
||||||
if InetNum.objects.filter(address=str(network.network_address), netmask=network.prefixlen).count() > 0:
|
if InetNum.objects.filter(address=str(network.network_address), netmask=network.prefixlen).count() > 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
origin = None
|
origin = None
|
||||||
if net["origin"]:
|
if net["origin"]:
|
||||||
origin = ASNumber.objects.get(number=net["origin"])
|
origin = ASNumber.objects.get(number=net["origin"])
|
||||||
obj = InetNum(address=str(network.network_address), netmask=network.prefixlen)
|
obj = InetNum(address=str(network.network_address), netmask=network.prefixlen)
|
||||||
obj.protocol = InetNum.IPv4 if network.version == 4 else InetNum.IPv6
|
obj.protocol = InetNum.IPv4 if network.version == 4 else InetNum.IPv6
|
||||||
|
|
||||||
x = list(filter(lambda _x: _x['number'] == net["origin"], data["as"]))
|
x = list(filter(lambda _x: _x['number'] == net["origin"], data["as"]))
|
||||||
if len(x) > 0 and x[0]["admin_c"]:
|
if len(x) > 0 and x[0]["admin_c"]:
|
||||||
name = data["handles"][x[0]["admin_c"][0]]["person"]
|
name = data["handles"][x[0]["admin_c"][0]]["person"]
|
||||||
obj.name = "Imported Network of %s" % name
|
obj.name = "Imported Network of %s" % name
|
||||||
obj.handle = InetNum.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
|
obj.handle = InetNum.genGenericHandle(re.sub("[^a-zA-Z0-9 ]", "", name))
|
||||||
else:
|
else:
|
||||||
obj.name = "Imported Network without admin info"
|
obj.name = "Imported Network without admin info"
|
||||||
obj.handle = InetNum.genGenericHandle("Unknown Imported Network")
|
obj.handle = InetNum.genGenericHandle("Unknown Imported Network")
|
||||||
obj.description = "Object has been imported from old DB and has not yet been edited"
|
obj.description = "Object has been imported from old DB and has not yet been edited"
|
||||||
|
|
||||||
for r in ranges:
|
for r in ranges:
|
||||||
if network.network_address in r.getNetwork():
|
if network.network_address in r.getNetwork():
|
||||||
obj.parent_range = r
|
obj.parent_range = r
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise ValueError("%s did not fit in any netblock" % network)
|
raise ValueError("%s did not fit in any netblock" % network)
|
||||||
|
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
obj.mnt_by.add(defMnt)
|
obj.mnt_by.add(defMnt)
|
||||||
obj.admin_c.add(defContact)
|
obj.admin_c.add(defContact)
|
||||||
if origin:
|
if origin:
|
||||||
obj.origin_as.add(origin)
|
obj.origin_as.add(origin)
|
||||||
obj.save()
|
obj.save()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -12,11 +12,11 @@ import os
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
files = [
|
files = [
|
||||||
("templates/help/faq.md", "templates/help/faq.html"),
|
("templates/help/faq.md", "templates/help/faq.html"),
|
||||||
]
|
]
|
||||||
|
|
||||||
for srcFile, dstFile in files:
|
for srcFile, dstFile in files:
|
||||||
srcFile = os.path.join(BASE_DIR, srcFile)
|
srcFile = os.path.join(BASE_DIR, srcFile)
|
||||||
dstFile = os.path.join(BASE_DIR, dstFile)
|
dstFile = os.path.join(BASE_DIR, dstFile)
|
||||||
markdown.markdownFromFile(open(srcFile, "rb"), open(dstFile, "wb"), extensions=[TocExtension(baselevel=1, permalink=True)])
|
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'
|
__VERSION__ = '0.1'
|
||||||
|
|
||||||
def _parser():
|
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():
|
def main():
|
||||||
parser = _parser()
|
parser = _parser()
|
||||||
parser.parse_args()
|
parser.parse_args()
|
||||||
|
|
||||||
roa = {}
|
roa = {}
|
||||||
for asn in ASNumber.objects.all():
|
for asn in ASNumber.objects.all():
|
||||||
nets = []
|
nets = []
|
||||||
for net in asn.inetnum_set.all():
|
for net in asn.inetnum_set.all():
|
||||||
nets.append(net.prefix())
|
nets.append(net.prefix())
|
||||||
|
|
||||||
if nets:
|
if nets:
|
||||||
roa[asn.number] = nets
|
roa[asn.number] = nets
|
||||||
|
|
||||||
print(json.dumps(roa))
|
print(json.dumps(roa))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
118
bin/whoisd
118
bin/whoisd
|
@ -24,84 +24,84 @@ log = logging.getLogger("whoisd")
|
||||||
__VERSION__ = '0.1'
|
__VERSION__ = '0.1'
|
||||||
|
|
||||||
class WhoisHandler(socketserver.BaseRequestHandler):
|
class WhoisHandler(socketserver.BaseRequestHandler):
|
||||||
header = "% This is the DARKNET database query service.\n" \
|
header = "% This is the DARKNET database query service.\n" \
|
||||||
"% The objects should be in something like RPSL format.\n" \
|
"% The objects should be in something like RPSL format.\n" \
|
||||||
"%\n" \
|
"%\n" \
|
||||||
"% The DARKNET database is subject to terms and conditions.\n" \
|
"% The DARKNET database is subject to terms and conditions.\n" \
|
||||||
"% Mostly these are \"be nice\" and \"don't knowingly break things\".\n" \
|
"% Mostly these are \"be nice\" and \"don't knowingly break things\".\n" \
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
self.request.sendall(self.header.encode())
|
self.request.sendall(self.header.encode())
|
||||||
line = self.request.recv(1024)
|
line = self.request.recv(1024)
|
||||||
line = line.split(b"\n", 2)[0].strip()
|
line = line.split(b"\n", 2)[0].strip()
|
||||||
print("Request object is %s" % line)
|
print("Request object is %s" % line)
|
||||||
log.info("Request by %s for %s" % (self.request.getpeername()[0], line))
|
log.info("Request by %s for %s" % (self.request.getpeername()[0], line))
|
||||||
self.request.send(b"\n")
|
self.request.send(b"\n")
|
||||||
|
|
||||||
objs = findInDatabase(line.decode())
|
objs = findInDatabase(line.decode())
|
||||||
if len(objs) > 0:
|
if len(objs) > 0:
|
||||||
self.request.sendall(("%% %d result%s\n" % (len(objs), "" if len(objs)==1 else "s")).encode())
|
self.request.sendall(("%% %d result%s\n" % (len(objs), "" if len(objs)==1 else "s")).encode())
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
self.sendObject(obj)
|
self.sendObject(obj)
|
||||||
else:
|
else:
|
||||||
self.request.sendall(b"%% NOT FOUND\n\n")
|
self.request.sendall(b"%% NOT FOUND\n\n")
|
||||||
|
|
||||||
def sendObject(self, obj):
|
def sendObject(self, obj):
|
||||||
result = [
|
result = [
|
||||||
"",
|
"",
|
||||||
"%% Object %s (%s)" % (obj, obj.getClassName()),
|
"%% Object %s (%s)" % (obj, obj.getClassName()),
|
||||||
""
|
""
|
||||||
]
|
]
|
||||||
|
|
||||||
for field, value in getWhoisObjectFields(obj, False):
|
for field, value in getWhoisObjectFields(obj, False):
|
||||||
fieldName = field.lower().replace(" ", "-") + ":"
|
fieldName = field.lower().replace(" ", "-") + ":"
|
||||||
if not value:
|
if not value:
|
||||||
value = ""
|
value = ""
|
||||||
|
|
||||||
if hasattr(value, "through"):
|
if hasattr(value, "through"):
|
||||||
for v in value.all():
|
for v in value.all():
|
||||||
result.append("%-16s %s" % (fieldName, v))
|
result.append("%-16s %s" % (fieldName, v))
|
||||||
else:
|
else:
|
||||||
result.append("%-16s %s" % (fieldName, value))
|
result.append("%-16s %s" % (fieldName, value))
|
||||||
result.extend(["", ""])
|
result.extend(["", ""])
|
||||||
|
|
||||||
self.request.sendall("\n".join(result).encode())
|
self.request.sendall("\n".join(result).encode())
|
||||||
|
|
||||||
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
|
||||||
allow_reuse_address = True
|
allow_reuse_address = True
|
||||||
|
|
||||||
|
|
||||||
def _parser():
|
def _parser():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
#prog='foo',
|
#prog='foo',
|
||||||
#description='do some awesome foo',
|
#description='do some awesome foo',
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument("-p", "--port", default=43, type=int, help="whoisd port")
|
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("-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():
|
def main():
|
||||||
parser = _parser()
|
parser = _parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
server = ThreadedTCPServer(('', args.port), WhoisHandler)
|
server = ThreadedTCPServer(('', args.port), WhoisHandler)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except select.error as e:
|
except select.error as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
log.info("^c hit, quitting.")
|
log.info("^c hit, quitting.")
|
||||||
break
|
break
|
||||||
|
|
||||||
server.server_close()
|
server.server_close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -7,6 +7,6 @@ from .models import User
|
||||||
|
|
||||||
|
|
||||||
class CustomUserCreationForm(UserCreationForm):
|
class CustomUserCreationForm(UserCreationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ("username",)
|
fields = ("username",)
|
||||||
|
|
|
@ -7,4 +7,4 @@ from django.db import models
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
|
||||||
class User(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
|
from . import views as dncore_views
|
||||||
|
|
||||||
urlpatterns = [
|
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'^login/$', auth_views.login, name='login'),
|
||||||
url(r'^register/$', dncore_views.RegisterUser.as_view(), name='register'),
|
url(r'^register/$', dncore_views.RegisterUser.as_view(), name='register'),
|
||||||
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
|
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
|
||||||
url(r'^profile/$', dncore_views.profile, name='profile'),
|
url(r'^profile/$', dncore_views.profile, name='profile'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -22,54 +22,54 @@ from .forms import CustomUserCreationForm
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def profile(request):
|
def profile(request):
|
||||||
pwForm = None
|
pwForm = None
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if request.POST.get("submit", None) == "pwchange":
|
if request.POST.get("submit", None) == "pwchange":
|
||||||
pwForm = PasswordChangeForm(user=request.user, data=request.POST)
|
pwForm = PasswordChangeForm(user=request.user, data=request.POST)
|
||||||
if pwForm.is_valid():
|
if pwForm.is_valid():
|
||||||
pwForm.save()
|
pwForm.save()
|
||||||
auth_login(request, pwForm.user)
|
auth_login(request, pwForm.user)
|
||||||
messages.success(request, "Password changed")
|
messages.success(request, "Password changed")
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse("user:profile"))
|
return HttpResponseRedirect(reverse("user:profile"))
|
||||||
|
|
||||||
if not pwForm:
|
if not pwForm:
|
||||||
pwForm = PasswordChangeForm(user=request.user)
|
pwForm = PasswordChangeForm(user=request.user)
|
||||||
|
|
||||||
return render(request, "registration/profile.html", {'pwForm': pwForm})
|
return render(request, "registration/profile.html", {'pwForm': pwForm})
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard(request):
|
def dashboard(request):
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
ownMnts = request.user.maintainer_set.filter(rir=False, lir=False).all().distinct()
|
ownMnts = request.user.maintainer_set.filter(rir=False, lir=False).all().distinct()
|
||||||
# if account only has rir/lir objects, show them
|
# if account only has rir/lir objects, show them
|
||||||
if ownMnts.count() == 0:
|
if ownMnts.count() == 0:
|
||||||
ownMnts = mnts
|
ownMnts = mnts
|
||||||
|
|
||||||
asns = ASNumber.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).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()
|
inetnums = InetNum.objects.filter(Q(mnt_by__in=ownMnts) | Q(mnt_lower__in=ownMnts)).distinct()
|
||||||
domains = Domain.objects.filter(mnt_by__in=mnts).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()
|
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):
|
def index(request):
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
return HttpResponseRedirect(reverse("dashboard"))
|
return HttpResponseRedirect(reverse("dashboard"))
|
||||||
|
|
||||||
return render(request, "index.html", {})
|
return render(request, "index.html", {})
|
||||||
|
|
||||||
|
|
||||||
class RegisterUser(CreateView):
|
class RegisterUser(CreateView):
|
||||||
template_name = "dncore/registration.html"
|
template_name = "dncore/registration.html"
|
||||||
form_class = CustomUserCreationForm
|
form_class = CustomUserCreationForm
|
||||||
success_url = reverse_lazy("user:login")
|
success_url = reverse_lazy("user:login")
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
ret = super(RegisterUser, self).form_valid(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)
|
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__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
TLD_NAMESERVERS = [
|
TLD_NAMESERVERS = [
|
||||||
'10.100.100.100',
|
'10.100.100.100',
|
||||||
]
|
]
|
||||||
|
|
||||||
DATETIME_FORMAT = "Y-m-d H:i:s"
|
DATETIME_FORMAT = "Y-m-d H:i:s"
|
||||||
|
@ -42,47 +42,47 @@ ALLOWED_HOSTS = ["*"]
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'crispy_forms',
|
'crispy_forms',
|
||||||
'formtools',
|
'formtools',
|
||||||
'dncore',
|
'dncore',
|
||||||
'whoisdb',
|
'whoisdb',
|
||||||
'rrequests',
|
'rrequests',
|
||||||
'domains',
|
'domains',
|
||||||
'api',
|
'api',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'dnmgmt.urls'
|
ROOT_URLCONF = 'dnmgmt.urls'
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [os.path.join(BASE_DIR, "templates/")],
|
'DIRS': [os.path.join(BASE_DIR, "templates/")],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
'django.template.context_processors.debug',
|
'django.template.context_processors.debug',
|
||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'django.contrib.messages.context_processors.messages',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = 'dnmgmt.wsgi.application'
|
WSGI_APPLICATION = 'dnmgmt.wsgi.application'
|
||||||
|
@ -92,10 +92,10 @@ WSGI_APPLICATION = 'dnmgmt.wsgi.application'
|
||||||
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
|
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.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
|
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,11 +139,11 @@ USE_TZ = True
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATIC_ROOT = os.path.join(BASE_DIR, "cstatic")
|
STATIC_ROOT = os.path.join(BASE_DIR, "cstatic")
|
||||||
STATICFILES_DIRS = [
|
STATICFILES_DIRS = [
|
||||||
os.path.join(BASE_DIR, "static"),
|
os.path.join(BASE_DIR, "static"),
|
||||||
]
|
]
|
||||||
CRISPY_TEMPLATE_PACK = 'bootstrap3'
|
CRISPY_TEMPLATE_PACK = 'bootstrap3'
|
||||||
MESSAGE_TAGS = {
|
MESSAGE_TAGS = {
|
||||||
messages.ERROR: 'danger',
|
messages.ERROR: 'danger',
|
||||||
}
|
}
|
||||||
|
|
||||||
AUTH_USER_MODEL = 'dncore.User'
|
AUTH_USER_MODEL = 'dncore.User'
|
||||||
|
|
|
@ -30,15 +30,15 @@ import api.urls
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', dncore.views.index, name='index'),
|
url(r'^$', dncore.views.index, name='index'),
|
||||||
url(r'^dashboard/$', dncore.views.dashboard, name='dashboard'),
|
url(r'^dashboard/$', dncore.views.dashboard, name='dashboard'),
|
||||||
|
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
url(r'^user/', include(dncore.urls, namespace='user')),
|
url(r'^user/', include(dncore.urls, namespace='user')),
|
||||||
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
|
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
|
||||||
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
|
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
|
||||||
url(r'^domains/', include(domains.urls, namespace='domains')),
|
url(r'^domains/', include(domains.urls, namespace='domains')),
|
||||||
url(r'^api/', include(api.urls, namespace='api')),
|
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'),
|
||||||
]
|
]
|
||||||
|
|
361
domains/forms.py
361
domains/forms.py
|
@ -15,229 +15,260 @@ import re
|
||||||
import ipaddress
|
import ipaddress
|
||||||
|
|
||||||
|
|
||||||
class DomainForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
class DSRecordMixin(object):
|
||||||
class Meta:
|
ds_re = re.compile(r"^(?P<id>\d+)\s+(?P<crypto>\d+)\s+(?P<hashtype>\d+)\s+(?P<hash>[0-9a-fA-F]+)$")
|
||||||
model = Domain
|
HASH_SUPPORTED = (1, 2)
|
||||||
fields = ['name', 'nameservers', 'mnt_by', 'admin_c']
|
CRYPTO_SUPPORTED = (3, 5, 6, 8, 10, 13, 15)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def clean_ds_records(self):
|
||||||
super(DomainForm, self).__init__(*args, **kwargs)
|
ds_records = self.cleaned_data['ds_records'].strip()
|
||||||
|
result = []
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
if not ds_records:
|
||||||
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
|
return ''
|
||||||
|
|
||||||
instance = getattr(self, "instance", None)
|
for n, rec in enumerate(ds_records.split("\n"), 1):
|
||||||
self._create = not (instance and instance.pk)
|
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:
|
if int(m.group('hashtype')) not in self.HASH_SUPPORTED:
|
||||||
self.fields['name'].disabled = True
|
raise forms.ValidationError("Record {} has an invalid hashtype of {}, supported are {}"
|
||||||
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
|
"".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):
|
return "\n".join(result)
|
||||||
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:
|
class DomainForm(MntFormMixin, WhoisObjectFormMixin, DSRecordMixin, forms.ModelForm):
|
||||||
raise forms.ValidationError("No subdomains can be registered")
|
class Meta:
|
||||||
|
model = Domain
|
||||||
|
fields = ['name', 'nameservers', 'mnt_by', 'admin_c', 'ds_records']
|
||||||
|
|
||||||
if not re.match("^[a-z0-9.-]+$", name):
|
def __init__(self, *args, **kwargs):
|
||||||
raise forms.ValidationError("Only a-z, 0-9 and - are allowed inside the domain name")
|
super(DomainForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
try:
|
mnts = self._user.maintainer_set.all()
|
||||||
Domain.objects.get(name=name)
|
self.fields['nameservers'].queryset = Nameserver.objects.filter(Q(mnt_by__in=mnts))
|
||||||
raise forms.ValidationError("Domain already exists")
|
|
||||||
except Domain.DoesNotExist:
|
|
||||||
pass
|
|
||||||
|
|
||||||
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 NameserverForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Nameserver
|
model = Nameserver
|
||||||
fields = ['name', 'glueIPv4', 'glueIPv6', 'mnt_by', 'admin_c']
|
fields = ['name', 'glueIPv4', 'glueIPv6', 'mnt_by', 'admin_c']
|
||||||
|
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"glueIPv4": "Note: You can only set a glue record if the base domain of this nameserver belongs to you!"
|
"glueIPv4": "Note: You can only set a glue record if the base domain of this nameserver belongs to you!"
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(NameserverForm, self).__init__(*args, **kwargs)
|
super(NameserverForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
instance = getattr(self, "instance", None)
|
instance = getattr(self, "instance", None)
|
||||||
self._create = not (instance and instance.pk)
|
self._create = not (instance and instance.pk)
|
||||||
|
|
||||||
def cleanNetwork(self, glue):
|
def cleanNetwork(self, glue):
|
||||||
ip = ipaddress.ip_address(glue)
|
ip = ipaddress.ip_address(glue)
|
||||||
proto = InetNum.IPv4 if ip.version == 4 else InetNum.IPv6
|
proto = InetNum.IPv4 if ip.version == 4 else InetNum.IPv6
|
||||||
nets = InetNum.objects.filter(parent_range=None, protocol=proto)
|
nets = InetNum.objects.filter(parent_range=None, protocol=proto)
|
||||||
|
|
||||||
if len(nets) == 0:
|
if len(nets) == 0:
|
||||||
raise forms.ValidationError("No range has been registered for IPv%s in the whois interface" % ip.version)
|
raise forms.ValidationError("No range has been registered for IPv%s in the whois interface" % ip.version)
|
||||||
|
|
||||||
for net in nets:
|
for net in nets:
|
||||||
if ip in net.getNetwork():
|
if ip in net.getNetwork():
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise forms.ValidationError("Glue record address is not inside DarkNet (subnet %s)" % ", ".join(map(lambda _x: _x.prefix(), nets)))
|
raise forms.ValidationError("Glue record address is not inside DarkNet (subnet %s)" % ", ".join(map(lambda _x: _x.prefix(), nets)))
|
||||||
|
|
||||||
def clean_glueIPv4(self):
|
def clean_glueIPv4(self):
|
||||||
glue = self.cleaned_data['glueIPv4']
|
glue = self.cleaned_data['glueIPv4']
|
||||||
|
|
||||||
if glue:
|
if glue:
|
||||||
self.cleanNetwork(glue)
|
self.cleanNetwork(glue)
|
||||||
|
|
||||||
return glue
|
return glue
|
||||||
|
|
||||||
def clean_glueIPv6(self):
|
def clean_glueIPv6(self):
|
||||||
glue = self.cleaned_data['glueIPv6']
|
glue = self.cleaned_data['glueIPv6']
|
||||||
|
|
||||||
if glue:
|
if glue:
|
||||||
self.cleanNetwork(glue)
|
self.cleanNetwork(glue)
|
||||||
|
|
||||||
return glue
|
return glue
|
||||||
|
|
||||||
def clean_name(self):
|
def clean_name(self):
|
||||||
name = self.cleaned_data['name'].lower().strip()
|
name = self.cleaned_data['name'].lower().strip()
|
||||||
if not name.endswith("."):
|
if not name.endswith("."):
|
||||||
name += "."
|
name += "."
|
||||||
|
|
||||||
# allow name to stay if it did not change
|
# allow name to stay if it did not change
|
||||||
if not self._create and self.instance.name == name:
|
if not self._create and self.instance.name == name:
|
||||||
return name
|
return name
|
||||||
|
|
||||||
if name.count(".") <= 2:
|
if name.count(".") <= 2:
|
||||||
raise forms.ValidationError("Nameserver must be inside a domain (e.g. ns1.noot.dn.)")
|
raise forms.ValidationError("Nameserver must be inside a domain (e.g. ns1.noot.dn.)")
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
try:
|
try:
|
||||||
obj = Nameserver.objects.get(name=name, mnt_by__in=mnts)
|
obj = Nameserver.objects.get(name=name, mnt_by__in=mnts)
|
||||||
if self._create or not self._create and obj.pk != self.instance.pk:
|
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")
|
raise forms.ValidationError("You already have a nameserver with this name under your control")
|
||||||
except Nameserver.DoesNotExist:
|
except Nameserver.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
except Nameserver.MultipleObjectsReturned:
|
except Nameserver.MultipleObjectsReturned:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(NameserverForm, self).clean()
|
cleaned_data = super(NameserverForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
name = cleaned_data.get("name")
|
name = cleaned_data.get("name")
|
||||||
mntBy = cleaned_data.get("mnt_by")
|
mntBy = cleaned_data.get("mnt_by")
|
||||||
zone = ".".join(name.split(".")[-3:])
|
zone = ".".join(name.split(".")[-3:])
|
||||||
ipv4 = cleaned_data.get("glueIPv4", None)
|
ipv4 = cleaned_data.get("glueIPv4", None)
|
||||||
ipv6 = cleaned_data.get("glueIPv6", None)
|
ipv6 = cleaned_data.get("glueIPv6", None)
|
||||||
|
|
||||||
if not ipv4:
|
if not ipv4:
|
||||||
ipv4 = None
|
ipv4 = None
|
||||||
if not ipv6:
|
if not ipv6:
|
||||||
ipv6 = None
|
ipv6 = None
|
||||||
|
|
||||||
if self._create and (ipv4 or ipv6) or not self._create and not (self.instance.glueIPv4 == ipv4 and self.instance.glueIPv6 == ipv6):
|
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()
|
mnts = self._user.maintainer_set.all()
|
||||||
domains = Domain.objects.filter(mnt_by__in=mnts)
|
domains = Domain.objects.filter(mnt_by__in=mnts)
|
||||||
found = False
|
found = False
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
if domain.name == zone:
|
if domain.name == zone:
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
|
|
||||||
if not found:
|
if not found:
|
||||||
raise forms.ValidationError("You have glue IPs set, but this domain is not under a domain you control.")
|
raise forms.ValidationError("You have glue IPs set, but this domain is not under a domain you control.")
|
||||||
|
|
||||||
if ipv4 or ipv6:
|
if ipv4 or ipv6:
|
||||||
try:
|
try:
|
||||||
ns = Nameserver.objects.get(Q(name=name) & (Q(glueIPv4__isnull=False) | Q(glueIPv6__isnull=False)))
|
ns = Nameserver.objects.get(Q(name=name) & (Q(glueIPv4__isnull=False) | Q(glueIPv6__isnull=False)))
|
||||||
if self._create or ns.pk != self.instance.pk:
|
if self._create or ns.pk != self.instance.pk:
|
||||||
nsMnts = ", ".join(n.handle for n in ns.mnt_by.all())
|
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)
|
raise forms.ValidationError("Only one nameserver for this domain can have glue records and one already exists (maintained by %s)" % nsMnts)
|
||||||
except Nameserver.DoesNotExist:
|
except Nameserver.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
failedMnts = set()
|
failedMnts = set()
|
||||||
for ns in Nameserver.objects.filter(name=name, mnt_by__in=mntBy):
|
for ns in Nameserver.objects.filter(name=name, mnt_by__in=mntBy):
|
||||||
if self._create or self.instance.pk != ns.pk:
|
if self._create or self.instance.pk != ns.pk:
|
||||||
for mnt in ns.mnt_by.all():
|
for mnt in ns.mnt_by.all():
|
||||||
if mnt in mntBy:
|
if mnt in mntBy:
|
||||||
failedMnts.add(mnt.handle)
|
failedMnts.add(mnt.handle)
|
||||||
|
|
||||||
if len(failedMnts) > 0:
|
if len(failedMnts) > 0:
|
||||||
raise forms.ValidationError("The following maintainer objects already have this nameservers: %s" % ", ".join(failedMnts))
|
raise forms.ValidationError("The following maintainer objects already have this nameservers: %s" % ", ".join(failedMnts))
|
||||||
|
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class ReverseZoneForm(forms.ModelForm):
|
class ReverseZoneForm(DSRecordMixin, forms.ModelForm):
|
||||||
prefix = forms.CharField(validators=[IP46CIDRValidator])
|
prefix = forms.CharField(validators=[IP46CIDRValidator])
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ReverseZone
|
model = ReverseZone
|
||||||
fields = ['parentNet', 'nameservers']
|
fields = ['parentNet', 'nameservers']
|
||||||
|
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"prefix": "The prefix in CIDR form for which this object is responsible",
|
"prefix": "The prefix in CIDR form for which this object is responsible",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, user, *args, **kwargs):
|
def __init__(self, user, *args, **kwargs):
|
||||||
self._user = user
|
self._user = user
|
||||||
|
|
||||||
super(ReverseZoneForm, self).__init__(*args, **kwargs)
|
super(ReverseZoneForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
instance = getattr(self, "instance", None)
|
instance = getattr(self, "instance", None)
|
||||||
self._create = not (instance and instance.pk)
|
self._create = not (instance and instance.pk)
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
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['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:
|
if not self._create:
|
||||||
self.fields['prefix'].disabled = True
|
self.fields['prefix'].disabled = True
|
||||||
self.fields['nameservers'].queryset |= self.instance.nameservers.all()
|
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):
|
def clean_prefix(self):
|
||||||
prefix = self.cleaned_data['prefix']
|
prefix = self.cleaned_data['prefix']
|
||||||
|
|
||||||
net = ipaddress.ip_network(prefix)
|
net = ipaddress.ip_network(prefix)
|
||||||
if net.version == 6 and net.prefixlen % 4 != 0:
|
if net.version == 6 and net.prefixlen % 4 != 0:
|
||||||
raise forms.ValidationError("IPv6 reverse zone prefix length has to be a multiple of 4")
|
raise forms.ValidationError("IPv6 reverse zone prefix length has to be a multiple of 4")
|
||||||
|
|
||||||
return prefix
|
return prefix
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ReverseZoneForm, self).clean()
|
cleaned_data = super(ReverseZoneForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
if self._create:
|
if self._create:
|
||||||
net = ipaddress.ip_network(cleaned_data['prefix'])
|
net = ipaddress.ip_network(cleaned_data['prefix'])
|
||||||
parentNet = cleaned_data['parentNet'].getNetwork()
|
parentNet = cleaned_data['parentNet'].getNetwork()
|
||||||
|
|
||||||
if net.network_address not in parentNet:
|
if net.network_address not in parentNet:
|
||||||
raise forms.ValidationError("Given prefix %s is not inside of parent netblock %s" % (net, parentNet))
|
raise forms.ValidationError("Given prefix %s is not inside of parent netblock %s" % (net, parentNet))
|
||||||
|
|
||||||
# For now just check all the zones...
|
# For now just check all the zones...
|
||||||
#zones = ReverseZone.objects.filter(parentNet=cleaned_data['parentNet'])
|
#zones = ReverseZone.objects.filter(parentNet=cleaned_data['parentNet'])
|
||||||
zones = ReverseZone.objects.all()
|
zones = ReverseZone.objects.all()
|
||||||
for zone in zones:
|
for zone in zones:
|
||||||
if net.network_address in zone.parentNet.getNetwork():
|
if net.network_address in zone.parentNet.getNetwork():
|
||||||
raise forms.ValidationError("Given prefix already has a reverse zone object associated to it: %s" % zone)
|
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.address = str(net.network_address)
|
||||||
self.instance.netmask = net.prefixlen
|
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?
|
# 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):
|
class Nameserver(MntdObject):
|
||||||
handleSuffix = "NS"
|
handleSuffix = "NS"
|
||||||
# dns name
|
# dns name
|
||||||
# ip address, if glue
|
# ip address, if glue
|
||||||
# ipv4/ipv6 address?
|
# ipv4/ipv6 address?
|
||||||
handle = None
|
handle = None
|
||||||
name = models.CharField(max_length=256)
|
name = models.CharField(max_length=256)
|
||||||
glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True)
|
glueIPv4 = models.GenericIPAddressField(protocol='IPv4', blank=True, null=True)
|
||||||
glueIPv6 = models.GenericIPAddressField(protocol='IPv6', 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):
|
def getPK(self):
|
||||||
return self.pk
|
return self.pk
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("domains:nameserver-show", args=(self.pk,))
|
return reverse("domains:nameserver-show", args=(self.pk,))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def getAppName(self):
|
def getAppName(self):
|
||||||
return "domains"
|
return "domains"
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
# nameservers can always be deleted
|
# nameservers can always be deleted
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
class Domain(MntdObject):
|
class Domain(DSRecordModelMixin, MntdObject):
|
||||||
handle = None
|
handle = None
|
||||||
handleSuffix = "DOM"
|
handleSuffix = "DOM"
|
||||||
name = models.CharField(max_length=67, unique=True, db_index=True)
|
name = models.CharField(max_length=67, unique=True, db_index=True)
|
||||||
|
|
||||||
nameservers = models.ManyToManyField(Nameserver, blank=True)
|
nameservers = models.ManyToManyField(Nameserver, blank=True)
|
||||||
admin_c = models.ManyToManyField(Contact)
|
admin_c = models.ManyToManyField(Contact)
|
||||||
|
|
||||||
def getPK(self):
|
def getPK(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def getZone(self):
|
def getZone(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("domains:domain-show", args=(self.name,))
|
return reverse("domains:domain-show", args=(self.name,))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def getAppName(self):
|
def getAppName(self):
|
||||||
return "domains"
|
return "domains"
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
nameservers = Nameserver.objects.filter(name__endswith="." + self.name)
|
nameservers = Nameserver.objects.filter(name__endswith="." + self.name)
|
||||||
for ns in nameservers:
|
for ns in nameservers:
|
||||||
# FIXME: check if the nameserver has a glue record.... and also if it is maintained by us
|
# 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)
|
reasons.append("Nameserver %s depends on this domain" % ns.name)
|
||||||
|
|
||||||
return reasons
|
return reasons
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fixName(clazz, name):
|
def fixName(clazz, name):
|
||||||
if not name.endswith("."):
|
if not name.endswith("."):
|
||||||
name += "."
|
name += "."
|
||||||
return name.lower()
|
return name.lower()
|
||||||
|
|
||||||
|
|
||||||
class ReverseZone(WhoisObject):
|
class ReverseZone(DSRecordModelMixin, WhoisObject):
|
||||||
handle = None
|
handle = None
|
||||||
|
|
||||||
parentNet = models.ForeignKey(InetNum)
|
parentNet = models.ForeignKey(InetNum)
|
||||||
address = models.GenericIPAddressField(db_index=True)
|
address = models.GenericIPAddressField(db_index=True)
|
||||||
netmask = models.PositiveIntegerField()
|
netmask = models.PositiveIntegerField()
|
||||||
|
|
||||||
nameservers = models.ManyToManyField(Nameserver)
|
nameservers = models.ManyToManyField(Nameserver)
|
||||||
|
|
||||||
def getPK(self):
|
def getPK(self):
|
||||||
return self.pk
|
return self.pk
|
||||||
|
|
||||||
def prefix(self):
|
def prefix(self):
|
||||||
""" Helper function, mainly used in templates """
|
""" Helper function, mainly used in templates """
|
||||||
return "%s/%s" % (self.address, self.netmask)
|
return "%s/%s" % (self.address, self.netmask)
|
||||||
|
|
||||||
def getNetwork(self):
|
def getNetwork(self):
|
||||||
return ipaddress.ip_network(self.prefix())
|
return ipaddress.ip_network(self.prefix())
|
||||||
|
|
||||||
def getZone(self):
|
def getZone(self):
|
||||||
net = self.parentNet.getNetwork()
|
net = self.parentNet.getNetwork()
|
||||||
if net.version == 4:
|
if net.version == 4:
|
||||||
# does not work with python3.4
|
# does not work with python3.4
|
||||||
## for these we delegate the full domain
|
## for these we delegate the full domain
|
||||||
#if 0 < net.prefixlen < 32 and net.prefixlen % 8 == 0:
|
#if 0 < net.prefixlen < 32 and net.prefixlen % 8 == 0:
|
||||||
# zoneParts = net.reverse_pointer.split(".")
|
# zoneParts = net.reverse_pointer.split(".")
|
||||||
|
|
||||||
# return ".".join(zoneParts[1:])
|
# return ".".join(zoneParts[1:])
|
||||||
#else:
|
#else:
|
||||||
# # return RFC2317 compliant zone
|
# # return RFC2317 compliant zone
|
||||||
# return net.reverse_pointer
|
# return net.reverse_pointer
|
||||||
parts = list(reversed(str(net.network_address).split(".")))
|
parts = list(reversed(str(net.network_address).split(".")))
|
||||||
domain = ".".join(parts[4 - net.prefixlen // 8:]) + ".in-addr.arpa."
|
domain = ".".join(parts[4 - net.prefixlen // 8:]) + ".in-addr.arpa."
|
||||||
if net.prefixlen % 8 == 0:
|
if net.prefixlen % 8 == 0:
|
||||||
# clean cut!
|
# clean cut!
|
||||||
return domain
|
return domain
|
||||||
else:
|
else:
|
||||||
# RFC2317 compliant!
|
# RFC2317 compliant!
|
||||||
rfc2317Domain = "%s/%s.%s" % (parts[4 - net.prefixlen // 8 - 1], net.prefixlen, domain)
|
rfc2317Domain = "%s/%s.%s" % (parts[4 - net.prefixlen // 8 - 1], net.prefixlen, domain)
|
||||||
return rfc2317Domain
|
return rfc2317Domain
|
||||||
else:
|
else:
|
||||||
## does not work with python3.4
|
## does not work with python3.4
|
||||||
## ipv6
|
## ipv6
|
||||||
## thefuck ipaddress lib... _the_ _fuck_
|
## thefuck ipaddress lib... _the_ _fuck_
|
||||||
#zoneParts = net.reverse_pointer.split(".")[-2 - net.prefixlen // 4:]
|
#zoneParts = net.reverse_pointer.split(".")[-2 - net.prefixlen // 4:]
|
||||||
#return ".".join(zoneParts)
|
#return ".".join(zoneParts)
|
||||||
|
|
||||||
parts = list(reversed(net.exploded.split("/")[0].replace(":", "")))[32 - net.prefixlen // 4:]
|
parts = list(reversed(net.exploded.split("/")[0].replace(":", "")))[32 - net.prefixlen // 4:]
|
||||||
return ".".join(parts) + ".ip6.arpa."
|
return ".".join(parts) + ".ip6.arpa."
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("domains:reversezone-show", args=(self.pk,))
|
return reverse("domains:reversezone-show", args=(self.pk,))
|
||||||
|
|
||||||
def getAppName(self):
|
def getAppName(self):
|
||||||
return "domains"
|
return "domains"
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s @ %s" % (self.prefix(), self.parentNet)
|
return "%s @ %s" % (self.prefix(), self.parentNet)
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def canEdit(self, user):
|
def canEdit(self, user):
|
||||||
if self.parentNet:
|
if self.parentNet:
|
||||||
return self.parentNet.canEdit(user)
|
return self.parentNet.canEdit(user)
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -7,23 +7,23 @@ from django.conf.urls import url
|
||||||
from . import views as domains_views
|
from . import views as domains_views
|
||||||
|
|
||||||
urlpatterns = [
|
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/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/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/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/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/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/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/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/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/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/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/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/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/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/delete/(?P<pk>[0-9]+)/$', domains_views.ReverseZoneDelete.as_view(), name='reversezone-delete'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
186
domains/views.py
186
domains/views.py
|
@ -17,157 +17,157 @@ from .forms import DomainForm, NameserverForm, ReverseZoneForm
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def overview(request):
|
def overview(request):
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
|
|
||||||
# get all domains and nameservers
|
# get all domains and nameservers
|
||||||
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
|
domains = Domain.objects.filter(mnt_by__in=mnts).distinct()
|
||||||
nameservers = Nameserver.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()
|
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):
|
class DomainCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "domains/obj_create.html"
|
template_name = "domains/obj_create.html"
|
||||||
form_class = DomainForm
|
form_class = DomainForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(DomainCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(DomainCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class DomainCheck(LoginRequiredMixin, DetailView):
|
class DomainCheck(LoginRequiredMixin, DetailView):
|
||||||
model = Domain
|
model = Domain
|
||||||
slug_field = "name"
|
slug_field = "name"
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
context_object_name = "domain"
|
context_object_name = "domain"
|
||||||
template_name = "domains/dns_check.html"
|
template_name = "domains/dns_check.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super(DomainCheck, self).get_context_data(**kwargs)
|
ctx = super(DomainCheck, self).get_context_data(**kwargs)
|
||||||
ctx["key"] = self.object.name
|
ctx["key"] = self.object.name
|
||||||
ctx["apiUrl"] = reverse("api:domain-check")
|
ctx["apiUrl"] = reverse("api:domain-check")
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class DomainDetail(LoginRequiredMixin, DetailView):
|
class DomainDetail(LoginRequiredMixin, DetailView):
|
||||||
model = Domain
|
model = Domain
|
||||||
slug_field = "name"
|
slug_field = "name"
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
context_object_name = "domain"
|
context_object_name = "domain"
|
||||||
|
|
||||||
template_name = "whoisdb/handle_show.html"
|
template_name = "whoisdb/handle_show.html"
|
||||||
|
|
||||||
|
|
||||||
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class DomainEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Domain
|
model = Domain
|
||||||
form_class = DomainForm
|
form_class = DomainForm
|
||||||
slug_field = "name"
|
slug_field = "name"
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
template_name = "domains/obj_edit.html"
|
template_name = "domains/obj_edit.html"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(DomainEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(DomainEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class DomainDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class DomainDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "domains/obj_delete.html"
|
template_name = "domains/obj_delete.html"
|
||||||
model = Domain
|
model = Domain
|
||||||
slug_field = "name"
|
slug_field = "name"
|
||||||
slug_url_kwarg = "domain"
|
slug_url_kwarg = "domain"
|
||||||
success_url = reverse_lazy("domains:overview")
|
success_url = reverse_lazy("domains:overview")
|
||||||
|
|
||||||
|
|
||||||
class NameserverCreate(LoginRequiredMixin, CreateView):
|
class NameserverCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "domains/obj_create.html"
|
template_name = "domains/obj_create.html"
|
||||||
form_class = NameserverForm
|
form_class = NameserverForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(NameserverCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(NameserverCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class NameserverDetail(LoginRequiredMixin, DetailView):
|
class NameserverDetail(LoginRequiredMixin, DetailView):
|
||||||
model = Nameserver
|
model = Nameserver
|
||||||
template_name = "whoisdb/handle_show.html"
|
template_name = "whoisdb/handle_show.html"
|
||||||
|
|
||||||
|
|
||||||
class NameserverEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class NameserverEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = Nameserver
|
model = Nameserver
|
||||||
form_class = NameserverForm
|
form_class = NameserverForm
|
||||||
template_name = "domains/obj_edit.html"
|
template_name = "domains/obj_edit.html"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(NameserverEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(NameserverEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class NameserverDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class NameserverDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "domains/obj_delete.html"
|
template_name = "domains/obj_delete.html"
|
||||||
model = Nameserver
|
model = Nameserver
|
||||||
success_url = reverse_lazy("domains:overview")
|
success_url = reverse_lazy("domains:overview")
|
||||||
|
|
||||||
|
|
||||||
class ReverseZoneCreate(LoginRequiredMixin, CreateView):
|
class ReverseZoneCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "domains/obj_create.html"
|
template_name = "domains/obj_create.html"
|
||||||
form_class = ReverseZoneForm
|
form_class = ReverseZoneForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ReverseZoneCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ReverseZoneCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ReverseZoneCheck(LoginRequiredMixin, DetailView):
|
class ReverseZoneCheck(LoginRequiredMixin, DetailView):
|
||||||
model = ReverseZone
|
model = ReverseZone
|
||||||
template_name = "domains/dns_check.html"
|
template_name = "domains/dns_check.html"
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super(ReverseZoneCheck, self).get_context_data(**kwargs)
|
ctx = super(ReverseZoneCheck, self).get_context_data(**kwargs)
|
||||||
ctx["key"] = self.object.id
|
ctx["key"] = self.object.id
|
||||||
ctx["apiUrl"] = reverse("api:reversezone-check")
|
ctx["apiUrl"] = reverse("api:reversezone-check")
|
||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
class ReverseZoneDetail(LoginRequiredMixin, DetailView):
|
class ReverseZoneDetail(LoginRequiredMixin, DetailView):
|
||||||
model = ReverseZone
|
model = ReverseZone
|
||||||
template_name = "whoisdb/handle_show.html"
|
template_name = "whoisdb/handle_show.html"
|
||||||
|
|
||||||
|
|
||||||
class ReverseZoneEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class ReverseZoneEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
model = ReverseZone
|
model = ReverseZone
|
||||||
form_class = ReverseZoneForm
|
form_class = ReverseZoneForm
|
||||||
template_name = "domains/obj_edit.html"
|
template_name = "domains/obj_edit.html"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ReverseZoneEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ReverseZoneEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
if "initial" not in kwargs:
|
if "initial" not in kwargs:
|
||||||
kwargs["initial"] = {}
|
kwargs["initial"] = {}
|
||||||
|
|
||||||
kwargs["initial"]["prefix"] = self.object.prefix()
|
kwargs["initial"]["prefix"] = self.object.prefix()
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
mnts = self.request.user.maintainer_set.all()
|
mnts = self.request.user.maintainer_set.all()
|
||||||
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
|
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
|
||||||
|
|
||||||
|
|
||||||
class ReverseZoneDelete(LoginRequiredMixin, DeleteCheckView):
|
class ReverseZoneDelete(LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "domains/obj_delete.html"
|
template_name = "domains/obj_delete.html"
|
||||||
model = ReverseZone
|
model = ReverseZone
|
||||||
success_url = reverse_lazy("domains:overview")
|
success_url = reverse_lazy("domains:overview")
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
mnts = self.request.user.maintainer_set.all()
|
mnts = self.request.user.maintainer_set.all()
|
||||||
return ReverseZone.objects.filter(Q(parentNet__mnt_by__in=mnts) | Q(parentNet__mnt_lower__in=mnts)).distinct()
|
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
|
from whoisdb.models import Maintainer
|
||||||
|
|
||||||
class RequestForm(forms.Form):
|
class RequestForm(forms.Form):
|
||||||
RESOURCES = map(lambda _x: (_x, _x), [
|
RESOURCES = map(lambda _x: (_x, _x), [
|
||||||
"AS Number (16bit)", "IPv4 /27", "IPv4 > /27", "IPv6", "other"
|
"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")
|
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")
|
provider = forms.ModelChoiceField(Maintainer.objects.none(), label="Provider", help_text="LIR/RIR you want to request resources from")
|
||||||
|
|
||||||
subject = forms.CharField(label="Subject")
|
subject = forms.CharField(label="Subject")
|
||||||
resources = forms.CheckboxSelectMultiple(choices=RESOURCES)
|
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")
|
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):
|
def __init__(self, user, *args, **kwargs):
|
||||||
super(RequestForm, self).__init__(*args, **kwargs)
|
super(RequestForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
self._user = user
|
self._user = user
|
||||||
self.fields['applicant'].queryset = self._user.maintainer_set.all()
|
self.fields['applicant'].queryset = self._user.maintainer_set.all()
|
||||||
self.fields['provider'].queryset = Maintainer.objects.filter(Q(rir=True) | Q(lir=True))
|
self.fields['provider'].queryset = Maintainer.objects.filter(Q(rir=True) | Q(lir=True))
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(RequestForm, self).clean()
|
cleaned_data = super(RequestForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
if cleaned_data['applicant'] in mnts and cleaned_data['provider'] in mnts:
|
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.")
|
raise forms.ValidationError("You could request resources from yourself, but this would actually not make that much sense.")
|
||||||
|
|
||||||
class ResponseForm(forms.Form):
|
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")
|
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)
|
message = forms.CharField(widget=forms.Textarea)
|
||||||
|
|
||||||
def __init__(self, request, user, *args, **kwargs):
|
def __init__(self, request, user, *args, **kwargs):
|
||||||
super(ResponseForm, self).__init__(*args, **kwargs)
|
super(ResponseForm, self).__init__(*args, **kwargs)
|
||||||
self._request = request
|
self._request = request
|
||||||
self._user = user
|
self._user = user
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ResponseForm, self).clean()
|
cleaned_data = super(ResponseForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
if cleaned_data['new_status'] == self._request.status:
|
if cleaned_data['new_status'] == self._request.status:
|
||||||
raise forms.ValidationError("Status changed to same as ticket")
|
raise forms.ValidationError("Status changed to same as ticket")
|
||||||
if self._request.status in (Request.STATE_RESOLVED, Request.STATE_REJECTED) and \
|
if self._request.status in (Request.STATE_RESOLVED, Request.STATE_REJECTED) and \
|
||||||
cleaned_data['new_status'] not in (Request.STATE_OPEN,):
|
cleaned_data['new_status'] not in (Request.STATE_OPEN,):
|
||||||
raise forms.ValidationError("Please put this ticket in an open state before adding messages")
|
raise forms.ValidationError("Please put this ticket in an open state before adding messages")
|
||||||
|
|
||||||
|
|
||||||
class ProviderResponseForm(ResponseForm):
|
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
|
from whoisdb.models import Maintainer
|
||||||
|
|
||||||
class Request(models.Model):
|
class Request(models.Model):
|
||||||
STATE_OPEN = "OPEN"
|
STATE_OPEN = "OPEN"
|
||||||
STATE_RESOLVED = "RESOLVED"
|
STATE_RESOLVED = "RESOLVED"
|
||||||
STATE_REJECTED = "REJECTED"
|
STATE_REJECTED = "REJECTED"
|
||||||
STATES = (
|
STATES = (
|
||||||
(STATE_OPEN, 'Open'),
|
(STATE_OPEN, 'Open'),
|
||||||
(STATE_RESOLVED, 'Resolved'),
|
(STATE_RESOLVED, 'Resolved'),
|
||||||
(STATE_REJECTED, 'Rejected'),
|
(STATE_REJECTED, 'Rejected'),
|
||||||
)
|
)
|
||||||
|
|
||||||
# request goes to mnt?
|
# request goes to mnt?
|
||||||
subject = models.CharField(max_length=200)
|
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)
|
applicant = models.ForeignKey(Maintainer)
|
||||||
provider = models.ForeignKey(Maintainer, related_name='requestfrom_set')
|
provider = models.ForeignKey(Maintainer, related_name='requestfrom_set')
|
||||||
|
|
||||||
requestResources = models.TextField()
|
requestResources = models.TextField()
|
||||||
grantedResources = models.TextField()
|
grantedResources = models.TextField()
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
lastAction = models.DateTimeField(auto_now_add=True)
|
lastAction = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("rrequests:show", args=(self.pk,))
|
return reverse("rrequests:show", args=(self.pk,))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "(%s -> %s) [%s] %s" % (self.applicant, self.provider, self.status, self.subject)
|
return "(%s -> %s) [%s] %s" % (self.applicant, self.provider, self.status, self.subject)
|
||||||
|
|
||||||
def getLastActionBy(self):
|
def getLastActionBy(self):
|
||||||
msgs = self.requestmessage_set.order_by("-created")
|
msgs = self.requestmessage_set.order_by("-created")
|
||||||
|
|
||||||
if msgs.count() > 0:
|
if msgs.count() > 0:
|
||||||
return msgs[0].creator
|
return msgs[0].creator
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class RequestMessage(models.Model):
|
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)
|
creator = models.ForeignKey(Maintainer)
|
||||||
message = models.TextField()
|
message = models.TextField()
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
|
@ -7,8 +7,8 @@ from django.conf.urls import url
|
||||||
from . import views as rrequests_views
|
from . import views as rrequests_views
|
||||||
|
|
||||||
urlpatterns = [
|
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'create/$', rrequests_views.RrequestCreate.as_view(), name='create'),
|
||||||
url(r'show/(?P<pk>\d+)/$', rrequests_views.rrequestDetail, name='show'),
|
url(r'show/(?P<pk>\d+)/$', rrequests_views.rrequestDetail, name='show'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,88 +17,88 @@ from .forms import RequestForm, ResponseForm, ProviderResponseForm
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def listRequests(request):
|
def listRequests(request):
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
requestedFromMe = Request.objects.filter(applicant__in=mnts)
|
requestedFromMe = Request.objects.filter(applicant__in=mnts)
|
||||||
requestedToMe = Request.objects.filter(provider__in=mnts)
|
requestedToMe = Request.objects.filter(provider__in=mnts)
|
||||||
requests = (requestedFromMe | requestedToMe).order_by("-lastAction")
|
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):
|
class RrequestCreate(LoginRequiredMixin, FormView):
|
||||||
template_name = "rrequests/request_create.html"
|
template_name = "rrequests/request_create.html"
|
||||||
form_class = RequestForm
|
form_class = RequestForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(RrequestCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(RrequestCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs['user'] = self.request.user
|
kwargs['user'] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
formData = form.cleaned_data
|
formData = form.cleaned_data
|
||||||
print(formData)
|
print(formData)
|
||||||
request = Request(
|
request = Request(
|
||||||
subject=formData['subject'],
|
subject=formData['subject'],
|
||||||
status=Request.STATE_OPEN,
|
status=Request.STATE_OPEN,
|
||||||
applicant=formData['applicant'],
|
applicant=formData['applicant'],
|
||||||
provider=formData['provider'],
|
provider=formData['provider'],
|
||||||
)
|
)
|
||||||
request.save()
|
request.save()
|
||||||
|
|
||||||
requestMsg = RequestMessage(
|
requestMsg = RequestMessage(
|
||||||
request=request,
|
request=request,
|
||||||
|
|
||||||
creator=formData['applicant'],
|
creator=formData['applicant'],
|
||||||
message=formData['message'],
|
message=formData['message'],
|
||||||
)
|
)
|
||||||
requestMsg.save()
|
requestMsg.save()
|
||||||
|
|
||||||
return HttpResponseRedirect(request.get_absolute_url())
|
return HttpResponseRedirect(request.get_absolute_url())
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def rrequestDetail(request, pk):
|
def rrequestDetail(request, pk):
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
reqObj = get_object_or_404(Request.objects.filter(Q(provider__in=mnts) | Q(applicant__in=mnts)), pk=pk)
|
reqObj = get_object_or_404(Request.objects.filter(Q(provider__in=mnts) | Q(applicant__in=mnts)), pk=pk)
|
||||||
|
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
formClass = None
|
formClass = None
|
||||||
provider = None
|
provider = None
|
||||||
initialFormData = {}
|
initialFormData = {}
|
||||||
if reqObj.provider in mnts:
|
if reqObj.provider in mnts:
|
||||||
provider = True
|
provider = True
|
||||||
formClass = ProviderResponseForm
|
formClass = ProviderResponseForm
|
||||||
initialFormData["createdResources"] = reqObj.grantedResources
|
initialFormData["createdResources"] = reqObj.grantedResources
|
||||||
else:
|
else:
|
||||||
provider = False
|
provider = False
|
||||||
formClass = ResponseForm
|
formClass = ResponseForm
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = formClass(request=reqObj, user=request.user, data=request.POST)
|
form = formClass(request=reqObj, user=request.user, data=request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
# create message object
|
# create message object
|
||||||
msg = RequestMessage(
|
msg = RequestMessage(
|
||||||
request=reqObj,
|
request=reqObj,
|
||||||
creator=reqObj.provider if provider else reqObj.applicant,
|
creator=reqObj.provider if provider else reqObj.applicant,
|
||||||
message=form.cleaned_data['message']
|
message=form.cleaned_data['message']
|
||||||
)
|
)
|
||||||
if form.cleaned_data['new_status'] != "KEEP":
|
if form.cleaned_data['new_status'] != "KEEP":
|
||||||
msg.statusChanged = form.cleaned_data['new_status']
|
msg.statusChanged = form.cleaned_data['new_status']
|
||||||
reqObj.status = msg.statusChanged
|
reqObj.status = msg.statusChanged
|
||||||
|
|
||||||
msg.save()
|
msg.save()
|
||||||
|
|
||||||
if "createdResources" in form.cleaned_data and \
|
if "createdResources" in form.cleaned_data and \
|
||||||
form.cleaned_data['createdResources'].strip() != "":
|
form.cleaned_data['createdResources'].strip() != "":
|
||||||
reqObj.grantedResources = form.cleaned_data["createdResources"].strip()
|
reqObj.grantedResources = form.cleaned_data["createdResources"].strip()
|
||||||
|
|
||||||
reqObj.lastAction = timezone.now()
|
reqObj.lastAction = timezone.now()
|
||||||
reqObj.save()
|
reqObj.save()
|
||||||
|
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse("rrequests:show", args=(pk,)))
|
return HttpResponseRedirect(reverse("rrequests:show", args=(pk,)))
|
||||||
else:
|
else:
|
||||||
form = formClass(request=reqObj, user=request.user, initial=initialFormData)
|
form = formClass(request=reqObj, user=request.user, initial=initialFormData)
|
||||||
|
|
||||||
return render(request, "rrequests/request_detail.html", {"request": reqObj, "form": form})
|
return render(request, "rrequests/request_detail.html", {"request": reqObj, "form": form})
|
||||||
|
|
||||||
|
|
|
@ -6,33 +6,33 @@ from django import forms
|
||||||
|
|
||||||
|
|
||||||
class MultiTextInput(forms.widgets.Input):
|
class MultiTextInput(forms.widgets.Input):
|
||||||
input_type = "text"
|
input_type = "text"
|
||||||
|
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
selectedOptions = []
|
selectedOptions = []
|
||||||
for val in value:
|
for val in value:
|
||||||
for k, v in self.choices:
|
for k, v in self.choices:
|
||||||
if val == k:
|
if val == k:
|
||||||
selectedOptions.append(v)
|
selectedOptions.append(v)
|
||||||
|
|
||||||
value = " ".join(selectedOptions)
|
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):
|
def value_from_datadict(self, data, files, name):
|
||||||
values = list(filter(bool, map(lambda _x: _x.strip(), data.get(name).split(" "))))
|
values = list(filter(bool, map(lambda _x: _x.strip(), data.get(name).split(" "))))
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for value in values:
|
for value in values:
|
||||||
# FIXME: using value here throws a weird error message at some point
|
# FIXME: using value here throws a weird error message at some point
|
||||||
# could be handled by overriding the messages in ChoiceField
|
# could be handled by overriding the messages in ChoiceField
|
||||||
# or... well, don't know
|
# or... well, don't know
|
||||||
kId = value
|
kId = value
|
||||||
for k, v in self.choices:
|
for k, v in self.choices:
|
||||||
if v.lower() == value.lower():
|
if v.lower() == value.lower():
|
||||||
kId = str(k)
|
kId = str(k)
|
||||||
break
|
break
|
||||||
result.append(kId)
|
result.append(kId)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
494
whoisdb/forms.py
494
whoisdb/forms.py
|
@ -15,351 +15,351 @@ import ipaddress
|
||||||
|
|
||||||
|
|
||||||
class WhoisObjectFormMixin(object):
|
class WhoisObjectFormMixin(object):
|
||||||
def __init__(self, user, *args, **kwargs):
|
def __init__(self, user, *args, **kwargs):
|
||||||
super(WhoisObjectFormMixin, self).__init__(*args, **kwargs)
|
super(WhoisObjectFormMixin, self).__init__(*args, **kwargs)
|
||||||
self._user = user
|
self._user = user
|
||||||
|
|
||||||
instance = getattr(self, 'instance', None)
|
instance = getattr(self, 'instance', None)
|
||||||
if instance and instance.pk:
|
if instance and instance.pk:
|
||||||
self._create = False
|
self._create = False
|
||||||
#self.fields['handle'].disabled = True
|
#self.fields['handle'].disabled = True
|
||||||
else:
|
else:
|
||||||
self._create = True
|
self._create = True
|
||||||
|
|
||||||
if 'handle' in self.fields:
|
if 'handle' in self.fields:
|
||||||
self.fields['handle'].help_text = "Handle for this object in uppercase with a suffix of -%s" % instance.handleSuffix
|
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
|
# only show users contacts and already present contacts
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
if 'admin_c' in self.fields:
|
if 'admin_c' in self.fields:
|
||||||
self.fields['admin_c'].queryset = Contact.getMntQueryset(mnts, self.instance, "admin_c")
|
self.fields['admin_c'].queryset = Contact.getMntQueryset(mnts, self.instance, "admin_c")
|
||||||
|
|
||||||
def clean_handle(self):
|
def clean_handle(self):
|
||||||
HandleValidatorWithSuffix(self.instance.handleSuffix)(self.cleaned_data['handle'])
|
HandleValidatorWithSuffix(self.instance.handleSuffix)(self.cleaned_data['handle'])
|
||||||
return self.cleaned_data['handle']
|
return self.cleaned_data['handle']
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(WhoisObjectFormMixin, self).clean()
|
cleaned_data = super(WhoisObjectFormMixin, self).clean()
|
||||||
if cleaned_data.get("handle") == "AUTO" and not self.errors:
|
if cleaned_data.get("handle") == "AUTO" and not self.errors:
|
||||||
name = cleaned_data.get("name")
|
name = cleaned_data.get("name")
|
||||||
if name is None:
|
if name is None:
|
||||||
name = self._user.username
|
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
|
# XXX: Find a better position to update last_changed
|
||||||
self.instance.last_modified = timezone.now()
|
self.instance.last_modified = timezone.now()
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class MntFormMixin(object):
|
class MntFormMixin(object):
|
||||||
protectedFields = []
|
protectedFields = []
|
||||||
|
|
||||||
def __init__(self, lower=False, *args, **kwargs):
|
def __init__(self, lower=False, *args, **kwargs):
|
||||||
super(MntFormMixin, self).__init__(*args, **kwargs)
|
super(MntFormMixin, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
self._editLower = lower
|
self._editLower = lower
|
||||||
|
|
||||||
if self._editLower:
|
if self._editLower:
|
||||||
for key in self.protectedFields:
|
for key in self.protectedFields:
|
||||||
self.fields[key].disabled = True
|
self.fields[key].disabled = True
|
||||||
|
|
||||||
instance = getattr(self, "instance", None)
|
instance = getattr(self, "instance", None)
|
||||||
if not hasattr(self, "_create"):
|
if not hasattr(self, "_create"):
|
||||||
self._create = not (instance and instance.pk)
|
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)
|
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
|
self.fields["mnt_by"].queryset = mntQs
|
||||||
|
|
||||||
if "mnt_lower" in self.fields:
|
if "mnt_lower" in self.fields:
|
||||||
self.fields["mnt_lower"].queryset = mntQs
|
self.fields["mnt_lower"].queryset = mntQs
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(MntFormMixin, self).clean()
|
cleaned_data = super(MntFormMixin, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
if self._create:
|
if self._create:
|
||||||
# at least one own mnt on creation
|
# at least one own mnt on creation
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
|
|
||||||
for mnt in cleaned_data['mnt_by']:
|
for mnt in cleaned_data['mnt_by']:
|
||||||
if mnt in mnts:
|
if mnt in mnts:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise forms.ValidationError("On object creation at least one maintainer needs to be under your control")
|
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:
|
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")
|
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 MntForm(WhoisObjectFormMixin, forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
#fields = ['handle', 'description', 'admin_c', 'auth']
|
#fields = ['handle', 'description', 'admin_c', 'auth']
|
||||||
fields = ['handle', 'description', 'admin_c']
|
fields = ['handle', 'description', 'admin_c']
|
||||||
widgets = {'auth': MultiTextInput()}
|
widgets = {'auth': MultiTextInput()}
|
||||||
|
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'auth': 'Enter names of users which can edit this object (space separated; '
|
'auth': 'Enter names of users which can edit this object (space separated; '
|
||||||
'and yes, validation is somewhat broken (values disappear on error - just reload))'
|
'and yes, validation is somewhat broken (values disappear on error - just reload))'
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(MntForm, self).__init__(*args, **kwargs)
|
super(MntForm, self).__init__(*args, **kwargs)
|
||||||
print(args, kwargs)
|
print(args, kwargs)
|
||||||
|
|
||||||
#if self._create:
|
#if self._create:
|
||||||
# self.fields['auth'].text("noot")
|
# self.fields['auth'].text("noot")
|
||||||
|
|
||||||
|
|
||||||
class MntInitialForm(MntForm):
|
class MntInitialForm(MntForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
fields = ['handle', 'description']
|
fields = ['handle', 'description']
|
||||||
|
|
||||||
|
|
||||||
class ContactForm(WhoisObjectFormMixin, forms.ModelForm):
|
class ContactForm(WhoisObjectFormMixin, forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contact
|
model = Contact
|
||||||
fields = ['handle', 'name', 'mnt_by']
|
fields = ['handle', 'name', 'mnt_by']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ContactForm, self).__init__(*args, **kwargs)
|
super(ContactForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if "mnt_by" in self.fields:
|
if "mnt_by" in self.fields:
|
||||||
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user).distinct()
|
self.fields['mnt_by'].queryset = Maintainer.objects.filter(auth=self._user).distinct()
|
||||||
|
|
||||||
|
|
||||||
class ContactInitialForm(ContactForm):
|
class ContactInitialForm(ContactForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Contact
|
model = Contact
|
||||||
fields = ['handle', 'name']
|
fields = ['handle', 'name']
|
||||||
|
|
||||||
|
|
||||||
class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
class InetNumForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
prefix = forms.CharField()
|
prefix = forms.CharField()
|
||||||
protectedFields = ['protocol', 'parent_range', 'mnt_by', 'prefix']
|
protectedFields = ['protocol', 'parent_range', 'mnt_by', 'prefix']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = InetNum
|
model = InetNum
|
||||||
fields = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'origin_as', 'mnt_by', 'mnt_lower', 'admin_c']
|
fields = ['handle', 'protocol', 'parent_range', 'prefix', 'name', 'description', 'origin_as', 'mnt_by', 'mnt_lower', 'admin_c']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(InetNumForm, self).__init__(*args, **kwargs)
|
super(InetNumForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if self._editLower:
|
if self._editLower:
|
||||||
for key in self.protectedFields:
|
for key in self.protectedFields:
|
||||||
self.fields[key].disabled = True
|
self.fields[key].disabled = True
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
#self.fields['parent_range'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts))
|
#self.fields['parent_range'].queryset = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts))
|
||||||
#if not self._create:
|
#if not self._create:
|
||||||
# self.fields['parent_range'].queryset |= InetNum.objects.filter(pk=self.instance.pk)
|
# 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 = self.fields['parent_range'].queryset.distinct()
|
||||||
self.fields['parent_range'].queryset = InetNum.getMntQueryset(mnts, self.instance, "parent_range")
|
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['origin_as'].queryset = ASNumber.getMntQueryset(mnts, self.instance, "origin_as")
|
||||||
|
|
||||||
def clean_prefix(self):
|
def clean_prefix(self):
|
||||||
# make sure this is a subnet we're getting
|
# make sure this is a subnet we're getting
|
||||||
net = self.cleaned_data['prefix'].lower()
|
net = self.cleaned_data['prefix'].lower()
|
||||||
IP46CIDRValidator(net)
|
IP46CIDRValidator(net)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
net = ipaddress.ip_network(net)
|
net = ipaddress.ip_network(net)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise forms.ValidationError(str(e))
|
raise forms.ValidationError(str(e))
|
||||||
|
|
||||||
return net
|
return net
|
||||||
|
|
||||||
def clean_parent_range(self):
|
def clean_parent_range(self):
|
||||||
parent_range = self.cleaned_data.get('parent_range', None)
|
parent_range = self.cleaned_data.get('parent_range', None)
|
||||||
|
|
||||||
|
|
||||||
# allow parent range to be unset for already present objects
|
# 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):
|
if not parent_range and (self._create or not self._create and self.instance.parent_range):
|
||||||
raise forms.ValidationError("Parent range must be set")
|
raise forms.ValidationError("Parent range must be set")
|
||||||
|
|
||||||
if not self._create and parent_range:
|
if not self._create and parent_range:
|
||||||
# make sure we don't have circular dependencies
|
# make sure we don't have circular dependencies
|
||||||
obj = parent_range
|
obj = parent_range
|
||||||
while obj.parent_range:
|
while obj.parent_range:
|
||||||
if obj.pk == self.instance.pk:
|
if obj.pk == self.instance.pk:
|
||||||
raise forms.ValidationError("No circular dependencies allowed")
|
raise forms.ValidationError("No circular dependencies allowed")
|
||||||
obj = obj.parent_range
|
obj = obj.parent_range
|
||||||
|
|
||||||
if parent_range.origin_as.count() > 0:
|
if parent_range.origin_as.count() > 0:
|
||||||
raise forms.ValidationError("Parent range has origin as set")
|
raise forms.ValidationError("Parent range has origin as set")
|
||||||
|
|
||||||
return parent_range
|
return parent_range
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(InetNumForm, self).clean()
|
cleaned_data = super(InetNumForm, self).clean()
|
||||||
|
|
||||||
if not self._editLower:
|
if not self._editLower:
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
if not self._create and self.cleaned_data['origin_as']:
|
if not self._create and self.cleaned_data['origin_as']:
|
||||||
if self.instance.inetnum_set.count() > 0:
|
if self.instance.inetnum_set.count() > 0:
|
||||||
ranges = ", ".join(map(str, self.instance.inetnum_set.all()))
|
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))
|
raise forms.ValidationError("You cannot set an origin as if there are already existing subranges (%s)" % (ranges))
|
||||||
|
|
||||||
prefix = cleaned_data['prefix']
|
prefix = cleaned_data['prefix']
|
||||||
parent = cleaned_data['parent_range']
|
parent = cleaned_data['parent_range']
|
||||||
if parent:
|
if parent:
|
||||||
parentNet = parent.getNetwork()
|
parentNet = parent.getNetwork()
|
||||||
|
|
||||||
if cleaned_data['protocol'] != parent.protocol:
|
if cleaned_data['protocol'] != parent.protocol:
|
||||||
raise forms.ValidationError("Protocol type for prefix must be same as parent network")
|
raise forms.ValidationError("Protocol type for prefix must be same as parent network")
|
||||||
|
|
||||||
# check if in parent block
|
# check if in parent block
|
||||||
if prefix.network_address not in parentNet or prefix.prefixlen < parentNet.prefixlen:
|
if prefix.network_address not in parentNet or prefix.prefixlen < parentNet.prefixlen:
|
||||||
raise forms.ValidationError("Prefix must be inside parent network range")
|
raise forms.ValidationError("Prefix must be inside parent network range")
|
||||||
|
|
||||||
|
|
||||||
# check if parent block has net that overlaps with us
|
# check if parent block has net that overlaps with us
|
||||||
for otherNet in parent.inetnum_set.all():
|
for otherNet in parent.inetnum_set.all():
|
||||||
if self.instance and self.instance.pk == otherNet.pk:
|
if self.instance and self.instance.pk == otherNet.pk:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if otherNet.getNetwork().overlaps(prefix):
|
if otherNet.getNetwork().overlaps(prefix):
|
||||||
raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle)
|
raise forms.ValidationError("The given prefix overlaps with network %s" % otherNet.handle)
|
||||||
|
|
||||||
# check if subnets to this subnet are (still) in current network
|
# check if subnets to this subnet are (still) in current network
|
||||||
if not self._create:
|
if not self._create:
|
||||||
for subnet in self.instance.inetnum_set.all():
|
for subnet in self.instance.inetnum_set.all():
|
||||||
if subnet.getNetwork().network_address not in self.instance.getNetwork():
|
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()))
|
raise forms.ValidationError("Subnet %s with %s is not in block anymore" % (subnet, subnet.getNetwork()))
|
||||||
|
|
||||||
self.instance.address = str(prefix.network_address)
|
self.instance.address = str(prefix.network_address)
|
||||||
self.instance.netmask = prefix.prefixlen
|
self.instance.netmask = prefix.prefixlen
|
||||||
|
|
||||||
return cleaned_data
|
return cleaned_data
|
||||||
|
|
||||||
|
|
||||||
class ASBlockForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
class ASBlockForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
protectedFields = ['parent_block', 'asBegin', 'asEnd', 'mnt_by']
|
protectedFields = ['parent_block', 'asBegin', 'asEnd', 'mnt_by']
|
||||||
|
|
||||||
# FIXME: Filter blocks
|
# FIXME: Filter blocks
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ASBlock
|
model = ASBlock
|
||||||
fields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
|
fields = ['handle', 'parent_block', 'asBegin', 'asEnd', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ASBlockForm, self).__init__(*args, **kwargs)
|
super(ASBlockForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if not self.instance or self.instance and self.instance and self.instance.parent_block:
|
if not self.instance or self.instance and self.instance and self.instance.parent_block:
|
||||||
self.fields["parent_block"].required = True
|
self.fields["parent_block"].required = True
|
||||||
if self.instance and self.instance.pk:
|
if self.instance and self.instance.pk:
|
||||||
self.fields["parent_block"].disabled = True
|
self.fields["parent_block"].disabled = True
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
self.fields['parent_block'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "parent_block")
|
self.fields['parent_block'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "parent_block")
|
||||||
|
|
||||||
def clean_parent_block(self):
|
def clean_parent_block(self):
|
||||||
parent_block = self.cleaned_data.get('parent_block', None)
|
parent_block = self.cleaned_data.get('parent_block', None)
|
||||||
|
|
||||||
# allow parent range to be unset for already present objects
|
# 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):
|
if not parent_block and (self._create or not self._create and self.instance.parent_block):
|
||||||
raise forms.ValidationError("Parent block must be set")
|
raise forms.ValidationError("Parent block must be set")
|
||||||
|
|
||||||
if not self._create and parent_block:
|
if not self._create and parent_block:
|
||||||
# make sure we don't have circular dependencies
|
# make sure we don't have circular dependencies
|
||||||
obj = parent_block
|
obj = parent_block
|
||||||
while obj.parent_block:
|
while obj.parent_block:
|
||||||
if obj.pk == self.instance.pk:
|
if obj.pk == self.instance.pk:
|
||||||
raise forms.ValidationError("No circular dependencies allowed")
|
raise forms.ValidationError("No circular dependencies allowed")
|
||||||
obj = obj.parent_block
|
obj = obj.parent_block
|
||||||
|
|
||||||
return parent_block
|
return parent_block
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ASBlockForm, self).clean()
|
cleaned_data = super(ASBlockForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
asBegin = cleaned_data['asBegin']
|
asBegin = cleaned_data['asBegin']
|
||||||
asEnd = cleaned_data['asEnd']
|
asEnd = cleaned_data['asEnd']
|
||||||
parent = cleaned_data['parent_block']
|
parent = cleaned_data['parent_block']
|
||||||
# check if somebody is already using this block
|
# check if somebody is already using this block
|
||||||
|
|
||||||
# check if in range
|
# check if in range
|
||||||
if asBegin > asEnd:
|
if asBegin > asEnd:
|
||||||
raise forms.ValidationError("AS beginning must be smaller or equal to AS end")
|
raise forms.ValidationError("AS beginning must be smaller or equal to AS end")
|
||||||
|
|
||||||
if parent:
|
if parent:
|
||||||
if parent.asnumber_set.count() > 0:
|
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())),))
|
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
|
# check if same range
|
||||||
if not (asBegin >= parent.asBegin and asEnd <= parent.asEnd):
|
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")
|
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:
|
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")
|
raise forms.ValidationError("The range of this block cannot be the same range AS the parent AS block")
|
||||||
|
|
||||||
# check for overlap with other asblocks
|
# check for overlap with other asblocks
|
||||||
for block in parent.asblock_set.all():
|
for block in parent.asblock_set.all():
|
||||||
if self.instance and self.instance.pk and block.pk == self.instance.pk:
|
if self.instance and self.instance.pk and block.pk == self.instance.pk:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
|
if block.asBegin <= asBegin <= block.asEnd or block.asBegin <= asEnd <= block.asEnd or \
|
||||||
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
|
asBegin <= block.asBegin <= asEnd or asBegin <= block.asEnd <= asEnd:
|
||||||
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
|
raise forms.ValidationError("Block overlaps with block %s" % block.handle)
|
||||||
|
|
||||||
if not self._create:
|
if not self._create:
|
||||||
# check if subblocks are still in range
|
# check if subblocks are still in range
|
||||||
for subblock in self.instance.asblock_set.all():
|
for subblock in self.instance.asblock_set.all():
|
||||||
if not (asBegin <= subblock.asBegin <= asEnd and asBegin <= subblock.asEnd <= asEnd):
|
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))
|
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
|
# check if asnumbers are still in range
|
||||||
for asnumber in self.instance.asnumber_set.all():
|
for asnumber in self.instance.asnumber_set.all():
|
||||||
if not (asBegin <= asnumber.number <= asEnd):
|
if not (asBegin <= asnumber.number <= asEnd):
|
||||||
raise forms.ValidationError("AS %s (%s) is not contained in this block anymore" % (asnumber, asnumber.number))
|
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):
|
class ASNumberForm(MntFormMixin, WhoisObjectFormMixin, forms.ModelForm):
|
||||||
protectedFields = ['asblock', 'number', 'mnt_by']
|
protectedFields = ['asblock', 'number', 'mnt_by']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ASNumber
|
model = ASNumber
|
||||||
fields = ['handle', 'asblock', 'number', 'volatile', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
|
fields = ['handle', 'asblock', 'number', 'volatile', 'name', 'description', 'mnt_by', 'mnt_lower', 'admin_c']
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ASNumberForm, self).__init__(*args, **kwargs)
|
super(ASNumberForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
if not (self.instance and self.instance.pk):
|
if not (self.instance and self.instance.pk):
|
||||||
self.fields["asblock"].required = True
|
self.fields["asblock"].required = True
|
||||||
else:
|
else:
|
||||||
self.fields["asblock"].disabled = True
|
self.fields["asblock"].disabled = True
|
||||||
|
|
||||||
mnts = self._user.maintainer_set.all()
|
mnts = self._user.maintainer_set.all()
|
||||||
self.fields['asblock'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "asblock")
|
self.fields['asblock'].queryset = ASBlock.getMntQueryset(mnts, self.instance, "asblock")
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
cleaned_data = super(ASNumberForm, self).clean()
|
cleaned_data = super(ASNumberForm, self).clean()
|
||||||
|
|
||||||
if not self.errors:
|
if not self.errors:
|
||||||
number = cleaned_data['number']
|
number = cleaned_data['number']
|
||||||
block = cleaned_data['asblock']
|
block = cleaned_data['asblock']
|
||||||
|
|
||||||
# belongs to asblock?
|
# belongs to asblock?
|
||||||
if number < block.asBegin or number > block.asEnd:
|
if number < block.asBegin or number > block.asEnd:
|
||||||
raise forms.ValidationError("AS number is not inside AS block")
|
raise forms.ValidationError("AS number is not inside AS block")
|
||||||
|
|
||||||
# does an entry already exist?
|
# does an entry already exist?
|
||||||
try:
|
try:
|
||||||
otherAS = ASNumber.objects.get(number=number)
|
otherAS = ASNumber.objects.get(number=number)
|
||||||
if not (self.instance and self.instance.pk and self.instance.pk == otherAS.pk):
|
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)
|
raise forms.ValidationError("This AS number is already represented by %s" % otherAS.handle)
|
||||||
except ASNumber.DoesNotExist:
|
except ASNumber.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# has already other asblock?
|
# has already other asblock?
|
||||||
if block.asblock_set.count() > 0:
|
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())),))
|
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):
|
class DeleteCheckView(DeleteView):
|
||||||
""" Check if object actually can be deleted. Provide reasons to template
|
""" Check if object actually can be deleted. Provide reasons to template
|
||||||
if not.
|
if not.
|
||||||
"""
|
"""
|
||||||
def delete(self, request, *args, **kwargs):
|
def delete(self, request, *args, **kwargs):
|
||||||
self.object = self.get_object()
|
self.object = self.get_object()
|
||||||
success_url = self.get_success_url()
|
success_url = self.get_success_url()
|
||||||
|
|
||||||
reasons = self.object.getNoDeleteReasons()
|
reasons = self.object.getNoDeleteReasons()
|
||||||
if reasons:
|
if reasons:
|
||||||
# do not delete, do what get does...
|
# do not delete, do what get does...
|
||||||
return self.get(request, *args, **kwargs)
|
return self.get(request, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
self.object.delete()
|
self.object.delete()
|
||||||
messages.info(request, "Object %s has been deleted" % str(self.object))
|
messages.info(request, "Object %s has been deleted" % str(self.object))
|
||||||
return HttpResponseRedirect(success_url)
|
return HttpResponseRedirect(success_url)
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
if 'reasons' not in kwargs:
|
if 'reasons' not in kwargs:
|
||||||
kwargs['reasons'] = self.object.getNoDeleteReasons()
|
kwargs['reasons'] = self.object.getNoDeleteReasons()
|
||||||
return super(DeleteCheckView, self).get_context_data(**kwargs)
|
return super(DeleteCheckView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class MntGenericMixin(object):
|
class MntGenericMixin(object):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
mnts = self.request.user.maintainer_set.all()
|
mnts = self.request.user.maintainer_set.all()
|
||||||
|
|
||||||
q = Q(mnt_by__in=mnts)
|
q = Q(mnt_by__in=mnts)
|
||||||
if hasattr(self.model, "mnt_lower"):
|
if hasattr(self.model, "mnt_lower"):
|
||||||
q |= Q(mnt_lower__in=mnts)
|
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):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(MntGenericMixin, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(MntGenericMixin, self).get_form_kwargs(*args, **kwargs)
|
||||||
|
|
||||||
if hasattr(self.model, "mnt_lower"):
|
if hasattr(self.model, "mnt_lower"):
|
||||||
mnts = self.request.user.maintainer_set.all()
|
mnts = self.request.user.maintainer_set.all()
|
||||||
if not any(mnt in self.object.mnt_by.all() for mnt in mnts):
|
if not any(mnt in self.object.mnt_by.all() for mnt in mnts):
|
||||||
# we are in mnt_lower
|
# we are in mnt_lower
|
||||||
kwargs["lower"] = True
|
kwargs["lower"] = True
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
|
@ -11,161 +11,161 @@ import ipaddress
|
||||||
import re
|
import re
|
||||||
|
|
||||||
def _addFields(fields, obj, fieldNames):
|
def _addFields(fields, obj, fieldNames):
|
||||||
for fieldName in fieldNames:
|
for fieldName in fieldNames:
|
||||||
fields.append((fieldName.capitalize().replace("_", " "), getattr(obj, fieldName)))
|
fields.append((fieldName.capitalize().replace("_", " "), getattr(obj, fieldName)))
|
||||||
|
|
||||||
|
|
||||||
def getWhoisObjectFields(obj, owner):
|
def getWhoisObjectFields(obj, owner):
|
||||||
fields = []
|
fields = []
|
||||||
|
|
||||||
if getattr(obj, "handle", None):
|
if getattr(obj, "handle", None):
|
||||||
_addFields(fields, obj, ["handle"])
|
_addFields(fields, obj, ["handle"])
|
||||||
|
|
||||||
c = type(obj)
|
c = type(obj)
|
||||||
if c == whoisdb.models.Maintainer:
|
if c == whoisdb.models.Maintainer:
|
||||||
_addFields(fields, obj, ["description", "admin_c"])
|
_addFields(fields, obj, ["description", "admin_c"])
|
||||||
if owner:
|
if owner:
|
||||||
_addFields(fields, obj, ["auth"])
|
_addFields(fields, obj, ["auth"])
|
||||||
elif c == whoisdb.models.Contact:
|
elif c == whoisdb.models.Contact:
|
||||||
_addFields(fields, obj, ["name", "mnt_by"])
|
_addFields(fields, obj, ["name", "mnt_by"])
|
||||||
elif c == whoisdb.models.ASBlock:
|
elif c == whoisdb.models.ASBlock:
|
||||||
_addFields(fields, obj, ["name"])
|
_addFields(fields, obj, ["name"])
|
||||||
fields.append(("AS Range", "%s - %s" % (obj.asBegin, obj.asEnd)))
|
fields.append(("AS Range", "%s - %s" % (obj.asBegin, obj.asEnd)))
|
||||||
_addFields(fields, obj, ["description", "parent_block", "mnt_by", "mnt_lower", "admin_c"])
|
_addFields(fields, obj, ["description", "parent_block", "mnt_by", "mnt_lower", "admin_c"])
|
||||||
elif c == whoisdb.models.ASNumber:
|
elif c == whoisdb.models.ASNumber:
|
||||||
_addFields(fields, obj, ["name", "number", "description", "asblock", "volatile", "mnt_by", "mnt_lower", "admin_c"])
|
_addFields(fields, obj, ["name", "number", "description", "asblock", "volatile", "mnt_by", "mnt_lower", "admin_c"])
|
||||||
elif c == whoisdb.models.InetNum:
|
elif c == whoisdb.models.InetNum:
|
||||||
_addFields(fields, obj, ["name"])
|
_addFields(fields, obj, ["name"])
|
||||||
fields.append(("Address CIDR", obj.prefix()))
|
fields.append(("Address CIDR", obj.prefix()))
|
||||||
_addFields(fields, obj, ["description", "parent_range", "origin_as", "mnt_by", "mnt_lower", "admin_c"])
|
_addFields(fields, obj, ["description", "parent_range", "origin_as", "mnt_by", "mnt_lower", "admin_c"])
|
||||||
elif c == domains.models.Domain:
|
elif c == domains.models.Domain:
|
||||||
_addFields(fields, obj, ["name", "nameservers", "mnt_by", "admin_c"])
|
_addFields(fields, obj, ["name", "nameservers", "mnt_by", "admin_c", "ds_records"])
|
||||||
elif c == domains.models.Nameserver:
|
elif c == domains.models.Nameserver:
|
||||||
_addFields(fields, obj, ["name", "glueIPv4", "glueIPv6", "mnt_by", "admin_c"])
|
_addFields(fields, obj, ["name", "glueIPv4", "glueIPv6", "mnt_by", "admin_c"])
|
||||||
elif c == domains.models.ReverseZone:
|
elif c == domains.models.ReverseZone:
|
||||||
#_addFields(fields, obj, ["name"])
|
#_addFields(fields, obj, ["name"])
|
||||||
fields.append(("Address CIDR", obj.prefix()))
|
fields.append(("Address CIDR", obj.prefix()))
|
||||||
_addFields(fields, obj, ["parentNet", "nameservers"])
|
_addFields(fields, obj, ["parentNet", "nameservers"])
|
||||||
|
|
||||||
_addFields(fields, obj, ["created", "last_modified"])
|
_addFields(fields, obj, ["created", "last_modified"])
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
|
||||||
def guessWhoisObject(self, handle):
|
def guessWhoisObject(self, handle):
|
||||||
# is it a normal handle?
|
# is it a normal handle?
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def findInDatabase(rawValue):
|
def findInDatabase(rawValue):
|
||||||
# is this an ip address?
|
# is this an ip address?
|
||||||
rawValue = rawValue.strip().upper()
|
rawValue = rawValue.strip().upper()
|
||||||
value = None
|
value = None
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
# try subnetwork
|
# try subnetwork
|
||||||
try:
|
try:
|
||||||
value = ipaddress.ip_network(rawValue, strict=False)
|
value = ipaddress.ip_network(rawValue, strict=False)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
# ssubnet
|
# ssubnet
|
||||||
obj = whoisdb.models.InetNum.objects.filter(address=str(value.network_address), netmask=value.prefixlen)
|
obj = whoisdb.models.InetNum.objects.filter(address=str(value.network_address), netmask=value.prefixlen)
|
||||||
results.extend(obj)
|
results.extend(obj)
|
||||||
|
|
||||||
# single ip
|
# single ip
|
||||||
value = None
|
value = None
|
||||||
try:
|
try:
|
||||||
value = ipaddress.ip_address(rawValue)
|
value = ipaddress.ip_address(rawValue)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
# NOTE: this is only for "small subnets", we could increase this...
|
# NOTE: this is only for "small subnets", we could increase this...
|
||||||
baseaddr = None
|
baseaddr = None
|
||||||
if value.version == 4:
|
if value.version == 4:
|
||||||
basenet = ipaddress.ip_network("%s/24" % value, strict=False)
|
basenet = ipaddress.ip_network("%s/24" % value, strict=False)
|
||||||
baseaddr = ".".join(str(basenet).split(".")[0:3]) + "."
|
baseaddr = ".".join(str(basenet).split(".")[0:3]) + "."
|
||||||
else:
|
else:
|
||||||
basenet = ipaddress.ip_network("%s/56" % value.exploded, strict=False)
|
basenet = ipaddress.ip_network("%s/56" % value.exploded, strict=False)
|
||||||
baseaddr = ":".join(str(basenet).split(":")[0:4])[-2]
|
baseaddr = ":".join(str(basenet).split(":")[0:4])[-2]
|
||||||
|
|
||||||
nets = whoisdb.models.InetNum.objects.filter(address__startswith=baseaddr).order_by("-netmask")
|
nets = whoisdb.models.InetNum.objects.filter(address__startswith=baseaddr).order_by("-netmask")
|
||||||
for net in nets:
|
for net in nets:
|
||||||
if value in net.getNetwork():
|
if value in net.getNetwork():
|
||||||
results.append(net)
|
results.append(net)
|
||||||
break
|
break
|
||||||
|
|
||||||
# asnumber?
|
# asnumber?
|
||||||
m = re.match("^(?:AS)?(\d+)$", rawValue)
|
m = re.match("^(?:AS)?(\d+)$", rawValue)
|
||||||
if m:
|
if m:
|
||||||
# asnumber!
|
# asnumber!
|
||||||
num = int(m.group(1))
|
num = int(m.group(1))
|
||||||
obj = whoisdb.models.ASNumber.objects.filter(number=num)
|
obj = whoisdb.models.ASNumber.objects.filter(number=num)
|
||||||
results.extend(obj)
|
results.extend(obj)
|
||||||
|
|
||||||
# find a matching block
|
# 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')
|
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:
|
if blocks.count() > 0:
|
||||||
results.append(blocks[0])
|
results.append(blocks[0])
|
||||||
|
|
||||||
# asblocks? smallest asblock containing the range
|
# asblocks? smallest asblock containing the range
|
||||||
# WHEN anotation foo... could also be done in asnumber match
|
# WHEN anotation foo... could also be done in asnumber match
|
||||||
# also look for number - number queries?
|
# also look for number - number queries?
|
||||||
|
|
||||||
# domain?
|
# domain?
|
||||||
if rawValue.endswith("DN") or rawValue.endswith("DN."):
|
if rawValue.endswith("DN") or rawValue.endswith("DN."):
|
||||||
value = rawValue.lower()
|
value = rawValue.lower()
|
||||||
if not value.endswith("."):
|
if not value.endswith("."):
|
||||||
value += "."
|
value += "."
|
||||||
|
|
||||||
obj = domains.models.Domain.objects.filter(name=value)
|
obj = domains.models.Domain.objects.filter(name=value)
|
||||||
results.extend(obj)
|
results.extend(obj)
|
||||||
|
|
||||||
# contact by name?
|
# contact by name?
|
||||||
|
|
||||||
# handlenames for Maintainer, Contact, InetNum, ASNumber, ASBlock
|
# handlenames for Maintainer, Contact, InetNum, ASNumber, ASBlock
|
||||||
handleObjs = [
|
handleObjs = [
|
||||||
whoisdb.models.Contact,
|
whoisdb.models.Contact,
|
||||||
whoisdb.models.Maintainer,
|
whoisdb.models.Maintainer,
|
||||||
whoisdb.models.InetNum,
|
whoisdb.models.InetNum,
|
||||||
whoisdb.models.ASBlock,
|
whoisdb.models.ASBlock,
|
||||||
whoisdb.models.ASNumber,
|
whoisdb.models.ASNumber,
|
||||||
]
|
]
|
||||||
for handleObj in handleObjs:
|
for handleObj in handleObjs:
|
||||||
obj = handleObj.objects.filter(handle=rawValue)
|
obj = handleObj.objects.filter(handle=rawValue)
|
||||||
if not obj and len(rawValue) >= 3:
|
if not obj and len(rawValue) >= 3:
|
||||||
obj = handleObj.objects.filter(handle__startswith=rawValue)
|
obj = handleObj.objects.filter(handle__startswith=rawValue)
|
||||||
results.extend(obj)
|
results.extend(obj)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def findHandleFromStr(rawValue):
|
def findHandleFromStr(rawValue):
|
||||||
handleObjs = [
|
handleObjs = [
|
||||||
whoisdb.models.Contact,
|
whoisdb.models.Contact,
|
||||||
whoisdb.models.Maintainer,
|
whoisdb.models.Maintainer,
|
||||||
whoisdb.models.InetNum,
|
whoisdb.models.InetNum,
|
||||||
whoisdb.models.ASBlock,
|
whoisdb.models.ASBlock,
|
||||||
whoisdb.models.ASNumber,
|
whoisdb.models.ASNumber,
|
||||||
]
|
]
|
||||||
|
|
||||||
for handleObj in handleObjs:
|
for handleObj in handleObjs:
|
||||||
try:
|
try:
|
||||||
return handleObj.objects.get(handle=rawValue)
|
return handleObj.objects.get(handle=rawValue)
|
||||||
except handleObj.DoesNotExist:
|
except handleObj.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def orderQueryset(qs, userOwned, objOwned):
|
def orderQueryset(qs, userOwned, objOwned):
|
||||||
# when for
|
# when for
|
||||||
whens = [When(userOwned, then=2)]
|
whens = [When(userOwned, then=2)]
|
||||||
if objOwned:
|
if objOwned:
|
||||||
# add existing
|
# add existing
|
||||||
whens.append(When(objOwned, then=1))
|
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 WhoisObject(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
handleSuffix = ""
|
handleSuffix = ""
|
||||||
|
|
||||||
handle = models.SlugField(max_length=32, unique=True, verbose_name='handle', validators=[HandleValidator()])
|
handle = models.SlugField(max_length=32, unique=True, verbose_name='handle', validators=[HandleValidator()])
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
last_modified = models.DateTimeField(auto_now_add=True)
|
last_modified = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
#def __init__(self, *args, **kwargs):
|
#def __init__(self, *args, **kwargs):
|
||||||
# super(WhoisObject, self).__init__(*args, **kwargs)
|
# super(WhoisObject, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
# if getattr(self, "handle"):
|
# if getattr(self, "handle"):
|
||||||
# field = self._meta.get_field("handle")
|
# field = self._meta.get_field("handle")
|
||||||
# if HandleValidatorWithSuffix not in map(type, field.validators):
|
# if HandleValidatorWithSuffix not in map(type, field.validators):
|
||||||
# print(self.handle, "NOOOOT")
|
# print(self.handle, "NOOOOT")
|
||||||
# field.validators.append(HandleValidatorWithSuffix(self.handleSuffix))
|
# field.validators.append(HandleValidatorWithSuffix(self.handleSuffix))
|
||||||
# else:
|
# else:
|
||||||
# print(self.handle, list(map(type, field.validators)))
|
# print(self.handle, list(map(type, field.validators)))
|
||||||
|
|
||||||
def getPK(self):
|
def getPK(self):
|
||||||
return self.handle
|
return self.handle
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.handle
|
return self.handle
|
||||||
|
|
||||||
def getAppName(self):
|
def getAppName(self):
|
||||||
return "whoisdb"
|
return "whoisdb"
|
||||||
|
|
||||||
def getClassName(self):
|
def getClassName(self):
|
||||||
return self._meta.object_name
|
return self._meta.object_name
|
||||||
|
|
||||||
def genHandle(self, main=None):
|
def genHandle(self, main=None):
|
||||||
if not main:
|
if not main:
|
||||||
main = self.name
|
main = self.name
|
||||||
return self.genGenericHandle(main)
|
return self.genGenericHandle(main)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def genGenericHandle(clazz, main):
|
def genGenericHandle(clazz, main):
|
||||||
prefix = ""
|
prefix = ""
|
||||||
if " " in main:
|
if " " in main:
|
||||||
parts = main.split(" ")
|
parts = main.split(" ")
|
||||||
prefix = "".join(map(lambda _x: _x[0], parts))
|
prefix = "".join(map(lambda _x: _x[0], parts))
|
||||||
if len(prefix) < 3 and len(parts[-1]) > 1:
|
if len(prefix) < 3 and len(parts[-1]) > 1:
|
||||||
prefix += parts[-1][1:4 - len(prefix)]
|
prefix += parts[-1][1:4 - len(prefix)]
|
||||||
else:
|
else:
|
||||||
prefix = main[0:3]
|
prefix = main[0:3]
|
||||||
prefix = prefix.upper()
|
prefix = prefix.upper()
|
||||||
|
|
||||||
i = 1
|
i = 1
|
||||||
handle = "%s%%d-%s" % (prefix, clazz.handleSuffix)
|
handle = "%s%%d-%s" % (prefix, clazz.handleSuffix)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
prefix
|
prefix
|
||||||
clazz.objects.get(handle=handle % i)
|
clazz.objects.get(handle=handle % i)
|
||||||
i += 1
|
i += 1
|
||||||
except clazz.DoesNotExist:
|
except clazz.DoesNotExist:
|
||||||
break
|
break
|
||||||
|
|
||||||
return handle % i
|
return handle % i
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
raise NotImplementedError("Delete reason checking is not implemented for this model")
|
raise NotImplementedError("Delete reason checking is not implemented for this model")
|
||||||
|
|
||||||
def canBeDeleted(self):
|
def canBeDeleted(self):
|
||||||
return not bool(self.getNoDeleteReasons())
|
return not bool(self.getNoDeleteReasons())
|
||||||
|
|
||||||
def handleAuto(self, name=None):
|
def handleAuto(self, name=None):
|
||||||
if self.handle == "AUTO":
|
if self.handle == "AUTO":
|
||||||
self.handle = self.genHandle(name)
|
self.handle = self.genHandle(name)
|
||||||
|
|
||||||
|
|
||||||
class Maintainer(WhoisObject):
|
class Maintainer(WhoisObject):
|
||||||
handleSuffix = "MNT"
|
handleSuffix = "MNT"
|
||||||
|
|
||||||
auth = models.ManyToManyField(User)
|
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")
|
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")
|
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)
|
rir = models.BooleanField(default=False)
|
||||||
lir = models.BooleanField(default=False)
|
lir = models.BooleanField(default=False)
|
||||||
|
|
||||||
# autoInclude = models.BooleanField(default=True)
|
# autoInclude = models.BooleanField(default=True)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
# FIXME: Tempfix for circular dependency problem
|
# FIXME: Tempfix for circular dependency problem
|
||||||
import domains.models
|
import domains.models
|
||||||
|
|
||||||
mntables = [Contact, ASBlock, ASNumber, InetNum, domains.models.Domain, domains.models.Nameserver]
|
mntables = [Contact, ASBlock, ASNumber, InetNum, domains.models.Domain, domains.models.Nameserver]
|
||||||
for mntable in mntables:
|
for mntable in mntables:
|
||||||
candidates = mntable.objects.filter(mnt_by=self).annotate(mntCount=models.Count('mnt_by')).filter(mntCount__lte=1)
|
candidates = mntable.objects.filter(mnt_by=self).annotate(mntCount=models.Count('mnt_by')).filter(mntCount__lte=1)
|
||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
reasons.append("Object %s would have no maintainers left." % candidate.handle)
|
reasons.append("Object %s would have no maintainers left." % candidate.handle)
|
||||||
|
|
||||||
return reasons
|
return reasons
|
||||||
|
|
||||||
def canEdit(self, user):
|
def canEdit(self, user):
|
||||||
return user in self.auth.all()
|
return user in self.auth.all()
|
||||||
|
|
||||||
|
|
||||||
class MntdObject(WhoisObject):
|
class MntdObject(WhoisObject):
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
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):
|
def canEdit(self, user):
|
||||||
if not hasattr(user, "maintainer_set"):
|
if not hasattr(user, "maintainer_set"):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
mnts = user.maintainer_set.all()
|
mnts = user.maintainer_set.all()
|
||||||
objmnts = self.mnt_by.all()
|
objmnts = self.mnt_by.all()
|
||||||
if hasattr(self, "mnt_lower"):
|
if hasattr(self, "mnt_lower"):
|
||||||
objmnts |= self.mnt_lower.all()
|
objmnts |= self.mnt_lower.all()
|
||||||
|
|
||||||
for objmnt in objmnts:
|
for objmnt in objmnts:
|
||||||
if objmnt in mnts:
|
if objmnt in mnts:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def getMntQueryset(clazz, mnts, instance, attr=None):
|
def getMntQueryset(clazz, mnts, instance, attr=None):
|
||||||
mntQ = Q(mnt_by__in=mnts)
|
mntQ = Q(mnt_by__in=mnts)
|
||||||
if hasattr(clazz, "mnt_lower"):
|
if hasattr(clazz, "mnt_lower"):
|
||||||
mntQ |= Q(mnt_lower__in=mnts)
|
mntQ |= Q(mnt_lower__in=mnts)
|
||||||
|
|
||||||
qs = clazz.objects.filter(mntQ)
|
qs = clazz.objects.filter(mntQ)
|
||||||
if attr and instance and instance.pk:
|
if attr and instance and instance.pk:
|
||||||
if type(instance._meta.get_field(attr)) == models.ManyToManyField:
|
if type(instance._meta.get_field(attr)) == models.ManyToManyField:
|
||||||
qs |= getattr(instance, attr).all()
|
qs |= getattr(instance, attr).all()
|
||||||
elif getattr(instance, attr) is not None:
|
elif getattr(instance, attr) is not None:
|
||||||
qs |= clazz.objects.filter(pk=getattr(instance, attr).pk)
|
qs |= clazz.objects.filter(pk=getattr(instance, attr).pk)
|
||||||
|
|
||||||
return qs.distinct()
|
return qs.distinct()
|
||||||
|
|
||||||
|
|
||||||
class Contact(MntdObject):
|
class Contact(MntdObject):
|
||||||
handleSuffix = "DN"
|
handleSuffix = "DN"
|
||||||
TYPE_PERSON = 'PERSON'
|
TYPE_PERSON = 'PERSON'
|
||||||
TYPE_ROLE = 'ROLE'
|
TYPE_ROLE = 'ROLE'
|
||||||
TYPE = (('person', TYPE_PERSON), ('role', TYPE_ROLE))
|
TYPE = (('person', TYPE_PERSON), ('role', TYPE_ROLE))
|
||||||
TYPE = (('person', TYPE_PERSON),)
|
TYPE = (('person', TYPE_PERSON),)
|
||||||
|
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
|
type = models.CharField(max_length=10, choices=TYPE, default=TYPE_PERSON)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
contactables = [Maintainer, ASBlock, ASNumber, InetNum]
|
contactables = [Maintainer, ASBlock, ASNumber, InetNum]
|
||||||
for contactable in contactables:
|
for contactable in contactables:
|
||||||
candidates = contactable.objects.filter(admin_c=self).annotate(contactCount=models.Count('admin_c')).filter(contactCount__lte=1)
|
candidates = contactable.objects.filter(admin_c=self).annotate(contactCount=models.Count('admin_c')).filter(contactCount__lte=1)
|
||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
reasons.append("Object %s would have no contact left." % candidate.handle)
|
reasons.append("Object %s would have no contact left." % candidate.handle)
|
||||||
|
|
||||||
return reasons
|
return reasons
|
||||||
|
|
||||||
|
|
||||||
class ASBlock(MntdObject):
|
class ASBlock(MntdObject):
|
||||||
handleSuffix = "ASB"
|
handleSuffix = "ASB"
|
||||||
|
|
||||||
parent_block = models.ForeignKey("ASBlock", models.CASCADE, null=True, blank=True, default=None)
|
parent_block = models.ForeignKey("ASBlock", models.CASCADE, null=True, blank=True, default=None)
|
||||||
name = models.CharField(max_length=32)
|
name = models.CharField(max_length=32)
|
||||||
asBegin = models.PositiveIntegerField()
|
asBegin = models.PositiveIntegerField()
|
||||||
asEnd = models.PositiveIntegerField()
|
asEnd = models.PositiveIntegerField()
|
||||||
description = models.CharField(max_length=64, blank=True)
|
description = models.CharField(max_length=64, blank=True)
|
||||||
admin_c = models.ManyToManyField("Contact")
|
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):
|
def contains(self, block):
|
||||||
return self.asBegin <= block.asBegin <= self.asEnd and self.asBegin <= block.asEnd <= self.asEnd
|
return self.asBegin <= block.asBegin <= self.asEnd and self.asBegin <= block.asEnd <= self.asEnd
|
||||||
|
|
||||||
def getResource(self):
|
def getResource(self):
|
||||||
return "%s - %s" % (self.asBegin, self.asEnd)
|
return "%s - %s" % (self.asBegin, self.asEnd)
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
if self.asblock_set.count() > 0:
|
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()))))
|
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:
|
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()))))
|
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):
|
class ASNumber(MntdObject):
|
||||||
handleSuffix = "AS"
|
handleSuffix = "AS"
|
||||||
|
|
||||||
number = models.PositiveIntegerField(unique=True, db_index=True)
|
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)")
|
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)
|
asblock = models.ForeignKey(ASBlock, models.CASCADE)
|
||||||
name = models.CharField(max_length=32)
|
name = models.CharField(max_length=32)
|
||||||
description = models.CharField(max_length=64, blank=True)
|
description = models.CharField(max_length=64, blank=True)
|
||||||
admin_c = models.ManyToManyField("Contact")
|
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):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
|
|
||||||
return reasons
|
return reasons
|
||||||
|
|
||||||
def getResource(self):
|
def getResource(self):
|
||||||
return str(self.number)
|
return str(self.number)
|
||||||
|
|
||||||
|
|
||||||
class InetNum(MntdObject):
|
class InetNum(MntdObject):
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = (
|
unique_together = (
|
||||||
("address", "netmask"),
|
("address", "netmask"),
|
||||||
)
|
)
|
||||||
|
|
||||||
handleSuffix = "NET"
|
handleSuffix = "NET"
|
||||||
|
|
||||||
IPv4 = "ipv4"
|
IPv4 = "ipv4"
|
||||||
IPv6 = "ipv6"
|
IPv6 = "ipv6"
|
||||||
|
|
||||||
PROTO = ((IPv4, 'IPv4'), (IPv6, 'IPv6'))
|
PROTO = ((IPv4, 'IPv4'), (IPv6, 'IPv6'))
|
||||||
protocol = models.CharField(max_length=4, choices=PROTO)
|
protocol = models.CharField(max_length=4, choices=PROTO)
|
||||||
address = models.GenericIPAddressField(db_index=True)
|
address = models.GenericIPAddressField(db_index=True)
|
||||||
netmask = models.PositiveIntegerField()
|
netmask = models.PositiveIntegerField()
|
||||||
parent_range = models.ForeignKey("InetNum", models.CASCADE, null=True, blank=True, default=None)
|
parent_range = models.ForeignKey("InetNum", models.CASCADE, null=True, blank=True, default=None)
|
||||||
name = models.CharField(max_length=64)
|
name = models.CharField(max_length=64)
|
||||||
description = models.CharField(max_length=64, blank=True)
|
description = models.CharField(max_length=64, blank=True)
|
||||||
origin_as = models.ManyToManyField(ASNumber, blank=True)
|
origin_as = models.ManyToManyField(ASNumber, blank=True)
|
||||||
admin_c = models.ManyToManyField("Contact")
|
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):
|
def getResource(self):
|
||||||
return self.prefix()
|
return self.prefix()
|
||||||
|
|
||||||
def prefix(self):
|
def prefix(self):
|
||||||
""" Helper function, mainly used in templates """
|
""" Helper function, mainly used in templates """
|
||||||
return "%s/%s" % (self.address, self.netmask)
|
return "%s/%s" % (self.address, self.netmask)
|
||||||
|
|
||||||
def getNetwork(self):
|
def getNetwork(self):
|
||||||
return ipaddress.ip_network(self.prefix())
|
return ipaddress.ip_network(self.prefix())
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
return reverse("whoisdb:handle-detail", kwargs={"handle": self.handle})
|
||||||
|
|
||||||
def getNoDeleteReasons(self):
|
def getNoDeleteReasons(self):
|
||||||
reasons = []
|
reasons = []
|
||||||
if self.inetnum_set.all().count() > 0:
|
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())))
|
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
|
@register.filter
|
||||||
def linkObject(value):
|
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
|
@register.filter
|
||||||
def tryLinkHandle(handle):
|
def tryLinkHandle(handle):
|
||||||
try:
|
try:
|
||||||
if not handle:
|
if not handle:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
HandleValidator()(str(handle))
|
HandleValidator()(str(handle))
|
||||||
obj = findHandleFromStr(handle)
|
obj = findHandleFromStr(handle)
|
||||||
if obj:
|
if obj:
|
||||||
return linkObject(obj)
|
return linkObject(obj)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return handle
|
return handle
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def linkObjects(value):
|
def linkObjects(value):
|
||||||
links = []
|
links = []
|
||||||
for obj in value:
|
for obj in value:
|
||||||
if hasattr(obj, "get_absolute_url"):
|
if hasattr(obj, "get_absolute_url"):
|
||||||
links.append('<a href="%s">%s</a>' % (obj.get_absolute_url(), str(obj)))
|
links.append('<a href="%s">%s</a>' % (obj.get_absolute_url(), str(obj)))
|
||||||
else:
|
else:
|
||||||
links.append(str(obj))
|
links.append(str(obj))
|
||||||
|
|
||||||
return mark_safe(", ".join(links))
|
return mark_safe(", ".join(links))
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def getFields(value, user):
|
def getFields(value, user):
|
||||||
owner = value.canEdit(user)
|
owner = value.canEdit(user)
|
||||||
|
|
||||||
return getWhoisObjectFields(value, owner)
|
return getWhoisObjectFields(value, owner)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def userCanEdit(value, user):
|
def userCanEdit(value, user):
|
||||||
if hasattr(value, "canEdit"):
|
if hasattr(value, "canEdit"):
|
||||||
return value.canEdit(user)
|
return value.canEdit(user)
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -7,40 +7,40 @@ from django.conf.urls import url
|
||||||
from . import views as whoisdb_views
|
from . import views as whoisdb_views
|
||||||
|
|
||||||
urlpatterns = [
|
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'^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='showhandle'),
|
||||||
url(r'^handle/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.showHandle, name='handle-detail'),
|
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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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
|
@deconstructible
|
||||||
class HandleValidator(validators.RegexValidator):
|
class HandleValidator(validators.RegexValidator):
|
||||||
regex = r'^(?:[A-Z]+[0-9]*(-[A-Z]+)|AUTO)$'
|
regex = r'^(?:[A-Z]+[0-9]*(-[A-Z]+)|AUTO)$'
|
||||||
message = _(
|
message = _(
|
||||||
'Enter a valid handle (all uppercase)'
|
'Enter a valid handle (all uppercase)'
|
||||||
)
|
)
|
||||||
flags = re.ASCII if six.PY3 else 0
|
flags = re.ASCII if six.PY3 else 0
|
||||||
|
|
||||||
|
|
||||||
@deconstructible
|
@deconstructible
|
||||||
class HandleValidatorWithSuffix(validators.RegexValidator):
|
class HandleValidatorWithSuffix(validators.RegexValidator):
|
||||||
flags = re.ASCII if six.PY3 else 0
|
flags = re.ASCII if six.PY3 else 0
|
||||||
|
|
||||||
def __init__(self, suffix):
|
def __init__(self, suffix):
|
||||||
self.regex = r'^(?:[A-Z]+[0-9]*-%s|AUTO)$' % re.escape(suffix)
|
self.regex = r'^(?:[A-Z]+[0-9]*-%s|AUTO)$' % re.escape(suffix)
|
||||||
self.message = _(
|
self.message = _(
|
||||||
'Enter a valid handle with suffix %s (all uppercase), e.g. FOO3-%s' % (suffix, suffix)
|
'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):
|
def IP46CIDRValidator(value):
|
||||||
if not re.match(r"[0-9a-fA-F:.]+/[0-9]+", 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")
|
raise ValidationError("Address needs to be a subnet in the format of ip/prefix")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ipaddress.ip_network(value)
|
ipaddress.ip_network(value)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise ValidationError(str(e))
|
raise ValidationError(str(e))
|
||||||
|
|
458
whoisdb/views.py
458
whoisdb/views.py
|
@ -20,349 +20,349 @@ from .helpers import findInDatabase
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def createObjectOverview(request):
|
def createObjectOverview(request):
|
||||||
mnts = request.user.maintainer_set.filter().all()
|
mnts = request.user.maintainer_set.filter().all()
|
||||||
netblocks = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
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()
|
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
|
@login_required
|
||||||
def dbDashboard(request):
|
def dbDashboard(request):
|
||||||
mnts = request.user.maintainer_set.filter(rir=False, lir=False).all()
|
mnts = request.user.maintainer_set.filter(rir=False, lir=False).all()
|
||||||
if request.GET.get("delegated", None) or mnts.count() == 0:
|
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
|
# if user wants to see rir/lir objects or only has rir/lir mnts, use all available mnts
|
||||||
mnts = request.user.maintainer_set.all()
|
mnts = request.user.maintainer_set.all()
|
||||||
showDelegations = True
|
showDelegations = True
|
||||||
else:
|
else:
|
||||||
showDelegations = False
|
showDelegations = False
|
||||||
|
|
||||||
hasDelegations = request.user.maintainer_set.filter(Q(rir=True) | Q(lir=True)).count() > 0
|
hasDelegations = request.user.maintainer_set.filter(Q(rir=True) | Q(lir=True)).count() > 0
|
||||||
|
|
||||||
contacts = Contact.objects.filter(mnt_by__in=mnts)
|
contacts = Contact.objects.filter(mnt_by__in=mnts)
|
||||||
netblocks = InetNum.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
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()
|
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()
|
asnumbers = ASNumber.objects.filter(Q(mnt_by__in=mnts) | Q(mnt_lower__in=mnts)).distinct()
|
||||||
mntForm = contactForm = None
|
mntForm = contactForm = None
|
||||||
|
|
||||||
if mnts.count() == 0:
|
if mnts.count() == 0:
|
||||||
mntForm = contactForm = None
|
mntForm = contactForm = None
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
mntForm = MntInitialForm(user=request.user, data=request.POST, prefix="mnt")
|
mntForm = MntInitialForm(user=request.user, data=request.POST, prefix="mnt")
|
||||||
contactForm = ContactInitialForm(user=request.user, data=request.POST, prefix="contact")
|
contactForm = ContactInitialForm(user=request.user, data=request.POST, prefix="contact")
|
||||||
if mntForm.is_valid() and contactForm.is_valid():
|
if mntForm.is_valid() and contactForm.is_valid():
|
||||||
mnt = mntForm.save(commit=False)
|
mnt = mntForm.save(commit=False)
|
||||||
mnt.handleAuto(request.user.username)
|
mnt.handleAuto(request.user.username)
|
||||||
mnt.save()
|
mnt.save()
|
||||||
|
|
||||||
contact = contactForm.save(commit=False)
|
contact = contactForm.save(commit=False)
|
||||||
contact.handleAuto()
|
contact.handleAuto()
|
||||||
contact.type = Contact.TYPE_PERSON
|
contact.type = Contact.TYPE_PERSON
|
||||||
contact.save()
|
contact.save()
|
||||||
contact.mnt_by.add(mnt.id)
|
contact.mnt_by.add(mnt.id)
|
||||||
contact.save()
|
contact.save()
|
||||||
|
|
||||||
mnt.auth.add(request.user.id)
|
mnt.auth.add(request.user.id)
|
||||||
mnt.admin_c.add(contact.id)
|
mnt.admin_c.add(contact.id)
|
||||||
mnt.save()
|
mnt.save()
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
|
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
|
||||||
else:
|
else:
|
||||||
mntForm = MntInitialForm(user=request.user, prefix="mnt", initial={'handle': 'AUTO', 'description': 'Primary maintainer of %s' % request.user.username})
|
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')
|
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})
|
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):
|
def showHandle(request, handle):
|
||||||
# a) find handle
|
# a) find handle
|
||||||
models = [Contact, Maintainer, ASBlock, ASNumber, InetNum]
|
models = [Contact, Maintainer, ASBlock, ASNumber, InetNum]
|
||||||
obj = None
|
obj = None
|
||||||
|
|
||||||
for model in models:
|
for model in models:
|
||||||
if handle.endswith(model.handleSuffix):
|
if handle.endswith(model.handleSuffix):
|
||||||
obj = get_object_or_404(model, handle=handle)
|
obj = get_object_or_404(model, handle=handle)
|
||||||
break
|
break
|
||||||
|
|
||||||
if not obj:
|
if not obj:
|
||||||
raise Http404("Handle object not found")
|
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):
|
def searchObject(request):
|
||||||
results = None
|
results = None
|
||||||
term = request.GET.get("q", None)
|
term = request.GET.get("q", None)
|
||||||
if term:
|
if term:
|
||||||
results = findInDatabase(term)
|
results = findInDatabase(term)
|
||||||
return render(request, "whoisdb/search.html", {"results": results, "term": term})
|
return render(request, "whoisdb/search.html", {"results": results, "term": term})
|
||||||
|
|
||||||
|
|
||||||
class MaintainerCreate(LoginRequiredMixin, CreateView):
|
class MaintainerCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "whoisdb/obj_create.html"
|
template_name = "whoisdb/obj_create.html"
|
||||||
form_class = MntForm
|
form_class = MntForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(MaintainerCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(MaintainerCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
"handle": "AUTO",
|
"handle": "AUTO",
|
||||||
#"auth": self.request.user.username,
|
#"auth": self.request.user.username,
|
||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
self.object = form.save(commit=False)
|
self.object = form.save(commit=False)
|
||||||
self.object.handleAuto(self.request.user.username)
|
self.object.handleAuto(self.request.user.username)
|
||||||
self.object.save()
|
self.object.save()
|
||||||
self.object.auth.add(self.request.user)
|
self.object.auth.add(self.request.user)
|
||||||
self.object.save()
|
self.object.save()
|
||||||
|
|
||||||
return super(MaintainerCreate, self).form_valid(form)
|
return super(MaintainerCreate, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class MaintainerEdit(LoginRequiredMixin, UpdateView):
|
class MaintainerEdit(LoginRequiredMixin, UpdateView):
|
||||||
template_name = "whoisdb/obj_edit.html"
|
template_name = "whoisdb/obj_edit.html"
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
form_class = MntForm
|
form_class = MntForm
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(MaintainerEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(MaintainerEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.model.objects.filter(auth=self.request.user)
|
return self.model.objects.filter(auth=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
class MaintainerDelete(LoginRequiredMixin, DeleteCheckView):
|
class MaintainerDelete(LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "whoisdb/obj_delete.html"
|
template_name = "whoisdb/obj_delete.html"
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
success_url = reverse_lazy("whoisdb:dashboard")
|
success_url = reverse_lazy("whoisdb:dashboard")
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return self.model.objects.filter(auth=self.request.user)
|
return self.model.objects.filter(auth=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
class MaintainerDetail(LoginRequiredMixin, DetailView):
|
class MaintainerDetail(LoginRequiredMixin, DetailView):
|
||||||
template_name = "whoisdb/handle_show.html"
|
template_name = "whoisdb/handle_show.html"
|
||||||
model = Maintainer
|
model = Maintainer
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
#context_object_name = "mnt"
|
#context_object_name = "mnt"
|
||||||
|
|
||||||
|
|
||||||
class ContactDetail(DetailView):
|
class ContactDetail(DetailView):
|
||||||
model = Contact
|
model = Contact
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
context_object_name = "contact"
|
context_object_name = "contact"
|
||||||
|
|
||||||
|
|
||||||
class ContactEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class ContactEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
template_name = "whoisdb/obj_edit.html"
|
template_name = "whoisdb/obj_edit.html"
|
||||||
model = Contact
|
model = Contact
|
||||||
form_class = ContactForm
|
form_class = ContactForm
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ContactEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ContactEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ContactCreate(LoginRequiredMixin, CreateView):
|
class ContactCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "whoisdb/obj_create.html"
|
template_name = "whoisdb/obj_create.html"
|
||||||
form_class = ContactForm
|
form_class = ContactForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ContactCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ContactCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
"handle": "AUTO",
|
"handle": "AUTO",
|
||||||
"type": Contact.TYPE_PERSON
|
"type": Contact.TYPE_PERSON
|
||||||
}
|
}
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ContactDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class ContactDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "whoisdb/obj_delete.html"
|
template_name = "whoisdb/obj_delete.html"
|
||||||
model = Contact
|
model = Contact
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
success_url = reverse_lazy("whoisdb:dashboard")
|
success_url = reverse_lazy("whoisdb:dashboard")
|
||||||
|
|
||||||
|
|
||||||
# InetNum
|
# InetNum
|
||||||
class InetNumCreate(LoginRequiredMixin, CreateView):
|
class InetNumCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "whoisdb/obj_create.html"
|
template_name = "whoisdb/obj_create.html"
|
||||||
form_class = InetNumForm
|
form_class = InetNumForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
print("NOOOOOOOOOOOOOOOOOOOOOOOOOOOOT", args, kwargs)
|
print("NOOOOOOOOOOOOOOOOOOOOOOOOOOOOT", args, kwargs)
|
||||||
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(InetNumCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
"handle": "AUTO",
|
"handle": "AUTO",
|
||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class InetNumDetail(DetailView):
|
class InetNumDetail(DetailView):
|
||||||
model = InetNum
|
model = InetNum
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
context_object_name = "inetnum"
|
context_object_name = "inetnum"
|
||||||
|
|
||||||
|
|
||||||
class InetNumEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class InetNumEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
template_name = "whoisdb/obj_edit.html"
|
template_name = "whoisdb/obj_edit.html"
|
||||||
model = InetNum
|
model = InetNum
|
||||||
form_class = InetNumForm
|
form_class = InetNumForm
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(InetNumEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(InetNumEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
|
kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class InetNumDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class InetNumDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "whoisdb/obj_delete.html"
|
template_name = "whoisdb/obj_delete.html"
|
||||||
model = InetNum
|
model = InetNum
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
success_url = reverse_lazy("whoisdb:dashboard")
|
success_url = reverse_lazy("whoisdb:dashboard")
|
||||||
|
|
||||||
|
|
||||||
# asblock
|
# asblock
|
||||||
class ASBlockCreate(LoginRequiredMixin, CreateView):
|
class ASBlockCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "whoisdb/obj_create.html"
|
template_name = "whoisdb/obj_create.html"
|
||||||
form_class = ASBlockForm
|
form_class = ASBlockForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ASBlockCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ASBlockCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
"handle": "AUTO",
|
"handle": "AUTO",
|
||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ASBlockDetail(DetailView):
|
class ASBlockDetail(DetailView):
|
||||||
model = ASBlock
|
model = ASBlock
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
context_object_name = "asblock"
|
context_object_name = "asblock"
|
||||||
|
|
||||||
|
|
||||||
class ASBlockEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class ASBlockEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
template_name = "whoisdb/obj_edit.html"
|
template_name = "whoisdb/obj_edit.html"
|
||||||
model = ASBlock
|
model = ASBlock
|
||||||
form_class = ASBlockForm
|
form_class = ASBlockForm
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ASBlockEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ASBlockEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
#kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
|
#kwargs["initial"] = {'prefix': str(self.object.getNetwork())}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ASBlockDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class ASBlockDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "whoisdb/obj_delete.html"
|
template_name = "whoisdb/obj_delete.html"
|
||||||
model = ASBlock
|
model = ASBlock
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
success_url = reverse_lazy("whoisdb:dashboard")
|
success_url = reverse_lazy("whoisdb:dashboard")
|
||||||
|
|
||||||
|
|
||||||
# asnumber
|
# asnumber
|
||||||
class ASNumberCreate(LoginRequiredMixin, CreateView):
|
class ASNumberCreate(LoginRequiredMixin, CreateView):
|
||||||
template_name = "whoisdb/obj_create.html"
|
template_name = "whoisdb/obj_create.html"
|
||||||
form_class = ASNumberForm
|
form_class = ASNumberForm
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ASNumberCreate, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ASNumberCreate, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
kwargs["initial"] = {
|
kwargs["initial"] = {
|
||||||
"handle": "AUTO",
|
"handle": "AUTO",
|
||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ASNumberDetail(DetailView):
|
class ASNumberDetail(DetailView):
|
||||||
model = ASNumber
|
model = ASNumber
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
context_object_name = "asnumber"
|
context_object_name = "asnumber"
|
||||||
|
|
||||||
|
|
||||||
class ASNumberEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
class ASNumberEdit(MntGenericMixin, LoginRequiredMixin, UpdateView):
|
||||||
template_name = "whoisdb/obj_edit.html"
|
template_name = "whoisdb/obj_edit.html"
|
||||||
model = ASNumber
|
model = ASNumber
|
||||||
form_class = ASNumberForm
|
form_class = ASNumberForm
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
|
|
||||||
def get_form_kwargs(self, *args, **kwargs):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ASNumberEdit, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ASNumberEdit, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
class ASNumberDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
class ASNumberDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
||||||
template_name = "whoisdb/obj_delete.html"
|
template_name = "whoisdb/obj_delete.html"
|
||||||
model = ASNumber
|
model = ASNumber
|
||||||
slug_field = "handle"
|
slug_field = "handle"
|
||||||
slug_url_kwarg = "handle"
|
slug_url_kwarg = "handle"
|
||||||
success_url = reverse_lazy("whoisdb:dashboard")
|
success_url = reverse_lazy("whoisdb:dashboard")
|
||||||
|
|
||||||
|
|
||||||
class ASAndSubnetWizard(LoginRequiredMixin, SessionWizardView):
|
class ASAndSubnetWizard(LoginRequiredMixin, SessionWizardView):
|
||||||
form_list = [ASNumberForm, InetNumForm]
|
form_list = [ASNumberForm, InetNumForm]
|
||||||
template_name = "whoisdb/wizard.html"
|
template_name = "whoisdb/wizard.html"
|
||||||
|
|
||||||
def get_form_initial(self, step):
|
def get_form_initial(self, step):
|
||||||
return {"handle": "AUTO"}
|
return {"handle": "AUTO"}
|
||||||
|
|
||||||
def done(self, form_list, **kwargs):
|
def done(self, form_list, **kwargs):
|
||||||
fl = list(form_list)
|
fl = list(form_list)
|
||||||
asNum = fl[0].save()
|
asNum = fl[0].save()
|
||||||
net = fl[1].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):
|
def get_form_kwargs(self, *args, **kwargs):
|
||||||
kwargs = super(ASAndSubnetWizard, self).get_form_kwargs(*args, **kwargs)
|
kwargs = super(ASAndSubnetWizard, self).get_form_kwargs(*args, **kwargs)
|
||||||
kwargs["user"] = self.request.user
|
kwargs["user"] = self.request.user
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs):
|
||||||
d = super(ASAndSubnetWizard, self).get_context_data(*args, **kwargs)
|
d = super(ASAndSubnetWizard, self).get_context_data(*args, **kwargs)
|
||||||
|
|
||||||
step = d["wizard"]["steps"].step1
|
step = d["wizard"]["steps"].step1
|
||||||
if step == 1:
|
if step == 1:
|
||||||
d["message"] = "Create an AS object"
|
d["message"] = "Create an AS object"
|
||||||
elif step == 2:
|
elif step == 2:
|
||||||
d["message"] = "Create a Subnet"
|
d["message"] = "Create a Subnet"
|
||||||
|
|
||||||
return d
|
return d
|
||||||
|
|
Loading…
Reference in New Issue