Init commit of biz logic and fixed unit tests

This commit is contained in:
Rebecca Hsieh 2024-04-12 10:45:01 -07:00
parent 64d0ec3f93
commit d6355f2293
No known key found for this signature in database
3 changed files with 101 additions and 3 deletions

View file

@ -1685,6 +1685,61 @@ class Domain(TimeStampedModel, DomainHelper):
else:
logger.error("Error _delete_hosts_if_not_used, code was %s error was %s" % (e.code, e))
def _fix_unknown_state(self, cleaned):
# print("!! GOT INTO _fix_unknown_state")
try:
self._add_missing_contacts(cleaned)
except Exception as e:
logger.error(
"%s couldn't _add_missing_contacts, error was %s."
"Domain will still be in UNKNOWN state." % (self.name, e)
)
if len(self.nameservers) >= 2:
# print("!! GOT INTO _fix_unknown_state -> have 2 or more nameserver so ready state")
self.ready()
self.save()
@transition(field="state", source=State.UNKNOWN, target=State.DNS_NEEDED)
def _add_missing_contacts(self, cleaned):
"""
_add_missing_contacts: Add contacts (SECURITY, TECHNICAL, and/or ADMINISTRATIVE)
if they are missing, AND switch the state to DNS_NEEDED from UNKNOWN (if it
is in an UNKNOWN state, that is an error state)
Note: The transition state change happens at the end of the function
"""
# print("!! GOT INTO _add_missing_contacts ")
missingAdmin = True
missingSecurity = True
missingTech = True
# print("cleaned ", cleaned)
if len(cleaned.get("_contacts")) < 3:
# print("!! GOT INTO _add_missing_contacts -> in if statement")
for contact in cleaned.get("_contacts"):
# this means we see it
if contact.type == "admin":
missingAdmin = False
if contact.type == "security":
missingSecurity = False
if contact.type == "tech":
missingTech = False
# we are only creating if it doesn't exist so we don't overwrite
if missingAdmin:
administrative_contact = self.get_default_administrative_contact()
administrative_contact.save()
if missingSecurity:
security_contact = self.get_default_security_contact()
security_contact.save()
if missingTech:
technical_contact = self.get_default_technical_contact()
technical_contact.save()
# print("!! GOT INTO _add_missing_contacts -> if statement finished ")
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
"""Contact registry for info about a domain."""
try:
@ -1692,6 +1747,10 @@ class Domain(TimeStampedModel, DomainHelper):
cache = self._extract_data_from_response(data_response)
cleaned = self._clean_cache(cache, data_response)
self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts)
if self.state == self.State.UNKNOWN:
# print("!! GOT INTO if self.state == self.State.UNKNOWN: ")
self._fix_unknown_state(cleaned)
if fetch_hosts:
self._update_hosts_and_ips_in_db(cleaned)
if fetch_contacts:

View file

@ -28,8 +28,9 @@ from registrar.models import (
User,
DomainInvitation,
Contact,
PublicContact,
Host,
Website,
DraftDomain,
)
from registrar.models.user_domain_role import UserDomainRole
from registrar.models.verified_by_staff import VerifiedByStaff
@ -618,6 +619,8 @@ class TestDomainAdmin(MockEppLib, WebTest):
def tearDown(self):
super().tearDown()
PublicContact.objects.all().delete()
Host.objects.all().delete()
Domain.objects.all().delete()
DomainInformation.objects.all().delete()
DomainRequest.objects.all().delete()

View file

@ -309,6 +309,38 @@ class TestDomainCache(MockEppLib):
)
self.assertEqual(context.exception.code, desired_error)
def test_fix_unknown_to_ready_state(self):
"""
Scenario: A error occurred and the domain's state is in UNKONWN
which shouldn't happen. The biz logic and test is to make sure
we resolve that UNKNOWN state to READY because it has 2 nameservers.
Note:
* Default state when you do get_or_create is UNKNOWN
* justnameserver.com has 2 nameservers which is why we are using it
* justnameserver.com also has all 3 contacts hence 0 count
"""
with less_console_noise():
domain, _ = Domain.objects.get_or_create(name="justnameserver.com")
_ = domain.nameservers
self.assertEqual(domain.state, Domain.State.READY)
self.assertEqual(PublicContact.objects.filter(domain=domain.id).count(), 0)
def test_fix_unknown_to_dns_needed_state(self):
"""
Scenario: A error occurred and the domain's state is in UNKONWN
which shouldn't happen. The biz logic and test is to make sure
we resolve that UNKNOWN state to DNS_NEEDED because it has 1 nameserver.
Note:
* Default state when you do get_or_create is UNKNOWN
* defaulttechnical.gov has 1 nameservers which is why we are using it
* defaulttechnical.gov already has a security contact (1) hence 2 count
"""
with less_console_noise():
domain, _ = Domain.objects.get_or_create(name="defaulttechnical.gov")
_ = domain.nameservers
self.assertEqual(domain.state, Domain.State.DNS_NEEDED)
self.assertEqual(PublicContact.objects.filter(domain=domain.id).count(), 2)
class TestDomainCreation(MockEppLib):
"""Rule: An approved domain request must result in a domain"""
@ -346,7 +378,7 @@ class TestDomainCreation(MockEppLib):
Given that no domain object exists in the registry
When a property is accessed
Then Domain sends `commands.CreateDomain` to the registry
And `domain.state` is set to `UNKNOWN`
And `domain.state` is set to `DNS_NEEDED`
And `domain.is_active()` returns False
"""
with less_console_noise():
@ -375,7 +407,7 @@ class TestDomainCreation(MockEppLib):
any_order=False, # Ensure calls are in the specified order
)
self.assertEqual(domain.state, Domain.State.UNKNOWN)
self.assertEqual(domain.state, Domain.State.DNS_NEEDED)
self.assertEqual(domain.is_active(), False)
@skip("assertion broken with mock addition")
@ -485,6 +517,7 @@ class TestDomainStatuses(MockEppLib):
def tearDown(self) -> None:
PublicContact.objects.all().delete()
Host.objects.all().delete()
Domain.objects.all().delete()
super().tearDown()
@ -624,6 +657,7 @@ class TestRegistrantContacts(MockEppLib):
self.domain._invalidate_cache()
self.domain_contact._invalidate_cache()
PublicContact.objects.all().delete()
Host.objects.all().delete()
Domain.objects.all().delete()
def test_no_security_email(self):
@ -1847,6 +1881,8 @@ class TestRegistrantDNSSEC(MockEppLib):
self.domain, _ = Domain.objects.get_or_create(name="fake.gov")
def tearDown(self):
PublicContact.objects.all().delete()
Host.objects.all().delete()
Domain.objects.all().delete()
super().tearDown()