Checking for subdomains, fixing more ip logic stuff and tests

This commit is contained in:
Rebecca Hsieh 2023-09-28 15:55:54 -07:00
parent 026860c88a
commit 1f149700e3
No known key found for this signature in database
GPG key ID: 644527A2F375A379
4 changed files with 401 additions and 196 deletions

View file

@ -21,7 +21,8 @@ class DomainNameserverForm(forms.Form):
"""Form for changing nameservers.""" """Form for changing nameservers."""
server = forms.CharField(label="Name server", strip=True) server = forms.CharField(label="Name server", strip=True)
#when adding IPs to this form ensure they are stripped as well # when adding IPs to this form ensure they are stripped as well
NameserverFormset = formset_factory( NameserverFormset = formset_factory(
DomainNameserverForm, DomainNameserverForm,

View file

@ -228,8 +228,6 @@ class Domain(TimeStampedModel, DomainHelper):
""" """
try: try:
hosts = self._get_property("hosts") hosts = self._get_property("hosts")
print("HOST IS ")
print(hosts)
except Exception as err: except Exception as err:
# TODO-848: Check/add to error handling ticket if it's not addressed # TODO-848: Check/add to error handling ticket if it's not addressed
# (Don't throw error as this is normal for a new domain?) # (Don't throw error as this is normal for a new domain?)
@ -238,7 +236,7 @@ class Domain(TimeStampedModel, DomainHelper):
hostList = [] hostList = []
for host in hosts: for host in hosts:
hostList.append((host["name"],host["addrs"])) hostList.append((host["name"], host["addrs"]))
return hostList return hostList
@ -267,14 +265,11 @@ class Domain(TimeStampedModel, DomainHelper):
returns ErrorCode (int)""" returns ErrorCode (int)"""
logger.info("Creating host") logger.info("Creating host")
if addrs is not None: if addrs is not None:
# TODO-848: Make sure to have 1 with ip address + 1 without
addresses = [epp.Ip(addr=addr) for addr in addrs] addresses = [epp.Ip(addr=addr) for addr in addrs]
request = commands.CreateHost(name=host, addrs=addresses) request = commands.CreateHost(name=host, addrs=addresses)
else: else:
# NOTE-848: ip is a specification within the nameserver
request = commands.CreateHost(name=host) request = commands.CreateHost(name=host)
# NOTE-848: if you talk to registry you MUST do try/except
try: try:
logger.info("_create_host()-> sending req as %s" % request) logger.info("_create_host()-> sending req as %s" % request)
response = registry.send(request, cleaned=True) response = registry.send(request, cleaned=True)
@ -284,35 +279,41 @@ class Domain(TimeStampedModel, DomainHelper):
return e.code return e.code
def _convert_list_to_dict(self, listToConvert: list[tuple[str]]): def _convert_list_to_dict(self, listToConvert: list[tuple[str]]):
newDict={} newDict = {}
# TODO-848: If duplicated nameserver names, throw error
for tup in listToConvert: for tup in listToConvert:
if len(tup) == 1: if len(tup) == 1:
newDict[tup[0]] = None newDict[tup[0]] = None
else: else:
newDict[tup[0]] = tup[1] newDict[tup[0]] = tup[1]
return newDict return newDict
def isDotGov(self, nameserver): def isSubdomain(self, nameserver):
return nameserver.find(".gov")!=-1 return nameserver.find(self.name) != -1
def checkHostIPCombo(self, nameserver:str, ip:list): def checkHostIPCombo(self, nameserver: str, ip: list):
if ( self.isDotGov(nameserver) and (ip is None or if self.isSubdomain(nameserver) and (ip is None or ip == []):
ip==[]) ): raise ValueError("Nameserver %s needs to have an ip address" % nameserver)
raise ValueError("Nameserver %s needs to have an ip address", nameserver) elif not self.isSubdomain(nameserver) and (ip is not None and ip != []):
raise ValueError(
"Nameserver %s cannot be linked "
"because %s is not a subdomain" % (nameserver, ip)
)
return None return None
def getNameserverChanges(self, hosts:list[tuple[str]]): def getNameserverChanges(self, hosts: list[tuple[str]]):
""" """
calls self.nameserver, it should pull from cache but may result calls self.nameserver, it should pull from cache but may result
in an epp call in an epp call
returns tuple of four values as follows: returns tuple of four values as follows:
deleted_values: deleted_values:
updated_values: updated_values:
new_values: dict new_values: dict
oldNameservers:""" oldNameservers:"""
oldNameservers=self.nameservers oldNameservers = self.nameservers
previousHostDict = self._convert_list_to_dict(oldNameservers) previousHostDict = self._convert_list_to_dict(oldNameservers)
newHostDict = self._convert_list_to_dict(hosts) newHostDict = self._convert_list_to_dict(hosts)
deleted_values = [] deleted_values = []
@ -320,44 +321,39 @@ class Domain(TimeStampedModel, DomainHelper):
new_values = [] new_values = []
for prevHost in previousHostDict: for prevHost in previousHostDict:
addrs=previousHostDict[prevHost] addrs = previousHostDict[prevHost]
# get deleted values-which are values in previous nameserver list # get deleted values-which are values in previous nameserver list
# but are not in the list of new host values # but are not in the list of new host values
if prevHost not in newHostDict: if prevHost not in newHostDict:
deleted_values.append((prevHost,addrs)) deleted_values.append((prevHost, addrs))
# if the host exists in both, check if the addresses changed # if the host exists in both, check if the addresses changed
else: else:
#TODO - host is being updated when previous was None and new is an empty list # TODO - host is being updated when previous was None and new is an empty list
# add check here # add check here
if (newHostDict[prevHost] != addrs if newHostDict[prevHost] is not None and set(
and newHostDict[prevHost] is not None): newHostDict[prevHost]
# could raise error here if new value is empty and is a dotgov ) != set(addrs):
self.checkHostIPCombo(nameserver=prevHost, ip=newHostDict[prevHost]) self.checkHostIPCombo(nameserver=prevHost, ip=newHostDict[prevHost])
updated_values.append((prevHost,newHostDict[prevHost])) updated_values.append((prevHost, newHostDict[prevHost]))
new_values=set(newHostDict)-set(previousHostDict) #returns actually a set new_values = {
key: newHostDict.get(key)
for key in newHostDict
if key not in previousHostDict
}
final_new_values = dict.fromkeys(new_values, None) for nameserver, ip in new_values.items():
# loop in final new values to check for .gov and missing addresses self.checkHostIPCombo(nameserver=nameserver, ip=ip)
for nameserver, ip in final_new_values.items():
# check the new values for missing IPs return (deleted_values, updated_values, new_values, previousHostDict)
# raise error if missing
self.checkHostIPCombo(nameserver=nameserver,ip=ip)
return (deleted_values,updated_values,final_new_values, previousHostDict)
@nameservers.setter # type: ignore @nameservers.setter # type: ignore
def nameservers(self, hosts: list[tuple[str]]): def nameservers(self, hosts: list[tuple[str]]):
"""host should be a tuple of type str, str,... where the elements are """host should be a tuple of type str, str,... where the elements are
Fully qualified host name, addresses associated with the host Fully qualified host name, addresses associated with the host
example: [(ns1.okay.gov, 127.0.0.1, others ips)]""" example: [(ns1.okay.gov, 127.0.0.1, others ips)]"""
# TODO-848: ip version checking may need to be added in a different ticket
# We currently don't have IP address functionality # TODO-848: ip version checking may need to be added in a different ticket
# We can have multiple IP addresses
# If you have a dotgov, then you HAVE to have at least 1 IP address (can have multiple)
# Nameservers already have IP addresses, these IP addresses are additionals
if len(hosts) > 13: if len(hosts) > 13:
raise ValueError( raise ValueError(
@ -366,9 +362,14 @@ class Domain(TimeStampedModel, DomainHelper):
logger.info("Setting nameservers") logger.info("Setting nameservers")
logger.info(hosts) logger.info(hosts)
#get the changes made by user and old nameserver values # get the changes made by user and old nameserver values
deleted_values, updated_values, new_values, oldNameservers=self.getNameserverChanges(hosts=hosts) (
successDeletedCount = 0 deleted_values,
updated_values,
new_values,
oldNameservers,
) = self.getNameserverChanges(hosts=hosts)
successDeletedCount = 0
successCreatedCount = 0 successCreatedCount = 0
print("deleted_values") print("deleted_values")
@ -380,29 +381,31 @@ class Domain(TimeStampedModel, DomainHelper):
print("oldNameservers") print("oldNameservers")
print(oldNameservers) print(oldNameservers)
for hostTuple in deleted_values: for hostTuple in deleted_values:
print("hostTuple in deleted_values")
print(hostTuple)
print(deleted_values)
deleted_response_code = self._delete_host(hostTuple[0]) deleted_response_code = self._delete_host(hostTuple[0])
if deleted_response_code == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY: if deleted_response_code == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY:
successDeletedCount += 1 successDeletedCount += 1
for hostTuple in updated_values: for hostTuple in updated_values:
updated_response_code = self._update_host(hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0])) updated_response_code = self._update_host(
if updated_response_code not in [ ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY, ErrorCode.OBJECT_EXISTS]: hostTuple[0], hostTuple[1], oldNameservers.get(hostTuple[0])
logger.warning("Could not update host %s. Error code was: %s " % (hostTuple[0], updated_response_code)) )
if updated_response_code not in [
ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
ErrorCode.OBJECT_EXISTS,
]:
logger.warning(
"Could not update host %s. Error code was: %s "
% (hostTuple[0], updated_response_code)
)
for key, value in new_values.items(): for key, value in new_values.items():
print("HELLO THERE KEY, VALUE PAIR") createdCode = self._create_host(
print(key) host=key, addrs=value
print(value) ) # creates in registry
createdCode = self._create_host(host=key, addrs=value) # creates in registry if (
# TODO-848: Double check if _create_host should handle duplicates + update domain obj? createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
# NOTE-848: if createdCode == ErrorCode.OBJECT_EXISTS: --> self.nameservers or createdCode == ErrorCode.OBJECT_EXISTS
):
# NOTE-848: Host can be used by multiple domains
if createdCode == ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY or createdCode == ErrorCode.OBJECT_EXISTS:
request = commands.UpdateDomain( request = commands.UpdateDomain(
name=self.name, add=[epp.HostObjSet([key])] name=self.name, add=[epp.HostObjSet([key])]
) )
@ -415,9 +418,10 @@ class Domain(TimeStampedModel, DomainHelper):
% (e.code, e) % (e.code, e)
) )
print("") successTotalNameservers = (
successTotalNameservers = len(oldNameservers) - successDeletedCount+ successCreatedCount len(oldNameservers) - successDeletedCount + successCreatedCount
)
print("len(oldNameservers) IS ") print("len(oldNameservers) IS ")
print(len(oldNameservers)) print(len(oldNameservers))
print("successDeletedCount IS ") print("successDeletedCount IS ")
@ -425,9 +429,6 @@ class Domain(TimeStampedModel, DomainHelper):
print("successCreatedCount IS ") print("successCreatedCount IS ")
print(successCreatedCount) print(successCreatedCount)
print("SUCCESSTOTALNAMESERVERS IS ") print("SUCCESSTOTALNAMESERVERS IS ")
print(successTotalNameservers) print(successTotalNameservers)
if successTotalNameservers < 2: if successTotalNameservers < 2:
@ -438,17 +439,19 @@ class Domain(TimeStampedModel, DomainHelper):
except Exception as err: except Exception as err:
logger.info( logger.info(
"nameserver setter checked for dns_needed state " "nameserver setter checked for dns_needed state "
"and it did not succeed. Error: %s" % err "and it did not succeed. Warning: %s" % err
) )
elif successTotalNameservers >= 2 and successTotalNameservers <= 13: elif successTotalNameservers >= 2 and successTotalNameservers <= 13:
try: try:
print("READY/SAVE: We are in happy path where btwen 2 and 13 inclusive ns") print(
"READY/SAVE: We are in happy path where btwen 2 and 13 inclusive ns"
)
self.ready() self.ready()
self.save() self.save()
except Exception as err: except Exception as err:
logger.info( logger.info(
"nameserver setter checked for create state " "nameserver setter checked for create state "
"and it did not succeed. Error: %s" % err "and it did not succeed. Warning: %s" % err
) )
# TODO-848: Handle removed nameservers here, will need to change the state then go back to DNS_NEEDED # TODO-848: Handle removed nameservers here, will need to change the state then go back to DNS_NEEDED
@ -838,7 +841,7 @@ class Domain(TimeStampedModel, DomainHelper):
req = commands.InfoDomain(name=self.name) req = commands.InfoDomain(name=self.name)
domainInfo = registry.send(req, cleaned=True).res_data[0] domainInfo = registry.send(req, cleaned=True).res_data[0]
exitEarly = True exitEarly = True
return domainInfo return domainInfo
except RegistryError as e: except RegistryError as e:
count += 1 count += 1
@ -931,17 +934,17 @@ class Domain(TimeStampedModel, DomainHelper):
# when EPP calling is made more efficient # when EPP calling is made more efficient
# this should be added back in # this should be added back in
# The goal is to double check that # The goal is to double check that
# the nameservers we set are in fact # the nameservers we set are in fact
# on the registry # on the registry
# """ # """
# self._invalidate_cache() # self._invalidate_cache()
# nameserverList = self.nameservers # nameserverList = self.nameservers
# return len(nameserverList) < 2 # return len(nameserverList) < 2
# def dns_not_needed(self): # def dns_not_needed(self):
# return not self.is_dns_needed() # return not self.is_dns_needed()
@transition( @transition(
field="state", field="state",
source=[State.DNS_NEEDED], source=[State.DNS_NEEDED],
@ -964,10 +967,10 @@ class Domain(TimeStampedModel, DomainHelper):
) )
def dns_needed(self): def dns_needed(self):
"""Transition to the DNS_NEEDED state """Transition to the DNS_NEEDED state
domain should NOT have nameservers but domain should NOT have nameservers but
SHOULD have all contacts SHOULD have all contacts
Going to check nameservers and will Going to check nameservers and will
result in an EPP call result in an EPP call
""" """
logger.info("Changing to DNS_NEEDED state") logger.info("Changing to DNS_NEEDED state")
logger.info("able to transition to DNS_NEEDED state") logger.info("able to transition to DNS_NEEDED state")
@ -1087,22 +1090,33 @@ class Domain(TimeStampedModel, DomainHelper):
edited_ip_list = [] edited_ip_list = []
if ip_list is None: if ip_list is None:
return [] return []
for ip_addr in ip_list: for ip_addr in ip_list:
if self.is_ipv6(): if self.is_ipv6(ip_addr):
edited_ip_list.append(epp.Ip(addr=ip_addr, ip="v6")) edited_ip_list.append(epp.Ip(addr=ip_addr, ip="v6"))
else: # default ip addr is v4 else: # default ip addr is v4
edited_ip_list.append(epp.Ip(addr=ip_addr)) edited_ip_list.append(epp.Ip(addr=ip_addr))
return edited_ip_list return edited_ip_list
def _update_host(self, nameserver: str, ip_list: list[str], old_ip_list: list[str]): def _update_host(self, nameserver: str, ip_list: list[str], old_ip_list: list[str]):
try: try:
if (
if ip_list is None or len(ip_list) == 0 and isinstance(old_ip_list,list) and len(old_ip_list)!=0 : ip_list is None
or len(ip_list) == 0
and isinstance(old_ip_list, list)
and len(old_ip_list) != 0
):
return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY return ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY
request = commands.UpdateHost(name=nameserver, add=self._convert_ips(ip_list), rem=self._convert_ips(old_ip_list)) added_ip_list = set(ip_list) - set(old_ip_list)
removed_ip_list = set(old_ip_list) - set(ip_list)
request = commands.UpdateHost(
name=nameserver,
add=self._convert_ips(list(added_ip_list)),
rem=self._convert_ips(list(removed_ip_list)),
)
response = registry.send(request, cleaned=True) response = registry.send(request, cleaned=True)
logger.info("_update_host()-> sending req as %s" % request) logger.info("_update_host()-> sending req as %s" % request)
return response.code return response.code
@ -1113,23 +1127,30 @@ class Domain(TimeStampedModel, DomainHelper):
def _delete_host(self, nameserver: str): def _delete_host(self, nameserver: str):
try: try:
updateReq = commands.UpdateDomain( updateReq = commands.UpdateDomain(
name=self.name, rem=[epp.HostObjSet([nameserver])] name=self.name, rem=[epp.HostObjSet([nameserver])]
) )
response=registry.send(updateReq, cleaned=True) response = registry.send(updateReq, cleaned=True)
logger.info("_delete_host()-> sending update domain req as %s" % updateReq) logger.info("_delete_host()-> sending update domain req as %s" % updateReq)
deleteHostReq = commands.DeleteHost(name=nameserver) deleteHostReq = commands.DeleteHost(name=nameserver)
response = registry.send(deleteHostReq, cleaned=True) response = registry.send(deleteHostReq, cleaned=True)
logger.info("_delete_host()-> sending delete host req as %s" % deleteHostReq) logger.info(
"_delete_host()-> sending delete host req as %s" % deleteHostReq
)
return response.code return response.code
except RegistryError as e: except RegistryError as e:
if e.code==ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION: if e.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION:
logger.info("Did not remove host %s because it is in use on another domain." % nameserver) logger.info(
"Did not remove host %s because it is in use on another domain."
% nameserver
)
else: else:
logger.error("Error _delete_host, code was %s error was %s" % (e.code, e)) logger.error(
"Error _delete_host, code was %s error was %s" % (e.code, e)
)
return e.code return e.code
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False): def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
"""Contact registry for info about a domain.""" """Contact registry for info about a domain."""
try: try:

View file

@ -562,7 +562,7 @@ class MockEppLib(TestCase):
self.contacts = contacts self.contacts = contacts
self.hosts = hosts self.hosts = hosts
self.statuses = statuses self.statuses = statuses
self.avail = avail #use for CheckDomain self.avail = avail # use for CheckDomain
self.addrs = addrs self.addrs = addrs
mockDataInfoDomain = fakedEppObject( mockDataInfoDomain = fakedEppObject(
@ -581,36 +581,52 @@ class MockEppLib(TestCase):
contacts=[], contacts=[],
hosts=["fake.host.com"], hosts=["fake.host.com"],
) )
infoDomainThreeHosts =fakedEppObject( infoDomainThreeHosts = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[], contacts=[],
hosts=["ns1.my-nameserver-1.com","ns1.my-nameserver-2.com","ns1.cats-are-superior3.com"], hosts=[
"ns1.my-nameserver-1.com",
"ns1.my-nameserver-2.com",
"ns1.cats-are-superior3.com",
],
) )
infoDomainNoHost =fakedEppObject( infoDomainNoHost = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[], contacts=[],
hosts=[], hosts=[],
) )
infoDomainTwoHosts =fakedEppObject( infoDomainTwoHosts = fakedEppObject(
"my-nameserver.gov", "my-nameserver.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[], contacts=[],
hosts=["ns1.my-nameserver-1.com","ns1.my-nameserver-2.com"], hosts=["ns1.my-nameserver-1.com", "ns1.my-nameserver-2.com"],
) )
mockDataInfoContact = fakedEppObject( mockDataInfoContact = fakedEppObject(
"anotherPw", cr_date=datetime.datetime(2023, 7, 25, 19, 45, 35) "anotherPw", cr_date=datetime.datetime(2023, 7, 25, 19, 45, 35)
) )
mockDataInfoHosts = fakedEppObject( mockDataInfoHosts = fakedEppObject(
"lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35), addrs=["1.2.3", "2.3.4"] "lastPw",
cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35),
addrs=["1.2.3", "2.3.4"],
) )
mockDataHostChange =fakedEppObject( mockDataHostChange = fakedEppObject(
"lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35) "lastPw", cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35)
) )
infoDomainHasIP = fakedEppObject(
extendedValues=False "nameserverwithip.gov",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[],
hosts=[
"ns1.nameserverwithip.gov",
"ns2.nameserverwithip.gov",
"ns3.nameserverwithip.gov",
],
)
extendedValues = False
def mockSend(self, _request, cleaned): def mockSend(self, _request, cleaned):
"""Mocks the registry.send function used inside of domain.py """Mocks the registry.send function used inside of domain.py
@ -623,10 +639,14 @@ class MockEppLib(TestCase):
elif getattr(_request, "name", None) == "my-nameserver.gov": elif getattr(_request, "name", None) == "my-nameserver.gov":
if self.extendedValues: if self.extendedValues:
return MagicMock(res_data=[self.infoDomainThreeHosts]) return MagicMock(res_data=[self.infoDomainThreeHosts])
elif self.mockedSendFunction.call_count==5: ## remove this breaks anything? elif (
self.mockedSendFunction.call_count == 5
): ## remove this breaks anything?
return MagicMock(res_data=[self.infoDomainTwoHosts]) return MagicMock(res_data=[self.infoDomainTwoHosts])
else: else:
return MagicMock(res_data=[self.infoDomainNoHost]) return MagicMock(res_data=[self.infoDomainNoHost])
elif getattr(_request, "name", None) == "nameserverwithip.gov":
return MagicMock(res_data=[self.infoDomainHasIP])
return MagicMock(res_data=[self.mockDataInfoDomain]) return MagicMock(res_data=[self.mockDataInfoDomain])
elif isinstance(_request, commands.InfoContact): elif isinstance(_request, commands.InfoContact):
return MagicMock(res_data=[self.mockDataInfoContact]) return MagicMock(res_data=[self.mockDataInfoContact])
@ -638,12 +658,21 @@ class MockEppLib(TestCase):
# use this for when a contact is being updated # use this for when a contact is being updated
# sets the second send() to fail # sets the second send() to fail
raise RegistryError(code=ErrorCode.OBJECT_EXISTS) raise RegistryError(code=ErrorCode.OBJECT_EXISTS)
elif (isinstance(_request, commands.CreateHost)): elif isinstance(_request, commands.CreateHost):
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY) return MagicMock(
elif (isinstance(_request, commands.UpdateHost)): res_data=[self.mockDataHostChange],
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY) code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
elif (isinstance(_request, commands.DeleteHost)): )
return MagicMock(res_data=[self.mockDataHostChange], code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY) elif isinstance(_request, commands.UpdateHost):
return MagicMock(
res_data=[self.mockDataHostChange],
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
)
elif isinstance(_request, commands.DeleteHost):
return MagicMock(
res_data=[self.mockDataHostChange],
code=ErrorCode.COMMAND_COMPLETED_SUCCESSFULLY,
)
return MagicMock(res_data=[self.mockDataInfoHosts]) return MagicMock(res_data=[self.mockDataInfoHosts])
def setUp(self): def setUp(self):

