mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-26 04:28:39 +02:00
Merge pull request #1619 from cisagov/es/1535-update-security-email-disclose
#1535 Update disclose on domain security emails
This commit is contained in:
commit
5e1f99eae6
3 changed files with 129 additions and 2 deletions
|
@ -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}"
|
||||||
|
)
|
|
@ -1396,11 +1396,13 @@ class Domain(TimeStampedModel, DomainHelper):
|
||||||
def _disclose_fields(self, contact: PublicContact):
|
def _disclose_fields(self, contact: PublicContact):
|
||||||
"""creates a disclose object that can be added to a contact Create using
|
"""creates a disclose object that can be added to a contact Create using
|
||||||
.disclose= <this function> on the command before sending.
|
.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
|
is_security = contact.contact_type == contact.ContactTypeChoices.SECURITY
|
||||||
DF = epp.DiscloseField
|
DF = epp.DiscloseField
|
||||||
fields = {DF.EMAIL}
|
fields = {DF.EMAIL}
|
||||||
disclose = is_security and contact.email != PublicContact.get_default_security().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
|
# Will only disclose DF.EMAIL if its not the default
|
||||||
return epp.Disclose(
|
return epp.Disclose(
|
||||||
flag=disclose,
|
flag=disclose,
|
||||||
|
|
|
@ -11,9 +11,11 @@ from registrar.models import (
|
||||||
DomainInformation,
|
DomainInformation,
|
||||||
UserDomainRole,
|
UserDomainRole,
|
||||||
)
|
)
|
||||||
|
from registrar.models.public_contact import PublicContact
|
||||||
|
|
||||||
from django.core.management import call_command
|
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
|
from .common import MockEppLib
|
||||||
|
|
||||||
|
@ -441,3 +443,57 @@ class TestExtendExpirationDates(MockEppLib):
|
||||||
|
|
||||||
# Explicitly test the expiration date - should be the same
|
# Explicitly test the expiration date - should be the same
|
||||||
self.assertEqual(desired_domain.expiration_date, datetime.date(2024, 11, 15))
|
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,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue