Merge pull request #1619 from cisagov/es/1535-update-security-email-disclose

#1535 Update disclose on domain security emails
This commit is contained in:
Erin Song 2024-01-18 16:59:05 -08:00 committed by GitHub
commit 5e1f99eae6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 129 additions and 2 deletions

View file

@ -0,0 +1,69 @@
""""
Converts all ready and DNS needed domains with a non-default public contact
to disclose their public contact. Created for Issue#1535 to resolve
disclose issue of domains with missing security emails.
"""
import logging
import copy
from django.core.management import BaseCommand
from registrar.models import Domain
logger = logging.getLogger(__name__)
class Command(BaseCommand):
help = "Disclose all nondefault domain security emails."
def __init__(self):
"""Sets global variables for code tidiness"""
super().__init__()
# domains with errors, which are not successfully updated to disclose
self.domains_with_errors: list[str] = []
# domains that are successfully disclosed
self.disclosed_domain_contacts_count = 0
# domains that skip disclose due to having contact registrar@dotgov.gov
self.skipped_domain_contacts_count = 0
def handle(self, **options):
"""
Converts all ready and DNS needed domains with a non-default public contact
to disclose their public contact.
"""
logger.info("Updating security emails to public")
# Initializes domains that need to be disclosed
statuses = [Domain.State.READY, Domain.State.DNS_NEEDED]
domains = Domain.objects.filter(state__in=statuses)
logger.info(f"Found {len(domains)} domains with status Ready or DNS Needed.")
# Update EPP contact for domains with a security contact
for domain in domains:
try:
contact = domain.security_contact # noqa on these items as we only want to call security_contact
logger.info(f"Domain {domain.name} security contact: {domain.security_contact.email}")
if domain.security_contact.email != "registrar@dotgov.gov":
domain._update_epp_contact(contact=domain.security_contact)
self.disclosed_domain_contacts_count += 1
else:
logger.info(
f"Skipping disclose for {domain.name} security contact {domain.security_contact.email}."
)
self.skipped_domain_contacts_count += 1
except Exception as err:
# error condition if domain not in database
self.domains_with_errors.append(copy.deepcopy(domain.name))
logger.error(f"error retrieving domain {domain.name} contact {domain.security_contact}: {err}")
# Inform user how many contacts were disclosed, skipped, and errored
logger.info(f"Updated {self.disclosed_domain_contacts_count} contacts to disclosed.")
logger.info(
f"Skipped disclosing {self.skipped_domain_contacts_count} contacts with security email "
f"registrar@dotgov.gov."
)
logger.info(
f"Error disclosing the following {len(self.domains_with_errors)} contacts: {self.domains_with_errors}"
)

View file

@ -1396,11 +1396,13 @@ class Domain(TimeStampedModel, DomainHelper):
def _disclose_fields(self, contact: PublicContact):
"""creates a disclose object that can be added to a contact Create using
.disclose= <this function> on the command before sending.
if item is security email then make sure email is visable"""
if item is security email then make sure email is visible"""
is_security = contact.contact_type == contact.ContactTypeChoices.SECURITY
DF = epp.DiscloseField
fields = {DF.EMAIL}
disclose = is_security and contact.email != PublicContact.get_default_security().email
# Delete after testing on other devices
logger.info("Updated domain contact %s to disclose: %s", contact.email, disclose)
# Will only disclose DF.EMAIL if its not the default
return epp.Disclose(
flag=disclose,

View file

@ -11,9 +11,11 @@ from registrar.models import (
DomainInformation,
UserDomainRole,
)
from registrar.models.public_contact import PublicContact
from django.core.management import call_command
from unittest.mock import patch
from unittest.mock import patch, call
from epplibwrapper import commands, common
from .common import MockEppLib
@ -441,3 +443,57 @@ class TestExtendExpirationDates(MockEppLib):
# Explicitly test the expiration date - should be the same
self.assertEqual(desired_domain.expiration_date, datetime.date(2024, 11, 15))
class TestDiscloseEmails(MockEppLib):
def setUp(self):
super().setUp()
def tearDown(self):
super().tearDown()
PublicContact.objects.all().delete()
Domain.objects.all().delete()
def run_disclose_security_emails(self):
"""
This method executes the disclose_security_emails command.
The 'call_command' function from Django's management framework is then used to
execute the disclose_security_emails command.
"""
with patch(
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
return_value=True,
):
call_command("disclose_security_emails")
def test_disclose_security_emails(self):
"""
Tests that command disclose_security_emails runs successfully with
appropriate EPP calll to UpdateContact.
"""
domain, _ = Domain.objects.get_or_create(name="testdisclose.gov", state=Domain.State.READY)
expectedSecContact = PublicContact.get_default_security()
expectedSecContact.domain = domain
expectedSecContact.email = "123@mail.gov"
# set domain security email to 123@mail.gov instead of default email
domain.security_contact = expectedSecContact
self.run_disclose_security_emails()
# running disclose_security_emails sends EPP call UpdateContact with disclose
self.mockedSendFunction.assert_has_calls(
[
call(
commands.UpdateContact(
id=domain.security_contact.registry_id,
postal_info=domain._make_epp_contact_postal_info(contact=domain.security_contact),
email=domain.security_contact.email,
voice=domain.security_contact.voice,
fax=domain.security_contact.fax,
auth_info=common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
disclose=domain._disclose_fields(contact=domain.security_contact),
),
cleaned=True,
)
]
)