View file

@ -537,27 +537,39 @@ class TestRegistrantNameservers(MockEppLib):
self.nameserver2 = "ns1.my-nameserver-2.com" self.nameserver2 = "ns1.my-nameserver-2.com"
self.nameserver3 = "ns1.cats-are-superior3.com" self.nameserver3 = "ns1.cats-are-superior3.com"
self.domain, _ = Domain.objects.get_or_create(name="my-nameserver.gov", state=Domain.State.DNS_NEEDED) self.domain, _ = Domain.objects.get_or_create(
name="my-nameserver.gov", state=Domain.State.DNS_NEEDED
)
def test_get_nameserver_changes(self): def test_get_nameserver_changes(self):
self.domain._cache["hosts"]=[{ self.domain._cache["hosts"] = [
"name": "ns1.example.com", {"name": "ns1.example.com", "addrs": None},
"addrs": None {"name": "ns2.example.com", "addrs": ["1.2.3"]},
}, {"name": "ns3.my-nameserver.gov", "addrs": ["1.2.3"]},
{"name": "ns2.example.com",
"addrs": ["1.2.3"]
},
{"name": "ns3.example.com",
"addrs": ["1.2.3"]
}
] ]
newChanges=[("ns1.example.com",),("ns3.example.com",["1.2.4"]),("ns4.example.com",)] newChanges = [
deleted_values,updated_values,new_values, oldNameservers=self.domain.getNameserverChanges(newChanges) ("ns1.example.com",),
("ns3.my-nameserver.gov", ["1.2.4"]),
("ns4.example.com",),
]
(
deleted_values,
updated_values,
new_values,
oldNameservers,
) = self.domain.getNameserverChanges(newChanges)
print(oldNameservers) print(oldNameservers)
self.assertEqual(deleted_values, [('ns2.example.com', ['1.2.3'])]) self.assertEqual(deleted_values, [("ns2.example.com", ["1.2.3"])])
self.assertEqual(updated_values, [('ns3.example.com', ['1.2.4'])]) self.assertEqual(updated_values, [("ns3.my-nameserver.gov", ["1.2.4"])])
self.assertEqual(new_values, {'ns4.example.com':None}) self.assertEqual(new_values, {"ns4.example.com": None})
self.assertEqual(oldNameservers, {'ns1.example.com': None, 'ns2.example.com': ['1.2.3'], 'ns3.example.com': ['1.2.3']}) self.assertEqual(
oldNameservers,
{
"ns1.example.com": None,
"ns2.example.com": ["1.2.3"],
"ns3.my-nameserver.gov": ["1.2.3"],
},
)
def test_user_adds_one_nameserver(self): def test_user_adds_one_nameserver(self):
""" """
@ -571,11 +583,13 @@ class TestRegistrantNameservers(MockEppLib):
# set 1 nameserver # set 1 nameserver
nameserver = "ns1.my-nameserver.com" nameserver = "ns1.my-nameserver.com"
self.domain.nameservers = [(nameserver,)] self.domain.nameservers = [(nameserver,)]
# when you create a host, you also have to update at same time # when you create a host, you also have to update at same time
created_host = commands.CreateHost(nameserver) created_host = commands.CreateHost(nameserver)
update_domain_with_created = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host.name])]) update_domain_with_created = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host.name])]
)
# checking if commands were sent (commands have to be sent in order) # checking if commands were sent (commands have to be sent in order)
expectedCalls = [ expectedCalls = [
@ -600,16 +614,20 @@ class TestRegistrantNameservers(MockEppLib):
# set 2 nameservers # set 2 nameservers
print("DOCKER DIDNT SUCK THIS TIME") print("DOCKER DIDNT SUCK THIS TIME")
self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)] self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)]
# when you create a host, you also have to update at same time # when you create a host, you also have to update at same time
created_host1 = commands.CreateHost(self.nameserver1) created_host1 = commands.CreateHost(self.nameserver1)
update_domain_with_created1 = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host1.name])]) update_domain_with_created1 = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host1.name])]
)
created_host2 = commands.CreateHost(self.nameserver2) created_host2 = commands.CreateHost(self.nameserver2)
update_domain_with_created2 = commands.UpdateDomain(name=self.domain.name, add=[common.HostObjSet([created_host2.name])]) update_domain_with_created2 = commands.UpdateDomain(
name=self.domain.name, add=[common.HostObjSet([created_host2.name])]
)
infoDomain = commands.InfoDomain(name='my-nameserver.gov', auth_info=None) infoDomain = commands.InfoDomain(name="my-nameserver.gov", auth_info=None)
# checking if commands were sent (commands have to be sent in order) # checking if commands were sent (commands have to be sent in order)
expectedCalls = [ expectedCalls = [
call(infoDomain, cleaned=True), call(infoDomain, cleaned=True),
@ -619,9 +637,6 @@ class TestRegistrantNameservers(MockEppLib):
call(update_domain_with_created2, cleaned=True), call(update_domain_with_created2, cleaned=True),
] ]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True) self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertEqual(5, self.mockedSendFunction.call_count) self.assertEqual(5, self.mockedSendFunction.call_count)
# check that status is READY # check that status is READY
@ -650,11 +665,24 @@ class TestRegistrantNameservers(MockEppLib):
nameserver12 = "ns1.cats-are-superior12.com" nameserver12 = "ns1.cats-are-superior12.com"
nameserver13 = "ns1.cats-are-superior13.com" nameserver13 = "ns1.cats-are-superior13.com"
nameserver14 = "ns1.cats-are-superior14.com" nameserver14 = "ns1.cats-are-superior14.com"
def _get_14_nameservers(): def _get_14_nameservers():
self.domain.nameservers = [(nameserver1,), (nameserver2,), (nameserver3,), (nameserver4,), self.domain.nameservers = [
(nameserver5,), (nameserver6,), (nameserver7,), (nameserver8,), (nameserver9), (nameserver10,), (nameserver1,),
(nameserver11,), (nameserver12,), (nameserver13,), (nameserver14,)] (nameserver2,),
(nameserver3,),
(nameserver4,),
(nameserver5,),
(nameserver6,),
(nameserver7,),
(nameserver8,),
(nameserver9),
(nameserver10,),
(nameserver11,),
(nameserver12,),
(nameserver13,),
(nameserver14,),
]
self.assertRaises(ValueError, _get_14_nameservers) self.assertRaises(ValueError, _get_14_nameservers)
self.assertEqual(self.mockedSendFunction.call_count, 0) self.assertEqual(self.mockedSendFunction.call_count, 0)
@ -670,25 +698,37 @@ class TestRegistrantNameservers(MockEppLib):
""" """
# Mock is set to return 3 nameservers on infodomain # Mock is set to return 3 nameservers on infodomain
self.extendedValues=True self.extendedValues = True
self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)] self.domain.nameservers = [(self.nameserver1,), (self.nameserver2,)]
expectedCalls=[ expectedCalls = [
# calls info domain, and info on all hosts # calls info domain, and info on all hosts
# to get past values # to get past values
# then removes the single host and updates domain # then removes the single host and updates domain
call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True), call(
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True), commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True), cleaned=True,
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True), ),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.cats-are-superior3.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True), call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.DeleteHost(name='ns1.cats-are-superior3.com'), cleaned=True)] call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.cats-are-superior3.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.cats-are-superior3.com"), cleaned=True),
]
print("self.mockedSendFunction.call_args_list is ")
print(self.mockedSendFunction.call_args_list)
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True) self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(self.domain.is_active()) self.assertTrue(self.domain.is_active())
def test_user_removes_too_many_nameservers(self): def test_user_removes_too_many_nameservers(self):
""" """
Scenario: Registrant removes some nameservers, bringing the total to less than 2 Scenario: Registrant removes some nameservers, bringing the total to less than 2
@ -697,27 +737,51 @@ class TestRegistrantNameservers(MockEppLib):
Then `commands.UpdateDomain` and `commands.DeleteHost` is sent Then `commands.UpdateDomain` and `commands.DeleteHost` is sent
to the registry to the registry
And `domain.is_active` returns False And `domain.is_active` returns False
""" """
self.extendedValues=True self.extendedValues = True
print("domain state") print("domain state")
print(self.domain.state) print(self.domain.state)
self.domain.ready() self.domain.ready()
print("Domain state is now") print("Domain state is now")
print(self.domain.state) print(self.domain.state)
self.domain.nameservers = [(self.nameserver1,)] self.domain.nameservers = [(self.nameserver1,)]
print("self.mockedSendFunction.call_args_list is ") expectedCalls = [
print(self.mockedSendFunction.call_args_list) call(
expectedCalls=[call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True), commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True), cleaned=True,
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True), ),
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True), call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.my-nameserver-2.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True), call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(commands.DeleteHost(name='ns1.my-nameserver-2.com'), cleaned=True), call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.cats-are-superior3.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True), call(
call(commands.DeleteHost(name='ns1.cats-are-superior3.com'), cleaned=True)] commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.my-nameserver-2.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.cats-are-superior3.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.cats-are-superior3.com"), cleaned=True),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True) self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertFalse(self.domain.is_active()) self.assertFalse(self.domain.is_active())
@ -731,27 +795,72 @@ class TestRegistrantNameservers(MockEppLib):
And `commands.UpdateDomain` is sent to add #4 and #5 plus remove #2 and #3 And `commands.UpdateDomain` is sent to add #4 and #5 plus remove #2 and #3
And `commands.DeleteHost` is sent to delete #2 and #3 And `commands.DeleteHost` is sent to delete #2 and #3
""" """
self.extendedValues=True self.extendedValues = True
self.domain.ready() self.domain.ready()
self.domain.nameservers=[(self.nameserver1,), ("ns1.cats-are-superior1.com",), ("ns1.cats-are-superior2.com",)] self.domain.nameservers = [
print("self.mockedSendFunction.call_args_list is ") (self.nameserver1,),
print(self.mockedSendFunction.call_args_list) ("ns1.cats-are-superior1.com",),
expectedCalls=[call(commands.InfoDomain(name='my-nameserver.gov', auth_info=None), cleaned=True), ("ns1.cats-are-superior2.com",),
call(commands.InfoHost(name='ns1.my-nameserver-1.com'), cleaned=True), ]
call(commands.InfoHost(name='ns1.my-nameserver-2.com'), cleaned=True),
call(commands.InfoHost(name='ns1.cats-are-superior3.com'), cleaned=True), expectedCalls = [
call(commands.UpdateDomain(name='my-nameserver.gov', add=[], rem=[common.HostObjSet(hosts=['ns1.my-nameserver-2.com'])], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True), call(
call(commands.DeleteHost(name='ns1.my-nameserver-2.com'), cleaned=True), commands.InfoDomain(name="my-nameserver.gov", auth_info=None),
call(commands.CreateHost(name='ns1.cats-are-superior1.com', addrs=[]), cleaned=True), cleaned=True,
call(commands.UpdateDomain(name='my-nameserver.gov', add=[common.HostObjSet(hosts=['ns1.cats-are-superior1.com'])], rem=[], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True), ),
call(commands.CreateHost(name='ns1.cats-are-superior2.com', addrs=[]), cleaned=True), call(commands.InfoHost(name="ns1.my-nameserver-1.com"), cleaned=True),
call(commands.UpdateDomain(name='my-nameserver.gov', add=[common.HostObjSet(hosts=['ns1.cats-are-superior2.com'])], rem=[], nsset=None, keyset=None, registrant=None, auth_info=None), cleaned=True) call(commands.InfoHost(name="ns1.my-nameserver-2.com"), cleaned=True),
] call(commands.InfoHost(name="ns1.cats-are-superior3.com"), cleaned=True),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[],
rem=[common.HostObjSet(hosts=["ns1.my-nameserver-2.com"])],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(commands.DeleteHost(name="ns1.my-nameserver-2.com"), cleaned=True),
call(
commands.CreateHost(name="ns1.cats-are-superior1.com", addrs=[]),
cleaned=True,
),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[common.HostObjSet(hosts=["ns1.cats-are-superior1.com"])],
rem=[],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
call(
commands.CreateHost(name="ns1.cats-are-superior2.com", addrs=[]),
cleaned=True,
),
call(
commands.UpdateDomain(
name="my-nameserver.gov",
add=[common.HostObjSet(hosts=["ns1.cats-are-superior2.com"])],
rem=[],
nsset=None,
keyset=None,
registrant=None,
auth_info=None,
),
cleaned=True,
),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True) self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(self.domain.is_active()) self.assertTrue(self.domain.is_active())
def test_user_cannot_add_subordinate_without_ip(self): def test_user_cannot_add_subordinate_without_ip(self):
""" """
Scenario: Registrant adds a nameserver which is a subdomain of their .gov Scenario: Registrant adds a nameserver which is a subdomain of their .gov
@ -760,11 +869,12 @@ class TestRegistrantNameservers(MockEppLib):
with a subdomain of the domain and no IP addresses with a subdomain of the domain and no IP addresses
Then Domain raises a user-friendly error Then Domain raises a user-friendly error
""" """
#add a nameserver with a .gov and no ip
##assertRaises error
raise
@skip("not implemented yet") dotgovnameserver = "my-nameserver.gov"
with self.assertRaises(ValueError):
self.domain.nameservers = [(dotgovnameserver,)]
def test_user_updates_ips(self): def test_user_updates_ips(self):
""" """
Scenario: Registrant changes IP addresses for a nameserver Scenario: Registrant changes IP addresses for a nameserver
@ -774,9 +884,49 @@ class TestRegistrantNameservers(MockEppLib):
with a different IP address(es) with a different IP address(es)
Then `commands.UpdateHost` is sent to the registry Then `commands.UpdateHost` is sent to the registry
""" """
raise domain, _ = Domain.objects.get_or_create(
name="nameserverwithip.gov", state=Domain.State.READY
)
domain.nameservers = [
("ns1.nameserverwithip.gov", ["2.3.4", "1.2.3"]),
("ns2.nameserverwithip.gov", ["1.2.3", "2.3.4", "3.4.5"]),
("ns3.nameserverwithip.gov", ["2.3.4"]),
]
# print("self.mockedSendFunction.call_args_list is ")
# print(self.mockedSendFunction.call_args_list)
expectedCalls = [
call(
commands.InfoDomain(name="nameserverwithip.gov", auth_info=None),
cleaned=True,
),
call(commands.InfoHost(name="ns1.nameserverwithip.gov"), cleaned=True),
call(commands.InfoHost(name="ns2.nameserverwithip.gov"), cleaned=True),
call(commands.InfoHost(name="ns3.nameserverwithip.gov"), cleaned=True),
call(
commands.UpdateHost(
name="ns2.nameserverwithip.gov",
add=[common.Ip(addr="3.4.5", ip="v6")],
rem=[],
chg=None,
),
cleaned=True,
),
call(
commands.UpdateHost(
name="ns3.nameserverwithip.gov",
add=[],
rem=[common.Ip(addr="1.2.3", ip="v6")],
chg=None,
),
cleaned=True,
),
]
self.mockedSendFunction.assert_has_calls(expectedCalls, any_order=True)
self.assertTrue(domain.is_active())
@skip("not implemented yet")
def test_user_cannot_add_non_subordinate_with_ip(self): def test_user_cannot_add_non_subordinate_with_ip(self):
""" """
Scenario: Registrant adds a nameserver which is NOT a subdomain of their .gov Scenario: Registrant adds a nameserver which is NOT a subdomain of their .gov
@ -785,7 +935,10 @@ class TestRegistrantNameservers(MockEppLib):
which is not a subdomain of the domain and has IP addresses which is not a subdomain of the domain and has IP addresses
Then Domain raises a user-friendly error Then Domain raises a user-friendly error
""" """
raise dotgovnameserver = "mynameserverdotgov.gov"
with self.assertRaises(ValueError):
self.domain.nameservers = [(dotgovnameserver, ["1.2.3"])]
@skip("not implemented yet") @skip("not implemented yet")
def test_nameservers_are_idempotent(self): def test_nameservers_are_idempotent(self):
@ -810,9 +963,10 @@ class TestRegistrantNameservers(MockEppLib):
raise raise
def tearDown(self): def tearDown(self):
self.extendedValues=False self.extendedValues = False
return super().tearDown() return super().tearDown()
class TestRegistrantDNSSEC(TestCase): class TestRegistrantDNSSEC(TestCase):
"""Rule: Registrants may modify their secure DNS data""" """Rule: Registrants may modify their secure DNS data"""