Simplify PR

Remove refactors + simplify logic
This commit is contained in:
zandercymatics 2024-10-01 09:24:48 -06:00
parent 6bb907c6bc
commit 5a96855ccc
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
14 changed files with 113 additions and 217 deletions

View file

@ -21,12 +21,6 @@ from epplibwrapper.errors import ErrorCode, RegistryError
from registrar.models.user_domain_role import UserDomainRole
from waffle.admin import FlagAdmin
from waffle.models import Sample, Switch
from registrar.utility.admin_helpers import (
get_all_action_needed_reason_emails,
get_action_needed_reason_default_email,
get_all_rejection_reason_emails,
get_rejection_reason_default_email,
)
from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website, SeniorOfficial
from registrar.utility.constants import BranchChoices
from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes

View file

@ -254,18 +254,18 @@ class DomainRequest(TimeStampedModel):
)
class RejectionReasons(models.TextChoices):
DOMAIN_PURPOSE = "purpose_not_met", "Purpose requirements not met"
REQUESTOR = "requestor_not_eligible", "Requestor not eligible to make request"
SECOND_DOMAIN_REASONING = (
DOMAIN_PURPOSE = "domain_purpose", "Purpose requirements not met"
REQUESTOR_NOT_ELIGIBLE = "requestor_not_eligible", "Requestor not eligible to make request"
ORG_HAS_DOMAIN = (
"org_has_domain",
"Org already has a .gov domain",
)
CONTACTS_OR_ORGANIZATION_LEGITIMACY = (
CONTACTS_NOT_VERIFIED = (
"contacts_not_verified",
"Org contacts couldn't be verified",
)
ORGANIZATION_ELIGIBILITY = "org_not_eligible", "Org not eligible for a .gov domain"
NAMING_REQUIREMENTS = "naming_not_met", "Naming requirements not met"
ORG_NOT_ELIGIBLE = "org_not_eligible", "Org not eligible for a .gov domain"
NAMING_REQUIREMENTS = "naming_requirements", "Naming requirements not met"
OTHER = "other", "Other/Unspecified"
@classmethod
@ -958,7 +958,7 @@ class DomainRequest(TimeStampedModel):
"""
if self.status == self.DomainRequestStatus.APPROVED:
self.delete_and_clean_up_domain("reject_with_prejudice")
self.delete_and_clean_up_domain("action_needed")
elif self.status == self.DomainRequestStatus.REJECTED:
self.rejection_reason = None

View file

@ -1,10 +0,0 @@
THANK YOU
.Gov helps the public identify official, trusted information. Thank you for requesting a .gov domain.
----------------------------------------------------------------
The .gov team
Contact us: <https://get.gov/contact/>
Learn about .gov <https://get.gov>
The .gov registry is a part of the Cybersecurity and Infrastructure Security Agency (CISA) <https://cisa.gov/>

View file

@ -1,8 +0,0 @@
Hi, {{ recipient.first_name }}.
Your .gov domain request has been rejected.
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
REQUEST RECEIVED ON: {{ domain_request.last_submitted_date|date }}
STATUS: Rejected
----------------------------------------------------------------

View file

@ -1,8 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because we could not verify the organizational
contacts you provided. If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -1,15 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because it does not meet our naming requirements.
Domains should uniquely identify a government organization and be clear to the
general public. Learn more about naming requirements for your type of organization
<https://get.gov/domains/choosing/>.
YOU CAN SUBMIT A NEW REQUEST
We encourage you to request a domain that meets our requirements. If you have
questions or want to discuss potential domain names, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -1,15 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because {{ domain_request.organization_name }} has a .gov domain. Our
practice is to approve one domain per online service per government organization. We
evaluate additional requests on a case-by-case basis. You did not provide sufficient
justification for an additional domain.
Read more about our practice of approving one domain per online service
<https://get.gov/domains/before/#one-domain-per-service>.
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -1,14 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because we determined that {{ domain_request.organization_name }} is not
eligible for a .gov domain. .Gov domains are only available to official U.S.-based
government organizations.
Learn more about eligibility for .gov domains
<https://get.gov/domains/eligibility/>.
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -1,15 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because the purpose you provided did not meet our
requirements. You didnt provide enough information about how you intend to use the
domain.
Learn more about:
- Eligibility for a .gov domain <https://get.gov/domains/eligibility>
- What you can and cant do with .gov domains <https://get.gov/domains/requirements/>
If you have questions or comments, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -1,14 +0,0 @@
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
{% include "emails/includes/status_change_rejected_header.txt" %}
REJECTION REASON
Your domain request was rejected because we dont believe youre eligible to request a
.gov domain on behalf of {{ domain_request.organization_name }}. You must be a government employee, or be
working on behalf of a government organization, to request a .gov domain.
DEMONSTRATE ELIGIBILITY
If you can provide more information that demonstrates your eligibility, or you want to
discuss further, reply to this email.
{% include "emails/includes/email_footer.txt" %}
{% endautoescape %}

View file

@ -8,8 +8,8 @@ REQUEST RECEIVED ON: {{ domain_request.last_submitted_date|date }}
STATUS: Rejected
----------------------------------------------------------------
{% if domain_request.rejection_reason != 'other' %}
REJECTION REASON{% endif %}{% if domain_request.rejection_reason == 'purpose_not_met' %}
{% if reason != domain_request.RejectionReasons.DOMAIN_PURPOSE.OTHER %}
REJECTION REASON{% endif %}{% if reason == domain_request.RejectionReasons.DOMAIN_PURPOSE %}
Your domain request was rejected because the purpose you provided did not meet our
requirements. You didnt provide enough information about how you intend to use the
domain.
@ -18,7 +18,7 @@ Learn more about:
- Eligibility for a .gov domain <https://get.gov/domains/eligibility>
- What you can and cant do with .gov domains <https://get.gov/domains/requirements/>
If you have questions or comments, reply to this email.{% elif domain_request.rejection_reason == 'requestor_not_eligible' %}
If you have questions or comments, reply to this email.{% elif reason == domain_request.RejectionReasons.DOMAIN_PURPOSE.REQUESTOR_NOT_ELIGIBLE %}
Your domain request was rejected because we dont believe youre eligible to request a
.gov domain on behalf of {{ domain_request.organization_name }}. You must be a government employee, or be
working on behalf of a government organization, to request a .gov domain.
@ -26,7 +26,7 @@ working on behalf of a government organization, to request a .gov domain.
DEMONSTRATE ELIGIBILITY
If you can provide more information that demonstrates your eligibility, or you want to
discuss further, reply to this email.{% elif domain_request.rejection_reason == 'org_has_domain' %}
discuss further, reply to this email.{% elif reason == domain_request.RejectionReasons.DOMAIN_PURPOSE.ORG_HAS_DOMAIN %}
Your domain request was rejected because {{ domain_request.organization_name }} has a .gov domain. Our
practice is to approve one domain per online service per government organization. We
evaluate additional requests on a case-by-case basis. You did not provide sufficient
@ -35,9 +35,9 @@ justification for an additional domain.
Read more about our practice of approving one domain per online service
<https://get.gov/domains/before/#one-domain-per-service>.
If you have questions or comments, reply to this email.{% elif domain_request.rejection_reason == 'contacts_not_verified' %}
If you have questions or comments, reply to this email.{% elif reason == 'contacts_not_verified' %}
Your domain request was rejected because we could not verify the organizational
contacts you provided. If you have questions or comments, reply to this email.{% elif domain_request.rejection_reason == 'org_not_eligible' %}
contacts you provided. If you have questions or comments, reply to this email.{% elif reason == domain_request.RejectionReasons.DOMAIN_PURPOSE.ORG_NOT_ELIGIBLE %}
Your domain request was rejected because we determined that {{ domain_request.organization_name }} is not
eligible for a .gov domain. .Gov domains are only available to official U.S.-based
government organizations.
@ -46,7 +46,7 @@ Learn more about eligibility for .gov domains
<https://get.gov/domains/eligibility/>.
If you have questions or comments, reply to this email.
{% elif domain_request.rejection_reason == 'naming_not_met' %}
{% elif reason == domain_request.RejectionReasons.DOMAIN_PURPOSE.NAMING_NOT_MET %}
Your domain request was rejected because it does not meet our naming requirements.
Domains should uniquely identify a government organization and be clear to the
general public. Learn more about naming requirements for your type of organization
@ -55,7 +55,7 @@ general public. Learn more about naming requirements for your type of organizati
YOU CAN SUBMIT A NEW REQUEST
We encourage you to request a domain that meets our requirements. If you have
questions or want to discuss potential domain names, reply to this email.{% elif domain_request.rejection_reason == 'other' %}
questions or want to discuss potential domain names, reply to this email.{% elif reason == domain_request.RejectionReasons.DOMAIN_PURPOSE.OTHER %}
YOU CAN SUBMIT A NEW REQUEST
If your organization is eligible for a .gov domain and you meet our other requirements, you can submit a new request.

View file

@ -595,7 +595,12 @@ class TestDomainRequestAdmin(MockEppLib):
@less_console_noise_decorator
def transition_state_and_send_email(
self, domain_request, status, rejection_reason=None, action_needed_reason=None, action_needed_reason_email=None
self,
domain_request,
status,
rejection_reason=None,
rejection_reason_email=None,
action_needed_reason=None, action_needed_reason_email=None
):
"""Helper method for the email test cases."""
@ -613,6 +618,9 @@ class TestDomainRequestAdmin(MockEppLib):
if rejection_reason:
domain_request.rejection_reason = rejection_reason
if rejection_reason_email:
domain_request.rejection_reason_email = rejection_reason_email
if action_needed_reason:
domain_request.action_needed_reason = action_needed_reason
@ -632,6 +640,7 @@ class TestDomainRequestAdmin(MockEppLib):
with less_console_noise():
# Access the arguments passed to send_email
call_args = self.mock_client.EMAILS_SENT
logger.info(f"what are the call args? {call_args}")
kwargs = call_args[email_index]["kwargs"]
# Retrieve the email details from the arguments
@ -757,55 +766,85 @@ class TestDomainRequestAdmin(MockEppLib):
)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 6)
# def test_action_needed_sends_reason_email_prod_bcc(self):
# """When an action needed reason is set, an email is sent out and help@get.gov
# is BCC'd in production"""
# # Ensure there is no user with this email
# EMAIL = "mayor@igorville.gov"
# BCC_EMAIL = settings.DEFAULT_FROM_EMAIL
# User.objects.filter(email=EMAIL).delete()
# in_review = DomainRequest.DomainRequestStatus.IN_REVIEW
# action_needed = DomainRequest.DomainRequestStatus.ACTION_NEEDED
@override_settings(IS_PRODUCTION=True)
@less_console_noise_decorator
def test_rejected_sends_reason_email_prod_bcc(self):
"""When a rejection reason is set, an email is sent out and help@get.gov
is BCC'd in production"""
# Create fake creator
EMAIL = "meoward.jones@igorville.gov"
# # Create a sample domain request
# domain_request = completed_domain_request(status=in_review)
_creator = User.objects.create(
username="MrMeoward",
first_name="Meoward",
last_name="Jones",
email=EMAIL,
phone="(555) 123 12345",
title="Treat inspector",
)
# # Test the email sent out for already_has_domains
# already_has_domains = DomainRequest.ActionNeededReasons.ALREADY_HAS_DOMAINS
# self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=already_has_domains)
# self.assert_email_is_accurate("ORGANIZATION ALREADY HAS A .GOV DOMAIN", 0, EMAIL, bcc_email_address=BCC_EMAIL)
# self.assertEqual(len(self.mock_client.EMAILS_SENT), 1)
BCC_EMAIL = settings.DEFAULT_FROM_EMAIL
in_review = DomainRequest.DomainRequestStatus.IN_REVIEW
rejected = DomainRequest.DomainRequestStatus.REJECTED
# # Test the email sent out for bad_name
# bad_name = DomainRequest.ActionNeededReasons.BAD_NAME
# self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=bad_name)
# self.assert_email_is_accurate(
# "DOMAIN NAME DOES NOT MEET .GOV REQUIREMENTS", 1, EMAIL, bcc_email_address=BCC_EMAIL
# )
# self.assertEqual(len(self.mock_client.EMAILS_SENT), 2)
# Create a sample domain request
domain_request = completed_domain_request(status=in_review, user=_creator)
# # Test the email sent out for eligibility_unclear
# eligibility_unclear = DomainRequest.ActionNeededReasons.ELIGIBILITY_UNCLEAR
# self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=eligibility_unclear)
# self.assert_email_is_accurate(
# "ORGANIZATION MAY NOT MEET ELIGIBILITY REQUIREMENTS", 2, EMAIL, bcc_email_address=BCC_EMAIL
# )
# self.assertEqual(len(self.mock_client.EMAILS_SENT), 3)
expected_emails = {
DomainRequest.RejectionReasons.DOMAIN_PURPOSE: "You didnt provide enough information about how",
DomainRequest.RejectionReasons.REQUESTOR_NOT_ELIGIBLE: "You must be a government employee, or be",
DomainRequest.RejectionReasons.ORG_HAS_DOMAIN: "Our practice is to approve one domain",
DomainRequest.RejectionReasons.CONTACTS_NOT_VERIFIED: "we could not verify the organizational",
DomainRequest.RejectionReasons.ORG_NOT_ELIGIBLE: ".Gov domains are only available to official U.S.-based",
DomainRequest.RejectionReasons.NAMING_REQUIREMENTS: "does not meet our naming requirements",
# TODO - add back other?
#DomainRequest.RejectionReasons.OTHER: "",
}
for i, (reason, email_content) in enumerate(expected_emails.items()):
with self.subTest(reason=reason):
self.transition_state_and_send_email(domain_request, status=rejected, rejection_reason=reason)
self.assert_email_is_accurate(email_content, i, EMAIL, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), i+1)
# # Test the email sent out for questionable_so
# questionable_so = DomainRequest.ActionNeededReasons.QUESTIONABLE_SENIOR_OFFICIAL
# self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=questionable_so)
# self.assert_email_is_accurate(
# "SENIOR OFFICIAL DOES NOT MEET ELIGIBILITY REQUIREMENTS", 3, EMAIL, bcc_email_address=BCC_EMAIL
# )
# self.assertEqual(len(self.mock_client.EMAILS_SENT), 4)
# Tests if an analyst can override existing email content
domain_purpose = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
self.transition_state_and_send_email(
domain_request,
status=rejected,
rejection_reason=domain_purpose,
rejection_reason_email="custom email content",
)
# # Assert that no other emails are sent on OTHER
# other = DomainRequest.ActionNeededReasons.OTHER
# self.transition_state_and_send_email(domain_request, action_needed, action_needed_reason=other)
logger.info(f"look: {len(self.mock_client.EMAILS_SENT)}")
domain_request.refresh_from_db()
self.assert_email_is_accurate("custom email content", 6, _creator.email, bcc_email_address=BCC_EMAIL)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 7)
# # Should be unchanged from before
# self.assertEqual(len(self.mock_client.EMAILS_SENT), 4)
# Tests if a new email gets sent when just the email is changed.
# An email should NOT be sent out if we just modify the email content.
self.transition_state_and_send_email(
domain_request,
status=rejected,
action_needed_reason=domain_purpose,
action_needed_reason_email="dummy email content",
)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 7)
# Set the request back to in review
domain_request.in_review()
# Try sending another email when changing states AND including content
self.transition_state_and_send_email(
domain_request,
status=rejected,
rejection_reason=domain_purpose,
rejection_reason_email="custom content when starting anew",
)
self.assert_email_is_accurate(
"custom content when starting anew", 7, _creator.email, bcc_email_address=BCC_EMAIL
)
self.assertEqual(len(self.mock_client.EMAILS_SENT), 8)
@less_console_noise_decorator
def test_save_model_sends_submitted_email(self):
@ -1034,7 +1073,7 @@ class TestDomainRequestAdmin(MockEppLib):
# Reject for reason REQUESTOR and test email including dynamic organization name
self.transition_state_and_send_email(
domain_request, DomainRequest.DomainRequestStatus.REJECTED, DomainRequest.RejectionReasons.REQUESTOR
domain_request, DomainRequest.DomainRequestStatus.REJECTED, DomainRequest.RejectionReasons.REQUESTOR_NOT_ELIGIBLE
)
self.assert_email_is_accurate(
"Your domain request was rejected because we dont believe youre eligible to request a \n.gov "
@ -1072,7 +1111,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.transition_state_and_send_email(
domain_request,
DomainRequest.DomainRequestStatus.REJECTED,
DomainRequest.RejectionReasons.SECOND_DOMAIN_REASONING,
DomainRequest.RejectionReasons.ORG_HAS_DOMAIN,
)
self.assert_email_is_accurate(
"Your domain request was rejected because Testorg has a .gov domain.", 0, _creator.email
@ -1108,7 +1147,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.transition_state_and_send_email(
domain_request,
DomainRequest.DomainRequestStatus.REJECTED,
DomainRequest.RejectionReasons.CONTACTS_OR_ORGANIZATION_LEGITIMACY,
DomainRequest.RejectionReasons.CONTACTS_NOT_VERIFIED,
)
self.assert_email_is_accurate(
"Your domain request was rejected because we could not verify the organizational \n"
@ -1146,7 +1185,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.transition_state_and_send_email(
domain_request,
DomainRequest.DomainRequestStatus.REJECTED,
DomainRequest.RejectionReasons.ORGANIZATION_ELIGIBILITY,
DomainRequest.RejectionReasons.ORG_NOT_ELIGIBLE,
)
self.assert_email_is_accurate(
"Your domain request was rejected because we determined that Testorg is not \neligible for "
@ -1275,7 +1314,7 @@ class TestDomainRequestAdmin(MockEppLib):
stack.enter_context(patch.object(messages, "error"))
stack.enter_context(patch.object(messages, "warning"))
domain_request.status = DomainRequest.DomainRequestStatus.REJECTED
domain_request.rejection_reason = DomainRequest.RejectionReasons.CONTACTS_OR_ORGANIZATION_LEGITIMACY
domain_request.rejection_reason = DomainRequest.RejectionReasons.CONTACTS_NOT_VERIFIED
self.admin.save_model(request, domain_request, None, True)
@ -1840,7 +1879,7 @@ class TestDomainRequestAdmin(MockEppLib):
self.trigger_saving_approved_to_another_state(
False,
DomainRequest.DomainRequestStatus.REJECTED,
DomainRequest.RejectionReasons.CONTACTS_OR_ORGANIZATION_LEGITIMACY,
DomainRequest.RejectionReasons.CONTACTS_NOT_VERIFIED,
)
def test_side_effects_when_saving_approved_to_ineligible(self):

View file

@ -39,9 +39,13 @@ from .common import (
from django_fsm import TransitionNotAllowed
from waffle.testutils import override_flag
import logging
from api.tests.common import less_console_noise_decorator
logger = logging.getLogger(__name__)
@boto3_mocking.patching
class TestDomainRequest(TestCase):
@less_console_noise_decorator

View file

@ -2,63 +2,26 @@ from registrar.models.domain_request import DomainRequest
from django.template.loader import get_template
def get_all_action_needed_reason_emails(domain_request):
"""Returns a dictionary of every action needed reason and its associated email
for this particular domain request."""
return _get_all_default_emails(
reasons=DomainRequest.ActionNeededReasons,
# Where the emails are stored. This assumes that it contains a list of .txt files with the reason.
path_root="emails/action_needed_reasons",
# What reasons don't send out emails (none is handled automagically)
excluded_reasons=[DomainRequest.ActionNeededReasons.OTHER],
# Who to send it to, and from what domain request to reference
domain_request=domain_request
)
def get_action_needed_reason_default_email(domain_request, action_needed_reason):
"""Returns the default email associated with the given action needed reason"""
return _get_default_email(
domain_request,
path_root="emails/action_needed_reasons",
file_path=f"emails/action_needed_reasons/{action_needed_reason}.txt",
reason=action_needed_reason,
excluded_reasons=[DomainRequest.ActionNeededReasons.OTHER]
)
def get_all_rejection_reason_emails(domain_request):
"""Returns a dictionary of every rejection reason and its associated email
for this particular domain request."""
return _get_all_default_emails(
reasons=DomainRequest.RejectionReasons,
# Where the emails are stored. This assumes that it contains a list of .txt files with the reason.
path_root="emails/rejection_reasons",
# What reasons don't send out emails (none is handled automagically)
excluded_reasons=[DomainRequest.RejectionReasons.OTHER],
# Who to send it to, and from what domain request to reference
domain_request=domain_request
)
def get_rejection_reason_default_email(domain_request, rejection_reason):
"""Returns the default email associated with the given rejection reason"""
return _get_default_email(
domain_request,
path_root="emails/rejection_reasons",
file_path="emails/status_change_rejected.txt",
reason=rejection_reason,
excluded_reasons=[DomainRequest.RejectionReasons.OTHER]
)
def _get_all_default_emails(reasons, path_root, excluded_reasons, domain_request):
emails = {}
for reason in reasons:
# Map the reason to its default email
emails[reason.value] = _get_default_email(
domain_request, path_root, reason, excluded_reasons
)
return emails
def _get_default_email(domain_request, path_root, reason, excluded_reasons=None):
def _get_default_email(domain_request, file_path, reason, excluded_reasons=None):
if not reason:
return None
@ -67,14 +30,9 @@ def _get_default_email(domain_request, path_root, reason, excluded_reasons=None)
recipient = domain_request.creator
# Return the context of the rendered views
context = {"domain_request": domain_request, "recipient": recipient}
context = {"domain_request": domain_request, "recipient": recipient, "reason": reason}
# Get the email body
template_path = f"{path_root}/{reason}.txt"
email_body_text = get_template(template_path).render(context=context)
email_body_text_cleaned = None
if email_body_text:
email_body_text_cleaned = email_body_text.strip().lstrip("\n")
email_body_text = get_template(file_path).render(context=context)
email_body_text_cleaned = email_body_text.strip().lstrip("\n") if email_body_text else None
return email_body_text_cleaned