mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-22 18:56:15 +02:00
added security_contact_registry_id to domain model; modified fetch_cache to write to db; modified getter for security_contact to failover to db if epp down
This commit is contained in:
parent
ed7868efba
commit
274e4951ac
3 changed files with 105 additions and 9 deletions
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 4.2.7 on 2023-12-23 01:31
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("registrar", "0058_delete_nameserver"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="domain",
|
||||||
|
name="security_contact_registry_id",
|
||||||
|
field=models.TextField(
|
||||||
|
editable=False,
|
||||||
|
help_text="Duplication of registry's security contact id for when registry unavailable",
|
||||||
|
null=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -31,7 +31,7 @@ from epplibwrapper import (
|
||||||
|
|
||||||
from registrar.models.utility.contact_error import ContactError, ContactErrorCodes
|
from registrar.models.utility.contact_error import ContactError, ContactErrorCodes
|
||||||
|
|
||||||
from django.db.models import DateField
|
from django.db.models import DateField, TextField
|
||||||
from .utility.domain_field import DomainField
|
from .utility.domain_field import DomainField
|
||||||
from .utility.domain_helper import DomainHelper
|
from .utility.domain_helper import DomainHelper
|
||||||
from .utility.time_stamped_model import TimeStampedModel
|
from .utility.time_stamped_model import TimeStampedModel
|
||||||
|
@ -972,6 +972,12 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
help_text=("Duplication of registry's expiration date saved for ease of reporting"),
|
help_text=("Duplication of registry's expiration date saved for ease of reporting"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
security_contact_registry_id = TextField(
|
||||||
|
null=True,
|
||||||
|
help_text=("Duplication of registry's security contact id for when registry unavailable"),
|
||||||
|
editable=False,
|
||||||
|
)
|
||||||
|
|
||||||
def isActive(self):
|
def isActive(self):
|
||||||
return self.state == Domain.State.CREATED
|
return self.state == Domain.State.CREATED
|
||||||
|
|
||||||
|
@ -1113,15 +1119,21 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
# Grab from cache
|
# Grab from cache
|
||||||
contacts = self._get_property(desired_property)
|
contacts = self._get_property(desired_property)
|
||||||
except KeyError as error:
|
except KeyError as error:
|
||||||
logger.error(f"Could not find {contact_type_choice}: {error}")
|
# if contact type is security, attempt to retrieve registry id
|
||||||
return None
|
# for the security contact from domain.security_contact_registry_id
|
||||||
else:
|
if contact_type_choice == PublicContact.ContactTypeChoices.SECURITY and self.security_contact_registry_id:
|
||||||
cached_contact = self.get_contact_in_keys(contacts, contact_type_choice)
|
logger.info(self.security_contact_registry_id)
|
||||||
if cached_contact is None:
|
contacts = {PublicContact.ContactTypeChoices.SECURITY: self.security_contact_registry_id}
|
||||||
# TODO - #1103
|
else:
|
||||||
raise ContactError("No contact was found in cache or the registry")
|
logger.error(f"Could not find {contact_type_choice}: {error}")
|
||||||
|
return None
|
||||||
|
|
||||||
return cached_contact
|
cached_contact = self.get_contact_in_keys(contacts, contact_type_choice)
|
||||||
|
if cached_contact is None:
|
||||||
|
# TODO - #1103
|
||||||
|
raise ContactError("No contact was found in cache or the registry")
|
||||||
|
|
||||||
|
return cached_contact
|
||||||
|
|
||||||
def get_default_security_contact(self):
|
def get_default_security_contact(self):
|
||||||
"""Gets the default security contact."""
|
"""Gets the default security contact."""
|
||||||
|
@ -1609,6 +1621,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
cleaned = self._clean_cache(cache, data_response)
|
cleaned = self._clean_cache(cache, data_response)
|
||||||
self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts)
|
self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts)
|
||||||
self._update_hosts_and_ips_in_db(cleaned, fetch_hosts)
|
self._update_hosts_and_ips_in_db(cleaned, fetch_hosts)
|
||||||
|
self._update_security_contact_in_db(cleaned, fetch_contacts)
|
||||||
self._update_dates(cleaned)
|
self._update_dates(cleaned)
|
||||||
|
|
||||||
self._cache = cleaned
|
self._cache = cleaned
|
||||||
|
@ -1715,6 +1728,24 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
for ip_address in cleaned_ips:
|
for ip_address in cleaned_ips:
|
||||||
HostIP.objects.get_or_create(address=ip_address, host=host_in_db)
|
HostIP.objects.get_or_create(address=ip_address, host=host_in_db)
|
||||||
|
|
||||||
|
def _update_security_contact_in_db(self, cleaned, fetch_contacts):
|
||||||
|
"""Update security contact registry id in database if retrieved from registry.
|
||||||
|
If no value is retrieved from registry, set to empty string in db.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
self: the domain to be updated with security from cleaned
|
||||||
|
cleaned: dict containing contact registry ids. Security contact is of type
|
||||||
|
PublicContact.ContactTypeChoices.SECURITY
|
||||||
|
fetch_contacts: boolean indicating whether or not fetch_contacts was called
|
||||||
|
"""
|
||||||
|
if fetch_contacts:
|
||||||
|
cleaned_contacts = cleaned["contacts"]
|
||||||
|
security_contact_registry_id = ""
|
||||||
|
if cleaned_contacts[PublicContact.ContactTypeChoices.SECURITY]:
|
||||||
|
security_contact_registry_id = cleaned_contacts[PublicContact.ContactTypeChoices.SECURITY]
|
||||||
|
self.security_contact_registry_id = security_contact_registry_id
|
||||||
|
self.save()
|
||||||
|
|
||||||
def _update_dates(self, cleaned):
|
def _update_dates(self, cleaned):
|
||||||
"""Update dates (expiration and creation) from cleaned"""
|
"""Update dates (expiration and creation) from cleaned"""
|
||||||
requires_save = False
|
requires_save = False
|
||||||
|
|
|
@ -711,6 +711,50 @@ class TestRegistrantContacts(MockEppLib):
|
||||||
self.mockedSendFunction.assert_has_calls(expected_calls, any_order=True)
|
self.mockedSendFunction.assert_has_calls(expected_calls, any_order=True)
|
||||||
self.assertEqual(PublicContact.objects.filter(domain=self.domain).count(), 1)
|
self.assertEqual(PublicContact.objects.filter(domain=self.domain).count(), 1)
|
||||||
|
|
||||||
|
def test_security_email_returns_on_registry_error(self):
|
||||||
|
"""
|
||||||
|
Scenario: Security email previously set through EPP and stored in registrar's database.
|
||||||
|
Registry is unavailable and throws exception when attempting to build cache from
|
||||||
|
registry. Security email retrieved from database.
|
||||||
|
"""
|
||||||
|
# Use self.domain_contact which has been initialized with existing contacts, including securityContact
|
||||||
|
|
||||||
|
# call get_security_email to initially set the security_contact_registry_id in the domain model
|
||||||
|
self.domain_contact.get_security_email()
|
||||||
|
# invalidate the cache so the next time get_security_email is called, it has to attempt to populate cache
|
||||||
|
self.domain_contact._invalidate_cache()
|
||||||
|
|
||||||
|
# mock that registry throws an error on the EPP send
|
||||||
|
def side_effect(_request, cleaned):
|
||||||
|
raise RegistryError(code=ErrorCode.COMMAND_FAILED)
|
||||||
|
|
||||||
|
patcher = patch("registrar.models.domain.registry.send")
|
||||||
|
mocked_send = patcher.start()
|
||||||
|
mocked_send.side_effect = side_effect
|
||||||
|
|
||||||
|
# when get_security_email is called, the registry error will force the security contact
|
||||||
|
# to be retrieved using the security_contact_registry_id in the domain model
|
||||||
|
security_email = self.domain_contact.get_security_email()
|
||||||
|
|
||||||
|
# assert that the proper security contact was retrieved by testing the email matches expected value
|
||||||
|
self.assertEqual(security_email, "security@mail.gov")
|
||||||
|
patcher.stop()
|
||||||
|
|
||||||
|
def test_security_email_stored_on_fetch_cache(self):
|
||||||
|
"""
|
||||||
|
Scenario: Security email is stored in db when security contact is retrieved from fetch_cache.
|
||||||
|
Verify the success of this by asserting get_or_create calls to db.
|
||||||
|
The mocked data for the EPP calls for the freeman.gov domain returns a security
|
||||||
|
contact with registry id of securityContact when InfoContact is called
|
||||||
|
"""
|
||||||
|
# Use self.domain_contact which has been initialized with existing contacts, including securityContact
|
||||||
|
|
||||||
|
# force fetch_cache to be called, which will return above documented mocked hosts
|
||||||
|
self.domain_contact.get_security_email()
|
||||||
|
|
||||||
|
# assert that the security_contact_registry_id in the db matches "securityContact"
|
||||||
|
self.assertEqual(self.domain_contact.security_contact_registry_id, "securityContact")
|
||||||
|
|
||||||
def test_not_disclosed_on_other_contacts(self):
|
def test_not_disclosed_on_other_contacts(self):
|
||||||
"""
|
"""
|
||||||
Scenario: Registrant creates a new domain with multiple contacts
|
Scenario: Registrant creates a new domain with multiple contacts
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue