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`."""
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
def available(cls, domain: str) -> bool:
"""Check if a domain is available.
@ -1054,6 +1062,13 @@ class Domain(TimeStampedModel, DomainHelper):
RegistryError: if any subdomain cannot be deleted
"""
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]
hostsToDelete, _ = self.createDeleteHostList(nameservers)
logger.debug("HostsToDelete from %s inside _delete_subdomains -> %s", self.name, hostsToDelete)
@ -1070,9 +1085,10 @@ class Domain(TimeStampedModel, DomainHelper):
def _delete_domain_registrant(self):
"""This domain's registrant should be deleted from the registry
may raises RegistryError, should be caught or handled correctly by caller"""
registrantID = self.registrant_contact.registry_id
request = commands.DeleteContact(id=registrantID)
registry.send(request, cleaned=True)
if self.registrant_contact:
registrantID = self.registrant_contact.registry_id
request = commands.DeleteContact(id=registrantID)
registry.send(request, cleaned=True)
def __str__(self) -> str:
return self.name
@ -1486,6 +1502,7 @@ class Domain(TimeStampedModel, DomainHelper):
self._delete_domain()
self._delete_domain_registrant()
self.deleted = timezone.now()
self.expiration_date = None
except RegistryError as err:
logger.error(f"Could not delete domain. Registry returned error: {err}")
raise err

View file

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

View file

@ -2584,6 +2584,7 @@ class TestAnalystDelete(MockEppLib):
super().setUp()
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)
Host.objects.create(name="ns1.sharingiscaring.gov", domain=self.domain_on_hold)
def tearDown(self):
Host.objects.all().delete()
@ -2639,15 +2640,9 @@ class TestAnalystDelete(MockEppLib):
with self.assertRaises(RegistryError) as err:
domain.deletedInEpp()
domain.save()
self.assertTrue(err.is_client_error() and err.code == ErrorCode.OBJECT_ASSOCIATION_PROHIBITS_OPERATION)
self.mockedSendFunction.assert_has_calls(
[
call(
commands.DeleteHost(name="ns1.sharedhost.com"),
cleaned=True,
),
]
)
self.assertEqual(err.msg, "Host in use by another domain: fake-on-hold.gov")
# Domain itself should not be deleted
self.assertNotEqual(domain, None)
# State should not have changed
@ -2663,41 +2658,43 @@ class TestAnalystDelete(MockEppLib):
Then `commands.DeleteContact` is sent to the registry for the registrant contact
And `state` is set to `DELETED`
"""
# with less_console_noise():
# Desired domain
domain, _ = Domain.objects.get_or_create(name="freeman.gov", state=Domain.State.ON_HOLD)
# Put the domain in client hold
domain.place_client_hold()
# Delete it
domain.deletedInEpp()
domain.save()
with less_console_noise():
# Desired domain
domain, _ = Domain.objects.get_or_create(name="freeman.gov", state=Domain.State.ON_HOLD)
# Put the domain in client hold
domain.place_client_hold()
# Delete it
domain.deletedInEpp()
domain.save()
# Check that the host and contacts are deleted, order doesn't matter
self.mockedSendFunction.assert_has_calls(
[
call(commands.DeleteHost(name="fake.host.com"), cleaned=True),
call(commands.DeleteContact(id="securityContact"), cleaned=True),
call(commands.DeleteContact(id="technicalContact"), cleaned=True),
call(
commands.DeleteContact(id="adminContact"),
cleaned=True,
),
],
any_order=True,
)
# Check that the host and contacts are deleted, order doesn't matter
self.mockedSendFunction.assert_has_calls(
[
call(commands.DeleteHost(name="fake.host.com"), cleaned=True),
call(commands.DeleteContact(id="securityContact"), cleaned=True),
call(commands.DeleteContact(id="technicalContact"), cleaned=True),
call(
commands.DeleteContact(id="adminContact"),
cleaned=True,
),
],
any_order=True,
)
actual_calls = self.mockedSendFunction.call_args_list
print("actual_calls", actual_calls)
# These calls need to be in order
self.mockedSendFunction.assert_has_calls(
[
call(commands.DeleteDomain(name="freeman.gov"), cleaned=True),
call(commands.InfoContact(id="regContact"), cleaned=True),
call(commands.DeleteContact(id="regContact"), cleaned=True),
],
)
# Domain itself should not be deleted
self.assertNotEqual(domain, None)
# State should have changed
self.assertEqual(domain.state, Domain.State.DELETED)
# These calls need to be in order
self.mockedSendFunction.assert_has_calls(
[
call(commands.DeleteDomain(name="freeman.gov"), cleaned=True),
call(commands.InfoContact(id="regContact"), cleaned=True),
call(commands.DeleteContact(id="regContact"), cleaned=True),
],
)
# Domain itself should not be deleted
self.assertNotEqual(domain, None)
# State should have changed
self.assertEqual(domain.state, Domain.State.DELETED)
def test_deletion_ready_fsm_failure(self):
"""