include hostname in error messages for shared hosts

This commit is contained in:
matthewswspence 2024-12-04 16:28:33 -06:00
parent 89253a1626
commit f25bb9be05
No known key found for this signature in database
GPG key ID: FB458202A7852BA4
3 changed files with 59 additions and 44 deletions

View file

@ -231,6 +231,14 @@ class Domain(TimeStampedModel, DomainHelper):
"""Called during delete. Example: `del domain.registrant`.""" """Called during delete. Example: `del domain.registrant`."""
super().__delete__(obj) super().__delete__(obj)
def save(
self, force_insert=False, force_update=False, using=None, update_fields=None
):
# If the domain is deleted we don't want the expiration date to be set
if self.state == self.State.DELETED and self.expiration_date:
self.expiration_date = None
super().save(force_insert, force_update, using, update_fields)
@classmethod @classmethod
def available(cls, domain: str) -> bool: def available(cls, domain: str) -> bool:
"""Check if a domain is available. """Check if a domain is available.
@ -1054,6 +1062,13 @@ class Domain(TimeStampedModel, DomainHelper):
RegistryError: if any subdomain cannot be deleted RegistryError: if any subdomain cannot be deleted
""" """
logger.info("Deleting nameservers for %s", self.name) logger.info("Deleting nameservers for %s", self.name)
# check if any nameservers are in use by another domain
hosts = Host.objects.filter(name__regex=r'.+{}'.format(self.name))
for host in hosts:
if host.domain != self:
logger.error("Host %s in use by another domain: %s", host.name, host.domain)
raise RegistryError("Host in use by another domain: {}".format(host.domain), code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
nameservers = [n[0] for n in self.nameservers] nameservers = [n[0] for n in self.nameservers]
hostsToDelete, _ = self.createDeleteHostList(nameservers) hostsToDelete, _ = self.createDeleteHostList(nameservers)
logger.debug("HostsToDelete from %s inside _delete_subdomains -> %s", self.name, hostsToDelete) logger.debug("HostsToDelete from %s inside _delete_subdomains -> %s", self.name, hostsToDelete)
@ -1070,6 +1085,7 @@ class Domain(TimeStampedModel, DomainHelper):
def _delete_domain_registrant(self): def _delete_domain_registrant(self):
"""This domain's registrant should be deleted from the registry """This domain's registrant should be deleted from the registry
may raises RegistryError, should be caught or handled correctly by caller""" may raises RegistryError, should be caught or handled correctly by caller"""
if self.registrant_contact:
registrantID = self.registrant_contact.registry_id registrantID = self.registrant_contact.registry_id
request = commands.DeleteContact(id=registrantID) request = commands.DeleteContact(id=registrantID)
registry.send(request, cleaned=True) registry.send(request, cleaned=True)
@ -1486,6 +1502,7 @@ class Domain(TimeStampedModel, DomainHelper):
self._delete_domain() self._delete_domain()
self._delete_domain_registrant() self._delete_domain_registrant()
self.deleted = timezone.now() self.deleted = timezone.now()
self.expiration_date = None
except RegistryError as err: except RegistryError as err:
logger.error(f"Could not delete domain. Registry returned error: {err}") logger.error(f"Could not delete domain. Registry returned error: {err}")
raise err raise err

View file

@ -1676,6 +1676,7 @@ class MockEppLib(TestCase):
def mockDeleteHostCommands(self, _request, cleaned): def mockDeleteHostCommands(self, _request, cleaned):
host = getattr(_request, "name", None) host = getattr(_request, "name", None)
if "sharedhost.com" in host: if "sharedhost.com" in host:
print("raising registry error")
raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION) raise RegistryError(code=ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
return MagicMock( return MagicMock(
res_data=[self.mockDataHostChange], res_data=[self.mockDataHostChange],

View file

@ -2584,6 +2584,7 @@ class TestAnalystDelete(MockEppLib):
super().setUp() super().setUp()
self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY) self.domain, _ = Domain.objects.get_or_create(name="fake.gov", state=Domain.State.READY)
self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD) self.domain_on_hold, _ = Domain.objects.get_or_create(name="fake-on-hold.gov", state=Domain.State.ON_HOLD)
Host.objects.create(name="ns1.sharingiscaring.gov", domain=self.domain_on_hold)
def tearDown(self): def tearDown(self):
Host.objects.all().delete() Host.objects.all().delete()
@ -2639,15 +2640,9 @@ class TestAnalystDelete(MockEppLib):
with self.assertRaises(RegistryError) as err: with self.assertRaises(RegistryError) as err:
domain.deletedInEpp() domain.deletedInEpp()
domain.save() domain.save()
self.assertTrue(err.is_client_error() and err.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION) self.assertTrue(err.is_client_error() and err.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
self.mockedSendFunction.assert_has_calls( self.assertEqual(err.msg, "Host in use by another domain: fake-on-hold.gov")
[
call(
commands.DeleteHost(name="ns1.sharedhost.com"),
cleaned=True,
),
]
)
# Domain itself should not be deleted # Domain itself should not be deleted
self.assertNotEqual(domain, None) self.assertNotEqual(domain, None)
# State should not have changed # State should not have changed
@ -2663,7 +2658,7 @@ class TestAnalystDelete(MockEppLib):
Then `commands.DeleteContact` is sent to the registry for the registrant contact Then `commands.DeleteContact` is sent to the registry for the registrant contact
And `state` is set to `DELETED` And `state` is set to `DELETED`
""" """
# with less_console_noise(): with less_console_noise():
# Desired domain # Desired domain
domain, _ = Domain.objects.get_or_create(name="freeman.gov", state=Domain.State.ON_HOLD) domain, _ = Domain.objects.get_or_create(name="freeman.gov", state=Domain.State.ON_HOLD)
# Put the domain in client hold # Put the domain in client hold
@ -2685,6 +2680,8 @@ class TestAnalystDelete(MockEppLib):
], ],
any_order=True, any_order=True,
) )
actual_calls = self.mockedSendFunction.call_args_list
print("actual_calls", actual_calls)
# These calls need to be in order # These calls need to be in order
self.mockedSendFunction.assert_has_calls( self.mockedSendFunction.assert_has_calls(