Test cases and the like

This commit is contained in:
zandercymatics 2023-09-15 09:37:30 -06:00
parent 1edc21330d
commit aec32ca2ed
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
4 changed files with 197 additions and 99 deletions

View file

@ -1,4 +1,4 @@
# Generated by Django 4.2.1 on 2023-09-13 22:25 # Generated by Django 4.2.1 on 2023-09-15 13:59
from django.db import migrations, models from django.db import migrations, models
import django_fsm import django_fsm

View file

@ -651,9 +651,16 @@ class Domain(TimeStampedModel, DomainHelper):
# Q: I don't like this function name much, # Q: I don't like this function name much,
# what would be better here? # what would be better here?
def map_epp_contact_to_public_contact( def map_epp_contact_to_public_contact(
self, contact: eppInfo.InfoContactResultData, contact_type self, contact: eppInfo.InfoContactResultData, contact_id, contact_type
): ):
"""Maps the Epp contact representation to a PublicContact object""" """Maps the Epp contact representation to a PublicContact object.
contact -> eppInfo.InfoContactResultData: The converted contact object
contact_id -> str: The given registry_id of the object (i.e "cheese@cia.gov")
contact_type -> str: The given contact type, (i.e. "tech" or "registrant")
"""
if contact is None: if contact is None:
return None return None
@ -661,6 +668,9 @@ class Domain(TimeStampedModel, DomainHelper):
if contact_type is None: if contact_type is None:
raise ValueError("contact_type is None") raise ValueError("contact_type is None")
if contact_id is None:
raise ValueError("contact_id is None")
logger.debug(f"map_epp_contact_to_public_contact contact -> {contact}") logger.debug(f"map_epp_contact_to_public_contact contact -> {contact}")
logger.debug(f"What is the type? {type(contact)}") logger.debug(f"What is the type? {type(contact)}")
if not isinstance(contact, eppInfo.InfoContactResultData): if not isinstance(contact, eppInfo.InfoContactResultData):
@ -685,7 +695,7 @@ class Domain(TimeStampedModel, DomainHelper):
desired_contact = PublicContact( desired_contact = PublicContact(
domain=self, domain=self,
contact_type=contact_type, contact_type=contact_type,
registry_id=contact.id, registry_id=contact_id,
email=contact.email, email=contact.email,
voice=contact.voice, voice=contact.voice,
fax=contact.fax, fax=contact.fax,
@ -698,8 +708,6 @@ class Domain(TimeStampedModel, DomainHelper):
sp=addr.sp, sp=addr.sp,
**streets, **streets,
) )
logger.debug("lazy")
logger.debug(desired_contact.__dict__)
return desired_contact return desired_contact
def _request_contact_info(self, contact: PublicContact): def _request_contact_info(self, contact: PublicContact):
@ -716,6 +724,32 @@ class Domain(TimeStampedModel, DomainHelper):
) )
raise error raise error
def get_contact_default(
self, contact_type_choice: PublicContact.ContactTypeChoices
) -> PublicContact:
"""Returns a default contact based off the contact_type_choice.
Used
contact_type_choice is a literal in PublicContact.ContactTypeChoices,
for instance: PublicContact.ContactTypeChoices.SECURITY.
If you wanted to get the default contact for Security, you would call:
get_contact_default(PublicContact.ContactTypeChoices.SECURITY),
or get_contact_default("security")
"""
choices = PublicContact.ContactTypeChoices
contact: PublicContact
match (contact_type_choice):
case choices.ADMINISTRATIVE:
contact = self.get_default_administrative_contact()
case choices.SECURITY:
contact = self.get_default_security_contact()
case choices.TECHNICAL:
contact = self.get_default_technical_contact()
case choices.REGISTRANT:
contact = self.get_default_registrant_contact()
return contact
def generic_contact_getter( def generic_contact_getter(
self, contact_type_choice: PublicContact.ContactTypeChoices self, contact_type_choice: PublicContact.ContactTypeChoices
) -> PublicContact: ) -> PublicContact:
@ -734,9 +768,12 @@ class Domain(TimeStampedModel, DomainHelper):
if contact_type_choice == PublicContact.ContactTypeChoices.REGISTRANT: if contact_type_choice == PublicContact.ContactTypeChoices.REGISTRANT:
desired_property = "registrant" desired_property = "registrant"
contacts = self._get_property(desired_property) contacts = self._get_property(desired_property)
if contact_type_choice == PublicContact.ContactTypeChoices.REGISTRANT:
contacts = [contacts]
except KeyError as error: except KeyError as error:
logger.error("Contact does not exist") logger.warning("generic_contact_getter -> Contact does not exist")
raise error logger.warning(error)
return self.get_contact_default(contact_type_choice)
else: else:
print(f"generic_contact_getter -> contacts?? {contacts}") print(f"generic_contact_getter -> contacts?? {contacts}")
# --> Map to public contact # --> Map to public contact
@ -745,9 +782,7 @@ class Domain(TimeStampedModel, DomainHelper):
raise ValueError("No contact was found in cache or the registry") raise ValueError("No contact was found in cache or the registry")
# Convert it from an EppLib object to PublicContact # Convert it from an EppLib object to PublicContact
return self.map_epp_contact_to_public_contact( return cached_contact
cached_contact, contact_type_choice
)
def get_default_security_contact(self): def get_default_security_contact(self):
"""Gets the default security contact.""" """Gets the default security contact."""
@ -781,19 +816,17 @@ class Domain(TimeStampedModel, DomainHelper):
For example, check_type = 'security' For example, check_type = 'security'
""" """
for contact in contacts: for contact in contacts:
print(f"grab_contact_in_keys -> contact item {contact}") print(f"grab_contact_in_keys -> contact item {contact.__dict__}")
if ( if (
isinstance(contact, dict) isinstance(contact, PublicContact)
and "id" in contact.keys() and contact.registry_id is not None
and "type" in contact.keys() and contact.contact_type is not None
and contact["type"] == check_type and contact.contact_type == check_type
): ):
item = PublicContact( return contact
registry_id=contact["id"],
contact_type=contact["type"], # If the for loop didn't do a return,
) # then we know that it doesn't exist within cache
full_contact = self._request_contact_info(item)
return full_contact
# ForeignKey on UserDomainRole creates a "permissions" member for # ForeignKey on UserDomainRole creates a "permissions" member for
# all of the user-roles that are in place for this domain # all of the user-roles that are in place for this domain
@ -1075,10 +1108,11 @@ class Domain(TimeStampedModel, DomainHelper):
"tr_date": getattr(data, "tr_date", ...), "tr_date": getattr(data, "tr_date", ...),
"up_date": getattr(data, "up_date", ...), "up_date": getattr(data, "up_date", ...),
} }
print(f"precleaned stuff {cache}")
# remove null properties (to distinguish between "a value of None" and null) # remove null properties (to distinguish between "a value of None" and null)
cleaned = {k: v for k, v in cache.items() if v is not ...} cleaned = {k: v for k, v in cache.items() if v is not ...}
l = getattr(data, "contacts", ...)
logger.debug(f"here are the contacts {l}")
# statuses can just be a list no need to keep the epp object # statuses can just be a list no need to keep the epp object
if "statuses" in cleaned.keys(): if "statuses" in cleaned.keys():
cleaned["statuses"] = [status.state for status in cleaned["statuses"]] cleaned["statuses"] = [status.state for status in cleaned["statuses"]]
@ -1090,7 +1124,12 @@ class Domain(TimeStampedModel, DomainHelper):
registry_id=cleaned["registrant"], registry_id=cleaned["registrant"],
contact_type=PublicContact.ContactTypeChoices.REGISTRANT, contact_type=PublicContact.ContactTypeChoices.REGISTRANT,
) )
cleaned["registrant"] = self._request_contact_info(contact) # Grabs the expanded contact
full_object = self._request_contact_info(contact)
# Maps it to type PublicContact
cleaned["registrant"] = self.map_epp_contact_to_public_contact(
full_object, contact.registry_id, contact.contact_type
)
except RegistryError: except RegistryError:
cleaned["registrant"] = None cleaned["registrant"] = None
# get contact info, if there are any # get contact info, if there are any
@ -1100,6 +1139,7 @@ class Domain(TimeStampedModel, DomainHelper):
and isinstance(cleaned["_contacts"], list) and isinstance(cleaned["_contacts"], list)
and len(cleaned["_contacts"]) and len(cleaned["_contacts"])
): ):
logger.debug("hit!")
cleaned["contacts"] = [] cleaned["contacts"] = []
for domainContact in cleaned["_contacts"]: for domainContact in cleaned["_contacts"]:
# we do not use _get_or_create_* because we expect the object we # we do not use _get_or_create_* because we expect the object we
@ -1111,26 +1151,10 @@ class Domain(TimeStampedModel, DomainHelper):
req = commands.InfoContact(id=domainContact.contact) req = commands.InfoContact(id=domainContact.contact)
data = registry.send(req, cleaned=True).res_data[0] data = registry.send(req, cleaned=True).res_data[0]
# extract properties from response
# (Ellipsis is used to mean "null")
# convert this to use PublicContactInstead
contact = {
"id": domainContact.contact,
"type": domainContact.type,
"auth_info": getattr(data, "auth_info", ...),
"cr_date": getattr(data, "cr_date", ...),
"disclose": getattr(data, "disclose", ...),
"email": getattr(data, "email", ...),
"fax": getattr(data, "fax", ...),
"postal_info": getattr(data, "postal_info", ...),
"statuses": getattr(data, "statuses", ...),
"tr_date": getattr(data, "tr_date", ...),
"up_date": getattr(data, "up_date", ...),
"voice": getattr(data, "voice", ...),
}
cleaned["contacts"].append( cleaned["contacts"].append(
{k: v for k, v in contact.items() if v is not ...} self.map_epp_contact_to_public_contact(
data, domainContact.contact, domainContact.type
)
) )
# get nameserver info, if there are any # get nameserver info, if there are any
@ -1182,6 +1206,8 @@ class Domain(TimeStampedModel, DomainHelper):
) )
if property in self._cache: if property in self._cache:
logger.debug("hit here also!!")
logger.debug(self._cache[property])
return self._cache[property] return self._cache[property]
else: else:
raise KeyError( raise KeyError(

View file

@ -557,25 +557,25 @@ class MockEppLib(TestCase):
self.hosts = hosts self.hosts = hosts
self.registrant = registrant self.registrant = registrant
def dummyInfoContactResultData(self, id, email, contact_type): def dummyInfoContactResultData(id, email):
fake = info.InfoContactResultData( fake = info.InfoContactResultData(
id=id, id=id,
postal_info=common.PostalInfo( postal_info=common.PostalInfo(
name="Robert The Villain", name="Registry Customer Service",
addr=common.ContactAddr( addr=common.ContactAddr(
street=["street1", "street2", "street3"], street=["4200 Wilson Blvd."],
city="city", city="Arlington",
pc="pc", pc="VA",
cc="cc", cc="US",
sp="sp", sp="22201",
), ),
org="Skim Milk", org="Cybersecurity and Infrastructure Security Agency",
type="type", type="type",
), ),
voice="voice", voice="+1.8882820870",
fax="+1-212-9876543", fax="+1-212-9876543",
email=email, email=email,
auth_info=common.ContactAuthInfo(pw="fakepw"), auth_info=common.ContactAuthInfo(pw="thisisnotapassword"),
roid=..., roid=...,
statuses=[], statuses=[],
cl_id=..., cl_id=...,
@ -591,9 +591,13 @@ class MockEppLib(TestCase):
) )
return fake return fake
mockSecurityContact = dummyInfoContactResultData("securityContact", "security@mail.gov")
mockTechnicalContact = dummyInfoContactResultData("technicalContact", "tech@mail.gov")
mockAdministrativeContact = dummyInfoContactResultData("administrativeContact", "admin@mail.gov")
mockRegistrantContact = dummyInfoContactResultData("registrantContact", "registrant@mail.gov")
mockDataInfoDomain = fakedEppObject( mockDataInfoDomain = fakedEppObject(
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=datetime.datetime(2023, 8, 25, 19, 45, 35),
contacts=[common.DomainContact(contact="123", type="security")], contacts=[common.DomainContact(contact="123", type="security")],
hosts=["fake.host.com"], hosts=["fake.host.com"],
) )
@ -601,12 +605,12 @@ class MockEppLib(TestCase):
"fakepw", "fakepw",
cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35), cr_date=datetime.datetime(2023, 5, 25, 19, 45, 35),
contacts=[ contacts=[
common.DomainContact(contact="security", type="security"), common.DomainContact(contact="securityContact", type="security"),
common.DomainContact(contact="admin", type="admin"), common.DomainContact(contact="administrativeContact", type="admin"),
common.DomainContact(contact="tech", type="tech"), common.DomainContact(contact="technicalContact", type="tech"),
], ],
hosts=["fake.host.com"], hosts=["fake.host.com"],
registrant="registrant", registrant="registrantContact",
) )
infoDomainNoContact = fakedEppObject( infoDomainNoContact = fakedEppObject(
"security", "security",
@ -632,12 +636,20 @@ class MockEppLib(TestCase):
elif getattr(_request, "name", None) == "freeman.gov": elif getattr(_request, "name", None) == "freeman.gov":
return MagicMock(res_data=[self.InfoDomainWithContacts]) return MagicMock(res_data=[self.InfoDomainWithContacts])
elif isinstance(_request, commands.InfoContact): elif isinstance(_request, commands.InfoContact):
# Default contact return
mocked_result = self.mockDataInfoContact mocked_result = self.mockDataInfoContact
if getattr(_request, "id", None) in PublicContact.ContactTypeChoices: # For testing contact types...
desired_type = getattr(_request, "id", None) l = getattr(_request, "id", None)
mocked_result = self.dummyInfoContactResultData( logger.debug(f"get l'd {l}")
id=desired_type, email=f"{desired_type}@mail.gov" match getattr(_request, "id", None):
) case "securityContact":
mocked_result = self.mockSecurityContact
case "technicalContact":
mocked_result = self.mockTechnicalContact
case "administrativeContact":
mocked_result = self.mockAdministrativeContact
case "registrantContact":
mocked_result = self.mockRegistrantContact
return MagicMock(res_data=[mocked_result]) return MagicMock(res_data=[mocked_result])
elif ( elif (

View file

@ -185,6 +185,8 @@ class TestDomainCreation(TestCase):
DomainInformation.objects.all().delete() DomainInformation.objects.all().delete()
DomainApplication.objects.all().delete() DomainApplication.objects.all().delete()
Domain.objects.all().delete() Domain.objects.all().delete()
User.objects.all().delete()
DraftDomain.objects.all().delete()
class TestRegistrantContacts(MockEppLib): class TestRegistrantContacts(MockEppLib):
@ -201,6 +203,10 @@ class TestRegistrantContacts(MockEppLib):
def tearDown(self): def tearDown(self):
super().tearDown() super().tearDown()
PublicContact.objects.all().delete()
DomainInformation.objects.all().delete()
DomainApplication.objects.all().delete()
Domain.objects.all().delete()
# self.contactMailingAddressPatch.stop() # self.contactMailingAddressPatch.stop()
# self.createContactPatch.stop() # self.createContactPatch.stop()
@ -448,61 +454,115 @@ class TestRegistrantContacts(MockEppLib):
""" """
raise raise
@skip("not implemented yet")
def test_contact_getters_cache(self): def test_contact_getters_cache(self):
""" """
Scenario: A user is grabbing a domain that has multiple contact objects Scenario: A user is grabbing a domain that has multiple contact objects
When each contact is retrieved from cache When each contact is retrieved from cache
Then the user retrieves the correct contact objects Then the user retrieves the correct contact objects
""" """
domain, _ = Domain.objects.get_or_create(name="freeman.gov") @skip("not implemented yet")
def test_epp_public_contact_mapper(self):
pass
def test_contact_getter_security(self):
domain_contacts, _ = Domain.objects.get_or_create(name="freeman.gov")
self.maxDiff = None
security = PublicContact.get_default_security() security = PublicContact.get_default_security()
security.email = "security@mail.gov" security.email = "security@mail.gov"
security.domain = domain security.domain = domain_contacts
security.save() security.save()
expected_security_contact = security expected_security_contact = security
domain.security_contact = security
expected_security_contact = domain_contacts.map_epp_contact_to_public_contact(
self.mockSecurityContact, "securityContact", "security"
)
domain_contacts.security_contact = security
contact_dict = domain_contacts.security_contact.__dict__
expected_dict = expected_security_contact.__dict__
contact_dict.pop('_state')
expected_dict.pop('_state')
self.assertEqual(contact_dict, expected_dict)
def test_contact_getter_technical(self):
domain_contacts, _ = Domain.objects.get_or_create(name="freeman.gov")
technical = PublicContact.get_default_technical() technical = PublicContact.get_default_technical()
technical.email = "technical@mail.gov" technical.email = "tech@mail.gov"
technical.domain = domain technical.domain = domain_contacts
technical.save() technical.save()
expected_technical_contact = technical
domain.technical_contact = technical expected_technical_contact = domain_contacts.map_epp_contact_to_public_contact(
self.mockTechnicalContact, "technicalContact", "tech"
)
domain_contacts.technical_contact = technical
contact_dict = domain_contacts.technical_contact.__dict__
expected_dict = expected_technical_contact.__dict__
# There has to be a better way to do this.
# Since Cache creates a new object, it causes
# a desync between each instance. Basically,
# these two objects will never be the same.
contact_dict.pop('_state')
expected_dict.pop('_state')
self.assertEqual(contact_dict, expected_dict)
def test_contact_getter_administrative(self):
self.maxDiff = None
domain_contacts, _ = Domain.objects.get_or_create(name="freeman.gov")
administrative = PublicContact.get_default_administrative() administrative = PublicContact.get_default_administrative()
administrative.email = "administrative@mail.gov" administrative.email = "admin@mail.gov"
administrative.domain = domain administrative.domain = domain_contacts
administrative.save() administrative.save()
expected_administrative_contact = administrative
domain.administrative_contact = administrative expected_administrative_contact = domain_contacts.map_epp_contact_to_public_contact(
self.mockAdministrativeContact, "administrativeContact", "admin"
)
domain_contacts.administrative_contact = administrative
contact_dict = domain_contacts.administrative_contact.__dict__
expected_dict = expected_administrative_contact.__dict__
contact_dict.pop('_state')
expected_dict.pop('_state')
self.assertEqual(contact_dict, expected_dict)
def test_contact_getter_registrant(self):
domain_contacts, _ = Domain.objects.get_or_create(name="freeman.gov")
registrant = PublicContact.get_default_registrant() registrant = PublicContact.get_default_registrant()
registrant.email = "registrant@mail.gov" registrant.email = "registrant@mail.gov"
registrant.domain = domain registrant.domain = domain_contacts
registrant.save() registrant.save()
expected_registrant_contact = registrant expected_registrant_contact = registrant
domain.registrant_contact = registrant domain_contacts.registrant_contact = registrant
logger.debug(f"domain obj: {domain.security_contact.__dict__}") expected_registrant_contact = domain_contacts.map_epp_contact_to_public_contact(
logger.debug(f"expected: {expected_security_contact.__dict__}") self.mockRegistrantContact, "registrantContact", "registrant"
self.assertEqual(domain.security_contact, expected_security_contact) )
self.assertEqual(domain.technical_contact, expected_technical_contact)
self.assertEqual(domain.administrative_contact, expected_administrative_contact)
self.assertEqual(domain.registrant_contact, expected_registrant_contact)
@skip("not implemented yet") domain_contacts.registrant_contact = registrant
def test_contact_getters_registry(self):
""" contact_dict = domain_contacts.registrant_contact.__dict__
Scenario: A user is grabbing a domain that has multiple contact objects expected_dict = expected_registrant_contact.__dict__
When the domain is retrieved from cache
Then the user retrieves the correct domain object contact_dict.pop('_state')
""" expected_dict.pop('_state')
# Create something using infocontact for that domain
# Then just grab the domain object normally self.assertEqual(contact_dict, expected_dict)
# That 'something' doesn't exist on the local domain,
# so registry should be called
raise
class TestRegistrantNameservers(TestCase): class TestRegistrantNameservers(TestCase):