mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-14 05:29:43 +02:00
Merge branch 'main' into za/1484-domain-manager-delete
This commit is contained in:
commit
b72da91543
38 changed files with 207 additions and 57 deletions
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Which OIDC provider to use
|
# Which OIDC provider to use
|
||||||
OIDC_ACTIVE_PROVIDER: login.gov production
|
OIDC_ACTIVE_PROVIDER: login.gov production
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# use a non-default route to avoid conflicts
|
# use a non-default route to avoid conflicts
|
||||||
routes:
|
routes:
|
||||||
- route: getgov-ENVIRONMENT-migrate.app.cloud.gov
|
- route: getgov-ENVIRONMENT-migrate.app.cloud.gov
|
||||||
|
|
|
@ -22,7 +22,7 @@ applications:
|
||||||
# Tell Django how much stuff to log
|
# Tell Django how much stuff to log
|
||||||
DJANGO_LOG_LEVEL: INFO
|
DJANGO_LOG_LEVEL: INFO
|
||||||
# default public site location
|
# default public site location
|
||||||
GETGOV_PUBLIC_SITE_URL: https://beta.get.gov
|
GETGOV_PUBLIC_SITE_URL: https://get.gov
|
||||||
# Flag to disable/enable features in prod environments
|
# Flag to disable/enable features in prod environments
|
||||||
IS_PRODUCTION: False
|
IS_PRODUCTION: False
|
||||||
routes:
|
routes:
|
||||||
|
|
|
@ -32,7 +32,7 @@ services:
|
||||||
# Is this a production environment
|
# Is this a production environment
|
||||||
- IS_PRODUCTION
|
- IS_PRODUCTION
|
||||||
# Public site URL link
|
# Public site URL link
|
||||||
- GETGOV_PUBLIC_SITE_URL=https://beta.get.gov
|
- GETGOV_PUBLIC_SITE_URL=https://get.gov
|
||||||
# Set a username for accessing the registry
|
# Set a username for accessing the registry
|
||||||
- REGISTRY_CL_ID=nothing
|
- REGISTRY_CL_ID=nothing
|
||||||
# Set a password for accessing the registry
|
# Set a password for accessing the registry
|
||||||
|
|
|
@ -270,9 +270,21 @@ function removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier){
|
||||||
// h2 and legend for DS form, label for nameservers
|
// h2 and legend for DS form, label for nameservers
|
||||||
Array.from(form.querySelectorAll('h2, legend, label, p')).forEach((node) => {
|
Array.from(form.querySelectorAll('h2, legend, label, p')).forEach((node) => {
|
||||||
|
|
||||||
|
let innerSpan = node.querySelector('span')
|
||||||
|
if (innerSpan) {
|
||||||
|
innerSpan.textContent = innerSpan.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
||||||
|
} else {
|
||||||
|
node.textContent = node.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
||||||
|
node.textContent = node.textContent.replace(formExampleRegex, `ns${index + 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
// If the node is a nameserver label, one of the first 2 which was previously 3 and up (not required)
|
// If the node is a nameserver label, one of the first 2 which was previously 3 and up (not required)
|
||||||
// inject the USWDS required markup and make sure the INPUT is required
|
// inject the USWDS required markup and make sure the INPUT is required
|
||||||
if (isNameserversForm && index <= 1 && node.innerHTML.includes('server') && !node.innerHTML.includes('*')) {
|
if (isNameserversForm && index <= 1 && node.innerHTML.includes('server') && !node.innerHTML.includes('*')) {
|
||||||
|
|
||||||
|
// Remove the word optional
|
||||||
|
innerSpan.textContent = innerSpan.textContent.replace(/\s*\(\s*optional\s*\)\s*/, '');
|
||||||
|
|
||||||
// Create a new element
|
// Create a new element
|
||||||
const newElement = document.createElement('abbr');
|
const newElement = document.createElement('abbr');
|
||||||
newElement.textContent = '*';
|
newElement.textContent = '*';
|
||||||
|
@ -295,13 +307,8 @@ function removeForm(e, formLabel, isNameserversForm, addButton, formIdentifier){
|
||||||
nextInputElement.required = true;
|
nextInputElement.required = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let innerSpan = node.querySelector('span')
|
|
||||||
if (innerSpan) {
|
|
||||||
innerSpan.textContent = innerSpan.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
|
||||||
} else {
|
|
||||||
node.textContent = node.textContent.replace(formLabelRegex, `${formLabel} ${index + 1}`);
|
|
||||||
node.textContent = node.textContent.replace(formExampleRegex, `ns${index + 1}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Display the add more button if we have less than 13 forms
|
// Display the add more button if we have less than 13 forms
|
||||||
|
@ -521,16 +528,24 @@ function hideDeletedForms() {
|
||||||
formNum++;
|
formNum++;
|
||||||
|
|
||||||
newForm.innerHTML = newForm.innerHTML.replace(formNumberRegex, `${formIdentifier}-${formNum-1}-`);
|
newForm.innerHTML = newForm.innerHTML.replace(formNumberRegex, `${formIdentifier}-${formNum-1}-`);
|
||||||
// For the other contacts form, we need to update the fieldset headers based on what's visible vs hidden,
|
|
||||||
// since the form on the backend employs Django's DELETE widget. For the other formsets, we delete the form
|
|
||||||
// in JS (completely remove from teh DOM) so we update the headers/labels based on total number of forms.
|
|
||||||
if (isOtherContactsForm) {
|
if (isOtherContactsForm) {
|
||||||
|
// For the other contacts form, we need to update the fieldset headers based on what's visible vs hidden,
|
||||||
|
// since the form on the backend employs Django's DELETE widget.
|
||||||
let totalShownForms = document.querySelectorAll(`.repeatable-form:not([style*="display: none"])`).length;
|
let totalShownForms = document.querySelectorAll(`.repeatable-form:not([style*="display: none"])`).length;
|
||||||
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${totalShownForms + 1}`);
|
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${totalShownForms + 1}`);
|
||||||
} else {
|
} else {
|
||||||
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum}`);
|
// Nameservers form is cloned from index 2 which has the word optional on init, does not have the word optional
|
||||||
|
// if indices 0 or 1 have been deleted
|
||||||
|
let containsOptional = newForm.innerHTML.includes('(optional)');
|
||||||
|
if (isNameserversForm && !containsOptional) {
|
||||||
|
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum} (optional)`);
|
||||||
|
} else {
|
||||||
|
newForm.innerHTML = newForm.innerHTML.replace(formLabelRegex, `${formLabel} ${formNum}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
newForm.innerHTML = newForm.innerHTML.replace(formExampleRegex, `ns${formNum}`);
|
newForm.innerHTML = newForm.innerHTML.replace(formExampleRegex, `ns${formNum}`);
|
||||||
|
newForm.innerHTML = newForm.innerHTML.replace(/\n/g, ''); // Remove newline characters
|
||||||
|
newForm.innerHTML = newForm.innerHTML.replace(/>\s*</g, '><'); // Remove spaces between tags
|
||||||
container.insertBefore(newForm, addButton);
|
container.insertBefore(newForm, addButton);
|
||||||
|
|
||||||
newForm.style.display = 'block';
|
newForm.style.display = 'block';
|
||||||
|
|
|
@ -335,7 +335,7 @@ CSP_INCLUDE_NONCE_IN = ["script-src-elem"]
|
||||||
# Cross-Origin Resource Sharing (CORS) configuration
|
# Cross-Origin Resource Sharing (CORS) configuration
|
||||||
# Sets clients that allow access control to manage.get.gov
|
# Sets clients that allow access control to manage.get.gov
|
||||||
# TODO: remove :8080 to see if we can have all localhost access
|
# TODO: remove :8080 to see if we can have all localhost access
|
||||||
CORS_ALLOWED_ORIGINS = ["http://localhost:8080", "https://beta.get.gov"]
|
CORS_ALLOWED_ORIGINS = ["http://localhost:8080", "https://beta.get.gov", "https://get.gov"]
|
||||||
CORS_ALLOWED_ORIGIN_REGEXES = [r"https://[\w-]+\.sites\.pages\.cloud\.gov"]
|
CORS_ALLOWED_ORIGIN_REGEXES = [r"https://[\w-]+\.sites\.pages\.cloud\.gov"]
|
||||||
|
|
||||||
# Content-Length header is set by django.middleware.common.CommonMiddleware
|
# Content-Length header is set by django.middleware.common.CommonMiddleware
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends 'application_form.html' %}
|
{% extends 'application_form.html' %}
|
||||||
{% load field_helpers %}
|
{% load field_helpers url_helpers %}
|
||||||
|
|
||||||
{% block form_instructions %}
|
{% block form_instructions %}
|
||||||
<p>If your domain request is approved, the name of your organization and your city/state will be listed in <a href="https://beta.get.gov/about/data/" target="_blank">.gov’s public data.</a></p>
|
<p>If your domain request is approved, the name of your organization and your city/state will be listed in <a href="{% public_site_url 'about/data/' %}" target="_blank">.gov’s public data.</a></p>
|
||||||
|
|
||||||
<h2>What is the name and mailing address of the organization you represent?</h2>
|
<h2>What is the name and mailing address of the organization you represent?</h2>
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
{% load static field_helpers %}
|
{% load static field_helpers %}
|
||||||
|
|
||||||
{% block form_instructions %}
|
{% block form_instructions %}
|
||||||
<p>To help us assess your eligibility for a .gov domain, please provide contact information for other employees from your organization.
|
<p>To help us determine your organization’s eligibility for a .gov domain, it’s helpful to have contact information for other employees from your organization.
|
||||||
<ul class="usa-list">
|
<ul class="usa-list">
|
||||||
<li>They should be clearly and publicly affiliated with your organization and familiar with your domain request. </li>
|
<li>They should be clearly and publicly affiliated with your organization and familiar with your domain request.</li>
|
||||||
<li>They don't need to be involved with the technical management of your domain (although they can be). </li>
|
<li>They don’t need to be involved with the technical management of your domain (although they can be).</li>
|
||||||
<li>We typically don’t reach out to these employees, but if contact is necessary, our practice is to coordinate first with you, the requestor. </li>
|
<li><strong>We typically don’t reach out to these employees</strong>, but if contact is necessary, our practice is to coordinate with you first.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -88,9 +88,7 @@
|
||||||
<legend>
|
<legend>
|
||||||
<h2 class="margin-bottom-0">No other employees from your organization?</h2>
|
<h2 class="margin-bottom-0">No other employees from your organization?</h2>
|
||||||
</legend>
|
</legend>
|
||||||
<p>You don't need to provide names of other employees now, but it may
|
<p>You don’t need to provide names of other employees now, but it may slow down our assessment of your eligibility. Describe why there are no other employees who can help verify your request.</p>
|
||||||
slow down our assessment of your eligibility. Describe why there are
|
|
||||||
no other employees who can help verify your request.</p>
|
|
||||||
{% with attr_maxlength=1000 add_label_class="usa-sr-only" %}
|
{% with attr_maxlength=1000 add_label_class="usa-sr-only" %}
|
||||||
{% input_with_errors forms.2.no_other_contacts_rationale %}
|
{% input_with_errors forms.2.no_other_contacts_rationale %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
|
@ -90,7 +90,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if domainapplication.current_websites.all %}
|
{% if domainapplication.current_websites.all %}
|
||||||
{% include "includes/summary_item.html" with title='Current website for your organization' value=domainapplication.current_websites.all list='true' heading_level=heading_level %}
|
{% include "includes/summary_item.html" with title='Current websites' value=domainapplication.current_websites.all list='true' heading_level=heading_level %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if domainapplication.requested_domain %}
|
{% if domainapplication.requested_domain %}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{% extends "domain_base.html" %}
|
{% extends "domain_base.html" %}
|
||||||
{% load static field_helpers %}
|
{% load static field_helpers %}
|
||||||
|
|
||||||
{% block title %}Add another user | {% endblock %}
|
{% block title %}Add a domain manager | {% endblock %}
|
||||||
|
|
||||||
{% block domain_content %}
|
{% block domain_content %}
|
||||||
<h1>Add a domain manager</h1>
|
<h1>Add a domain manager</h1>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
class="usa-button"
|
class="usa-button"
|
||||||
>{% if form.security_email.value is None or form.security_email.value == "dotgov@cisa.dhs.gov"%}Add security email{% else %}Save{% endif %}</button>
|
>{% if form.security_email.value is None or form.security_email.value == "dotgov@cisa.dhs.gov" or form.security_email.value == "registrar@dotgov.gov"%}Add security email{% else %}Save{% endif %}</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %} {# domain_content #}
|
{% endblock %} {# domain_content #}
|
||||||
|
|
|
@ -17,7 +17,7 @@ About your organization:
|
||||||
Authorizing official:
|
Authorizing official:
|
||||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=application.authorizing_official %}{% endspaceless %}
|
{% spaceless %}{% include "emails/includes/contact.txt" with contact=application.authorizing_official %}{% endspaceless %}
|
||||||
{% if application.current_websites.exists %}{# if block makes a newline #}
|
{% if application.current_websites.exists %}{# if block makes a newline #}
|
||||||
Current website for your organization: {% for site in application.current_websites.all %}
|
Current websites: {% for site in application.current_websites.all %}
|
||||||
{% spaceless %}{{ site.website }}{% endspaceless %}
|
{% spaceless %}{{ site.website }}{% endspaceless %}
|
||||||
{% endfor %}{% endif %}
|
{% endfor %}{% endif %}
|
||||||
.gov domain:
|
.gov domain:
|
||||||
|
|
|
@ -32,6 +32,14 @@ Learn more about:
|
||||||
- Domain security best practices <https://get.gov/domains/security/>
|
- Domain security best practices <https://get.gov/domains/security/>
|
||||||
|
|
||||||
|
|
||||||
|
WE’LL PRELOAD THIS DOMAIN
|
||||||
|
We add new .gov domains to the HSTS preload list each month. This requires browsers to use a secure HTTPS connection to any website at this domain and ensures the content you publish is exactly what your visitors get. It also means you’ll need to support HTTPS anywhere the domain is used for websites – on the internet or internally. We’ll add your domain to the preload list soon.
|
||||||
|
|
||||||
|
Learn more about:
|
||||||
|
- What preloading is <https://get.gov/domains/security/#preload-your-domain>
|
||||||
|
- Why we preload new domains <https://get.gov/posts/2021-06-21-an-intent-to-preload/>
|
||||||
|
|
||||||
|
|
||||||
THANK YOU
|
THANK YOU
|
||||||
.Gov helps the public identify official, trusted information. Thank you for using a .gov domain.
|
.Gov helps the public identify official, trusted information. Thank you for using a .gov domain.
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
{% elif domain.state == domain.State.UNKNOWN or domain.state == domain.State.DNS_NEEDED %}
|
{% elif domain.state == domain.State.UNKNOWN or domain.state == domain.State.DNS_NEEDED %}
|
||||||
DNS needed
|
DNS needed
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ domain.state|title }}
|
{{ domain.state|capfirst }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -47,7 +47,7 @@ class TestEmails(TestCase):
|
||||||
# check for optional things
|
# check for optional things
|
||||||
self.assertIn("Other employees from your organization:", body)
|
self.assertIn("Other employees from your organization:", body)
|
||||||
self.assertIn("Testy2 Tester2", body)
|
self.assertIn("Testy2 Tester2", body)
|
||||||
self.assertIn("Current website for your organization:", body)
|
self.assertIn("Current websites:", body)
|
||||||
self.assertIn("city.com", body)
|
self.assertIn("city.com", body)
|
||||||
self.assertIn("About your organization:", body)
|
self.assertIn("About your organization:", body)
|
||||||
self.assertIn("Anything else", body)
|
self.assertIn("Anything else", body)
|
||||||
|
@ -61,7 +61,7 @@ class TestEmails(TestCase):
|
||||||
application.submit()
|
application.submit()
|
||||||
_, kwargs = self.mock_client.send_email.call_args
|
_, kwargs = self.mock_client.send_email.call_args
|
||||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||||
self.assertNotIn("Current website for your organization:", body)
|
self.assertNotIn("Current websites:", body)
|
||||||
# spacing should be right between adjacent elements
|
# spacing should be right between adjacent elements
|
||||||
self.assertRegex(body, r"5555\n\n.gov domain:")
|
self.assertRegex(body, r"5555\n\n.gov domain:")
|
||||||
|
|
||||||
|
@ -74,9 +74,9 @@ class TestEmails(TestCase):
|
||||||
application.submit()
|
application.submit()
|
||||||
_, kwargs = self.mock_client.send_email.call_args
|
_, kwargs = self.mock_client.send_email.call_args
|
||||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||||
self.assertIn("Current website for your organization:", body)
|
self.assertIn("Current websites:", body)
|
||||||
# spacing should be right between adjacent elements
|
# spacing should be right between adjacent elements
|
||||||
self.assertRegex(body, r"5555\n\nCurrent website for")
|
self.assertRegex(body, r"5555\n\nCurrent websites:")
|
||||||
self.assertRegex(body, r"city.com\n\n.gov domain:")
|
self.assertRegex(body, r"city.com\n\n.gov domain:")
|
||||||
|
|
||||||
@boto3_mocking.patching
|
@boto3_mocking.patching
|
||||||
|
|
|
@ -101,7 +101,7 @@ class TestFormValidation(MockEppLib):
|
||||||
(
|
(
|
||||||
"whitehouse.gov",
|
"whitehouse.gov",
|
||||||
"That domain isn’t available. <a class='usa-link' "
|
"That domain isn’t available. <a class='usa-link' "
|
||||||
"href='https://beta.get.gov/domains/choosing' target='_blank'>Read more about "
|
"href='https://get.gov/domains/choosing' target='_blank'>Read more about "
|
||||||
"choosing your .gov domain</a>.",
|
"choosing your .gov domain</a>.",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
@ -151,7 +151,7 @@ class TestFormValidation(MockEppLib):
|
||||||
(
|
(
|
||||||
"whitehouse.gov",
|
"whitehouse.gov",
|
||||||
"That domain isn’t available. <a class='usa-link' "
|
"That domain isn’t available. <a class='usa-link' "
|
||||||
"href='https://beta.get.gov/domains/choosing' target='_blank'>Read more about "
|
"href='https://get.gov/domains/choosing' target='_blank'>Read more about "
|
||||||
"choosing your .gov domain</a>.",
|
"choosing your .gov domain</a>.",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -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,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
|
@ -399,7 +399,7 @@ class ExportDataTest(MockEppLib):
|
||||||
"adomain10.gov,Federal,Armed Forces Retirement Home,Ready\n"
|
"adomain10.gov,Federal,Armed Forces Retirement Home,Ready\n"
|
||||||
"adomain2.gov,Interstate,(blank),Dns needed\n"
|
"adomain2.gov,Interstate,(blank),Dns needed\n"
|
||||||
"ddomain3.gov,Federal,Armed Forces Retirement Home,123@mail.gov,On hold,2023-05-25\n"
|
"ddomain3.gov,Federal,Armed Forces Retirement Home,123@mail.gov,On hold,2023-05-25\n"
|
||||||
"defaultsecurity.gov,Federal - Executive,World War I Centennial Commission,dotgov@cisa.dhs.gov,Ready"
|
"defaultsecurity.gov,Federal - Executive,World War I Centennial Commission,(blank),Ready"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Normalize line endings and remove commas,
|
# Normalize line endings and remove commas,
|
||||||
|
|
|
@ -38,7 +38,7 @@ def write_row(writer, columns, domain_info):
|
||||||
if security_contacts:
|
if security_contacts:
|
||||||
security_email = security_contacts[0].email
|
security_email = security_contacts[0].email
|
||||||
|
|
||||||
invalid_emails = {"registrar@dotgov.gov"}
|
invalid_emails = {"registrar@dotgov.gov", "dotgov@cisa.dhs.gov"}
|
||||||
# These are default emails that should not be displayed in the csv report
|
# These are default emails that should not be displayed in the csv report
|
||||||
if security_email is not None and security_email.lower() in invalid_emails:
|
if security_email is not None and security_email.lower() in invalid_emails:
|
||||||
security_email = "(blank)"
|
security_email = "(blank)"
|
||||||
|
|
|
@ -85,7 +85,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
||||||
Step.ORGANIZATION_CONTACT: _("Organization name and mailing address"),
|
Step.ORGANIZATION_CONTACT: _("Organization name and mailing address"),
|
||||||
Step.ABOUT_YOUR_ORGANIZATION: _("About your organization"),
|
Step.ABOUT_YOUR_ORGANIZATION: _("About your organization"),
|
||||||
Step.AUTHORIZING_OFFICIAL: _("Authorizing official"),
|
Step.AUTHORIZING_OFFICIAL: _("Authorizing official"),
|
||||||
Step.CURRENT_SITES: _("Current website for your organization"),
|
Step.CURRENT_SITES: _("Current websites"),
|
||||||
Step.DOTGOV_DOMAIN: _(".gov domain"),
|
Step.DOTGOV_DOMAIN: _(".gov domain"),
|
||||||
Step.PURPOSE: _("Purpose of your domain"),
|
Step.PURPOSE: _("Purpose of your domain"),
|
||||||
Step.YOUR_CONTACT: _("Your contact information"),
|
Step.YOUR_CONTACT: _("Your contact information"),
|
||||||
|
|
|
@ -570,7 +570,9 @@ class DomainSecurityEmailView(DomainFormBaseView):
|
||||||
"""The initial value for the form."""
|
"""The initial value for the form."""
|
||||||
initial = super().get_initial()
|
initial = super().get_initial()
|
||||||
security_contact = self.object.security_contact
|
security_contact = self.object.security_contact
|
||||||
if security_contact is None or security_contact.email == "dotgov@cisa.dhs.gov":
|
|
||||||
|
invalid_emails = ["dotgov@cisa.dhs.gov", "registrar@dotgov.gov"]
|
||||||
|
if security_contact is None or security_contact.email in invalid_emails:
|
||||||
initial["security_email"] = None
|
initial["security_email"] = None
|
||||||
return initial
|
return initial
|
||||||
initial["security_email"] = security_contact.email
|
initial["security_email"] = security_contact.email
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue