mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-30 14:36:32 +02:00
Merge remote-tracking branch 'origin/main' into nl/1798-update-email-signature
This commit is contained in:
commit
ef5358e7e2
88 changed files with 2597 additions and 1834 deletions
|
@ -14,7 +14,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.urls import reverse
|
||||
from dateutil.relativedelta import relativedelta # type: ignore
|
||||
from epplibwrapper.errors import ErrorCode, RegistryError
|
||||
from registrar.models import Contact, Domain, DomainApplication, DraftDomain, User, Website
|
||||
from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website
|
||||
from registrar.utility import csv_export
|
||||
from registrar.views.utility.mixins import OrderableFieldsMixin
|
||||
from django.contrib.admin.views.main import ORDER_VAR
|
||||
|
@ -69,12 +69,12 @@ class DomainInformationInlineForm(forms.ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class DomainApplicationAdminForm(forms.ModelForm):
|
||||
class DomainRequestAdminForm(forms.ModelForm):
|
||||
"""Custom form to limit transitions to available transitions.
|
||||
This form utilizes the custom widget for its class's ManyToMany UIs."""
|
||||
|
||||
class Meta:
|
||||
model = models.DomainApplication
|
||||
model = models.DomainRequest
|
||||
fields = "__all__"
|
||||
widgets = {
|
||||
"current_websites": NoAutocompleteFilteredSelectMultiple("current_websites", False),
|
||||
|
@ -85,24 +85,24 @@ class DomainApplicationAdminForm(forms.ModelForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
application = kwargs.get("instance")
|
||||
if application and application.pk:
|
||||
current_state = application.status
|
||||
domain_request = kwargs.get("instance")
|
||||
if domain_request and domain_request.pk:
|
||||
current_state = domain_request.status
|
||||
|
||||
# first option in status transitions is current state
|
||||
available_transitions = [(current_state, application.get_status_display())]
|
||||
available_transitions = [(current_state, domain_request.get_status_display())]
|
||||
|
||||
transitions = get_available_FIELD_transitions(
|
||||
application, models.DomainApplication._meta.get_field("status")
|
||||
domain_request, models.DomainRequest._meta.get_field("status")
|
||||
)
|
||||
|
||||
for transition in transitions:
|
||||
available_transitions.append((transition.target, transition.target.label))
|
||||
|
||||
# only set the available transitions if the user is not restricted
|
||||
# from editing the domain application; otherwise, the form will be
|
||||
# from editing the domain request; otherwise, the form will be
|
||||
# readonly and the status field will not have a widget
|
||||
if not application.creator.is_restricted():
|
||||
if not domain_request.creator.is_restricted():
|
||||
self.fields["status"].widget.choices = available_transitions
|
||||
|
||||
|
||||
|
@ -218,8 +218,8 @@ class AdminSortFields:
|
|||
"alternative_domains": (Website, "website"),
|
||||
# == DraftDomain == #
|
||||
"requested_domain": (DraftDomain, "name"),
|
||||
# == DomainApplication == #
|
||||
"domain_application": (DomainApplication, "requested_domain__name"),
|
||||
# == DomainRequest == #
|
||||
"domain_request": (DomainRequest, "requested_domain__name"),
|
||||
# == Domain == #
|
||||
"domain": (Domain, "name"),
|
||||
"approved_domain": (Domain, "name"),
|
||||
|
@ -466,7 +466,7 @@ class MyUserAdmin(BaseUserAdmin):
|
|||
def get_search_results(self, request, queryset, search_term):
|
||||
"""
|
||||
Override for get_search_results. This affects any upstream model using autocomplete_fields,
|
||||
such as DomainApplication. This is because autocomplete_fields uses an API call to fetch data,
|
||||
such as DomainRequest. This is because autocomplete_fields uses an API call to fetch data,
|
||||
and this fetch comes from this method.
|
||||
"""
|
||||
# Custom filtering logic
|
||||
|
@ -480,13 +480,13 @@ class MyUserAdmin(BaseUserAdmin):
|
|||
request_get = request.GET
|
||||
|
||||
# The request defines model name and field name.
|
||||
# For instance, model_name could be "DomainApplication"
|
||||
# For instance, model_name could be "DomainRequest"
|
||||
# and field_name could be "investigator".
|
||||
model_name = request_get.get("model_name", None)
|
||||
field_name = request_get.get("field_name", None)
|
||||
|
||||
# Make sure we're only modifying requests from these models.
|
||||
models_to_target = {"domainapplication"}
|
||||
models_to_target = {"domainrequest"}
|
||||
if model_name in models_to_target:
|
||||
# Define rules per field
|
||||
match field_name:
|
||||
|
@ -777,7 +777,7 @@ class DomainInformationAdmin(ListHeaderAdmin):
|
|||
search_help_text = "Search by domain."
|
||||
|
||||
fieldsets = [
|
||||
(None, {"fields": ["creator", "domain_application", "notes"]}),
|
||||
(None, {"fields": ["creator", "domain_request", "notes"]}),
|
||||
(
|
||||
"Type of organization",
|
||||
{
|
||||
|
@ -828,7 +828,7 @@ class DomainInformationAdmin(ListHeaderAdmin):
|
|||
"type_of_work",
|
||||
"more_organization_information",
|
||||
"domain",
|
||||
"domain_application",
|
||||
"domain_request",
|
||||
"submitter",
|
||||
"no_other_contacts_rationale",
|
||||
"anything_else",
|
||||
|
@ -841,7 +841,7 @@ class DomainInformationAdmin(ListHeaderAdmin):
|
|||
|
||||
autocomplete_fields = [
|
||||
"creator",
|
||||
"domain_application",
|
||||
"domain_request",
|
||||
"authorizing_official",
|
||||
"domain",
|
||||
"submitter",
|
||||
|
@ -866,10 +866,10 @@ class DomainInformationAdmin(ListHeaderAdmin):
|
|||
return readonly_fields # Read-only fields for analysts
|
||||
|
||||
|
||||
class DomainApplicationAdmin(ListHeaderAdmin):
|
||||
"""Custom domain applications admin class."""
|
||||
class DomainRequestAdmin(ListHeaderAdmin):
|
||||
"""Custom domain requests admin class."""
|
||||
|
||||
form = DomainApplicationAdminForm
|
||||
form = DomainRequestAdminForm
|
||||
|
||||
class InvestigatorFilter(admin.SimpleListFilter):
|
||||
"""Custom investigator filter that only displays users with the manager role"""
|
||||
|
@ -884,7 +884,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
"""
|
||||
# Select all investigators that are staff, then order by name and email
|
||||
privileged_users = (
|
||||
DomainApplication.objects.select_related("investigator")
|
||||
DomainRequest.objects.select_related("investigator")
|
||||
.filter(investigator__is_staff=True)
|
||||
.order_by("investigator__first_name", "investigator__last_name", "investigator__email")
|
||||
)
|
||||
|
@ -1055,17 +1055,17 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
# Trigger action when a fieldset is changed
|
||||
def save_model(self, request, obj, form, change):
|
||||
if obj and obj.creator.status != models.User.RESTRICTED:
|
||||
if change: # Check if the application is being edited
|
||||
# Get the original application from the database
|
||||
original_obj = models.DomainApplication.objects.get(pk=obj.pk)
|
||||
if change: # Check if the domain request is being edited
|
||||
# Get the original domain request from the database
|
||||
original_obj = models.DomainRequest.objects.get(pk=obj.pk)
|
||||
|
||||
if (
|
||||
obj
|
||||
and original_obj.status == models.DomainApplication.ApplicationStatus.APPROVED
|
||||
and obj.status != models.DomainApplication.ApplicationStatus.APPROVED
|
||||
and original_obj.status == models.DomainRequest.DomainRequestStatus.APPROVED
|
||||
and obj.status != models.DomainRequest.DomainRequestStatus.APPROVED
|
||||
and not obj.domain_is_not_active()
|
||||
):
|
||||
# If an admin tried to set an approved application to
|
||||
# If an admin tried to set an approved domain request to
|
||||
# another status and the related domain is already
|
||||
# active, shortcut the action and throw a friendly
|
||||
# error message. This action would still not go through
|
||||
|
@ -1081,9 +1081,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
)
|
||||
|
||||
elif (
|
||||
obj
|
||||
and obj.status == models.DomainApplication.ApplicationStatus.REJECTED
|
||||
and not obj.rejection_reason
|
||||
obj and obj.status == models.DomainRequest.DomainRequestStatus.REJECTED and not obj.rejection_reason
|
||||
):
|
||||
# This condition should never be triggered.
|
||||
# The opposite of this condition is acceptable (rejected -> other status and rejection_reason)
|
||||
|
@ -1100,14 +1098,14 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
else:
|
||||
if obj.status != original_obj.status:
|
||||
status_method_mapping = {
|
||||
models.DomainApplication.ApplicationStatus.STARTED: None,
|
||||
models.DomainApplication.ApplicationStatus.SUBMITTED: obj.submit,
|
||||
models.DomainApplication.ApplicationStatus.IN_REVIEW: obj.in_review,
|
||||
models.DomainApplication.ApplicationStatus.ACTION_NEEDED: obj.action_needed,
|
||||
models.DomainApplication.ApplicationStatus.APPROVED: obj.approve,
|
||||
models.DomainApplication.ApplicationStatus.WITHDRAWN: obj.withdraw,
|
||||
models.DomainApplication.ApplicationStatus.REJECTED: obj.reject,
|
||||
models.DomainApplication.ApplicationStatus.INELIGIBLE: (obj.reject_with_prejudice),
|
||||
models.DomainRequest.DomainRequestStatus.STARTED: None,
|
||||
models.DomainRequest.DomainRequestStatus.SUBMITTED: obj.submit,
|
||||
models.DomainRequest.DomainRequestStatus.IN_REVIEW: obj.in_review,
|
||||
models.DomainRequest.DomainRequestStatus.ACTION_NEEDED: obj.action_needed,
|
||||
models.DomainRequest.DomainRequestStatus.APPROVED: obj.approve,
|
||||
models.DomainRequest.DomainRequestStatus.WITHDRAWN: obj.withdraw,
|
||||
models.DomainRequest.DomainRequestStatus.REJECTED: obj.reject,
|
||||
models.DomainRequest.DomainRequestStatus.INELIGIBLE: (obj.reject_with_prejudice),
|
||||
}
|
||||
selected_method = status_method_mapping.get(obj.status)
|
||||
if selected_method is None:
|
||||
|
@ -1127,13 +1125,13 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
|
||||
messages.error(
|
||||
request,
|
||||
"This action is not permitted for applications with a restricted creator.",
|
||||
"This action is not permitted for domain requests with a restricted creator.",
|
||||
)
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
"""Set the read-only state on form elements.
|
||||
We have 2 conditions that determine which fields are read-only:
|
||||
admin user permissions and the application creator's status, so
|
||||
admin user permissions and the domain request creator's status, so
|
||||
we'll use the baseline readonly_fields and extend it as needed.
|
||||
"""
|
||||
readonly_fields = list(self.readonly_fields)
|
||||
|
@ -1158,7 +1156,7 @@ class DomainApplicationAdmin(ListHeaderAdmin):
|
|||
if obj and obj.creator.status == models.User.RESTRICTED:
|
||||
messages.warning(
|
||||
request,
|
||||
"Cannot edit an application with a restricted creator.",
|
||||
"Cannot edit a domain request with a restricted creator.",
|
||||
)
|
||||
|
||||
def change_view(self, request, object_id, form_url="", extra_context=None):
|
||||
|
@ -1202,7 +1200,7 @@ class DomainInformationInline(admin.StackedInline):
|
|||
|
||||
autocomplete_fields = [
|
||||
"creator",
|
||||
"domain_application",
|
||||
"domain_request",
|
||||
"authorizing_official",
|
||||
"domain",
|
||||
"submitter",
|
||||
|
@ -1712,6 +1710,6 @@ admin.site.register(models.DraftDomain, DraftDomainAdmin)
|
|||
admin.site.register(models.Host, MyHostAdmin)
|
||||
admin.site.register(models.Website, WebsiteAdmin)
|
||||
admin.site.register(models.PublicContact, AuditedAdmin)
|
||||
admin.site.register(models.DomainApplication, DomainApplicationAdmin)
|
||||
admin.site.register(models.DomainRequest, DomainRequestAdmin)
|
||||
admin.site.register(models.TransitionDomain, TransitionDomainAdmin)
|
||||
admin.site.register(models.VerifiedByStaff, VerifiedByStaffAdmin)
|
||||
|
|
|
@ -135,6 +135,8 @@ html[data-theme="dark"] {
|
|||
color: var(--primary-fg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#branding h1,
|
||||
h1, h2, h3,
|
||||
.module h2 {
|
||||
|
|
|
@ -13,18 +13,18 @@ from registrar import views
|
|||
from registrar.views.admin_views import ExportData
|
||||
|
||||
|
||||
from registrar.views.application import Step
|
||||
from registrar.views.domain_request import Step
|
||||
from registrar.views.utility import always_404
|
||||
from api.views import available, get_current_federal, get_current_full
|
||||
|
||||
|
||||
APPLICATION_NAMESPACE = views.ApplicationWizard.URL_NAMESPACE
|
||||
application_urls = [
|
||||
path("", views.ApplicationWizard.as_view(), name=""),
|
||||
DOMAIN_REQUEST_NAMESPACE = views.DomainRequestWizard.URL_NAMESPACE
|
||||
domain_request_urls = [
|
||||
path("", views.DomainRequestWizard.as_view(), name=""),
|
||||
path("finished/", views.Finished.as_view(), name="finished"),
|
||||
]
|
||||
|
||||
# dynamically generate the other application_urls
|
||||
# dynamically generate the other domain_request_urls
|
||||
for step, view in [
|
||||
# add/remove steps here
|
||||
(Step.ORGANIZATION_TYPE, views.OrganizationType),
|
||||
|
@ -43,7 +43,7 @@ for step, view in [
|
|||
(Step.REQUIREMENTS, views.Requirements),
|
||||
(Step.REVIEW, views.Review),
|
||||
]:
|
||||
application_urls.append(path(f"{step}/", view.as_view(), name=step))
|
||||
domain_request_urls.append(path(f"{step}/", view.as_view(), name=step))
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -55,28 +55,28 @@ urlpatterns = [
|
|||
path("export_data/", ExportData.as_view(), name="admin_export_data"),
|
||||
path("admin/", admin.site.urls),
|
||||
path(
|
||||
"application/<id>/edit/",
|
||||
views.ApplicationWizard.as_view(),
|
||||
name=views.ApplicationWizard.EDIT_URL_NAME,
|
||||
"domain-request/<id>/edit/",
|
||||
views.DomainRequestWizard.as_view(),
|
||||
name=views.DomainRequestWizard.EDIT_URL_NAME,
|
||||
),
|
||||
path(
|
||||
"application/<int:pk>",
|
||||
views.ApplicationStatus.as_view(),
|
||||
name="application-status",
|
||||
"domain-request/<int:pk>",
|
||||
views.DomainRequestStatus.as_view(),
|
||||
name="domain-request-status",
|
||||
),
|
||||
path(
|
||||
"application/<int:pk>/withdraw",
|
||||
views.ApplicationWithdrawConfirmation.as_view(),
|
||||
name="application-withdraw-confirmation",
|
||||
"domain-request/<int:pk>/withdraw",
|
||||
views.DomainRequestWithdrawConfirmation.as_view(),
|
||||
name="domain-request-withdraw-confirmation",
|
||||
),
|
||||
path(
|
||||
"application/<int:pk>/withdrawconfirmed",
|
||||
views.ApplicationWithdrawn.as_view(),
|
||||
name="application-withdrawn",
|
||||
"domain-request/<int:pk>/withdrawconfirmed",
|
||||
views.DomainRequestWithdrawn.as_view(),
|
||||
name="domain-request-withdrawn",
|
||||
),
|
||||
path("health", views.health, name="health"),
|
||||
path("openid/", include("djangooidc.urls")),
|
||||
path("request/", include((application_urls, APPLICATION_NAMESPACE))),
|
||||
path("request/", include((domain_request_urls, DOMAIN_REQUEST_NAMESPACE))),
|
||||
path("api/v1/available/", available, name="available"),
|
||||
path("api/v1/get-report/current-federal", get_current_federal, name="get-current-federal"),
|
||||
path("api/v1/get-report/current-full", get_current_full, name="get-current-full"),
|
||||
|
@ -138,9 +138,9 @@ urlpatterns = [
|
|||
name="invitation-delete",
|
||||
),
|
||||
path(
|
||||
"application/<int:pk>/delete",
|
||||
views.DomainApplicationDeleteView.as_view(http_method_names=["post"]),
|
||||
name="application-delete",
|
||||
"domain-request/<int:pk>/delete",
|
||||
views.DomainRequestDeleteView.as_view(http_method_names=["post"]),
|
||||
name="domain-request-delete",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/users/<int:user_pk>/delete",
|
||||
|
|
|
@ -4,7 +4,7 @@ from faker import Faker
|
|||
|
||||
from registrar.models import (
|
||||
User,
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
DraftDomain,
|
||||
Contact,
|
||||
Website,
|
||||
|
@ -14,9 +14,9 @@ fake = Faker()
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DomainApplicationFixture:
|
||||
class DomainRequestFixture:
|
||||
"""
|
||||
Load domain applications into the database.
|
||||
Load domain requests into the database.
|
||||
|
||||
Make sure this class' `load` method is called from `handle`
|
||||
in management/commands/load.py, then use `./manage.py load`
|
||||
|
@ -49,27 +49,27 @@ class DomainApplicationFixture:
|
|||
# },
|
||||
DA = [
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.STARTED,
|
||||
"status": DomainRequest.DomainRequestStatus.STARTED,
|
||||
"organization_name": "Example - Finished but not submitted",
|
||||
},
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.SUBMITTED,
|
||||
"status": DomainRequest.DomainRequestStatus.SUBMITTED,
|
||||
"organization_name": "Example - Submitted but pending investigation",
|
||||
},
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.IN_REVIEW,
|
||||
"status": DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
"organization_name": "Example - In investigation",
|
||||
},
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.IN_REVIEW,
|
||||
"status": DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
"organization_name": "Example - Approved",
|
||||
},
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.WITHDRAWN,
|
||||
"status": DomainRequest.DomainRequestStatus.WITHDRAWN,
|
||||
"organization_name": "Example - Withdrawn",
|
||||
},
|
||||
{
|
||||
"status": DomainApplication.ApplicationStatus.ACTION_NEEDED,
|
||||
"status": DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
"organization_name": "Example - Action needed",
|
||||
},
|
||||
{
|
||||
|
@ -94,7 +94,7 @@ class DomainApplicationFixture:
|
|||
return f"{fake.slug()}.gov"
|
||||
|
||||
@classmethod
|
||||
def _set_non_foreign_key_fields(cls, da: DomainApplication, app: dict):
|
||||
def _set_non_foreign_key_fields(cls, da: DomainRequest, app: dict):
|
||||
"""Helper method used by `load`."""
|
||||
da.status = app["status"] if "status" in app else "started"
|
||||
da.organization_type = app["organization_type"] if "organization_type" in app else "federal"
|
||||
|
@ -102,7 +102,7 @@ class DomainApplicationFixture:
|
|||
app["federal_agency"]
|
||||
if "federal_agency" in app
|
||||
# Random choice of agency for selects, used as placeholders for testing.
|
||||
else random.choice(DomainApplication.AGENCIES) # nosec
|
||||
else random.choice(DomainRequest.AGENCIES) # nosec
|
||||
)
|
||||
da.submission_date = fake.date()
|
||||
da.federal_type = (
|
||||
|
@ -121,7 +121,7 @@ class DomainApplicationFixture:
|
|||
da.is_policy_acknowledged = app["is_policy_acknowledged"] if "is_policy_acknowledged" in app else True
|
||||
|
||||
@classmethod
|
||||
def _set_foreign_key_fields(cls, da: DomainApplication, app: dict, user: User):
|
||||
def _set_foreign_key_fields(cls, da: DomainRequest, app: dict, user: User):
|
||||
"""Helper method used by `load`."""
|
||||
if not da.investigator:
|
||||
da.investigator = User.objects.get(username=user.username) if "investigator" in app else None
|
||||
|
@ -145,7 +145,7 @@ class DomainApplicationFixture:
|
|||
da.requested_domain = DraftDomain.objects.create(name=cls.fake_dot_gov())
|
||||
|
||||
@classmethod
|
||||
def _set_many_to_many_relations(cls, da: DomainApplication, app: dict):
|
||||
def _set_many_to_many_relations(cls, da: DomainRequest, app: dict):
|
||||
"""Helper method used by `load`."""
|
||||
if "other_contacts" in app:
|
||||
for contact in app["other_contacts"]:
|
||||
|
@ -176,8 +176,8 @@ class DomainApplicationFixture:
|
|||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
"""Creates domain applications for each user in the database."""
|
||||
logger.info("Going to load %s domain applications" % len(cls.DA))
|
||||
"""Creates domain requests for each user in the database."""
|
||||
logger.info("Going to load %s domain requests" % len(cls.DA))
|
||||
try:
|
||||
users = list(User.objects.all()) # force evaluation to catch db errors
|
||||
except Exception as e:
|
||||
|
@ -185,10 +185,10 @@ class DomainApplicationFixture:
|
|||
return
|
||||
|
||||
for user in users:
|
||||
logger.debug("Loading domain applications for %s" % user)
|
||||
logger.debug("Loading domain requests for %s" % user)
|
||||
for app in cls.DA:
|
||||
try:
|
||||
da, _ = DomainApplication.objects.get_or_create(
|
||||
da, _ = DomainRequest.objects.get_or_create(
|
||||
creator=user,
|
||||
organization_name=app["organization_name"],
|
||||
)
|
||||
|
@ -200,7 +200,7 @@ class DomainApplicationFixture:
|
|||
logger.warning(e)
|
||||
|
||||
|
||||
class DomainFixture(DomainApplicationFixture):
|
||||
class DomainFixture(DomainRequestFixture):
|
||||
"""Create one domain and permissions on it for each user."""
|
||||
|
||||
@classmethod
|
||||
|
@ -213,12 +213,12 @@ class DomainFixture(DomainApplicationFixture):
|
|||
|
||||
for user in users:
|
||||
# approve one of each users in review status domains
|
||||
application = DomainApplication.objects.filter(
|
||||
creator=user, status=DomainApplication.ApplicationStatus.IN_REVIEW
|
||||
domain_request = DomainRequest.objects.filter(
|
||||
creator=user, status=DomainRequest.DomainRequestStatus.IN_REVIEW
|
||||
).last()
|
||||
logger.debug(f"Approving {application} for {user}")
|
||||
logger.debug(f"Approving {domain_request} for {user}")
|
||||
|
||||
# We don't want fixtures sending out real emails to
|
||||
# fake email addresses, so we just skip that and log it instead
|
||||
application.approve(send_email=False)
|
||||
application.save()
|
||||
domain_request.approve(send_email=False)
|
||||
domain_request.save()
|
|
@ -1,4 +1,4 @@
|
|||
from .application_wizard import *
|
||||
from .domain_request_wizard import *
|
||||
from .domain import (
|
||||
DomainAddUserForm,
|
||||
NameserverFormset,
|
||||
|
|
|
@ -10,7 +10,7 @@ from django.core.validators import RegexValidator, MaxLengthValidator
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.db.models.fields.related import ForeignObjectRel
|
||||
|
||||
from registrar.models import Contact, DomainApplication, DraftDomain, Domain
|
||||
from registrar.models import Contact, DomainRequest, DraftDomain, Domain
|
||||
from registrar.templatetags.url_helpers import public_site_url
|
||||
from registrar.utility.enums import ValidationReturnType
|
||||
|
||||
|
@ -21,7 +21,7 @@ class RegistrarForm(forms.Form):
|
|||
"""
|
||||
A common set of methods and configuration.
|
||||
|
||||
The registrar's domain application is several pages of "steps".
|
||||
The registrar's domain request is several pages of "steps".
|
||||
Each step is an HTML form containing one or more Django "forms".
|
||||
|
||||
Subclass this class to create new forms.
|
||||
|
@ -29,11 +29,11 @@ class RegistrarForm(forms.Form):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("label_suffix", "")
|
||||
# save a reference to an application object
|
||||
self.application = kwargs.pop("application", None)
|
||||
# save a reference to a domain request object
|
||||
self.domain_request = kwargs.pop("domain_request", None)
|
||||
super(RegistrarForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def to_database(self, obj: DomainApplication | Contact):
|
||||
def to_database(self, obj: DomainRequest | Contact):
|
||||
"""
|
||||
Adds this form's cleaned data to `obj` and saves `obj`.
|
||||
|
||||
|
@ -46,7 +46,7 @@ class RegistrarForm(forms.Form):
|
|||
obj.save()
|
||||
|
||||
@classmethod
|
||||
def from_database(cls, obj: DomainApplication | Contact | None):
|
||||
def from_database(cls, obj: DomainRequest | Contact | None):
|
||||
"""Returns a dict of form field values gotten from `obj`."""
|
||||
if obj is None:
|
||||
return {}
|
||||
|
@ -61,8 +61,8 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# save a reference to an application object
|
||||
self.application = kwargs.pop("application", None)
|
||||
# save a reference to an domain_request object
|
||||
self.domain_request = kwargs.pop("domain_request", None)
|
||||
super(RegistrarFormSet, self).__init__(*args, **kwargs)
|
||||
# quick workaround to ensure that the HTML `required`
|
||||
# attribute shows up on required fields for any forms
|
||||
|
@ -85,7 +85,7 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
"""Code to run before an item in the formset is created in the database."""
|
||||
return cleaned
|
||||
|
||||
def to_database(self, obj: DomainApplication):
|
||||
def to_database(self, obj: DomainRequest):
|
||||
"""
|
||||
Adds this form's cleaned data to `obj` and saves `obj`.
|
||||
|
||||
|
@ -97,7 +97,7 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
|
||||
def _to_database(
|
||||
self,
|
||||
obj: DomainApplication,
|
||||
obj: DomainRequest,
|
||||
join: str,
|
||||
should_delete: Callable,
|
||||
pre_update: Callable,
|
||||
|
@ -137,14 +137,14 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
if should_delete(cleaned):
|
||||
if hasattr(db_obj, "has_more_than_one_join") and db_obj.has_more_than_one_join(related_name):
|
||||
# Remove the specific relationship without deleting the object
|
||||
getattr(db_obj, related_name).remove(self.application)
|
||||
getattr(db_obj, related_name).remove(self.domain_request)
|
||||
else:
|
||||
# If there are no other relationships, delete the object
|
||||
db_obj.delete()
|
||||
else:
|
||||
if hasattr(db_obj, "has_more_than_one_join") and db_obj.has_more_than_one_join(related_name):
|
||||
# create a new db_obj and disconnect existing one
|
||||
getattr(db_obj, related_name).remove(self.application)
|
||||
getattr(db_obj, related_name).remove(self.domain_request)
|
||||
kwargs = pre_create(db_obj, cleaned)
|
||||
getattr(obj, join).create(**kwargs)
|
||||
else:
|
||||
|
@ -163,15 +163,15 @@ class RegistrarFormSet(forms.BaseFormSet):
|
|||
return query.values()
|
||||
|
||||
@classmethod
|
||||
def from_database(cls, obj: DomainApplication, join: str, on_fetch: Callable):
|
||||
def from_database(cls, obj: DomainRequest, join: str, on_fetch: Callable):
|
||||
"""Returns a dict of form field values gotten from `obj`."""
|
||||
return on_fetch(getattr(obj, join).order_by("created_at")) # order matters
|
||||
|
||||
|
||||
class OrganizationTypeForm(RegistrarForm):
|
||||
organization_type = forms.ChoiceField(
|
||||
# use the long names in the application form
|
||||
choices=DomainApplication.OrganizationChoicesVerbose.choices,
|
||||
# use the long names in the domain request form
|
||||
choices=DomainRequest.OrganizationChoicesVerbose.choices,
|
||||
widget=forms.RadioSelect,
|
||||
error_messages={"required": "Select the type of organization you represent."},
|
||||
)
|
||||
|
@ -201,7 +201,7 @@ class TribalGovernmentForm(RegistrarForm):
|
|||
# into a link. There should be no user-facing input in the
|
||||
# HTML indicated here.
|
||||
mark_safe( # nosec
|
||||
"You can’t complete this application yet. "
|
||||
"You can’t complete this domain request yet. "
|
||||
"Only tribes recognized by the U.S. federal government "
|
||||
"or by a U.S. state government are eligible for .gov "
|
||||
'domains. Use our <a href="{}">contact form</a> to '
|
||||
|
@ -215,7 +215,7 @@ class TribalGovernmentForm(RegistrarForm):
|
|||
|
||||
class OrganizationFederalForm(RegistrarForm):
|
||||
federal_type = forms.ChoiceField(
|
||||
choices=DomainApplication.BranchChoices.choices,
|
||||
choices=DomainRequest.BranchChoices.choices,
|
||||
widget=forms.RadioSelect,
|
||||
error_messages={"required": ("Select the part of the federal government your organization is in.")},
|
||||
)
|
||||
|
@ -251,7 +251,7 @@ class OrganizationContactForm(RegistrarForm):
|
|||
# it is a federal agency. Use clean to check programatically
|
||||
# if it has been filled in when required.
|
||||
required=False,
|
||||
choices=[("", "--Select--")] + DomainApplication.AGENCY_CHOICES,
|
||||
choices=[("", "--Select--")] + DomainRequest.AGENCY_CHOICES,
|
||||
)
|
||||
organization_name = forms.CharField(
|
||||
label="Organization name",
|
||||
|
@ -271,7 +271,7 @@ class OrganizationContactForm(RegistrarForm):
|
|||
)
|
||||
state_territory = forms.ChoiceField(
|
||||
label="State, territory, or military post",
|
||||
choices=[("", "--Select--")] + DomainApplication.StateTerritoryChoices.choices,
|
||||
choices=[("", "--Select--")] + DomainRequest.StateTerritoryChoices.choices,
|
||||
error_messages={
|
||||
"required": ("Select the state, territory, or military post where your organization is located.")
|
||||
},
|
||||
|
@ -294,16 +294,16 @@ class OrganizationContactForm(RegistrarForm):
|
|||
def clean_federal_agency(self):
|
||||
"""Require something to be selected when this is a federal agency."""
|
||||
federal_agency = self.cleaned_data.get("federal_agency", None)
|
||||
# need the application object to know if this is federal
|
||||
if self.application is None:
|
||||
# hmm, no saved application object?, default require the agency
|
||||
# need the domain request object to know if this is federal
|
||||
if self.domain_request is None:
|
||||
# hmm, no saved domain request object?, default require the agency
|
||||
if not federal_agency:
|
||||
# no answer was selected
|
||||
raise forms.ValidationError(
|
||||
"Select the federal agency your organization is in.",
|
||||
code="required",
|
||||
)
|
||||
if self.application.is_federal():
|
||||
if self.domain_request.is_federal():
|
||||
if not federal_agency:
|
||||
# no answer was selected
|
||||
raise forms.ValidationError(
|
||||
|
@ -390,7 +390,7 @@ class BaseCurrentSitesFormSet(RegistrarFormSet):
|
|||
website = cleaned.get("website", "")
|
||||
return website.strip() == ""
|
||||
|
||||
def to_database(self, obj: DomainApplication):
|
||||
def to_database(self, obj: DomainRequest):
|
||||
# If we want to test against multiple joins for a website object, replace the empty array
|
||||
# and change the JOIN in the models to allow for reverse references
|
||||
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||
|
@ -444,7 +444,7 @@ class BaseAlternativeDomainFormSet(RegistrarFormSet):
|
|||
else:
|
||||
return {}
|
||||
|
||||
def to_database(self, obj: DomainApplication):
|
||||
def to_database(self, obj: DomainRequest):
|
||||
# If we want to test against multiple joins for a website object, replace the empty array and
|
||||
# change the JOIN in the models to allow for reverse references
|
||||
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||
|
@ -530,7 +530,7 @@ class YourContactForm(RegistrarForm):
|
|||
if not self.is_valid():
|
||||
return
|
||||
contact = getattr(obj, "submitter", None)
|
||||
if contact is not None and not contact.has_more_than_one_join("submitted_applications"):
|
||||
if contact is not None and not contact.has_more_than_one_join("submitted_domain_requests"):
|
||||
# if contact exists in the database and is not joined to other entities
|
||||
super().to_database(contact)
|
||||
else:
|
||||
|
@ -578,13 +578,13 @@ class OtherContactsYesNoForm(RegistrarForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
"""Extend the initialization of the form from RegistrarForm __init__"""
|
||||
super().__init__(*args, **kwargs)
|
||||
# set the initial value based on attributes of application
|
||||
if self.application and self.application.has_other_contacts():
|
||||
# set the initial value based on attributes of domain request
|
||||
if self.domain_request and self.domain_request.has_other_contacts():
|
||||
initial_value = True
|
||||
elif self.application and self.application.has_rationale():
|
||||
elif self.domain_request and self.domain_request.has_rationale():
|
||||
initial_value = False
|
||||
else:
|
||||
# No pre-selection for new applications
|
||||
# No pre-selection for new domain requests
|
||||
initial_value = None
|
||||
|
||||
self.fields["has_other_contacts"] = forms.TypedChoiceField(
|
||||
|
@ -687,7 +687,7 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
this case, all forms in formset are marked for deletion. Both of these conditions
|
||||
must co-exist.
|
||||
Also, other_contacts have db relationships to multiple db objects. When attempting
|
||||
to delete an other_contact from an application, those db relationships must be
|
||||
to delete an other_contact from a domain request, those db relationships must be
|
||||
tested and handled.
|
||||
"""
|
||||
|
||||
|
@ -701,7 +701,7 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
Override __init__ for RegistrarFormSet.
|
||||
"""
|
||||
self.formset_data_marked_for_deletion = False
|
||||
self.application = kwargs.pop("application", None)
|
||||
self.domain_request = kwargs.pop("domain_request", None)
|
||||
super(RegistrarFormSet, self).__init__(*args, **kwargs)
|
||||
# quick workaround to ensure that the HTML `required`
|
||||
# attribute shows up on required fields for the first form
|
||||
|
@ -722,7 +722,7 @@ class BaseOtherContactsFormSet(RegistrarFormSet):
|
|||
cleaned.pop("DELETE")
|
||||
return cleaned
|
||||
|
||||
def to_database(self, obj: DomainApplication):
|
||||
def to_database(self, obj: DomainRequest):
|
||||
self._to_database(obj, self.JOIN, self.should_delete, self.pre_update, self.pre_create)
|
||||
|
||||
@classmethod
|
|
@ -5,7 +5,7 @@ from auditlog.context import disable_auditlog # type: ignore
|
|||
|
||||
|
||||
from registrar.fixtures_users import UserFixture
|
||||
from registrar.fixtures_applications import DomainApplicationFixture, DomainFixture
|
||||
from registrar.fixtures_domain_requests import DomainRequestFixture, DomainFixture
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -16,6 +16,6 @@ class Command(BaseCommand):
|
|||
# https://github.com/jazzband/django-auditlog/issues/17
|
||||
with disable_auditlog():
|
||||
UserFixture.load()
|
||||
DomainApplicationFixture.load()
|
||||
DomainRequestFixture.load()
|
||||
DomainFixture.load()
|
||||
logger.info("All fixtures loaded.")
|
||||
|
|
|
@ -15,7 +15,7 @@ from registrar.management.commands.utility.terminal_helper import (
|
|||
TerminalHelper,
|
||||
)
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.models.domain_application import DomainApplication
|
||||
from registrar.models.domain_request import DomainRequest
|
||||
from registrar.models.domain_information import DomainInformation
|
||||
from registrar.models.user import User
|
||||
|
||||
|
@ -817,9 +817,9 @@ class Command(BaseCommand):
|
|||
raise Exception(f"Domain {existing_domain} wants to be added" "but doesn't exist in the DB")
|
||||
invitation.save()
|
||||
|
||||
valid_org_choices = [(name, value) for name, value in DomainApplication.OrganizationChoices.choices]
|
||||
valid_fed_choices = [value for name, value in DomainApplication.BranchChoices.choices]
|
||||
valid_agency_choices = DomainApplication.AGENCIES
|
||||
valid_org_choices = [(name, value) for name, value in DomainRequest.OrganizationChoices.choices]
|
||||
valid_fed_choices = [value for name, value in DomainRequest.BranchChoices.choices]
|
||||
valid_agency_choices = DomainRequest.AGENCIES
|
||||
# ======================================================
|
||||
# ================= DOMAIN INFORMATION =================
|
||||
logger.info(
|
||||
|
|
685
src/registrar/migrations/0073_domainrequest_and_more.py
Normal file
685
src/registrar/migrations/0073_domainrequest_and_more.py
Normal file
|
@ -0,0 +1,685 @@
|
|||
# Generated by Django 4.2.10 on 2024-03-07 21:52
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django_fsm
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0072_alter_publiccontact_fax_alter_publiccontact_voice"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="DomainRequest",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"status",
|
||||
django_fsm.FSMField(
|
||||
choices=[
|
||||
("started", "Started"),
|
||||
("submitted", "Submitted"),
|
||||
("in review", "In review"),
|
||||
("action needed", "Action needed"),
|
||||
("approved", "Approved"),
|
||||
("withdrawn", "Withdrawn"),
|
||||
("rejected", "Rejected"),
|
||||
("ineligible", "Ineligible"),
|
||||
],
|
||||
default="started",
|
||||
max_length=50,
|
||||
),
|
||||
),
|
||||
(
|
||||
"rejection_reason",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("purpose_not_met", "Purpose requirements not met"),
|
||||
("requestor_not_eligible", "Requestor not eligible to make request"),
|
||||
("org_has_domain", "Org already has a .gov domain"),
|
||||
("contacts_not_verified", "Org contacts couldn't be verified"),
|
||||
("org_not_eligible", "Org not eligible for a .gov domain"),
|
||||
("naming_not_met", "Naming requirements not met"),
|
||||
("other", "Other/Unspecified"),
|
||||
],
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"organization_type",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("federal", "Federal"),
|
||||
("interstate", "Interstate"),
|
||||
("state_or_territory", "State or territory"),
|
||||
("tribal", "Tribal"),
|
||||
("county", "County"),
|
||||
("city", "City"),
|
||||
("special_district", "Special district"),
|
||||
("school_district", "School district"),
|
||||
],
|
||||
help_text="Type of organization",
|
||||
max_length=255,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"federally_recognized_tribe",
|
||||
models.BooleanField(help_text="Is the tribe federally recognized", null=True),
|
||||
),
|
||||
(
|
||||
"state_recognized_tribe",
|
||||
models.BooleanField(help_text="Is the tribe recognized by a state", null=True),
|
||||
),
|
||||
("tribe_name", models.CharField(blank=True, help_text="Name of tribe", null=True)),
|
||||
(
|
||||
"federal_agency",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
(
|
||||
"Administrative Conference of the United States",
|
||||
"Administrative Conference of the United States",
|
||||
),
|
||||
("Advisory Council on Historic Preservation", "Advisory Council on Historic Preservation"),
|
||||
("American Battle Monuments Commission", "American Battle Monuments Commission"),
|
||||
("AMTRAK", "AMTRAK"),
|
||||
("Appalachian Regional Commission", "Appalachian Regional Commission"),
|
||||
(
|
||||
"Appraisal Subcommittee of the Federal Financial Institutions Examination Council",
|
||||
"Appraisal Subcommittee of the Federal Financial Institutions Examination Council",
|
||||
),
|
||||
("Appraisal Subcommittee", "Appraisal Subcommittee"),
|
||||
("Architect of the Capitol", "Architect of the Capitol"),
|
||||
("Armed Forces Retirement Home", "Armed Forces Retirement Home"),
|
||||
(
|
||||
"Barry Goldwater Scholarship and Excellence in Education Foundation",
|
||||
"Barry Goldwater Scholarship and Excellence in Education Foundation",
|
||||
),
|
||||
(
|
||||
"Barry Goldwater Scholarship and Excellence in Education Program",
|
||||
"Barry Goldwater Scholarship and Excellence in Education Program",
|
||||
),
|
||||
("Central Intelligence Agency", "Central Intelligence Agency"),
|
||||
("Chemical Safety Board", "Chemical Safety Board"),
|
||||
(
|
||||
"Christopher Columbus Fellowship Foundation",
|
||||
"Christopher Columbus Fellowship Foundation",
|
||||
),
|
||||
(
|
||||
"Civil Rights Cold Case Records Review Board",
|
||||
"Civil Rights Cold Case Records Review Board",
|
||||
),
|
||||
(
|
||||
"Commission for the Preservation of America's Heritage Abroad",
|
||||
"Commission for the Preservation of America's Heritage Abroad",
|
||||
),
|
||||
("Commission of Fine Arts", "Commission of Fine Arts"),
|
||||
(
|
||||
"Committee for Purchase From People Who Are Blind or Severely Disabled",
|
||||
"Committee for Purchase From People Who Are Blind or Severely Disabled",
|
||||
),
|
||||
("Commodity Futures Trading Commission", "Commodity Futures Trading Commission"),
|
||||
("Congressional Budget Office", "Congressional Budget Office"),
|
||||
("Consumer Financial Protection Bureau", "Consumer Financial Protection Bureau"),
|
||||
("Consumer Product Safety Commission", "Consumer Product Safety Commission"),
|
||||
(
|
||||
"Corporation for National & Community Service",
|
||||
"Corporation for National & Community Service",
|
||||
),
|
||||
(
|
||||
"Corporation for National and Community Service",
|
||||
"Corporation for National and Community Service",
|
||||
),
|
||||
(
|
||||
"Council of Inspectors General on Integrity and Efficiency",
|
||||
"Council of Inspectors General on Integrity and Efficiency",
|
||||
),
|
||||
("Court Services and Offender Supervision", "Court Services and Offender Supervision"),
|
||||
("Cyberspace Solarium Commission", "Cyberspace Solarium Commission"),
|
||||
(
|
||||
"DC Court Services and Offender Supervision Agency",
|
||||
"DC Court Services and Offender Supervision Agency",
|
||||
),
|
||||
("DC Pre-trial Services", "DC Pre-trial Services"),
|
||||
("Defense Nuclear Facilities Safety Board", "Defense Nuclear Facilities Safety Board"),
|
||||
("Delta Regional Authority", "Delta Regional Authority"),
|
||||
("Denali Commission", "Denali Commission"),
|
||||
("Department of Agriculture", "Department of Agriculture"),
|
||||
("Department of Commerce", "Department of Commerce"),
|
||||
("Department of Defense", "Department of Defense"),
|
||||
("Department of Education", "Department of Education"),
|
||||
("Department of Energy", "Department of Energy"),
|
||||
("Department of Health and Human Services", "Department of Health and Human Services"),
|
||||
("Department of Homeland Security", "Department of Homeland Security"),
|
||||
(
|
||||
"Department of Housing and Urban Development",
|
||||
"Department of Housing and Urban Development",
|
||||
),
|
||||
("Department of Justice", "Department of Justice"),
|
||||
("Department of Labor", "Department of Labor"),
|
||||
("Department of State", "Department of State"),
|
||||
("Department of the Interior", "Department of the Interior"),
|
||||
("Department of the Treasury", "Department of the Treasury"),
|
||||
("Department of Transportation", "Department of Transportation"),
|
||||
("Department of Veterans Affairs", "Department of Veterans Affairs"),
|
||||
("Director of National Intelligence", "Director of National Intelligence"),
|
||||
("Dwight D. Eisenhower Memorial Commission", "Dwight D. Eisenhower Memorial Commission"),
|
||||
("Election Assistance Commission", "Election Assistance Commission"),
|
||||
("Environmental Protection Agency", "Environmental Protection Agency"),
|
||||
("Equal Employment Opportunity Commission", "Equal Employment Opportunity Commission"),
|
||||
("Executive Office of the President", "Executive Office of the President"),
|
||||
("Export-Import Bank of the United States", "Export-Import Bank of the United States"),
|
||||
("Export/Import Bank of the U.S.", "Export/Import Bank of the U.S."),
|
||||
("Farm Credit Administration", "Farm Credit Administration"),
|
||||
("Farm Credit System Insurance Corporation", "Farm Credit System Insurance Corporation"),
|
||||
("Federal Communications Commission", "Federal Communications Commission"),
|
||||
("Federal Deposit Insurance Corporation", "Federal Deposit Insurance Corporation"),
|
||||
("Federal Election Commission", "Federal Election Commission"),
|
||||
("Federal Energy Regulatory Commission", "Federal Energy Regulatory Commission"),
|
||||
(
|
||||
"Federal Financial Institutions Examination Council",
|
||||
"Federal Financial Institutions Examination Council",
|
||||
),
|
||||
("Federal Housing Finance Agency", "Federal Housing Finance Agency"),
|
||||
("Federal Judiciary", "Federal Judiciary"),
|
||||
("Federal Labor Relations Authority", "Federal Labor Relations Authority"),
|
||||
("Federal Maritime Commission", "Federal Maritime Commission"),
|
||||
(
|
||||
"Federal Mediation and Conciliation Service",
|
||||
"Federal Mediation and Conciliation Service",
|
||||
),
|
||||
(
|
||||
"Federal Mine Safety and Health Review Commission",
|
||||
"Federal Mine Safety and Health Review Commission",
|
||||
),
|
||||
(
|
||||
"Federal Permitting Improvement Steering Council",
|
||||
"Federal Permitting Improvement Steering Council",
|
||||
),
|
||||
("Federal Reserve Board of Governors", "Federal Reserve Board of Governors"),
|
||||
("Federal Reserve System", "Federal Reserve System"),
|
||||
("Federal Trade Commission", "Federal Trade Commission"),
|
||||
("General Services Administration", "General Services Administration"),
|
||||
("gov Administration", "gov Administration"),
|
||||
("Government Accountability Office", "Government Accountability Office"),
|
||||
("Government Publishing Office", "Government Publishing Office"),
|
||||
("Gulf Coast Ecosystem Restoration Council", "Gulf Coast Ecosystem Restoration Council"),
|
||||
("Harry S Truman Scholarship Foundation", "Harry S Truman Scholarship Foundation"),
|
||||
("Harry S. Truman Scholarship Foundation", "Harry S. Truman Scholarship Foundation"),
|
||||
("Institute of Museum and Library Services", "Institute of Museum and Library Services"),
|
||||
("Institute of Peace", "Institute of Peace"),
|
||||
("Inter-American Foundation", "Inter-American Foundation"),
|
||||
(
|
||||
"International Boundary and Water Commission: United States and Mexico",
|
||||
"International Boundary and Water Commission: United States and Mexico",
|
||||
),
|
||||
(
|
||||
"International Boundary Commission: United States and Canada",
|
||||
"International Boundary Commission: United States and Canada",
|
||||
),
|
||||
(
|
||||
"International Joint Commission: United States and Canada",
|
||||
"International Joint Commission: United States and Canada",
|
||||
),
|
||||
(
|
||||
"James Madison Memorial Fellowship Foundation",
|
||||
"James Madison Memorial Fellowship Foundation",
|
||||
),
|
||||
("Japan-United States Friendship Commission", "Japan-United States Friendship Commission"),
|
||||
("Japan-US Friendship Commission", "Japan-US Friendship Commission"),
|
||||
(
|
||||
"John F. Kennedy Center for Performing Arts",
|
||||
"John F. Kennedy Center for Performing Arts",
|
||||
),
|
||||
(
|
||||
"John F. Kennedy Center for the Performing Arts",
|
||||
"John F. Kennedy Center for the Performing Arts",
|
||||
),
|
||||
("Legal Services Corporation", "Legal Services Corporation"),
|
||||
("Legislative Branch", "Legislative Branch"),
|
||||
("Library of Congress", "Library of Congress"),
|
||||
("Marine Mammal Commission", "Marine Mammal Commission"),
|
||||
(
|
||||
"Medicaid and CHIP Payment and Access Commission",
|
||||
"Medicaid and CHIP Payment and Access Commission",
|
||||
),
|
||||
("Medical Payment Advisory Commission", "Medical Payment Advisory Commission"),
|
||||
("Medicare Payment Advisory Commission", "Medicare Payment Advisory Commission"),
|
||||
("Merit Systems Protection Board", "Merit Systems Protection Board"),
|
||||
("Millennium Challenge Corporation", "Millennium Challenge Corporation"),
|
||||
(
|
||||
"Morris K. Udall and Stewart L. Udall Foundation",
|
||||
"Morris K. Udall and Stewart L. Udall Foundation",
|
||||
),
|
||||
(
|
||||
"National Aeronautics and Space Administration",
|
||||
"National Aeronautics and Space Administration",
|
||||
),
|
||||
(
|
||||
"National Archives and Records Administration",
|
||||
"National Archives and Records Administration",
|
||||
),
|
||||
("National Capital Planning Commission", "National Capital Planning Commission"),
|
||||
("National Council on Disability", "National Council on Disability"),
|
||||
("National Credit Union Administration", "National Credit Union Administration"),
|
||||
("National Endowment for the Arts", "National Endowment for the Arts"),
|
||||
("National Endowment for the Humanities", "National Endowment for the Humanities"),
|
||||
(
|
||||
"National Foundation on the Arts and the Humanities",
|
||||
"National Foundation on the Arts and the Humanities",
|
||||
),
|
||||
("National Gallery of Art", "National Gallery of Art"),
|
||||
("National Indian Gaming Commission", "National Indian Gaming Commission"),
|
||||
("National Labor Relations Board", "National Labor Relations Board"),
|
||||
("National Mediation Board", "National Mediation Board"),
|
||||
("National Science Foundation", "National Science Foundation"),
|
||||
(
|
||||
"National Security Commission on Artificial Intelligence",
|
||||
"National Security Commission on Artificial Intelligence",
|
||||
),
|
||||
("National Transportation Safety Board", "National Transportation Safety Board"),
|
||||
(
|
||||
"Networking Information Technology Research and Development",
|
||||
"Networking Information Technology Research and Development",
|
||||
),
|
||||
("Non-Federal Agency", "Non-Federal Agency"),
|
||||
("Northern Border Regional Commission", "Northern Border Regional Commission"),
|
||||
("Nuclear Regulatory Commission", "Nuclear Regulatory Commission"),
|
||||
("Nuclear Safety Oversight Committee", "Nuclear Safety Oversight Committee"),
|
||||
("Nuclear Waste Technical Review Board", "Nuclear Waste Technical Review Board"),
|
||||
(
|
||||
"Occupational Safety & Health Review Commission",
|
||||
"Occupational Safety & Health Review Commission",
|
||||
),
|
||||
(
|
||||
"Occupational Safety and Health Review Commission",
|
||||
"Occupational Safety and Health Review Commission",
|
||||
),
|
||||
("Office of Compliance", "Office of Compliance"),
|
||||
("Office of Congressional Workplace Rights", "Office of Congressional Workplace Rights"),
|
||||
("Office of Government Ethics", "Office of Government Ethics"),
|
||||
(
|
||||
"Office of Navajo and Hopi Indian Relocation",
|
||||
"Office of Navajo and Hopi Indian Relocation",
|
||||
),
|
||||
("Office of Personnel Management", "Office of Personnel Management"),
|
||||
("Open World Leadership Center", "Open World Leadership Center"),
|
||||
("Overseas Private Investment Corporation", "Overseas Private Investment Corporation"),
|
||||
("Peace Corps", "Peace Corps"),
|
||||
("Pension Benefit Guaranty Corporation", "Pension Benefit Guaranty Corporation"),
|
||||
("Postal Regulatory Commission", "Postal Regulatory Commission"),
|
||||
("Presidio Trust", "Presidio Trust"),
|
||||
(
|
||||
"Privacy and Civil Liberties Oversight Board",
|
||||
"Privacy and Civil Liberties Oversight Board",
|
||||
),
|
||||
("Public Buildings Reform Board", "Public Buildings Reform Board"),
|
||||
(
|
||||
"Public Defender Service for the District of Columbia",
|
||||
"Public Defender Service for the District of Columbia",
|
||||
),
|
||||
("Railroad Retirement Board", "Railroad Retirement Board"),
|
||||
("Securities and Exchange Commission", "Securities and Exchange Commission"),
|
||||
("Selective Service System", "Selective Service System"),
|
||||
("Small Business Administration", "Small Business Administration"),
|
||||
("Smithsonian Institution", "Smithsonian Institution"),
|
||||
("Social Security Administration", "Social Security Administration"),
|
||||
("Social Security Advisory Board", "Social Security Advisory Board"),
|
||||
("Southeast Crescent Regional Commission", "Southeast Crescent Regional Commission"),
|
||||
("Southwest Border Regional Commission", "Southwest Border Regional Commission"),
|
||||
("State Justice Institute", "State Justice Institute"),
|
||||
("State, Local, and Tribal Government", "State, Local, and Tribal Government"),
|
||||
("Stennis Center for Public Service", "Stennis Center for Public Service"),
|
||||
("Surface Transportation Board", "Surface Transportation Board"),
|
||||
("Tennessee Valley Authority", "Tennessee Valley Authority"),
|
||||
("The Executive Office of the President", "The Executive Office of the President"),
|
||||
("The Intelligence Community", "The Intelligence Community"),
|
||||
("The Legislative Branch", "The Legislative Branch"),
|
||||
("The Supreme Court", "The Supreme Court"),
|
||||
(
|
||||
"The United States World War One Centennial Commission",
|
||||
"The United States World War One Centennial Commission",
|
||||
),
|
||||
("U.S. Access Board", "U.S. Access Board"),
|
||||
("U.S. Agency for Global Media", "U.S. Agency for Global Media"),
|
||||
("U.S. Agency for International Development", "U.S. Agency for International Development"),
|
||||
("U.S. Capitol Police", "U.S. Capitol Police"),
|
||||
("U.S. Chemical Safety Board", "U.S. Chemical Safety Board"),
|
||||
(
|
||||
"U.S. China Economic and Security Review Commission",
|
||||
"U.S. China Economic and Security Review Commission",
|
||||
),
|
||||
(
|
||||
"U.S. Commission for the Preservation of Americas Heritage Abroad",
|
||||
"U.S. Commission for the Preservation of Americas Heritage Abroad",
|
||||
),
|
||||
("U.S. Commission of Fine Arts", "U.S. Commission of Fine Arts"),
|
||||
("U.S. Commission on Civil Rights", "U.S. Commission on Civil Rights"),
|
||||
(
|
||||
"U.S. Commission on International Religious Freedom",
|
||||
"U.S. Commission on International Religious Freedom",
|
||||
),
|
||||
("U.S. Courts", "U.S. Courts"),
|
||||
("U.S. Department of Agriculture", "U.S. Department of Agriculture"),
|
||||
("U.S. Interagency Council on Homelessness", "U.S. Interagency Council on Homelessness"),
|
||||
("U.S. International Trade Commission", "U.S. International Trade Commission"),
|
||||
("U.S. Nuclear Waste Technical Review Board", "U.S. Nuclear Waste Technical Review Board"),
|
||||
("U.S. Office of Special Counsel", "U.S. Office of Special Counsel"),
|
||||
("U.S. Peace Corps", "U.S. Peace Corps"),
|
||||
("U.S. Postal Service", "U.S. Postal Service"),
|
||||
("U.S. Semiquincentennial Commission", "U.S. Semiquincentennial Commission"),
|
||||
("U.S. Trade and Development Agency", "U.S. Trade and Development Agency"),
|
||||
(
|
||||
"U.S.-China Economic and Security Review Commission",
|
||||
"U.S.-China Economic and Security Review Commission",
|
||||
),
|
||||
("Udall Foundation", "Udall Foundation"),
|
||||
("United States AbilityOne", "United States AbilityOne"),
|
||||
("United States Access Board", "United States Access Board"),
|
||||
(
|
||||
"United States African Development Foundation",
|
||||
"United States African Development Foundation",
|
||||
),
|
||||
("United States Agency for Global Media", "United States Agency for Global Media"),
|
||||
("United States Arctic Research Commission", "United States Arctic Research Commission"),
|
||||
(
|
||||
"United States Global Change Research Program",
|
||||
"United States Global Change Research Program",
|
||||
),
|
||||
("United States Holocaust Memorial Museum", "United States Holocaust Memorial Museum"),
|
||||
("United States Institute of Peace", "United States Institute of Peace"),
|
||||
(
|
||||
"United States Interagency Council on Homelessness",
|
||||
"United States Interagency Council on Homelessness",
|
||||
),
|
||||
(
|
||||
"United States International Development Finance Corporation",
|
||||
"United States International Development Finance Corporation",
|
||||
),
|
||||
(
|
||||
"United States International Trade Commission",
|
||||
"United States International Trade Commission",
|
||||
),
|
||||
("United States Postal Service", "United States Postal Service"),
|
||||
("United States Senate", "United States Senate"),
|
||||
(
|
||||
"United States Trade and Development Agency",
|
||||
"United States Trade and Development Agency",
|
||||
),
|
||||
(
|
||||
"Utah Reclamation Mitigation and Conservation Commission",
|
||||
"Utah Reclamation Mitigation and Conservation Commission",
|
||||
),
|
||||
("Vietnam Education Foundation", "Vietnam Education Foundation"),
|
||||
("Western Hemisphere Drug Policy Commission", "Western Hemisphere Drug Policy Commission"),
|
||||
(
|
||||
"Woodrow Wilson International Center for Scholars",
|
||||
"Woodrow Wilson International Center for Scholars",
|
||||
),
|
||||
("World War I Centennial Commission", "World War I Centennial Commission"),
|
||||
],
|
||||
help_text="Federal agency",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"federal_type",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[("executive", "Executive"), ("judicial", "Judicial"), ("legislative", "Legislative")],
|
||||
help_text="Federal government branch",
|
||||
max_length=50,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_election_board",
|
||||
models.BooleanField(blank=True, help_text="Is your organization an election office?", null=True),
|
||||
),
|
||||
(
|
||||
"organization_name",
|
||||
models.CharField(blank=True, db_index=True, help_text="Organization name", null=True),
|
||||
),
|
||||
(
|
||||
"address_line1",
|
||||
models.CharField(blank=True, help_text="Street address", null=True, verbose_name="Address line 1"),
|
||||
),
|
||||
(
|
||||
"address_line2",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
help_text="Street address line 2 (optional)",
|
||||
null=True,
|
||||
verbose_name="Address line 2",
|
||||
),
|
||||
),
|
||||
("city", models.CharField(blank=True, help_text="City", null=True)),
|
||||
(
|
||||
"state_territory",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
("AL", "Alabama (AL)"),
|
||||
("AK", "Alaska (AK)"),
|
||||
("AS", "American Samoa (AS)"),
|
||||
("AZ", "Arizona (AZ)"),
|
||||
("AR", "Arkansas (AR)"),
|
||||
("CA", "California (CA)"),
|
||||
("CO", "Colorado (CO)"),
|
||||
("CT", "Connecticut (CT)"),
|
||||
("DE", "Delaware (DE)"),
|
||||
("DC", "District of Columbia (DC)"),
|
||||
("FL", "Florida (FL)"),
|
||||
("GA", "Georgia (GA)"),
|
||||
("GU", "Guam (GU)"),
|
||||
("HI", "Hawaii (HI)"),
|
||||
("ID", "Idaho (ID)"),
|
||||
("IL", "Illinois (IL)"),
|
||||
("IN", "Indiana (IN)"),
|
||||
("IA", "Iowa (IA)"),
|
||||
("KS", "Kansas (KS)"),
|
||||
("KY", "Kentucky (KY)"),
|
||||
("LA", "Louisiana (LA)"),
|
||||
("ME", "Maine (ME)"),
|
||||
("MD", "Maryland (MD)"),
|
||||
("MA", "Massachusetts (MA)"),
|
||||
("MI", "Michigan (MI)"),
|
||||
("MN", "Minnesota (MN)"),
|
||||
("MS", "Mississippi (MS)"),
|
||||
("MO", "Missouri (MO)"),
|
||||
("MT", "Montana (MT)"),
|
||||
("NE", "Nebraska (NE)"),
|
||||
("NV", "Nevada (NV)"),
|
||||
("NH", "New Hampshire (NH)"),
|
||||
("NJ", "New Jersey (NJ)"),
|
||||
("NM", "New Mexico (NM)"),
|
||||
("NY", "New York (NY)"),
|
||||
("NC", "North Carolina (NC)"),
|
||||
("ND", "North Dakota (ND)"),
|
||||
("MP", "Northern Mariana Islands (MP)"),
|
||||
("OH", "Ohio (OH)"),
|
||||
("OK", "Oklahoma (OK)"),
|
||||
("OR", "Oregon (OR)"),
|
||||
("PA", "Pennsylvania (PA)"),
|
||||
("PR", "Puerto Rico (PR)"),
|
||||
("RI", "Rhode Island (RI)"),
|
||||
("SC", "South Carolina (SC)"),
|
||||
("SD", "South Dakota (SD)"),
|
||||
("TN", "Tennessee (TN)"),
|
||||
("TX", "Texas (TX)"),
|
||||
("UM", "United States Minor Outlying Islands (UM)"),
|
||||
("UT", "Utah (UT)"),
|
||||
("VT", "Vermont (VT)"),
|
||||
("VI", "Virgin Islands (VI)"),
|
||||
("VA", "Virginia (VA)"),
|
||||
("WA", "Washington (WA)"),
|
||||
("WV", "West Virginia (WV)"),
|
||||
("WI", "Wisconsin (WI)"),
|
||||
("WY", "Wyoming (WY)"),
|
||||
("AA", "Armed Forces Americas (AA)"),
|
||||
("AE", "Armed Forces Africa, Canada, Europe, Middle East (AE)"),
|
||||
("AP", "Armed Forces Pacific (AP)"),
|
||||
],
|
||||
help_text="State, territory, or military post",
|
||||
max_length=2,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"zipcode",
|
||||
models.CharField(blank=True, db_index=True, help_text="Zip code", max_length=10, null=True),
|
||||
),
|
||||
(
|
||||
"urbanization",
|
||||
models.CharField(blank=True, help_text="Urbanization (required for Puerto Rico only)", null=True),
|
||||
),
|
||||
(
|
||||
"about_your_organization",
|
||||
models.TextField(blank=True, help_text="Information about your organization", null=True),
|
||||
),
|
||||
("purpose", models.TextField(blank=True, help_text="Purpose of your domain", null=True)),
|
||||
(
|
||||
"no_other_contacts_rationale",
|
||||
models.TextField(blank=True, help_text="Reason for listing no additional contacts", null=True),
|
||||
),
|
||||
("anything_else", models.TextField(blank=True, help_text="Anything else?", null=True)),
|
||||
(
|
||||
"is_policy_acknowledged",
|
||||
models.BooleanField(blank=True, help_text="Acknowledged .gov acceptable use policy", null=True),
|
||||
),
|
||||
("submission_date", models.DateField(blank=True, default=None, help_text="Date submitted", null=True)),
|
||||
("notes", models.TextField(blank=True, help_text="Notes about this request", null=True)),
|
||||
(
|
||||
"alternative_domains",
|
||||
models.ManyToManyField(blank=True, related_name="alternatives+", to="registrar.website"),
|
||||
),
|
||||
(
|
||||
"approved_domain",
|
||||
models.OneToOneField(
|
||||
blank=True,
|
||||
help_text="The approved domain",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="domain_request",
|
||||
to="registrar.domain",
|
||||
),
|
||||
),
|
||||
(
|
||||
"authorizing_official",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="authorizing_official",
|
||||
to="registrar.contact",
|
||||
),
|
||||
),
|
||||
(
|
||||
"creator",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="domain_requests_created",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"current_websites",
|
||||
models.ManyToManyField(
|
||||
blank=True, related_name="current+", to="registrar.website", verbose_name="websites"
|
||||
),
|
||||
),
|
||||
(
|
||||
"investigator",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="domain_requests_investigating",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"other_contacts",
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name="contact_domain_requests",
|
||||
to="registrar.contact",
|
||||
verbose_name="contacts",
|
||||
),
|
||||
),
|
||||
(
|
||||
"requested_domain",
|
||||
models.OneToOneField(
|
||||
blank=True,
|
||||
help_text="The requested domain",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="domain_request",
|
||||
to="registrar.draftdomain",
|
||||
),
|
||||
),
|
||||
(
|
||||
"submitter",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="submitted_domain_requests",
|
||||
to="registrar.contact",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="domaininformation",
|
||||
name="domain_application",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="other_contacts",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name="contact_domain_requests_information",
|
||||
to="registrar.contact",
|
||||
verbose_name="contacts",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="submitter",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="submitted_domain_requests_information",
|
||||
to="registrar.contact",
|
||||
),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="DomainApplication",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="domaininformation",
|
||||
name="domain_request",
|
||||
field=models.OneToOneField(
|
||||
blank=True,
|
||||
help_text="Associated domain request",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="DomainRequest_info",
|
||||
to="registrar.domainrequest",
|
||||
),
|
||||
),
|
||||
]
|
37
src/registrar/migrations/0074_create_groups_v08.py
Normal file
37
src/registrar/migrations/0074_create_groups_v08.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# This migration creates the create_full_access_group and create_cisa_analyst_group groups
|
||||
# It is dependent on 0035 (which populates ContentType and Permissions)
|
||||
# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS
|
||||
# in the user_group model then:
|
||||
# [NOT RECOMMENDED]
|
||||
# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions
|
||||
# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups
|
||||
# step 3: fake run the latest migration in the migrations list
|
||||
# [RECOMMENDED]
|
||||
# Alternatively:
|
||||
# step 1: duplicate the migration that loads data
|
||||
# step 2: docker-compose exec app ./manage.py migrate
|
||||
|
||||
from django.db import migrations
|
||||
from registrar.models import UserGroup
|
||||
from typing import Any
|
||||
|
||||
|
||||
# For linting: RunPython expects a function reference,
|
||||
# so let's give it one
|
||||
def create_groups(apps, schema_editor) -> Any:
|
||||
UserGroup.create_cisa_analyst_group(apps, schema_editor)
|
||||
UserGroup.create_full_access_group(apps, schema_editor)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("registrar", "0073_domainrequest_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
create_groups,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
atomic=True,
|
||||
),
|
||||
]
|
|
@ -1,6 +1,6 @@
|
|||
from auditlog.registry import auditlog # type: ignore
|
||||
from .contact import Contact
|
||||
from .domain_application import DomainApplication
|
||||
from .domain_request import DomainRequest
|
||||
from .domain_information import DomainInformation
|
||||
from .domain import Domain
|
||||
from .draft_domain import DraftDomain
|
||||
|
@ -17,7 +17,7 @@ from .verified_by_staff import VerifiedByStaff
|
|||
|
||||
__all__ = [
|
||||
"Contact",
|
||||
"DomainApplication",
|
||||
"DomainRequest",
|
||||
"DomainInformation",
|
||||
"Domain",
|
||||
"DraftDomain",
|
||||
|
@ -34,7 +34,7 @@ __all__ = [
|
|||
]
|
||||
|
||||
auditlog.register(Contact)
|
||||
auditlog.register(DomainApplication)
|
||||
auditlog.register(DomainRequest)
|
||||
auditlog.register(Domain)
|
||||
auditlog.register(DraftDomain)
|
||||
auditlog.register(DomainInvitation)
|
||||
|
|
|
@ -897,8 +897,8 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
def security_contact(self, contact: PublicContact):
|
||||
"""makes the contact in the registry,
|
||||
for security the public contact should have the org or registrant information
|
||||
from domain information (not domain application)
|
||||
and should have the security email from DomainApplication"""
|
||||
from domain information (not domain request)
|
||||
and should have the security email from DomainRequest"""
|
||||
logger.info("making security contact in registry")
|
||||
self._set_singleton_contact(contact, expectedType=contact.ContactTypeChoices.SECURITY)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||
from django.db import transaction
|
||||
|
||||
from registrar.models.utility.domain_helper import DomainHelper
|
||||
from .domain_application import DomainApplication
|
||||
from .domain_request import DomainRequest
|
||||
from .utility.time_stamped_model import TimeStampedModel
|
||||
|
||||
import logging
|
||||
|
@ -15,22 +15,22 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class DomainInformation(TimeStampedModel):
|
||||
"""A registrant's domain information for that domain, exported from
|
||||
DomainApplication. We use these field from DomainApplication with few exceptions
|
||||
DomainRequest. We use these field from DomainRequest with few exceptions
|
||||
which are 'removed' via pop at the bottom of this file. Most of design for domain
|
||||
management's user information are based on application, but we cannot change
|
||||
the application once approved, so copying them that way we can make changes
|
||||
after its approved. Most fields here are copied from Application."""
|
||||
management's user information are based on domain_request, but we cannot change
|
||||
the domain request once approved, so copying them that way we can make changes
|
||||
after its approved. Most fields here are copied from DomainRequest."""
|
||||
|
||||
StateTerritoryChoices = DomainApplication.StateTerritoryChoices
|
||||
StateTerritoryChoices = DomainRequest.StateTerritoryChoices
|
||||
|
||||
# use the short names in Django admin
|
||||
OrganizationChoices = DomainApplication.OrganizationChoices
|
||||
OrganizationChoices = DomainRequest.OrganizationChoices
|
||||
|
||||
BranchChoices = DomainApplication.BranchChoices
|
||||
BranchChoices = DomainRequest.BranchChoices
|
||||
|
||||
AGENCY_CHOICES = DomainApplication.AGENCY_CHOICES
|
||||
AGENCY_CHOICES = DomainRequest.AGENCY_CHOICES
|
||||
|
||||
# This is the application user who created this application. The contact
|
||||
# This is the domain request user who created this domain request. The contact
|
||||
# information that they gave is in the `submitter` field
|
||||
creator = models.ForeignKey(
|
||||
"registrar.User",
|
||||
|
@ -38,13 +38,13 @@ class DomainInformation(TimeStampedModel):
|
|||
related_name="information_created",
|
||||
)
|
||||
|
||||
domain_application = models.OneToOneField(
|
||||
"registrar.DomainApplication",
|
||||
domain_request = models.OneToOneField(
|
||||
"registrar.DomainRequest",
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="domainapplication_info",
|
||||
help_text="Associated domain application",
|
||||
related_name="DomainRequest_info",
|
||||
help_text="Associated domain request",
|
||||
unique=True,
|
||||
)
|
||||
|
||||
|
@ -163,13 +163,13 @@ class DomainInformation(TimeStampedModel):
|
|||
help_text="Domain to which this information belongs",
|
||||
)
|
||||
|
||||
# This is the contact information provided by the applicant. The
|
||||
# application user who created it is in the `creator` field.
|
||||
# This is the contact information provided by the domain requestor. The
|
||||
# user who created the domain request is in the `creator` field.
|
||||
submitter = models.ForeignKey(
|
||||
"registrar.Contact",
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="submitted_applications_information",
|
||||
related_name="submitted_domain_requests_information",
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
|
@ -182,7 +182,7 @@ class DomainInformation(TimeStampedModel):
|
|||
other_contacts = models.ManyToManyField(
|
||||
"registrar.Contact",
|
||||
blank=True,
|
||||
related_name="contact_applications_information",
|
||||
related_name="contact_domain_requests_information",
|
||||
verbose_name="contacts",
|
||||
)
|
||||
|
||||
|
@ -220,25 +220,25 @@ class DomainInformation(TimeStampedModel):
|
|||
return ""
|
||||
|
||||
@classmethod
|
||||
def create_from_da(cls, domain_application: DomainApplication, domain=None):
|
||||
"""Takes in a DomainApplication and converts it into DomainInformation"""
|
||||
def create_from_da(cls, domain_request: DomainRequest, domain=None):
|
||||
"""Takes in a DomainRequest and converts it into DomainInformation"""
|
||||
|
||||
# Throw an error if we get None - we can't create something from nothing
|
||||
if domain_application is None:
|
||||
raise ValueError("The provided DomainApplication is None")
|
||||
if domain_request is None:
|
||||
raise ValueError("The provided DomainRequest is None")
|
||||
|
||||
# Throw an error if the da doesn't have an id
|
||||
if not hasattr(domain_application, "id"):
|
||||
raise ValueError("The provided DomainApplication has no id")
|
||||
if not hasattr(domain_request, "id"):
|
||||
raise ValueError("The provided DomainRequest has no id")
|
||||
|
||||
# check if we have a record that corresponds with the domain
|
||||
# application, if so short circuit the create
|
||||
existing_domain_info = cls.objects.filter(domain_application__id=domain_application.id).first()
|
||||
# domain_request, if so short circuit the create
|
||||
existing_domain_info = cls.objects.filter(domain_request__id=domain_request.id).first()
|
||||
if existing_domain_info:
|
||||
return existing_domain_info
|
||||
|
||||
# Get the fields that exist on both DomainApplication and DomainInformation
|
||||
common_fields = DomainHelper.get_common_fields(DomainApplication, DomainInformation)
|
||||
# Get the fields that exist on both DomainRequest and DomainInformation
|
||||
common_fields = DomainHelper.get_common_fields(DomainRequest, DomainInformation)
|
||||
|
||||
# Get a list of all many_to_many relations on DomainInformation (needs to be saved differently)
|
||||
info_many_to_many_fields = DomainInformation._get_many_to_many_fields()
|
||||
|
@ -249,11 +249,11 @@ class DomainInformation(TimeStampedModel):
|
|||
for field in common_fields:
|
||||
# If the field isn't many_to_many, populate the da_dict.
|
||||
# If it is, populate da_many_to_many_dict as we need to save this later.
|
||||
if hasattr(domain_application, field):
|
||||
if hasattr(domain_request, field):
|
||||
if field not in info_many_to_many_fields:
|
||||
da_dict[field] = getattr(domain_application, field)
|
||||
da_dict[field] = getattr(domain_request, field)
|
||||
else:
|
||||
da_many_to_many_dict[field] = getattr(domain_application, field).all()
|
||||
da_many_to_many_dict[field] = getattr(domain_request, field).all()
|
||||
|
||||
# This will not happen in normal code flow, but having some redundancy doesn't hurt.
|
||||
# da_dict should not have "id" under any circumstances.
|
||||
|
@ -266,8 +266,8 @@ class DomainInformation(TimeStampedModel):
|
|||
# Create a placeholder DomainInformation object
|
||||
domain_info = DomainInformation(**da_dict)
|
||||
|
||||
# Add the domain_application and domain fields
|
||||
domain_info.domain_application = domain_application
|
||||
# Add the domain_request and domain fields
|
||||
domain_info.domain_request = domain_request
|
||||
if domain:
|
||||
domain_info.domain = domain
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@ from itertools import chain
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DomainApplication(TimeStampedModel):
|
||||
"""A registrant's application for a new domain."""
|
||||
class DomainRequest(TimeStampedModel):
|
||||
"""A registrant's domain request for a new domain."""
|
||||
|
||||
# Constants for choice fields
|
||||
class ApplicationStatus(models.TextChoices):
|
||||
class DomainRequestStatus(models.TextChoices):
|
||||
STARTED = "started", "Started"
|
||||
SUBMITTED = "submitted", "Submitted"
|
||||
IN_REVIEW = "in review", "In review"
|
||||
|
@ -115,7 +115,7 @@ class DomainApplication(TimeStampedModel):
|
|||
class OrganizationChoicesVerbose(models.TextChoices):
|
||||
"""
|
||||
Secondary organization choices
|
||||
For use in the application form and on the templates
|
||||
For use in the domain request form and on the templates
|
||||
Keys need to match OrganizationChoices
|
||||
"""
|
||||
|
||||
|
@ -366,10 +366,10 @@ class DomainApplication(TimeStampedModel):
|
|||
NAMING_REQUIREMENTS = "naming_not_met", "Naming requirements not met"
|
||||
OTHER = "other", "Other/Unspecified"
|
||||
|
||||
# #### Internal fields about the application #####
|
||||
# #### Internal fields about the domain request #####
|
||||
status = FSMField(
|
||||
choices=ApplicationStatus.choices, # possible states as an array of constants
|
||||
default=ApplicationStatus.STARTED, # sensible default
|
||||
choices=DomainRequestStatus.choices, # possible states as an array of constants
|
||||
default=DomainRequestStatus.STARTED, # sensible default
|
||||
protected=False, # can change state directly, particularly in Django admin
|
||||
)
|
||||
|
||||
|
@ -379,12 +379,12 @@ class DomainApplication(TimeStampedModel):
|
|||
blank=True,
|
||||
)
|
||||
|
||||
# This is the application user who created this application. The contact
|
||||
# This is the domain request user who created this domain request. The contact
|
||||
# information that they gave is in the `submitter` field
|
||||
creator = models.ForeignKey(
|
||||
"registrar.User",
|
||||
on_delete=models.PROTECT,
|
||||
related_name="applications_created",
|
||||
related_name="domain_requests_created",
|
||||
)
|
||||
|
||||
investigator = models.ForeignKey(
|
||||
|
@ -392,7 +392,7 @@ class DomainApplication(TimeStampedModel):
|
|||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name="applications_investigating",
|
||||
related_name="domain_requests_investigating",
|
||||
)
|
||||
|
||||
# ##### data fields from the initial form #####
|
||||
|
@ -499,7 +499,7 @@ class DomainApplication(TimeStampedModel):
|
|||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
# "+" means no reverse relation to lookup applications from Website
|
||||
# "+" means no reverse relation to lookup domain requests from Website
|
||||
current_websites = models.ManyToManyField(
|
||||
"registrar.Website",
|
||||
blank=True,
|
||||
|
@ -512,7 +512,7 @@ class DomainApplication(TimeStampedModel):
|
|||
null=True,
|
||||
blank=True,
|
||||
help_text="The approved domain",
|
||||
related_name="domain_application",
|
||||
related_name="domain_request",
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
|
||||
|
@ -521,7 +521,7 @@ class DomainApplication(TimeStampedModel):
|
|||
null=True,
|
||||
blank=True,
|
||||
help_text="The requested domain",
|
||||
related_name="domain_application",
|
||||
related_name="domain_request",
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
alternative_domains = models.ManyToManyField(
|
||||
|
@ -530,13 +530,13 @@ class DomainApplication(TimeStampedModel):
|
|||
related_name="alternatives+",
|
||||
)
|
||||
|
||||
# This is the contact information provided by the applicant. The
|
||||
# application user who created it is in the `creator` field.
|
||||
# This is the contact information provided by the domain requestor. The
|
||||
# user who created the domain request is in the `creator` field.
|
||||
submitter = models.ForeignKey(
|
||||
"registrar.Contact",
|
||||
null=True,
|
||||
blank=True,
|
||||
related_name="submitted_applications",
|
||||
related_name="submitted_domain_requests",
|
||||
on_delete=models.PROTECT,
|
||||
)
|
||||
|
||||
|
@ -549,7 +549,7 @@ class DomainApplication(TimeStampedModel):
|
|||
other_contacts = models.ManyToManyField(
|
||||
"registrar.Contact",
|
||||
blank=True,
|
||||
related_name="contact_applications",
|
||||
related_name="contact_domain_requests",
|
||||
verbose_name="contacts",
|
||||
)
|
||||
|
||||
|
@ -571,7 +571,7 @@ class DomainApplication(TimeStampedModel):
|
|||
help_text="Acknowledged .gov acceptable use policy",
|
||||
)
|
||||
|
||||
# submission date records when application is submitted
|
||||
# submission date records when domain request is submitted
|
||||
submission_date = models.DateField(
|
||||
null=True,
|
||||
blank=True,
|
||||
|
@ -590,7 +590,7 @@ class DomainApplication(TimeStampedModel):
|
|||
if self.requested_domain and self.requested_domain.name:
|
||||
return self.requested_domain.name
|
||||
else:
|
||||
return f"{self.status} application created by {self.creator}"
|
||||
return f"{self.status} domain request created by {self.creator}"
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
@ -638,7 +638,7 @@ class DomainApplication(TimeStampedModel):
|
|||
email_template,
|
||||
email_template_subject,
|
||||
self.submitter.email,
|
||||
context={"application": self},
|
||||
context={"domain_request": self},
|
||||
bcc_address=bcc_address,
|
||||
)
|
||||
logger.info(f"The {new_status} email sent to: {self.submitter.email}")
|
||||
|
@ -648,15 +648,15 @@ class DomainApplication(TimeStampedModel):
|
|||
@transition(
|
||||
field="status",
|
||||
source=[
|
||||
ApplicationStatus.STARTED,
|
||||
ApplicationStatus.IN_REVIEW,
|
||||
ApplicationStatus.ACTION_NEEDED,
|
||||
ApplicationStatus.WITHDRAWN,
|
||||
DomainRequestStatus.STARTED,
|
||||
DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequestStatus.ACTION_NEEDED,
|
||||
DomainRequestStatus.WITHDRAWN,
|
||||
],
|
||||
target=ApplicationStatus.SUBMITTED,
|
||||
target=DomainRequestStatus.SUBMITTED,
|
||||
)
|
||||
def submit(self):
|
||||
"""Submit an application that is started.
|
||||
"""Submit a domain request that is started.
|
||||
|
||||
As a side effect, an email notification is sent."""
|
||||
|
||||
|
@ -679,7 +679,7 @@ class DomainApplication(TimeStampedModel):
|
|||
self.save()
|
||||
|
||||
# Limit email notifications to transitions from Started and Withdrawn
|
||||
limited_statuses = [self.ApplicationStatus.STARTED, self.ApplicationStatus.WITHDRAWN]
|
||||
limited_statuses = [self.DomainRequestStatus.STARTED, self.DomainRequestStatus.WITHDRAWN]
|
||||
|
||||
bcc_address = ""
|
||||
if settings.IS_PRODUCTION:
|
||||
|
@ -697,17 +697,17 @@ class DomainApplication(TimeStampedModel):
|
|||
@transition(
|
||||
field="status",
|
||||
source=[
|
||||
ApplicationStatus.SUBMITTED,
|
||||
ApplicationStatus.ACTION_NEEDED,
|
||||
ApplicationStatus.APPROVED,
|
||||
ApplicationStatus.REJECTED,
|
||||
ApplicationStatus.INELIGIBLE,
|
||||
DomainRequestStatus.SUBMITTED,
|
||||
DomainRequestStatus.ACTION_NEEDED,
|
||||
DomainRequestStatus.APPROVED,
|
||||
DomainRequestStatus.REJECTED,
|
||||
DomainRequestStatus.INELIGIBLE,
|
||||
],
|
||||
target=ApplicationStatus.IN_REVIEW,
|
||||
target=DomainRequestStatus.IN_REVIEW,
|
||||
conditions=[domain_is_not_active],
|
||||
)
|
||||
def in_review(self):
|
||||
"""Investigate an application that has been submitted.
|
||||
"""Investigate a domain request that has been submitted.
|
||||
|
||||
This action is logged.
|
||||
|
||||
|
@ -716,13 +716,13 @@ class DomainApplication(TimeStampedModel):
|
|||
As side effects this will delete the domain and domain_information
|
||||
(will cascade) when they exist."""
|
||||
|
||||
if self.status == self.ApplicationStatus.APPROVED:
|
||||
if self.status == self.DomainRequestStatus.APPROVED:
|
||||
self.delete_and_clean_up_domain("in_review")
|
||||
|
||||
if self.status == self.ApplicationStatus.REJECTED:
|
||||
if self.status == self.DomainRequestStatus.REJECTED:
|
||||
self.rejection_reason = None
|
||||
|
||||
literal = DomainApplication.ApplicationStatus.IN_REVIEW
|
||||
literal = DomainRequest.DomainRequestStatus.IN_REVIEW
|
||||
# Check if the tuple exists, then grab its value
|
||||
in_review = literal if literal is not None else "In Review"
|
||||
logger.info(f"A status change occurred. {self} was changed to '{in_review}'")
|
||||
|
@ -730,16 +730,16 @@ class DomainApplication(TimeStampedModel):
|
|||
@transition(
|
||||
field="status",
|
||||
source=[
|
||||
ApplicationStatus.IN_REVIEW,
|
||||
ApplicationStatus.APPROVED,
|
||||
ApplicationStatus.REJECTED,
|
||||
ApplicationStatus.INELIGIBLE,
|
||||
DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequestStatus.APPROVED,
|
||||
DomainRequestStatus.REJECTED,
|
||||
DomainRequestStatus.INELIGIBLE,
|
||||
],
|
||||
target=ApplicationStatus.ACTION_NEEDED,
|
||||
target=DomainRequestStatus.ACTION_NEEDED,
|
||||
conditions=[domain_is_not_active],
|
||||
)
|
||||
def action_needed(self):
|
||||
"""Send back an application that is under investigation or rejected.
|
||||
"""Send back a domain request that is under investigation or rejected.
|
||||
|
||||
This action is logged.
|
||||
|
||||
|
@ -748,13 +748,13 @@ class DomainApplication(TimeStampedModel):
|
|||
As side effects this will delete the domain and domain_information
|
||||
(will cascade) when they exist."""
|
||||
|
||||
if self.status == self.ApplicationStatus.APPROVED:
|
||||
if self.status == self.DomainRequestStatus.APPROVED:
|
||||
self.delete_and_clean_up_domain("reject_with_prejudice")
|
||||
|
||||
if self.status == self.ApplicationStatus.REJECTED:
|
||||
if self.status == self.DomainRequestStatus.REJECTED:
|
||||
self.rejection_reason = None
|
||||
|
||||
literal = DomainApplication.ApplicationStatus.ACTION_NEEDED
|
||||
literal = DomainRequest.DomainRequestStatus.ACTION_NEEDED
|
||||
# Check if the tuple is setup correctly, then grab its value
|
||||
action_needed = literal if literal is not None else "Action Needed"
|
||||
logger.info(f"A status change occurred. {self} was changed to '{action_needed}'")
|
||||
|
@ -762,21 +762,21 @@ class DomainApplication(TimeStampedModel):
|
|||
@transition(
|
||||
field="status",
|
||||
source=[
|
||||
ApplicationStatus.SUBMITTED,
|
||||
ApplicationStatus.IN_REVIEW,
|
||||
ApplicationStatus.ACTION_NEEDED,
|
||||
ApplicationStatus.REJECTED,
|
||||
DomainRequestStatus.SUBMITTED,
|
||||
DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequestStatus.ACTION_NEEDED,
|
||||
DomainRequestStatus.REJECTED,
|
||||
],
|
||||
target=ApplicationStatus.APPROVED,
|
||||
target=DomainRequestStatus.APPROVED,
|
||||
)
|
||||
def approve(self, send_email=True):
|
||||
"""Approve an application that has been submitted.
|
||||
"""Approve a domain request that has been submitted.
|
||||
|
||||
This action cleans up the rejection status if moving away from rejected.
|
||||
|
||||
This has substantial side-effects because it creates another database
|
||||
object for the approved Domain and makes the user who created the
|
||||
application into an admin on that domain. It also triggers an email
|
||||
domain request into an admin on that domain. It also triggers an email
|
||||
notification."""
|
||||
|
||||
# create the domain
|
||||
|
@ -786,9 +786,9 @@ class DomainApplication(TimeStampedModel):
|
|||
created_domain = Domain.objects.create(name=self.requested_domain.name)
|
||||
self.approved_domain = created_domain
|
||||
|
||||
# copy the information from domainapplication into domaininformation
|
||||
# copy the information from DomainRequest into domaininformation
|
||||
DomainInformation = apps.get_model("registrar.DomainInformation")
|
||||
DomainInformation.create_from_da(domain_application=self, domain=created_domain)
|
||||
DomainInformation.create_from_da(domain_request=self, domain=created_domain)
|
||||
|
||||
# create the permission for the user
|
||||
UserDomainRole = apps.get_model("registrar.UserDomainRole")
|
||||
|
@ -796,11 +796,11 @@ class DomainApplication(TimeStampedModel):
|
|||
user=self.creator, domain=created_domain, role=UserDomainRole.Roles.MANAGER
|
||||
)
|
||||
|
||||
if self.status == self.ApplicationStatus.REJECTED:
|
||||
if self.status == self.DomainRequestStatus.REJECTED:
|
||||
self.rejection_reason = None
|
||||
|
||||
self._send_status_update_email(
|
||||
"application approved",
|
||||
"domain request approved",
|
||||
"emails/status_change_approved.txt",
|
||||
"emails/status_change_approved_subject.txt",
|
||||
send_email,
|
||||
|
@ -808,11 +808,11 @@ class DomainApplication(TimeStampedModel):
|
|||
|
||||
@transition(
|
||||
field="status",
|
||||
source=[ApplicationStatus.SUBMITTED, ApplicationStatus.IN_REVIEW, ApplicationStatus.ACTION_NEEDED],
|
||||
target=ApplicationStatus.WITHDRAWN,
|
||||
source=[DomainRequestStatus.SUBMITTED, DomainRequestStatus.IN_REVIEW, DomainRequestStatus.ACTION_NEEDED],
|
||||
target=DomainRequestStatus.WITHDRAWN,
|
||||
)
|
||||
def withdraw(self):
|
||||
"""Withdraw an application that has been submitted."""
|
||||
"""Withdraw a domain request that has been submitted."""
|
||||
|
||||
self._send_status_update_email(
|
||||
"withdraw",
|
||||
|
@ -822,17 +822,17 @@ class DomainApplication(TimeStampedModel):
|
|||
|
||||
@transition(
|
||||
field="status",
|
||||
source=[ApplicationStatus.IN_REVIEW, ApplicationStatus.ACTION_NEEDED, ApplicationStatus.APPROVED],
|
||||
target=ApplicationStatus.REJECTED,
|
||||
source=[DomainRequestStatus.IN_REVIEW, DomainRequestStatus.ACTION_NEEDED, DomainRequestStatus.APPROVED],
|
||||
target=DomainRequestStatus.REJECTED,
|
||||
conditions=[domain_is_not_active],
|
||||
)
|
||||
def reject(self):
|
||||
"""Reject an application that has been submitted.
|
||||
"""Reject a domain request that has been submitted.
|
||||
|
||||
As side effects this will delete the domain and domain_information
|
||||
(will cascade), and send an email notification."""
|
||||
|
||||
if self.status == self.ApplicationStatus.APPROVED:
|
||||
if self.status == self.DomainRequestStatus.APPROVED:
|
||||
self.delete_and_clean_up_domain("reject")
|
||||
|
||||
self._send_status_update_email(
|
||||
|
@ -844,24 +844,24 @@ class DomainApplication(TimeStampedModel):
|
|||
@transition(
|
||||
field="status",
|
||||
source=[
|
||||
ApplicationStatus.IN_REVIEW,
|
||||
ApplicationStatus.ACTION_NEEDED,
|
||||
ApplicationStatus.APPROVED,
|
||||
ApplicationStatus.REJECTED,
|
||||
DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequestStatus.ACTION_NEEDED,
|
||||
DomainRequestStatus.APPROVED,
|
||||
DomainRequestStatus.REJECTED,
|
||||
],
|
||||
target=ApplicationStatus.INELIGIBLE,
|
||||
target=DomainRequestStatus.INELIGIBLE,
|
||||
conditions=[domain_is_not_active],
|
||||
)
|
||||
def reject_with_prejudice(self):
|
||||
"""The applicant is a bad actor, reject with prejudice.
|
||||
|
||||
No email As a side effect, but we block the applicant from editing
|
||||
any existing domains/applications and from submitting new aplications.
|
||||
any existing domains/domain requests and from submitting new aplications.
|
||||
We do this by setting an ineligible status on the user, which the
|
||||
permissions classes test against. This will also delete the domain
|
||||
and domain_information (will cascade) when they exist."""
|
||||
|
||||
if self.status == self.ApplicationStatus.APPROVED:
|
||||
if self.status == self.DomainRequestStatus.APPROVED:
|
||||
self.delete_and_clean_up_domain("reject_with_prejudice")
|
||||
|
||||
self.creator.restrict_user()
|
||||
|
@ -869,18 +869,18 @@ class DomainApplication(TimeStampedModel):
|
|||
# ## Form policies ###
|
||||
#
|
||||
# These methods control what questions need to be answered by applicants
|
||||
# during the application flow. They are policies about the application so
|
||||
# during the domain request flow. They are policies about the domain request so
|
||||
# they appear here.
|
||||
|
||||
def show_organization_federal(self) -> bool:
|
||||
"""Show this step if the answer to the first question was "federal"."""
|
||||
user_choice = self.organization_type
|
||||
return user_choice == DomainApplication.OrganizationChoices.FEDERAL
|
||||
return user_choice == DomainRequest.OrganizationChoices.FEDERAL
|
||||
|
||||
def show_tribal_government(self) -> bool:
|
||||
"""Show this step if the answer to the first question was "tribal"."""
|
||||
user_choice = self.organization_type
|
||||
return user_choice == DomainApplication.OrganizationChoices.TRIBAL
|
||||
return user_choice == DomainRequest.OrganizationChoices.TRIBAL
|
||||
|
||||
def show_organization_election(self) -> bool:
|
||||
"""Show this step if the answer to the first question implies it.
|
||||
|
@ -890,9 +890,9 @@ class DomainApplication(TimeStampedModel):
|
|||
"""
|
||||
user_choice = self.organization_type
|
||||
excluded = [
|
||||
DomainApplication.OrganizationChoices.FEDERAL,
|
||||
DomainApplication.OrganizationChoices.INTERSTATE,
|
||||
DomainApplication.OrganizationChoices.SCHOOL_DISTRICT,
|
||||
DomainRequest.OrganizationChoices.FEDERAL,
|
||||
DomainRequest.OrganizationChoices.INTERSTATE,
|
||||
DomainRequest.OrganizationChoices.SCHOOL_DISTRICT,
|
||||
]
|
||||
return bool(user_choice and user_choice not in excluded)
|
||||
|
||||
|
@ -900,27 +900,27 @@ class DomainApplication(TimeStampedModel):
|
|||
"""Show this step if this is a special district or interstate."""
|
||||
user_choice = self.organization_type
|
||||
return user_choice in [
|
||||
DomainApplication.OrganizationChoices.SPECIAL_DISTRICT,
|
||||
DomainApplication.OrganizationChoices.INTERSTATE,
|
||||
DomainRequest.OrganizationChoices.SPECIAL_DISTRICT,
|
||||
DomainRequest.OrganizationChoices.INTERSTATE,
|
||||
]
|
||||
|
||||
def has_rationale(self) -> bool:
|
||||
"""Does this application have no_other_contacts_rationale?"""
|
||||
"""Does this domain request have no_other_contacts_rationale?"""
|
||||
return bool(self.no_other_contacts_rationale)
|
||||
|
||||
def has_other_contacts(self) -> bool:
|
||||
"""Does this application have other contacts listed?"""
|
||||
"""Does this domain request have other contacts listed?"""
|
||||
return self.other_contacts.exists()
|
||||
|
||||
def is_federal(self) -> Union[bool, None]:
|
||||
"""Is this application for a federal agency?
|
||||
"""Is this domain request for a federal agency?
|
||||
|
||||
organization_type can be both null and blank,
|
||||
"""
|
||||
if not self.organization_type:
|
||||
# organization_type is either blank or None, can't answer
|
||||
return None
|
||||
if self.organization_type == DomainApplication.OrganizationChoices.FEDERAL:
|
||||
if self.organization_type == DomainRequest.OrganizationChoices.FEDERAL:
|
||||
return True
|
||||
return False
|
||||
|
|
@ -33,8 +33,8 @@ class UserGroup(Group):
|
|||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
"model": "domainapplication",
|
||||
"permissions": ["change_domainapplication"],
|
||||
"model": "domainrequest",
|
||||
"permissions": ["change_domainrequest"],
|
||||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
|
|
|
@ -184,7 +184,7 @@ class DomainHelper:
|
|||
model_1_fields = set(field.name for field in model_1._meta.get_fields() if field.name != "id")
|
||||
model_2_fields = set(field.name for field in model_2._meta.get_fields() if field.name != "id")
|
||||
|
||||
# Get the fields that exist on both DomainApplication and DomainInformation
|
||||
# Get the fields that exist on both DomainRequest and DomainInformation
|
||||
common_fields = model_1_fields & model_2_fields
|
||||
|
||||
return common_fields
|
||||
|
|
|
@ -4,7 +4,7 @@ from .utility.time_stamped_model import TimeStampedModel
|
|||
|
||||
|
||||
class Website(TimeStampedModel):
|
||||
"""Keep domain names in their own table so that applications can refer to
|
||||
"""Keep domain names in their own table so that domain requests can refer to
|
||||
many of them."""
|
||||
|
||||
# domain names have strictly limited lengths, 255 characters is more than
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load custom_filters %}
|
||||
|
||||
{% block title %}Domain request status | {{ domainapplication.requested_domain.name }} | {% endblock %}
|
||||
{% load static url_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" class="grid-container">
|
||||
<div class="grid-col desktop:grid-offset-2 desktop:grid-col-8">
|
||||
<a href="{% url 'home' %}" class="breadcrumb__back">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img">
|
||||
<use xlink:href="{% static 'img/sprite.svg' %}#arrow_back"></use>
|
||||
</svg>
|
||||
|
||||
<p class="margin-left-05 margin-top-0 margin-bottom-0 line-height-sans-1">
|
||||
Back to manage your domains
|
||||
</p>
|
||||
</a>
|
||||
<h1>Domain request for {{ domainapplication.requested_domain.name }}</h1>
|
||||
<div
|
||||
class="usa-summary-box dotgov-status-box margin-top-3 padding-left-2"
|
||||
role="region"
|
||||
aria-labelledby="summary-box-key-information"
|
||||
>
|
||||
<div class="usa-summary-box__body">
|
||||
<p class="usa-summary-box__heading font-sans-md margin-bottom-0"
|
||||
id="summary-box-key-information"
|
||||
>
|
||||
<span class="text-bold text-primary-darker">
|
||||
Status:
|
||||
</span>
|
||||
{% if domainapplication.status == 'approved' %} Approved
|
||||
{% elif domainapplication.status == 'in review' %} In review
|
||||
{% elif domainapplication.status == 'rejected' %} Rejected
|
||||
{% elif domainapplication.status == 'submitted' %} Submitted
|
||||
{% elif domainapplication.status == 'ineligible' %} Ineligible
|
||||
{% else %}ERROR Please contact technical support/dev
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<p> <b class="review__step__name">Last updated:</b> {{domainapplication.updated_at|date:"F j, Y"}}<br>
|
||||
<b class="review__step__name">Request #:</b> {{domainapplication.id}}</p>
|
||||
<p>{% include "includes/domain_application.html" %}</p>
|
||||
<p><a href="{% url 'application-withdraw-confirmation' pk=domainapplication.id %}" class="usa-button usa-button--outline withdraw_outline">
|
||||
Withdraw request</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid-col desktop:grid-offset-2 maxw-tablet">
|
||||
<h2 class="text-primary-darker"> Summary of your domain request </h2>
|
||||
{% with heading_level='h3' %}
|
||||
{% with org_type=domainapplication.get_organization_type_display %}
|
||||
{% include "includes/summary_item.html" with title='Type of organization' value=org_type heading_level=heading_level %}
|
||||
{% endwith %}
|
||||
|
||||
{% if domainapplication.tribe_name %}
|
||||
{% include "includes/summary_item.html" with title='Tribal government' value=domainapplication.tribe_name heading_level=heading_level %}
|
||||
|
||||
{% if domainapplication.federally_recognized_tribe %}
|
||||
<p>Federally-recognized tribe</p>
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.state_recognized_tribe %}
|
||||
<p>State-recognized tribe</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.get_federal_type_display %}
|
||||
{% include "includes/summary_item.html" with title='Federal government branch' value=domainapplication.get_federal_type_display heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.is_election_board %}
|
||||
{% with value=domainapplication.is_election_board|yesno:"Yes,No,Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title='Election office' value=value heading_level=heading_level %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.organization_name %}
|
||||
{% include "includes/summary_item.html" with title='Organization name and mailing address' value=domainapplication address='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.about_your_organization %}
|
||||
{% include "includes/summary_item.html" with title='About your organization' value=domainapplication.about_your_organization heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.authorizing_official %}
|
||||
{% include "includes/summary_item.html" with title='Authorizing official' value=domainapplication.authorizing_official contact='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.current_websites.all %}
|
||||
{% include "includes/summary_item.html" with title='Current websites' value=domainapplication.current_websites.all list='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.requested_domain %}
|
||||
{% include "includes/summary_item.html" with title='.gov domain' value=domainapplication.requested_domain heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.alternative_domains.all %}
|
||||
{% include "includes/summary_item.html" with title='Alternative domains' value=domainapplication.alternative_domains.all list='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.purpose %}
|
||||
{% include "includes/summary_item.html" with title='Purpose of your domain' value=domainapplication.purpose heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.submitter %}
|
||||
{% include "includes/summary_item.html" with title='Your contact information' value=domainapplication.submitter contact='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if domainapplication.other_contacts.all %}
|
||||
{% include "includes/summary_item.html" with title='Other employees from your organization' value=domainapplication.other_contacts.all contact='true' list='true' heading_level=heading_level %}
|
||||
{% else %}
|
||||
{% include "includes/summary_item.html" with title='Other employees from your organization' value=domainapplication.no_other_contacts_rationale heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% include "includes/summary_item.html" with title='Anything else?' value=domainapplication.anything_else|default:"No" heading_level=heading_level %}
|
||||
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -1,21 +0,0 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Withdraw request for {{ domainapplication.requested_domain.name }} | {% endblock %}
|
||||
{% load static url_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid-container">
|
||||
<div class="grid-col desktop:grid-offset-2 desktop:grid-col-8">
|
||||
|
||||
|
||||
<h1>Withdraw request for {{ domainapplication.requested_domain.name }}?</h1>
|
||||
|
||||
<p>If you withdraw your request, we won't review it. Once you withdraw your request, you can edit it and submit it again. </p>
|
||||
|
||||
<p><a href="{% url 'application-withdrawn' domainapplication.id %}" class="usa-button withdraw">Withdraw request</a>
|
||||
<a href="{% url 'application-status' domainapplication.id %}">Cancel</a></p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers url_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load static field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load static field_helpers url_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -6,12 +6,12 @@
|
|||
<div class="grid-container">
|
||||
<div class="grid-row grid-gap">
|
||||
<div class="tablet:grid-col-3">
|
||||
{% include 'application_sidebar.html' %}
|
||||
{% include 'domain_request_sidebar.html' %}
|
||||
</div>
|
||||
<div class="tablet:grid-col-9">
|
||||
<main id="main-content" class="grid-container register-form-step">
|
||||
{% if steps.prev %}
|
||||
<a href="{% namespaced_url 'application' steps.prev %}" class="breadcrumb__back">
|
||||
<a href="{% namespaced_url 'domain-request' steps.prev %}" class="breadcrumb__back">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#arrow_back"></use>
|
||||
</svg><span class="margin-left-05">Previous step</span>
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers url_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load static field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers url_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load static url_helpers %}
|
||||
{% load custom_filters %}
|
||||
|
||||
|
@ -23,98 +23,98 @@
|
|||
<section class="summary-item margin-top-3">
|
||||
|
||||
{% if step == Step.ORGANIZATION_TYPE %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.organization_type is not None %}
|
||||
{% with title=form_titles|get_item:step value=application.get_organization_type_display|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.organization_type is not None %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.get_organization_type_display|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value="Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.TRIBAL_GOVERNMENT %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.tribe_name|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.tribe_name|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% if application.federally_recognized_tribe %}<p>Federally-recognized tribe</p>{% endif %}
|
||||
{% if application.state_recognized_tribe %}<p>State-recognized tribe</p>{% endif %}
|
||||
{% if domain_request.federally_recognized_tribe %}<p>Federally-recognized tribe</p>{% endif %}
|
||||
{% if domain_request.state_recognized_tribe %}<p>State-recognized tribe</p>{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if step == Step.ORGANIZATION_FEDERAL %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.get_federal_type_display|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.get_federal_type_display|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.ORGANIZATION_ELECTION %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.is_election_board|yesno:"Yes,No,Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.is_election_board|yesno:"Yes,No,Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.ORGANIZATION_CONTACT %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.organization_name %}
|
||||
{% with title=form_titles|get_item:step value=application %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url address='true' %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.organization_name %}
|
||||
{% with title=form_titles|get_item:step value=domain_request %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url address='true' %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value='Incomplete' %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.ABOUT_YOUR_ORGANIZATION %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.about_your_organization|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.about_your_organization|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.AUTHORIZING_OFFICIAL %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.authorizing_official is not None %}
|
||||
{% with title=form_titles|get_item:step value=application.authorizing_official %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url contact='true' %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.authorizing_official is not None %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.authorizing_official %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url contact='true' %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value="Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.CURRENT_SITES %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.current_websites.all %}
|
||||
{% with title=form_titles|get_item:step value=application.current_websites.all %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url list='true' %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.current_websites.all %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.current_websites.all %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url list='true' %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value='None' %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.DOTGOV_DOMAIN %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.requested_domain.name|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.requested_domain.name|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
|
||||
{% if application.alternative_domains.all %}
|
||||
{% if domain_request.alternative_domains.all %}
|
||||
<h3 class="register-form-review-header">Alternative domains</h3>
|
||||
<ul class="usa-list usa-list--unstyled margin-top-0">
|
||||
{% for site in application.alternative_domains.all %}
|
||||
{% for site in domain_request.alternative_domains.all %}
|
||||
<li>{{ site.website }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
@ -122,51 +122,51 @@
|
|||
{% endif %}
|
||||
|
||||
{% if step == Step.PURPOSE %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.purpose|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.purpose|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.YOUR_CONTACT %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.submitter is not None %}
|
||||
{% with title=form_titles|get_item:step value=application.submitter %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url contact='true' %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.submitter is not None %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.submitter %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url contact='true' %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value="Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.OTHER_CONTACTS %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% if application.other_contacts.all %}
|
||||
{% with title=form_titles|get_item:step value=application.other_contacts.all %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url contact='true' list='true' %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% if domain_request.other_contacts.all %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.other_contacts.all %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url contact='true' list='true' %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
{% with title=form_titles|get_item:step value=application.no_other_contacts_rationale|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.no_other_contacts_rationale|default:"Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if step == Step.ANYTHING_ELSE %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.anything_else|default:"No" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.anything_else|default:"No" %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if step == Step.REQUIREMENTS %}
|
||||
{% namespaced_url 'application' step as application_url %}
|
||||
{% with title=form_titles|get_item:step value=application.is_policy_acknowledged|yesno:"I agree.,I do not agree.,I do not agree." %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=application_url %}
|
||||
{% namespaced_url 'domain-request' step as domain_request_url %}
|
||||
{% with title=form_titles|get_item:step value=domain_request.is_policy_acknowledged|yesno:"I agree.,I do not agree.,I do not agree." %}
|
||||
{% include "includes/summary_item.html" with title=title value=value heading_level=heading_level editable=True edit_link=domain_request_url %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
</svg>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a href="{% namespaced_url 'application' this_step %}"
|
||||
<a href="{% namespaced_url 'domain-request' this_step %}"
|
||||
{% if this_step == steps.current %}
|
||||
class="usa-current"
|
||||
{% else %}
|
126
src/registrar/templates/domain_request_status.html
Normal file
126
src/registrar/templates/domain_request_status.html
Normal file
|
@ -0,0 +1,126 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load custom_filters %}
|
||||
|
||||
{% block title %}Domain request status | {{ DomainRequest.requested_domain.name }} | {% endblock %}
|
||||
{% load static url_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<main id="main-content" class="grid-container">
|
||||
<div class="grid-col desktop:grid-offset-2 desktop:grid-col-8">
|
||||
<a href="{% url 'home' %}" class="breadcrumb__back">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img">
|
||||
<use xlink:href="{% static 'img/sprite.svg' %}#arrow_back"></use>
|
||||
</svg>
|
||||
|
||||
<p class="margin-left-05 margin-top-0 margin-bottom-0 line-height-sans-1">
|
||||
Back to manage your domains
|
||||
</p>
|
||||
</a>
|
||||
<h1>Domain request for {{ DomainRequest.requested_domain.name }}</h1>
|
||||
<div
|
||||
class="usa-summary-box dotgov-status-box margin-top-3 padding-left-2"
|
||||
role="region"
|
||||
aria-labelledby="summary-box-key-information"
|
||||
>
|
||||
<div class="usa-summary-box__body">
|
||||
<p class="usa-summary-box__heading font-sans-md margin-bottom-0"
|
||||
id="summary-box-key-information"
|
||||
>
|
||||
<span class="text-bold text-primary-darker">
|
||||
Status:
|
||||
</span>
|
||||
{% if DomainRequest.status == 'approved' %} Approved
|
||||
{% elif DomainRequest.status == 'in review' %} In review
|
||||
{% elif DomainRequest.status == 'rejected' %} Rejected
|
||||
{% elif DomainRequest.status == 'submitted' %} Submitted
|
||||
{% elif DomainRequest.status == 'ineligible' %} Ineligible
|
||||
{% else %}ERROR Please contact technical support/dev
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<p> <b class="review__step__name">Last updated:</b> {{DomainRequest.updated_at|date:"F j, Y"}}<br>
|
||||
<b class="review__step__name">Request #:</b> {{DomainRequest.id}}</p>
|
||||
<p>{% include "includes/domain_request.html" %}</p>
|
||||
<p><a href="{% url 'domain-request-withdraw-confirmation' pk=DomainRequest.id %}" class="usa-button usa-button--outline withdraw_outline">
|
||||
Withdraw request</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid-col desktop:grid-offset-2 maxw-tablet">
|
||||
<h2 class="text-primary-darker"> Summary of your domain request </h2>
|
||||
{% with heading_level='h3' %}
|
||||
{% with org_type=DomainRequest.get_organization_type_display %}
|
||||
{% include "includes/summary_item.html" with title='Type of organization' value=org_type heading_level=heading_level %}
|
||||
{% endwith %}
|
||||
|
||||
{% if DomainRequest.tribe_name %}
|
||||
{% include "includes/summary_item.html" with title='Tribal government' value=DomainRequest.tribe_name heading_level=heading_level %}
|
||||
|
||||
{% if DomainRequest.federally_recognized_tribe %}
|
||||
<p>Federally-recognized tribe</p>
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.state_recognized_tribe %}
|
||||
<p>State-recognized tribe</p>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.get_federal_type_display %}
|
||||
{% include "includes/summary_item.html" with title='Federal government branch' value=DomainRequest.get_federal_type_display heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.is_election_board %}
|
||||
{% with value=DomainRequest.is_election_board|yesno:"Yes,No,Incomplete" %}
|
||||
{% include "includes/summary_item.html" with title='Election office' value=value heading_level=heading_level %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.organization_name %}
|
||||
{% include "includes/summary_item.html" with title='Organization name and mailing address' value=DomainRequest address='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.about_your_organization %}
|
||||
{% include "includes/summary_item.html" with title='About your organization' value=DomainRequest.about_your_organization heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.authorizing_official %}
|
||||
{% include "includes/summary_item.html" with title='Authorizing official' value=DomainRequest.authorizing_official contact='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.current_websites.all %}
|
||||
{% include "includes/summary_item.html" with title='Current websites' value=DomainRequest.current_websites.all list='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.requested_domain %}
|
||||
{% include "includes/summary_item.html" with title='.gov domain' value=DomainRequest.requested_domain heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.alternative_domains.all %}
|
||||
{% include "includes/summary_item.html" with title='Alternative domains' value=DomainRequest.alternative_domains.all list='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.purpose %}
|
||||
{% include "includes/summary_item.html" with title='Purpose of your domain' value=DomainRequest.purpose heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.submitter %}
|
||||
{% include "includes/summary_item.html" with title='Your contact information' value=DomainRequest.submitter contact='true' heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% if DomainRequest.other_contacts.all %}
|
||||
{% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.other_contacts.all contact='true' list='true' heading_level=heading_level %}
|
||||
{% else %}
|
||||
{% include "includes/summary_item.html" with title='Other employees from your organization' value=DomainRequest.no_other_contacts_rationale heading_level=heading_level %}
|
||||
{% endif %}
|
||||
|
||||
{% include "includes/summary_item.html" with title='Anything else?' value=DomainRequest.anything_else|default:"No" heading_level=heading_level %}
|
||||
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
</main>
|
||||
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -0,0 +1,21 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}Withdraw request for {{ DomainRequest.requested_domain.name }} | {% endblock %}
|
||||
{% load static url_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<div class="grid-container">
|
||||
<div class="grid-col desktop:grid-offset-2 desktop:grid-col-8">
|
||||
|
||||
|
||||
<h1>Withdraw request for {{ DomainRequest.requested_domain.name }}?</h1>
|
||||
|
||||
<p>If you withdraw your request, we won't review it. Once you withdraw your request, you can edit it and submit it again. </p>
|
||||
|
||||
<p><a href="{% url 'domain-request-withdrawn' DomainRequest.id %}" class="usa-button withdraw">Withdraw request</a>
|
||||
<a href="{% url 'domain-request-status' DomainRequest.id %}">Cancel</a></p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% extends 'domain_request_form.html' %}
|
||||
{% load field_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
|
@ -1,10 +1,10 @@
|
|||
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
|
||||
Hi, {{ application.submitter.first_name }}.
|
||||
Hi, {{ domain_request.submitter.first_name }}.
|
||||
|
||||
Your .gov domain request has been withdrawn and will not be reviewed by our team.
|
||||
|
||||
DOMAIN REQUESTED: {{ application.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ application.submission_date|date }}
|
||||
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ domain_request.submission_date|date }}
|
||||
STATUS: Withdrawn
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
|
|
@ -1 +1 @@
|
|||
Update on your .gov request: {{ application.requested_domain.name }}
|
||||
Update on your .gov request: {{ domain_request.requested_domain.name }}
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
SUMMARY OF YOUR DOMAIN REQUEST
|
||||
|
||||
Type of organization:
|
||||
{{ application.get_organization_type_display }}
|
||||
{% if application.show_organization_federal %}
|
||||
Federal government branch:
|
||||
{{ application.get_federal_type_display }}
|
||||
{% elif application.show_tribal_government %}
|
||||
Tribal government:
|
||||
{{ application.tribe_name|default:"Incomplete" }}{% if application.federally_recognized_tribe %}
|
||||
Federally-recognized tribe
|
||||
{% endif %}{% if application.state_recognized_tribe %}
|
||||
State-recognized tribe
|
||||
{% endif %}{% endif %}{% if application.show_organization_election %}
|
||||
Election office:
|
||||
{{ application.is_election_board|yesno:"Yes,No,Incomplete" }}
|
||||
{% endif %}
|
||||
Organization name and mailing address:
|
||||
{% spaceless %}{{ application.federal_agency }}
|
||||
{{ application.organization_name }}
|
||||
{{ application.address_line1 }}{% if application.address_line2 %}
|
||||
{{ application.address_line2 }}{% endif %}
|
||||
{{ application.city }}, {{ application.state_territory }}
|
||||
{{ application.zipcode }}{% if application.urbanization %}
|
||||
{{ application.urbanization }}{% endif %}{% endspaceless %}
|
||||
{% if application.about_your_organization %}{# if block makes one newline if it's false #}
|
||||
About your organization:
|
||||
{% spaceless %}{{ application.about_your_organization }}{% endspaceless %}
|
||||
{% endif %}
|
||||
Authorizing official:
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=application.authorizing_official %}{% endspaceless %}
|
||||
{% if application.current_websites.exists %}{# if block makes a newline #}
|
||||
Current websites: {% for site in application.current_websites.all %}
|
||||
{% spaceless %}{{ site.website }}{% endspaceless %}
|
||||
{% endfor %}{% endif %}
|
||||
.gov domain:
|
||||
{{ application.requested_domain.name }}
|
||||
{% if application.alternative_domains.all %}
|
||||
Alternative domains:
|
||||
{% for site in application.alternative_domains.all %}{% spaceless %}{{ site.website }}{% endspaceless %}
|
||||
{% endfor %}{% endif %}
|
||||
Purpose of your domain:
|
||||
{{ application.purpose }}
|
||||
|
||||
Your contact information:
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=application.submitter %}{% endspaceless %}
|
||||
|
||||
Other employees from your organization:{% for other in application.other_contacts.all %}
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=other %}{% endspaceless %}
|
||||
{% empty %}
|
||||
{{ application.no_other_contacts_rationale }}
|
||||
{% endfor %}{% if application.anything_else %}
|
||||
Anything else?
|
||||
{{ application.anything_else }}
|
||||
{% endif %}
|
|
@ -0,0 +1,55 @@
|
|||
SUMMARY OF YOUR DOMAIN REQUEST
|
||||
|
||||
Type of organization:
|
||||
{{ domain_request.get_organization_type_display }}
|
||||
{% if domain_request.show_organization_federal %}
|
||||
Federal government branch:
|
||||
{{ domain_request.get_federal_type_display }}
|
||||
{% elif domain_request.show_tribal_government %}
|
||||
Tribal government:
|
||||
{{ domain_request.tribe_name|default:"Incomplete" }}{% if domain_request.federally_recognized_tribe %}
|
||||
Federally-recognized tribe
|
||||
{% endif %}{% if domain_request.state_recognized_tribe %}
|
||||
State-recognized tribe
|
||||
{% endif %}{% endif %}{% if domain_request.show_organization_election %}
|
||||
Election office:
|
||||
{{ domain_request.is_election_board|yesno:"Yes,No,Incomplete" }}
|
||||
{% endif %}
|
||||
Organization name and mailing address:
|
||||
{% spaceless %}{{ domain_request.federal_agency }}
|
||||
{{ domain_request.organization_name }}
|
||||
{{ domain_request.address_line1 }}{% if domain_request.address_line2 %}
|
||||
{{ domain_request.address_line2 }}{% endif %}
|
||||
{{ domain_request.city }}, {{ domain_request.state_territory }}
|
||||
{{ domain_request.zipcode }}{% if domain_request.urbanization %}
|
||||
{{ domain_request.urbanization }}{% endif %}{% endspaceless %}
|
||||
{% if domain_request.about_your_organization %}{# if block makes one newline if it's false #}
|
||||
About your organization:
|
||||
{% spaceless %}{{ domain_request.about_your_organization }}{% endspaceless %}
|
||||
{% endif %}
|
||||
Authorizing official:
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=domain_request.authorizing_official %}{% endspaceless %}
|
||||
{% if domain_request.current_websites.exists %}{# if block makes a newline #}
|
||||
Current websites: {% for site in domain_request.current_websites.all %}
|
||||
{% spaceless %}{{ site.website }}{% endspaceless %}
|
||||
{% endfor %}{% endif %}
|
||||
.gov domain:
|
||||
{{ domain_request.requested_domain.name }}
|
||||
{% if domain_request.alternative_domains.all %}
|
||||
Alternative domains:
|
||||
{% for site in domain_request.alternative_domains.all %}{% spaceless %}{{ site.website }}{% endspaceless %}
|
||||
{% endfor %}{% endif %}
|
||||
Purpose of your domain:
|
||||
{{ domain_request.purpose }}
|
||||
|
||||
Your contact information:
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=domain_request.submitter %}{% endspaceless %}
|
||||
|
||||
Other employees from your organization:{% for other in domain_request.other_contacts.all %}
|
||||
{% spaceless %}{% include "emails/includes/contact.txt" with contact=other %}{% endspaceless %}
|
||||
{% empty %}
|
||||
{{ domain_request.no_other_contacts_rationale }}
|
||||
{% endfor %}{% if domain_request.anything_else %}
|
||||
Anything else?
|
||||
{{ domain_request.anything_else }}
|
||||
{% endif %}
|
|
@ -1,10 +1,10 @@
|
|||
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
|
||||
Hi, {{ application.submitter.first_name }}.
|
||||
Hi, {{ domain_request.submitter.first_name }}.
|
||||
|
||||
Congratulations! Your .gov domain request has been approved.
|
||||
|
||||
DOMAIN REQUESTED: {{ application.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ application.submission_date|date }}
|
||||
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ domain_request.submission_date|date }}
|
||||
STATUS: Approved
|
||||
|
||||
You can manage your approved domain on the .gov registrar <https://manage.get.gov>.
|
||||
|
|
|
@ -1 +1 @@
|
|||
Update on your .gov request: {{ application.requested_domain.name }}
|
||||
Update on your .gov request: {{ domain_request.requested_domain.name }}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
|
||||
Hi, {{ application.submitter.first_name }}.
|
||||
Hi, {{ domain_request.submitter.first_name }}.
|
||||
|
||||
Your .gov domain request has been rejected.
|
||||
|
||||
DOMAIN REQUESTED: {{ application.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ application.submission_date|date }}
|
||||
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ domain_request.submission_date|date }}
|
||||
STATUS: Rejected
|
||||
|
||||
----------------------------------------------------------------
|
||||
{% if application.rejection_reason != 'other' %}
|
||||
REJECTION REASON{% endif %}{% if application.rejection_reason == 'purpose_not_met' %}
|
||||
{% if domain_request.rejection_reason != 'other' %}
|
||||
REJECTION REASON{% endif %}{% if domain_request.rejection_reason == 'purpose_not_met' %}
|
||||
Your domain request was rejected because the purpose you provided did not meet our
|
||||
requirements. You didn’t provide enough information about how you intend to use the
|
||||
domain.
|
||||
|
@ -18,16 +18,16 @@ Learn more about:
|
|||
- Eligibility for a .gov domain <https://get.gov/domains/eligibility>
|
||||
- What you can and can’t do with .gov domains <https://get.gov/domains/requirements/>
|
||||
|
||||
If you have questions or comments, reply to this email.{% elif application.rejection_reason == 'requestor_not_eligible' %}
|
||||
If you have questions or comments, reply to this email.{% elif domain_request.rejection_reason == 'requestor_not_eligible' %}
|
||||
Your domain request was rejected because we don’t believe you’re eligible to request a
|
||||
.gov domain on behalf of {{ application.organization_name }}. You must be a government employee, or be
|
||||
.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.{% elif application.rejection_reason == 'org_has_domain' %}
|
||||
Your domain request was rejected because {{ application.organization_name }} has a .gov domain. Our
|
||||
discuss further, reply to this email.{% elif domain_request.rejection_reason == '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
|
||||
justification for an additional domain.
|
||||
|
@ -35,10 +35,10 @@ 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 application.rejection_reason == 'contacts_not_verified' %}
|
||||
If you have questions or comments, reply to this email.{% elif domain_request.rejection_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 application.rejection_reason == 'org_not_eligible' %}
|
||||
Your domain request was rejected because we determined that {{ application.organization_name }} is not
|
||||
contacts you provided. If you have questions or comments, reply to this email.{% elif domain_request.rejection_reason == '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.
|
||||
|
||||
|
@ -48,7 +48,7 @@ If you can provide documentation that demonstrates your eligibility, reply to th
|
|||
This can include links to (or copies of) your authorizing legislation, your founding
|
||||
charter or bylaws, or other similar documentation. Without this, we can’t approve a
|
||||
.gov domain for your organization. Learn more about eligibility for .gov domains
|
||||
<https://get.gov/domains/eligibility/>.{% elif application.rejection_reason == 'naming_not_met' %}
|
||||
<https://get.gov/domains/eligibility/>.{% elif domain_request.rejection_reason == '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
|
||||
|
@ -57,7 +57,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 application.rejection_reason == 'other' %}
|
||||
questions or want to discuss potential domain names, reply to this email.{% elif domain_request.rejection_reason == '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.
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Update on your .gov request: {{ application.requested_domain.name }}
|
||||
Update on your .gov request: {{ domain_request.requested_domain.name }}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
{% autoescape off %}{# In a text file, we don't want to have HTML entities escaped #}
|
||||
Hi, {{ application.submitter.first_name }}.
|
||||
Hi, {{ domain_request.submitter.first_name }}.
|
||||
|
||||
We received your .gov domain request.
|
||||
|
||||
DOMAIN REQUESTED: {{ application.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ application.submission_date|date }}
|
||||
DOMAIN REQUESTED: {{ domain_request.requested_domain.name }}
|
||||
REQUEST RECEIVED ON: {{ domain_request.submission_date|date }}
|
||||
STATUS: Submitted
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
@ -29,7 +29,7 @@ THANK YOU
|
|||
|
||||
----------------------------------------------------------------
|
||||
|
||||
{% include 'emails/includes/application_summary.txt' %}
|
||||
{% include 'emails/includes/domain_request_summary.txt' %}
|
||||
----------------------------------------------------------------
|
||||
|
||||
The .gov team
|
||||
|
|
|
@ -1 +1 @@
|
|||
Update on your .gov request: {{ application.requested_domain.name }}
|
||||
Update on your .gov request: {{ domain_request.requested_domain.name }}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
|
||||
<p class="margin-top-4">
|
||||
<a href="{% url 'application:' %}" class="usa-button"
|
||||
<a href="{% url 'domain-request:' %}" class="usa-button"
|
||||
>
|
||||
Start a new domain request
|
||||
</a>
|
||||
|
@ -103,7 +103,7 @@
|
|||
|
||||
<section class="section--outlined">
|
||||
<h2>Domain requests</h2>
|
||||
{% if domain_applications %}
|
||||
{% if domain_requests %}
|
||||
<table class="usa-table usa-table--borderless usa-table--stacked dotgov-table dotgov-table--stacked">
|
||||
<caption class="sr-only">Your domain requests</caption>
|
||||
<thead>
|
||||
|
@ -112,61 +112,61 @@
|
|||
<th data-sortable scope="col" role="columnheader">Date submitted</th>
|
||||
<th data-sortable scope="col" role="columnheader">Status</th>
|
||||
<th scope="col" role="columnheader"><span class="usa-sr-only">Action</span></th>
|
||||
{% if has_deletable_applications %}
|
||||
{% if has_deletable_domain_requests %}
|
||||
<th scope="col" role="columnheader"><span class="usa-sr-only">Delete Action</span></th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for application in domain_applications %}
|
||||
{% for domain_request in domain_requests %}
|
||||
<tr>
|
||||
<th th scope="row" role="rowheader" data-label="Domain name">
|
||||
{% if application.requested_domain is None %}
|
||||
{% if domain_request.requested_domain is None %}
|
||||
New domain request
|
||||
{# Add a breakpoint #}
|
||||
<div aria-hidden="true"></div>
|
||||
<span class="text-base font-body-xs">({{ application.created_at }} UTC)</span>
|
||||
<span class="text-base font-body-xs">({{ domain_request.created_at }} UTC)</span>
|
||||
{% else %}
|
||||
{{ application.requested_domain.name }}
|
||||
{{ domain_request.requested_domain.name }}
|
||||
{% endif %}
|
||||
</th>
|
||||
<td data-sort-value="{{ application.submission_date|date:"U" }}" data-label="Date submitted">
|
||||
{% if application.submission_date %}
|
||||
{{ application.submission_date|date }}
|
||||
<td data-sort-value="{{ domain_request.submission_date|date:"U" }}" data-label="Date submitted">
|
||||
{% if domain_request.submission_date %}
|
||||
{{ domain_request.submission_date|date }}
|
||||
{% else %}
|
||||
<span class="text-base">Not submitted</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td data-label="Status">{{ application.get_status_display }}</td>
|
||||
<td data-label="Status">{{ domain_request.get_status_display }}</td>
|
||||
<td>
|
||||
{% with prefix="New domain request ("%}
|
||||
{% with date=application.created_at|date:"DATETIME_FORMAT"%}
|
||||
{% with date=domain_request.created_at|date:"DATETIME_FORMAT"%}
|
||||
{% with name_default=prefix|add:date|add:" UTC)"%}
|
||||
{% if application.status == application.ApplicationStatus.STARTED or application.status == application.ApplicationStatus.ACTION_NEEDED or application.status == application.ApplicationStatus.WITHDRAWN %}
|
||||
<a href="{% url 'edit-application' application.pk %}">
|
||||
{% if domain_request.status == domain_request.DomainRequestStatus.STARTED or domain_request.status == domain_request.DomainRequestStatus.ACTION_NEEDED or domain_request.status == domain_request.DomainRequestStatus.WITHDRAWN %}
|
||||
<a href="{% url 'edit-domain-request' domain_request.pk %}">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#edit"></use>
|
||||
</svg>
|
||||
{% if application.requested_domain is not None%}
|
||||
Edit <span class="usa-sr-only">{{ application.requested_domain.name }}</span>
|
||||
{% if domain_request.requested_domain is not None%}
|
||||
Edit <span class="usa-sr-only">{{ domain_request.requested_domain.name }}</span>
|
||||
{% else %}
|
||||
Edit <span class="usa-sr-only">{{ name_default }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url 'application-status' application.pk %}">
|
||||
<a href="{% url 'domain-request-status' domain_request.pk %}">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#settings"></use>
|
||||
</svg>
|
||||
Manage <span class="usa-sr-only">{{ application.requested_domain.name|default:name_default }}</span>
|
||||
Manage <span class="usa-sr-only">{{ domain_request.requested_domain.name|default:name_default }}</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
</a>
|
||||
</td>
|
||||
{% if has_deletable_applications %}
|
||||
{% if has_deletable_domain_requests %}
|
||||
<td>
|
||||
{% if application.status == "started" or application.status == "withdrawn" %}
|
||||
{% if domain_request.status == "started" or domain_request.status == "withdrawn" %}
|
||||
<a
|
||||
role="button"
|
||||
id="button-toggle-delete-domain-alert-{{ forloop.counter }}"
|
||||
|
@ -179,10 +179,10 @@
|
|||
<use xlink:href="{%static 'img/sprite.svg'%}#delete"></use>
|
||||
</svg>
|
||||
{% with prefix="New domain request ("%}
|
||||
{% with date=application.created_at|date:"DATETIME_FORMAT"%}
|
||||
{% with date=domain_request.created_at|date:"DATETIME_FORMAT"%}
|
||||
{% with name_default=prefix|add:date|add:" UTC)"%}
|
||||
{% if application.requested_domain is not None %}
|
||||
Delete <span class="usa-sr-only">{{ application.requested_domain.name }}</span>
|
||||
{% if domain_request.requested_domain is not None %}
|
||||
Delete <span class="usa-sr-only">{{ domain_request.requested_domain.name }}</span>
|
||||
{% else %}
|
||||
Delete <span class="usa-sr-only">{{ name_default }}</span>
|
||||
{% endif %}
|
||||
|
@ -198,11 +198,11 @@
|
|||
aria-describedby="Domain will be removed"
|
||||
data-force-action
|
||||
>
|
||||
<form method="POST" action="{% url "application-delete" pk=application.id %}">
|
||||
{% if application.requested_domain is None %}
|
||||
{% if application.created_at %}
|
||||
<form method="POST" action="{% url "domain-request-delete" pk=domain_request.id %}">
|
||||
{% if domain_request.requested_domain is None %}
|
||||
{% if domain_request.created_at %}
|
||||
{% with prefix="(created " %}
|
||||
{% with formatted_date=application.created_at|date:"DATETIME_FORMAT" %}
|
||||
{% with formatted_date=domain_request.created_at|date:"DATETIME_FORMAT" %}
|
||||
{% with modal_content=prefix|add:formatted_date|add:" UTC)" %}
|
||||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete this domain request?" modal_description="This will remove the domain request "|add:modal_content|add:" from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
||||
{% endwith %}
|
||||
|
@ -212,7 +212,7 @@
|
|||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete New domain request?" modal_description="This will remove the domain request from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% with modal_heading_value=application.requested_domain.name|add:"?" %}
|
||||
{% with modal_heading_value=domain_request.requested_domain.name|add:"?" %}
|
||||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to delete" heading_value=modal_heading_value modal_description="This will remove the domain request from the .gov registrar. This action cannot be undone." modal_button=modal_button|safe %}
|
||||
{% endwith %}
|
||||
{% endif %}
|
||||
|
@ -231,7 +231,7 @@
|
|||
></div>
|
||||
{% else %}
|
||||
<p>You haven't requested any domains.</p>
|
||||
<!-- <p><a href="{% url 'application:' %}" class="usa-button">Start a new domain request</a></p> -->
|
||||
<!-- <p><a href="{% url 'domain-request:' %}" class="usa-button">Start a new domain request</a></p> -->
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
from django import template
|
||||
import re
|
||||
from registrar.models.domain_application import DomainApplication
|
||||
from registrar.models.domain_request import DomainRequest
|
||||
|
||||
register = template.Library()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -55,7 +55,7 @@ def contains_checkbox(html_list):
|
|||
|
||||
@register.filter
|
||||
def get_organization_long_name(organization_type):
|
||||
organization_choices_dict = dict(DomainApplication.OrganizationChoicesVerbose.choices)
|
||||
organization_choices_dict = dict(DomainRequest.OrganizationChoicesVerbose.choices)
|
||||
long_form_type = organization_choices_dict[organization_type]
|
||||
if long_form_type is None:
|
||||
logger.error("Organization type error, triggered by a template's custom filter")
|
||||
|
|
|
@ -18,7 +18,7 @@ from registrar.models import (
|
|||
Contact,
|
||||
DraftDomain,
|
||||
Website,
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
DomainInvitation,
|
||||
User,
|
||||
UserGroup,
|
||||
|
@ -221,7 +221,7 @@ class AuditedAdminMockData:
|
|||
|
||||
# Constants for different domain object types
|
||||
INFORMATION = "information"
|
||||
APPLICATION = "application"
|
||||
DOMAIN_REQUEST = "domain_request"
|
||||
INVITATION = "invitation"
|
||||
|
||||
def dummy_user(self, item_name, short_hand):
|
||||
|
@ -365,24 +365,24 @@ class AuditedAdminMockData:
|
|||
self,
|
||||
domain_type,
|
||||
item_name,
|
||||
status=DomainApplication.ApplicationStatus.STARTED,
|
||||
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||
org_type="federal",
|
||||
federal_type="executive",
|
||||
purpose="Purpose of the site",
|
||||
):
|
||||
"""
|
||||
Returns a prebuilt kwarg dictionary for DomainApplication,
|
||||
Returns a prebuilt kwarg dictionary for DomainRequest,
|
||||
DomainInformation, or DomainInvitation.
|
||||
Args:
|
||||
domain_type (str): is either 'application', 'information',
|
||||
domain_type (str): is either 'domain_request', 'information',
|
||||
or 'invitation'.
|
||||
|
||||
item_name (str): A shared str value appended to first_name, last_name,
|
||||
organization_name, address_line1, address_line2,
|
||||
title, email, and username.
|
||||
|
||||
status (str - optional): Defines the status for DomainApplication,
|
||||
e.g. DomainApplication.ApplicationStatus.STARTED
|
||||
status (str - optional): Defines the status for DomainRequest,
|
||||
e.g. DomainRequest.DomainRequestStatus.STARTED
|
||||
|
||||
org_type (str - optional): Sets a domains org_type
|
||||
|
||||
|
@ -391,13 +391,13 @@ class AuditedAdminMockData:
|
|||
purpose (str - optional): Sets a domains purpose
|
||||
Returns:
|
||||
dict: Returns a dictionary structurally consistent with the expected input
|
||||
of either DomainApplication, DomainInvitation, or DomainInformation
|
||||
of either DomainRequest, DomainInvitation, or DomainInformation
|
||||
based on the 'domain_type' field.
|
||||
""" # noqa
|
||||
common_args = self.get_common_domain_arg_dictionary(item_name, org_type, federal_type, purpose)
|
||||
full_arg_dict = None
|
||||
match domain_type:
|
||||
case self.APPLICATION:
|
||||
case self.DOMAIN_REQUEST:
|
||||
full_arg_dict = dict(
|
||||
**common_args,
|
||||
requested_domain=self.dummy_draft_domain(item_name),
|
||||
|
@ -405,11 +405,11 @@ class AuditedAdminMockData:
|
|||
status=status,
|
||||
)
|
||||
case self.INFORMATION:
|
||||
domain_app = self.create_full_dummy_domain_application(item_name)
|
||||
domain_req = self.create_full_dummy_domain_request(item_name)
|
||||
full_arg_dict = dict(
|
||||
**common_args,
|
||||
domain=self.dummy_domain(item_name, True),
|
||||
domain_application=domain_app,
|
||||
domain_request=domain_req,
|
||||
)
|
||||
case self.INVITATION:
|
||||
full_arg_dict = dict(
|
||||
|
@ -419,24 +419,24 @@ class AuditedAdminMockData:
|
|||
)
|
||||
return full_arg_dict
|
||||
|
||||
def create_full_dummy_domain_application(self, item_name, status=DomainApplication.ApplicationStatus.STARTED):
|
||||
"""Creates a dummy domain application object"""
|
||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.APPLICATION, item_name, status)
|
||||
application = DomainApplication.objects.get_or_create(**domain_application_kwargs)[0]
|
||||
return application
|
||||
def create_full_dummy_domain_request(self, item_name, status=DomainRequest.DomainRequestStatus.STARTED):
|
||||
"""Creates a dummy domain request object"""
|
||||
domain_request_kwargs = self.dummy_kwarg_boilerplate(self.DOMAIN_REQUEST, item_name, status)
|
||||
domain_request = DomainRequest.objects.get_or_create(**domain_request_kwargs)[0]
|
||||
return domain_request
|
||||
|
||||
def create_full_dummy_domain_information(self, item_name, status=DomainApplication.ApplicationStatus.STARTED):
|
||||
def create_full_dummy_domain_information(self, item_name, status=DomainRequest.DomainRequestStatus.STARTED):
|
||||
"""Creates a dummy domain information object"""
|
||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.INFORMATION, item_name, status)
|
||||
application = DomainInformation.objects.get_or_create(**domain_application_kwargs)[0]
|
||||
return application
|
||||
domain_request_kwargs = self.dummy_kwarg_boilerplate(self.INFORMATION, item_name, status)
|
||||
domain_request = DomainInformation.objects.get_or_create(**domain_request_kwargs)[0]
|
||||
return domain_request
|
||||
|
||||
def create_full_dummy_domain_invitation(self, item_name, status=DomainApplication.ApplicationStatus.STARTED):
|
||||
def create_full_dummy_domain_invitation(self, item_name, status=DomainRequest.DomainRequestStatus.STARTED):
|
||||
"""Creates a dummy domain invitation object"""
|
||||
domain_application_kwargs = self.dummy_kwarg_boilerplate(self.INVITATION, item_name, status)
|
||||
application = DomainInvitation.objects.get_or_create(**domain_application_kwargs)[0]
|
||||
domain_request_kwargs = self.dummy_kwarg_boilerplate(self.INVITATION, item_name, status)
|
||||
domain_request = DomainInvitation.objects.get_or_create(**domain_request_kwargs)[0]
|
||||
|
||||
return application
|
||||
return domain_request
|
||||
|
||||
def create_full_dummy_domain_object(
|
||||
self,
|
||||
|
@ -445,31 +445,31 @@ class AuditedAdminMockData:
|
|||
has_other_contacts=True,
|
||||
has_current_website=True,
|
||||
has_alternative_gov_domain=True,
|
||||
status=DomainApplication.ApplicationStatus.STARTED,
|
||||
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||
):
|
||||
"""A helper to create a dummy domain application object"""
|
||||
application = None
|
||||
"""A helper to create a dummy domain request object"""
|
||||
domain_request = None
|
||||
match domain_type:
|
||||
case self.APPLICATION:
|
||||
application = self.create_full_dummy_domain_application(item_name, status)
|
||||
case self.DOMAIN_REQUEST:
|
||||
domain_request = self.create_full_dummy_domain_request(item_name, status)
|
||||
case self.INVITATION:
|
||||
application = self.create_full_dummy_domain_invitation(item_name, status)
|
||||
domain_request = self.create_full_dummy_domain_invitation(item_name, status)
|
||||
case self.INFORMATION:
|
||||
application = self.create_full_dummy_domain_information(item_name, status)
|
||||
domain_request = self.create_full_dummy_domain_information(item_name, status)
|
||||
case _:
|
||||
raise ValueError("Invalid domain_type, must conform to given constants")
|
||||
|
||||
if has_other_contacts and domain_type != self.INVITATION:
|
||||
other = self.dummy_contact(item_name, "other")
|
||||
application.other_contacts.add(other)
|
||||
if has_current_website and domain_type == self.APPLICATION:
|
||||
domain_request.other_contacts.add(other)
|
||||
if has_current_website and domain_type == self.DOMAIN_REQUEST:
|
||||
current = self.dummy_current(item_name)
|
||||
application.current_websites.add(current)
|
||||
if has_alternative_gov_domain and domain_type == self.APPLICATION:
|
||||
domain_request.current_websites.add(current)
|
||||
if has_alternative_gov_domain and domain_type == self.DOMAIN_REQUEST:
|
||||
alt = self.dummy_alt(item_name)
|
||||
application.alternative_domains.add(alt)
|
||||
domain_request.alternative_domains.add(alt)
|
||||
|
||||
return application
|
||||
return domain_request
|
||||
|
||||
|
||||
def mock_user():
|
||||
|
@ -519,18 +519,18 @@ def create_ready_domain():
|
|||
return domain
|
||||
|
||||
|
||||
def completed_application(
|
||||
def completed_domain_request(
|
||||
has_other_contacts=True,
|
||||
has_current_website=True,
|
||||
has_alternative_gov_domain=True,
|
||||
has_about_your_organization=True,
|
||||
has_anything_else=True,
|
||||
status=DomainApplication.ApplicationStatus.STARTED,
|
||||
status=DomainRequest.DomainRequestStatus.STARTED,
|
||||
user=False,
|
||||
submitter=False,
|
||||
name="city.gov",
|
||||
):
|
||||
"""A completed domain application."""
|
||||
"""A completed domain request."""
|
||||
if not user:
|
||||
user = get_user_model().objects.create(username="username" + str(uuid.uuid4())[:8])
|
||||
ao, _ = Contact.objects.get_or_create(
|
||||
|
@ -558,7 +558,7 @@ def completed_application(
|
|||
email="testy2@town.com",
|
||||
phone="(555) 555 5557",
|
||||
)
|
||||
domain_application_kwargs = dict(
|
||||
domain_request_kwargs = dict(
|
||||
organization_type="federal",
|
||||
federal_type="executive",
|
||||
purpose="Purpose of the site",
|
||||
|
@ -575,43 +575,43 @@ def completed_application(
|
|||
status=status,
|
||||
)
|
||||
if has_about_your_organization:
|
||||
domain_application_kwargs["about_your_organization"] = "e-Government"
|
||||
domain_request_kwargs["about_your_organization"] = "e-Government"
|
||||
if has_anything_else:
|
||||
domain_application_kwargs["anything_else"] = "There is more"
|
||||
domain_request_kwargs["anything_else"] = "There is more"
|
||||
|
||||
application, _ = DomainApplication.objects.get_or_create(**domain_application_kwargs)
|
||||
domain_request, _ = DomainRequest.objects.get_or_create(**domain_request_kwargs)
|
||||
|
||||
if has_other_contacts:
|
||||
application.other_contacts.add(other)
|
||||
domain_request.other_contacts.add(other)
|
||||
if has_current_website:
|
||||
application.current_websites.add(current)
|
||||
domain_request.current_websites.add(current)
|
||||
if has_alternative_gov_domain:
|
||||
application.alternative_domains.add(alt)
|
||||
domain_request.alternative_domains.add(alt)
|
||||
|
||||
return application
|
||||
return domain_request
|
||||
|
||||
|
||||
def multiple_unalphabetical_domain_objects(
|
||||
domain_type=AuditedAdminMockData.APPLICATION,
|
||||
domain_type=AuditedAdminMockData.DOMAIN_REQUEST,
|
||||
):
|
||||
"""Returns a list of generic domain objects for testing purposes"""
|
||||
applications = []
|
||||
domain_requests = []
|
||||
list_of_letters = list(ascii_uppercase)
|
||||
random.shuffle(list_of_letters)
|
||||
|
||||
mock = AuditedAdminMockData()
|
||||
for object_name in list_of_letters:
|
||||
application = mock.create_full_dummy_domain_object(domain_type, object_name)
|
||||
applications.append(application)
|
||||
return applications
|
||||
domain_request = mock.create_full_dummy_domain_object(domain_type, object_name)
|
||||
domain_requests.append(domain_request)
|
||||
return domain_requests
|
||||
|
||||
|
||||
def generic_domain_object(domain_type, object_name):
|
||||
"""Returns a generic domain object of
|
||||
domain_type 'application', 'information', or 'invitation'"""
|
||||
domain_type 'domain_request', 'information', or 'invitation'"""
|
||||
mock = AuditedAdminMockData()
|
||||
application = mock.create_full_dummy_domain_object(domain_type, object_name)
|
||||
return application
|
||||
domain_request = mock.create_full_dummy_domain_object(domain_type, object_name)
|
||||
return domain_request
|
||||
|
||||
|
||||
class MockEppLib(TestCase):
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,7 +3,7 @@
|
|||
from unittest.mock import MagicMock
|
||||
|
||||
from django.test import TestCase
|
||||
from .common import completed_application, less_console_noise
|
||||
from .common import completed_domain_request, less_console_noise
|
||||
|
||||
|
||||
import boto3_mocking # type: ignore
|
||||
|
@ -17,11 +17,11 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation(self):
|
||||
"""Submission confirmation email works."""
|
||||
application = completed_application()
|
||||
domain_request = completed_domain_request()
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
|
||||
# check that an email was sent
|
||||
self.assertTrue(self.mock_client.send_email.called)
|
||||
|
@ -55,10 +55,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_no_current_website_spacing(self):
|
||||
"""Test line spacing without current_website."""
|
||||
application = completed_application(has_current_website=False)
|
||||
domain_request = completed_domain_request(has_current_website=False)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertNotIn("Current websites:", body)
|
||||
|
@ -68,10 +68,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_current_website_spacing(self):
|
||||
"""Test line spacing with current_website."""
|
||||
application = completed_application(has_current_website=True)
|
||||
domain_request = completed_domain_request(has_current_website=True)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertIn("Current websites:", body)
|
||||
|
@ -82,10 +82,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_other_contacts_spacing(self):
|
||||
"""Test line spacing with other contacts."""
|
||||
application = completed_application(has_other_contacts=True)
|
||||
domain_request = completed_domain_request(has_other_contacts=True)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertIn("Other employees from your organization:", body)
|
||||
|
@ -96,10 +96,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_no_other_contacts_spacing(self):
|
||||
"""Test line spacing without other contacts."""
|
||||
application = completed_application(has_other_contacts=False)
|
||||
domain_request = completed_domain_request(has_other_contacts=False)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
# spacing should be right between adjacent elements
|
||||
|
@ -109,10 +109,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_alternative_govdomain_spacing(self):
|
||||
"""Test line spacing with alternative .gov domain."""
|
||||
application = completed_application(has_alternative_gov_domain=True)
|
||||
domain_request = completed_domain_request(has_alternative_gov_domain=True)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertIn("city1.gov", body)
|
||||
|
@ -122,10 +122,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_no_alternative_govdomain_spacing(self):
|
||||
"""Test line spacing without alternative .gov domain."""
|
||||
application = completed_application(has_alternative_gov_domain=False)
|
||||
domain_request = completed_domain_request(has_alternative_gov_domain=False)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertNotIn("city1.gov", body)
|
||||
|
@ -135,10 +135,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_about_your_organization_spacing(self):
|
||||
"""Test line spacing with about your organization."""
|
||||
application = completed_application(has_about_your_organization=True)
|
||||
domain_request = completed_domain_request(has_about_your_organization=True)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertIn("About your organization:", body)
|
||||
|
@ -148,10 +148,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_no_about_your_organization_spacing(self):
|
||||
"""Test line spacing without about your organization."""
|
||||
application = completed_application(has_about_your_organization=False)
|
||||
domain_request = completed_domain_request(has_about_your_organization=False)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertNotIn("About your organization:", body)
|
||||
|
@ -161,10 +161,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_anything_else_spacing(self):
|
||||
"""Test line spacing with anything else."""
|
||||
application = completed_application(has_anything_else=True)
|
||||
domain_request = completed_domain_request(has_anything_else=True)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
# spacing should be right between adjacent elements
|
||||
|
@ -173,10 +173,10 @@ class TestEmails(TestCase):
|
|||
@boto3_mocking.patching
|
||||
def test_submission_confirmation_no_anything_else_spacing(self):
|
||||
"""Test line spacing without anything else."""
|
||||
application = completed_application(has_anything_else=False)
|
||||
domain_request = completed_domain_request(has_anything_else=False)
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
_, kwargs = self.mock_client.send_email.call_args
|
||||
body = kwargs["Content"]["Simple"]["Body"]["Text"]["Data"]
|
||||
self.assertNotIn("Anything else", body)
|
||||
|
|
|
@ -4,7 +4,7 @@ import json
|
|||
from django.test import TestCase, RequestFactory
|
||||
from api.views import available
|
||||
|
||||
from registrar.forms.application_wizard import (
|
||||
from registrar.forms.domain_request_wizard import (
|
||||
AlternativeDomainForm,
|
||||
CurrentSitesForm,
|
||||
DotGovDomainForm,
|
||||
|
|
|
@ -34,10 +34,10 @@ class TestGroups(TestCase):
|
|||
"view_logentry",
|
||||
"change_contact",
|
||||
"view_domain",
|
||||
"change_domainapplication",
|
||||
"change_domaininformation",
|
||||
"add_domaininvitation",
|
||||
"view_domaininvitation",
|
||||
"change_domainrequest",
|
||||
"change_draftdomain",
|
||||
"analyst_access_permission",
|
||||
"change_user",
|
||||
|
|
|
@ -4,7 +4,7 @@ from unittest.mock import patch
|
|||
|
||||
from registrar.models import (
|
||||
Contact,
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
DomainInformation,
|
||||
User,
|
||||
Website,
|
||||
|
@ -17,39 +17,39 @@ from registrar.models import (
|
|||
import boto3_mocking
|
||||
from registrar.models.transition_domain import TransitionDomain
|
||||
from registrar.models.verified_by_staff import VerifiedByStaff # type: ignore
|
||||
from .common import MockSESClient, less_console_noise, completed_application
|
||||
from .common import MockSESClient, less_console_noise, completed_domain_request
|
||||
from django_fsm import TransitionNotAllowed
|
||||
|
||||
|
||||
# Test comment for push -- will remove
|
||||
# The DomainApplication submit method has a side effect of sending an email
|
||||
# The DomainRequest submit method has a side effect of sending an email
|
||||
# with AWS SES, so mock that out in all of these test cases
|
||||
@boto3_mocking.patching
|
||||
class TestDomainApplication(TestCase):
|
||||
class TestDomainRequest(TestCase):
|
||||
def setUp(self):
|
||||
self.started_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.STARTED, name="started.gov"
|
||||
self.started_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.STARTED, name="started.gov"
|
||||
)
|
||||
self.submitted_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.SUBMITTED, name="submitted.gov"
|
||||
self.submitted_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.SUBMITTED, name="submitted.gov"
|
||||
)
|
||||
self.in_review_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.IN_REVIEW, name="in-review.gov"
|
||||
self.in_review_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.IN_REVIEW, name="in-review.gov"
|
||||
)
|
||||
self.action_needed_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.ACTION_NEEDED, name="action-needed.gov"
|
||||
self.action_needed_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.ACTION_NEEDED, name="action-needed.gov"
|
||||
)
|
||||
self.approved_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.APPROVED, name="approved.gov"
|
||||
self.approved_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.APPROVED, name="approved.gov"
|
||||
)
|
||||
self.withdrawn_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.WITHDRAWN, name="withdrawn.gov"
|
||||
self.withdrawn_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.WITHDRAWN, name="withdrawn.gov"
|
||||
)
|
||||
self.rejected_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.REJECTED, name="rejected.gov"
|
||||
self.rejected_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.REJECTED, name="rejected.gov"
|
||||
)
|
||||
self.ineligible_application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.INELIGIBLE, name="ineligible.gov"
|
||||
self.ineligible_domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.INELIGIBLE, name="ineligible.gov"
|
||||
)
|
||||
|
||||
self.mock_client = MockSESClient()
|
||||
|
@ -64,19 +64,19 @@ class TestDomainApplication(TestCase):
|
|||
return self.assertRaises(Exception, None, exception_type)
|
||||
|
||||
def test_empty_create_fails(self):
|
||||
"""Can't create a completely empty domain application.
|
||||
"""Can't create a completely empty domain request.
|
||||
NOTE: something about theexception this test raises messes up with the
|
||||
atomic block in a custom tearDown method for the parent test class."""
|
||||
with less_console_noise():
|
||||
with self.assertRaisesRegex(IntegrityError, "creator"):
|
||||
DomainApplication.objects.create()
|
||||
DomainRequest.objects.create()
|
||||
|
||||
def test_minimal_create(self):
|
||||
"""Can create with just a creator."""
|
||||
with less_console_noise():
|
||||
user, _ = User.objects.get_or_create(username="testy")
|
||||
application = DomainApplication.objects.create(creator=user)
|
||||
self.assertEqual(application.status, DomainApplication.ApplicationStatus.STARTED)
|
||||
domain_request = DomainRequest.objects.create(creator=user)
|
||||
self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.STARTED)
|
||||
|
||||
def test_full_create(self):
|
||||
"""Can create with all fields."""
|
||||
|
@ -86,11 +86,11 @@ class TestDomainApplication(TestCase):
|
|||
com_website, _ = Website.objects.get_or_create(website="igorville.com")
|
||||
gov_website, _ = Website.objects.get_or_create(website="igorville.gov")
|
||||
domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||
application = DomainApplication.objects.create(
|
||||
domain_request = DomainRequest.objects.create(
|
||||
creator=user,
|
||||
investigator=user,
|
||||
organization_type=DomainApplication.OrganizationChoices.FEDERAL,
|
||||
federal_type=DomainApplication.BranchChoices.EXECUTIVE,
|
||||
organization_type=DomainRequest.OrganizationChoices.FEDERAL,
|
||||
federal_type=DomainRequest.BranchChoices.EXECUTIVE,
|
||||
is_election_board=False,
|
||||
organization_name="Test",
|
||||
address_line1="100 Main St.",
|
||||
|
@ -104,10 +104,10 @@ class TestDomainApplication(TestCase):
|
|||
anything_else="All of Igorville loves the dotgov program.",
|
||||
is_policy_acknowledged=True,
|
||||
)
|
||||
application.current_websites.add(com_website)
|
||||
application.alternative_domains.add(gov_website)
|
||||
application.other_contacts.add(contact)
|
||||
application.save()
|
||||
domain_request.current_websites.add(com_website)
|
||||
domain_request.alternative_domains.add(gov_website)
|
||||
domain_request.other_contacts.add(contact)
|
||||
domain_request.save()
|
||||
|
||||
def test_domain_info(self):
|
||||
"""Can create domain info with all fields."""
|
||||
|
@ -140,35 +140,35 @@ class TestDomainApplication(TestCase):
|
|||
def test_status_fsm_submit_fail(self):
|
||||
with less_console_noise():
|
||||
user, _ = User.objects.get_or_create(username="testy")
|
||||
application = DomainApplication.objects.create(creator=user)
|
||||
domain_request = DomainRequest.objects.create(creator=user)
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
with self.assertRaises(ValueError):
|
||||
# can't submit an application with a null domain name
|
||||
application.submit()
|
||||
# can't submit a domain request with a null domain name
|
||||
domain_request.submit()
|
||||
|
||||
def test_status_fsm_submit_succeed(self):
|
||||
with less_console_noise():
|
||||
user, _ = User.objects.get_or_create(username="testy")
|
||||
site = DraftDomain.objects.create(name="igorville.gov")
|
||||
application = DomainApplication.objects.create(creator=user, requested_domain=site)
|
||||
domain_request = DomainRequest.objects.create(creator=user, requested_domain=site)
|
||||
|
||||
# no submitter email so this emits a log warning
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
application.submit()
|
||||
self.assertEqual(application.status, application.ApplicationStatus.SUBMITTED)
|
||||
domain_request.submit()
|
||||
self.assertEqual(domain_request.status, domain_request.DomainRequestStatus.SUBMITTED)
|
||||
|
||||
def check_email_sent(self, application, msg, action, expected_count):
|
||||
def check_email_sent(self, domain_request, msg, action, expected_count):
|
||||
"""Check if an email was sent after performing an action."""
|
||||
|
||||
with self.subTest(msg=msg, action=action):
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
# Perform the specified action
|
||||
action_method = getattr(application, action)
|
||||
action_method = getattr(domain_request, action)
|
||||
action_method()
|
||||
|
||||
# Check if an email was sent
|
||||
|
@ -180,62 +180,62 @@ class TestDomainApplication(TestCase):
|
|||
self.assertEqual(len(sent_emails), expected_count)
|
||||
|
||||
def test_submit_from_started_sends_email(self):
|
||||
msg = "Create an application and submit it and see if email was sent."
|
||||
application = completed_application()
|
||||
self.check_email_sent(application, msg, "submit", 1)
|
||||
msg = "Create a domain request and submit it and see if email was sent."
|
||||
domain_request = completed_domain_request()
|
||||
self.check_email_sent(domain_request, msg, "submit", 1)
|
||||
|
||||
def test_submit_from_withdrawn_sends_email(self):
|
||||
msg = "Create a withdrawn application and submit it and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.WITHDRAWN)
|
||||
self.check_email_sent(application, msg, "submit", 1)
|
||||
msg = "Create a withdrawn domain request and submit it and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.WITHDRAWN)
|
||||
self.check_email_sent(domain_request, msg, "submit", 1)
|
||||
|
||||
def test_submit_from_action_needed_does_not_send_email(self):
|
||||
msg = "Create an application with ACTION_NEEDED status and submit it, check if email was not sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.ACTION_NEEDED)
|
||||
self.check_email_sent(application, msg, "submit", 0)
|
||||
msg = "Create a domain request with ACTION_NEEDED status and submit it, check if email was not sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.ACTION_NEEDED)
|
||||
self.check_email_sent(domain_request, msg, "submit", 0)
|
||||
|
||||
def test_submit_from_in_review_does_not_send_email(self):
|
||||
msg = "Create a withdrawn application and submit it and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
|
||||
self.check_email_sent(application, msg, "submit", 0)
|
||||
msg = "Create a withdrawn domain request and submit it and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
|
||||
self.check_email_sent(domain_request, msg, "submit", 0)
|
||||
|
||||
def test_approve_sends_email(self):
|
||||
msg = "Create an application and approve it and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
|
||||
self.check_email_sent(application, msg, "approve", 1)
|
||||
msg = "Create a domain request and approve it and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
|
||||
self.check_email_sent(domain_request, msg, "approve", 1)
|
||||
|
||||
def test_withdraw_sends_email(self):
|
||||
msg = "Create an application and withdraw it and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.IN_REVIEW)
|
||||
self.check_email_sent(application, msg, "withdraw", 1)
|
||||
msg = "Create a domain request and withdraw it and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW)
|
||||
self.check_email_sent(domain_request, msg, "withdraw", 1)
|
||||
|
||||
def test_reject_sends_email(self):
|
||||
msg = "Create an application and reject it and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.APPROVED)
|
||||
self.check_email_sent(application, msg, "reject", 1)
|
||||
msg = "Create a domain request and reject it and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.APPROVED)
|
||||
self.check_email_sent(domain_request, msg, "reject", 1)
|
||||
|
||||
def test_reject_with_prejudice_does_not_send_email(self):
|
||||
msg = "Create an application and reject it with prejudice and see if email was sent."
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.APPROVED)
|
||||
self.check_email_sent(application, msg, "reject_with_prejudice", 0)
|
||||
msg = "Create a domain request and reject it with prejudice and see if email was sent."
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.APPROVED)
|
||||
self.check_email_sent(domain_request, msg, "reject_with_prejudice", 0)
|
||||
|
||||
def test_submit_transition_allowed(self):
|
||||
"""
|
||||
Test that calling submit from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -244,37 +244,37 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling submit against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.submit()
|
||||
domain_request.submit()
|
||||
|
||||
def test_in_review_transition_allowed(self):
|
||||
"""
|
||||
Test that calling in_review from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.in_review()
|
||||
domain_request.in_review()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -283,33 +283,33 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling in_review against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.in_review()
|
||||
domain_request.in_review()
|
||||
|
||||
def test_action_needed_transition_allowed(self):
|
||||
"""
|
||||
Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.action_needed()
|
||||
domain_request.action_needed()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -318,34 +318,34 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling action_needed against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.action_needed()
|
||||
domain_request.action_needed()
|
||||
|
||||
def test_approved_transition_allowed(self):
|
||||
"""
|
||||
Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.approve()
|
||||
domain_request.approve()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -357,7 +357,7 @@ class TestDomainApplication(TestCase):
|
|||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
self.submitted_application.approve(send_email=False)
|
||||
self.submitted_domain_request.approve(send_email=False)
|
||||
|
||||
# Assert that no emails were sent
|
||||
self.assertEqual(len(self.mock_client.EMAILS_SENT), 0)
|
||||
|
@ -367,35 +367,35 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling action_needed against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.approve()
|
||||
domain_request.approve()
|
||||
|
||||
def test_withdraw_transition_allowed(self):
|
||||
"""
|
||||
Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.withdraw()
|
||||
domain_request.withdraw()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -404,36 +404,36 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling action_needed against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.withdraw()
|
||||
domain_request.withdraw()
|
||||
|
||||
def test_reject_transition_allowed(self):
|
||||
"""
|
||||
Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.reject()
|
||||
domain_request.reject()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -442,37 +442,37 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling action_needed against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.reject()
|
||||
domain_request.reject()
|
||||
|
||||
def test_reject_with_prejudice_transition_allowed(self):
|
||||
"""
|
||||
Test that calling action_needed from allowable statuses does raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.in_review_application, TransitionNotAllowed),
|
||||
(self.action_needed_application, TransitionNotAllowed),
|
||||
(self.approved_application, TransitionNotAllowed),
|
||||
(self.rejected_application, TransitionNotAllowed),
|
||||
(self.in_review_domain_request, TransitionNotAllowed),
|
||||
(self.action_needed_domain_request, TransitionNotAllowed),
|
||||
(self.approved_domain_request, TransitionNotAllowed),
|
||||
(self.rejected_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
try:
|
||||
application.reject_with_prejudice()
|
||||
domain_request.reject_with_prejudice()
|
||||
except TransitionNotAllowed:
|
||||
self.fail("TransitionNotAllowed was raised, but it was not expected.")
|
||||
|
||||
|
@ -481,26 +481,26 @@ class TestDomainApplication(TestCase):
|
|||
Test that calling action_needed against transition rules raises TransitionNotAllowed.
|
||||
"""
|
||||
test_cases = [
|
||||
(self.started_application, TransitionNotAllowed),
|
||||
(self.submitted_application, TransitionNotAllowed),
|
||||
(self.withdrawn_application, TransitionNotAllowed),
|
||||
(self.ineligible_application, TransitionNotAllowed),
|
||||
(self.started_domain_request, TransitionNotAllowed),
|
||||
(self.submitted_domain_request, TransitionNotAllowed),
|
||||
(self.withdrawn_domain_request, TransitionNotAllowed),
|
||||
(self.ineligible_domain_request, TransitionNotAllowed),
|
||||
]
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
for application, exception_type in test_cases:
|
||||
with self.subTest(application=application, exception_type=exception_type):
|
||||
for domain_request, exception_type in test_cases:
|
||||
with self.subTest(domain_request=domain_request, exception_type=exception_type):
|
||||
with self.assertRaises(exception_type):
|
||||
application.reject_with_prejudice()
|
||||
domain_request.reject_with_prejudice()
|
||||
|
||||
def test_transition_not_allowed_approved_in_review_when_domain_is_active(self):
|
||||
"""Create an application with status approved, create a matching domain that
|
||||
"""Create a domain request with status approved, create a matching domain that
|
||||
is active, and call in_review against transition rules"""
|
||||
|
||||
domain = Domain.objects.create(name=self.approved_application.requested_domain.name)
|
||||
self.approved_application.approved_domain = domain
|
||||
self.approved_application.save()
|
||||
domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
|
||||
self.approved_domain_request.approved_domain = domain
|
||||
self.approved_domain_request.save()
|
||||
|
||||
# Define a custom implementation for is_active
|
||||
def custom_is_active(self):
|
||||
|
@ -512,15 +512,15 @@ class TestDomainApplication(TestCase):
|
|||
with patch.object(Domain, "is_active", custom_is_active):
|
||||
# Now, when you call is_active on Domain, it will return True
|
||||
with self.assertRaises(TransitionNotAllowed):
|
||||
self.approved_application.in_review()
|
||||
self.approved_domain_request.in_review()
|
||||
|
||||
def test_transition_not_allowed_approved_action_needed_when_domain_is_active(self):
|
||||
"""Create an application with status approved, create a matching domain that
|
||||
"""Create a domain request with status approved, create a matching domain that
|
||||
is active, and call action_needed against transition rules"""
|
||||
|
||||
domain = Domain.objects.create(name=self.approved_application.requested_domain.name)
|
||||
self.approved_application.approved_domain = domain
|
||||
self.approved_application.save()
|
||||
domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
|
||||
self.approved_domain_request.approved_domain = domain
|
||||
self.approved_domain_request.save()
|
||||
|
||||
# Define a custom implementation for is_active
|
||||
def custom_is_active(self):
|
||||
|
@ -532,15 +532,15 @@ class TestDomainApplication(TestCase):
|
|||
with patch.object(Domain, "is_active", custom_is_active):
|
||||
# Now, when you call is_active on Domain, it will return True
|
||||
with self.assertRaises(TransitionNotAllowed):
|
||||
self.approved_application.action_needed()
|
||||
self.approved_domain_request.action_needed()
|
||||
|
||||
def test_transition_not_allowed_approved_rejected_when_domain_is_active(self):
|
||||
"""Create an application with status approved, create a matching domain that
|
||||
"""Create a domain request with status approved, create a matching domain that
|
||||
is active, and call reject against transition rules"""
|
||||
|
||||
domain = Domain.objects.create(name=self.approved_application.requested_domain.name)
|
||||
self.approved_application.approved_domain = domain
|
||||
self.approved_application.save()
|
||||
domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
|
||||
self.approved_domain_request.approved_domain = domain
|
||||
self.approved_domain_request.save()
|
||||
|
||||
# Define a custom implementation for is_active
|
||||
def custom_is_active(self):
|
||||
|
@ -552,15 +552,15 @@ class TestDomainApplication(TestCase):
|
|||
with patch.object(Domain, "is_active", custom_is_active):
|
||||
# Now, when you call is_active on Domain, it will return True
|
||||
with self.assertRaises(TransitionNotAllowed):
|
||||
self.approved_application.reject()
|
||||
self.approved_domain_request.reject()
|
||||
|
||||
def test_transition_not_allowed_approved_ineligible_when_domain_is_active(self):
|
||||
"""Create an application with status approved, create a matching domain that
|
||||
"""Create a domain request with status approved, create a matching domain that
|
||||
is active, and call reject_with_prejudice against transition rules"""
|
||||
|
||||
domain = Domain.objects.create(name=self.approved_application.requested_domain.name)
|
||||
self.approved_application.approved_domain = domain
|
||||
self.approved_application.save()
|
||||
domain = Domain.objects.create(name=self.approved_domain_request.requested_domain.name)
|
||||
self.approved_domain_request.approved_domain = domain
|
||||
self.approved_domain_request.save()
|
||||
|
||||
# Define a custom implementation for is_active
|
||||
def custom_is_active(self):
|
||||
|
@ -572,83 +572,83 @@ class TestDomainApplication(TestCase):
|
|||
with patch.object(Domain, "is_active", custom_is_active):
|
||||
# Now, when you call is_active on Domain, it will return True
|
||||
with self.assertRaises(TransitionNotAllowed):
|
||||
self.approved_application.reject_with_prejudice()
|
||||
self.approved_domain_request.reject_with_prejudice()
|
||||
|
||||
def test_approve_from_rejected_clears_rejection_reason(self):
|
||||
"""When transitioning from rejected to approved on a domain request,
|
||||
the rejection_reason is cleared."""
|
||||
|
||||
with less_console_noise():
|
||||
# Create a sample application
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.REJECTED)
|
||||
application.rejection_reason = DomainApplication.RejectionReasons.DOMAIN_PURPOSE
|
||||
# Create a sample domain request
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
|
||||
domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
|
||||
|
||||
# Approve
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
application.approve()
|
||||
domain_request.approve()
|
||||
|
||||
self.assertEqual(application.status, DomainApplication.ApplicationStatus.APPROVED)
|
||||
self.assertEqual(application.rejection_reason, None)
|
||||
self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.APPROVED)
|
||||
self.assertEqual(domain_request.rejection_reason, None)
|
||||
|
||||
def test_in_review_from_rejected_clears_rejection_reason(self):
|
||||
"""When transitioning from rejected to in_review on a domain request,
|
||||
the rejection_reason is cleared."""
|
||||
|
||||
with less_console_noise():
|
||||
# Create a sample application
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.REJECTED)
|
||||
application.domain_is_not_active = True
|
||||
application.rejection_reason = DomainApplication.RejectionReasons.DOMAIN_PURPOSE
|
||||
# Create a sample domain request
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
|
||||
domain_request.domain_is_not_active = True
|
||||
domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
|
||||
|
||||
# Approve
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
application.in_review()
|
||||
domain_request.in_review()
|
||||
|
||||
self.assertEqual(application.status, DomainApplication.ApplicationStatus.IN_REVIEW)
|
||||
self.assertEqual(application.rejection_reason, None)
|
||||
self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.IN_REVIEW)
|
||||
self.assertEqual(domain_request.rejection_reason, None)
|
||||
|
||||
def test_action_needed_from_rejected_clears_rejection_reason(self):
|
||||
"""When transitioning from rejected to action_needed on a domain request,
|
||||
the rejection_reason is cleared."""
|
||||
|
||||
with less_console_noise():
|
||||
# Create a sample application
|
||||
application = completed_application(status=DomainApplication.ApplicationStatus.REJECTED)
|
||||
application.domain_is_not_active = True
|
||||
application.rejection_reason = DomainApplication.RejectionReasons.DOMAIN_PURPOSE
|
||||
# Create a sample domain request
|
||||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.REJECTED)
|
||||
domain_request.domain_is_not_active = True
|
||||
domain_request.rejection_reason = DomainRequest.RejectionReasons.DOMAIN_PURPOSE
|
||||
|
||||
# Approve
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
application.action_needed()
|
||||
domain_request.action_needed()
|
||||
|
||||
self.assertEqual(application.status, DomainApplication.ApplicationStatus.ACTION_NEEDED)
|
||||
self.assertEqual(application.rejection_reason, None)
|
||||
self.assertEqual(domain_request.status, DomainRequest.DomainRequestStatus.ACTION_NEEDED)
|
||||
self.assertEqual(domain_request.rejection_reason, None)
|
||||
|
||||
def test_has_rationale_returns_true(self):
|
||||
"""has_rationale() returns true when an application has no_other_contacts_rationale"""
|
||||
"""has_rationale() returns true when a domain request has no_other_contacts_rationale"""
|
||||
with less_console_noise():
|
||||
self.started_application.no_other_contacts_rationale = "You talkin' to me?"
|
||||
self.started_application.save()
|
||||
self.assertEquals(self.started_application.has_rationale(), True)
|
||||
self.started_domain_request.no_other_contacts_rationale = "You talkin' to me?"
|
||||
self.started_domain_request.save()
|
||||
self.assertEquals(self.started_domain_request.has_rationale(), True)
|
||||
|
||||
def test_has_rationale_returns_false(self):
|
||||
"""has_rationale() returns false when an application has no no_other_contacts_rationale"""
|
||||
"""has_rationale() returns false when a domain request has no no_other_contacts_rationale"""
|
||||
with less_console_noise():
|
||||
self.assertEquals(self.started_application.has_rationale(), False)
|
||||
self.assertEquals(self.started_domain_request.has_rationale(), False)
|
||||
|
||||
def test_has_other_contacts_returns_true(self):
|
||||
"""has_other_contacts() returns true when an application has other_contacts"""
|
||||
"""has_other_contacts() returns true when a domain request has other_contacts"""
|
||||
with less_console_noise():
|
||||
# completed_application has other contacts by default
|
||||
self.assertEquals(self.started_application.has_other_contacts(), True)
|
||||
# completed_domain_request has other contacts by default
|
||||
self.assertEquals(self.started_domain_request.has_other_contacts(), True)
|
||||
|
||||
def test_has_other_contacts_returns_false(self):
|
||||
"""has_other_contacts() returns false when an application has no other_contacts"""
|
||||
"""has_other_contacts() returns false when a domain request has no other_contacts"""
|
||||
with less_console_noise():
|
||||
application = completed_application(
|
||||
status=DomainApplication.ApplicationStatus.STARTED, name="no-others.gov", has_other_contacts=False
|
||||
domain_request = completed_domain_request(
|
||||
status=DomainRequest.DomainRequestStatus.STARTED, name="no-others.gov", has_other_contacts=False
|
||||
)
|
||||
self.assertEquals(application.has_other_contacts(), False)
|
||||
self.assertEquals(domain_request.has_other_contacts(), False)
|
||||
|
||||
|
||||
class TestPermissions(TestCase):
|
||||
|
@ -666,13 +666,13 @@ class TestPermissions(TestCase):
|
|||
def test_approval_creates_role(self):
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||
user, _ = User.objects.get_or_create()
|
||||
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain)
|
||||
domain_request = DomainRequest.objects.create(creator=user, requested_domain=draft_domain)
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
# skip using the submit method
|
||||
application.status = DomainApplication.ApplicationStatus.SUBMITTED
|
||||
application.approve()
|
||||
domain_request.status = DomainRequest.DomainRequestStatus.SUBMITTED
|
||||
domain_request.approve()
|
||||
|
||||
# should be a role for this user
|
||||
domain = Domain.objects.get(name="igorville.gov")
|
||||
|
@ -691,7 +691,7 @@ class TestDomainInformation(TestCase):
|
|||
self.mock_client.EMAILS_SENT.clear()
|
||||
Domain.objects.all().delete()
|
||||
DomainInformation.objects.all().delete()
|
||||
DomainApplication.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
DraftDomain.objects.all().delete()
|
||||
|
||||
|
@ -700,13 +700,13 @@ class TestDomainInformation(TestCase):
|
|||
self.maxDiff = None
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||
user, _ = User.objects.get_or_create()
|
||||
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain, notes="test notes")
|
||||
domain_request = DomainRequest.objects.create(creator=user, requested_domain=draft_domain, notes="test notes")
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client):
|
||||
with less_console_noise():
|
||||
# skip using the submit method
|
||||
application.status = DomainApplication.ApplicationStatus.SUBMITTED
|
||||
application.approve()
|
||||
domain_request.status = DomainRequest.DomainRequestStatus.SUBMITTED
|
||||
domain_request.approve()
|
||||
|
||||
# should be an information present for this domain
|
||||
domain = Domain.objects.get(name="igorville.gov")
|
||||
|
@ -719,7 +719,7 @@ class TestDomainInformation(TestCase):
|
|||
creator=user,
|
||||
domain=domain,
|
||||
notes="test notes",
|
||||
domain_application=application,
|
||||
domain_request=domain_request,
|
||||
).__dict__
|
||||
|
||||
# Test the two records for consistency
|
||||
|
@ -852,11 +852,11 @@ class TestContact(TestCase):
|
|||
self.contact, _ = Contact.objects.get_or_create(user=self.user)
|
||||
|
||||
self.contact_as_ao, _ = Contact.objects.get_or_create(email="newguy@igorville.gov")
|
||||
self.application = DomainApplication.objects.create(creator=self.user, authorizing_official=self.contact_as_ao)
|
||||
self.domain_request = DomainRequest.objects.create(creator=self.user, authorizing_official=self.contact_as_ao)
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
DomainApplication.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
Contact.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
|
||||
|
@ -936,6 +936,6 @@ class TestContact(TestCase):
|
|||
# test for a contact which has one user defined
|
||||
self.assertFalse(self.contact.has_more_than_one_join("user"))
|
||||
self.assertTrue(self.contact.has_more_than_one_join("authorizing_official"))
|
||||
# test for a contact which is assigned as an authorizing official on an application
|
||||
# test for a contact which is assigned as an authorizing official on a domain request
|
||||
self.assertFalse(self.contact_as_ao.has_more_than_one_join("authorizing_official"))
|
||||
self.assertTrue(self.contact_as_ao.has_more_than_one_join("submitted_applications"))
|
||||
self.assertTrue(self.contact_as_ao.has_more_than_one_join("submitted_domain_requests"))
|
||||
|
|
|
@ -12,7 +12,7 @@ from django.utils.timezone import make_aware
|
|||
from registrar.models import Domain, Host, HostIP
|
||||
|
||||
from unittest import skip
|
||||
from registrar.models.domain_application import DomainApplication
|
||||
from registrar.models.domain_request import DomainRequest
|
||||
from registrar.models.domain_information import DomainInformation
|
||||
from registrar.models.draft_domain import DraftDomain
|
||||
from registrar.models.public_contact import PublicContact
|
||||
|
@ -311,27 +311,27 @@ class TestDomainCache(MockEppLib):
|
|||
|
||||
|
||||
class TestDomainCreation(MockEppLib):
|
||||
"""Rule: An approved domain application must result in a domain"""
|
||||
"""Rule: An approved domain request must result in a domain"""
|
||||
|
||||
@boto3_mocking.patching
|
||||
def test_approved_application_creates_domain_locally(self):
|
||||
def test_approved_domain_request_creates_domain_locally(self):
|
||||
"""
|
||||
Scenario: Analyst approves a domain application
|
||||
When the DomainApplication transitions to approved
|
||||
Scenario: Analyst approves a domain request
|
||||
When the DomainRequest transitions to approved
|
||||
Then a Domain exists in the database with the same `name`
|
||||
But a domain object does not exist in the registry
|
||||
"""
|
||||
with less_console_noise():
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville.gov")
|
||||
user, _ = User.objects.get_or_create()
|
||||
application = DomainApplication.objects.create(creator=user, requested_domain=draft_domain)
|
||||
domain_request = DomainRequest.objects.create(creator=user, requested_domain=draft_domain)
|
||||
|
||||
mock_client = MockSESClient()
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
# skip using the submit method
|
||||
application.status = DomainApplication.ApplicationStatus.SUBMITTED
|
||||
domain_request.status = DomainRequest.DomainRequestStatus.SUBMITTED
|
||||
# transition to approve state
|
||||
application.approve()
|
||||
domain_request.approve()
|
||||
# should have information present for this domain
|
||||
domain = Domain.objects.get(name="igorville.gov")
|
||||
self.assertTrue(domain)
|
||||
|
@ -395,7 +395,7 @@ class TestDomainCreation(MockEppLib):
|
|||
|
||||
def tearDown(self) -> None:
|
||||
DomainInformation.objects.all().delete()
|
||||
DomainApplication.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
PublicContact.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
|
|
|
@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class TestProcessedMigrations(TestCase):
|
||||
"""This test case class is designed to verify the idempotency of migrations
|
||||
related to domain transitions in the application."""
|
||||
related to domain transitions in the domain_request."""
|
||||
|
||||
def setUp(self):
|
||||
"""Defines the file name of migration_json and the folder its contained in"""
|
||||
|
|
|
@ -5,7 +5,7 @@ from .common import MockEppLib # type: ignore
|
|||
|
||||
|
||||
from registrar.models import (
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
DomainInformation,
|
||||
)
|
||||
import logging
|
||||
|
@ -26,8 +26,8 @@ class TestViews(TestCase):
|
|||
response = self.client.get("/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_application_form_not_logged_in(self):
|
||||
"""Application form not accessible without a logged-in user."""
|
||||
def test_domain_request_form_not_logged_in(self):
|
||||
"""Domain request form not accessible without a logged-in user."""
|
||||
response = self.client.get("/request/")
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertIn("/login?next=/request/", response.headers["Location"])
|
||||
|
@ -45,9 +45,9 @@ class TestWithUser(MockEppLib):
|
|||
)
|
||||
|
||||
def tearDown(self):
|
||||
# delete any applications too
|
||||
# delete any domain requests too
|
||||
super().tearDown()
|
||||
DomainApplication.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
DomainInformation.objects.all().delete()
|
||||
self.user.delete()
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,7 +21,7 @@ from registrar.utility.errors import (
|
|||
)
|
||||
|
||||
from registrar.models import (
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
Domain,
|
||||
DomainInformation,
|
||||
DomainInvitation,
|
||||
|
@ -120,7 +120,7 @@ class TestWithDomainPermissions(TestWithUser):
|
|||
UserDomainRole.objects.all().delete()
|
||||
if hasattr(self.domain, "contacts"):
|
||||
self.domain.contacts.all().delete()
|
||||
DomainApplication.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
DomainInformation.objects.all().delete()
|
||||
PublicContact.objects.all().delete()
|
||||
HostIP.objects.all().delete()
|
||||
|
@ -309,9 +309,9 @@ class TestDomainDetail(TestDomainOverview):
|
|||
self.assertContains(detail_page, "(1.2.3.4,")
|
||||
self.assertContains(detail_page, "2.3.4.5)")
|
||||
|
||||
def test_domain_detail_with_no_information_or_application(self):
|
||||
def test_domain_detail_with_no_information_or_domain_request(self):
|
||||
"""Test that domain management page returns 200 and displays error
|
||||
when no domain information or domain application exist"""
|
||||
when no domain information or domain request exist"""
|
||||
with less_console_noise():
|
||||
# have to use staff user for this test
|
||||
staff_user = create_user()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .application import *
|
||||
from .domain_request import *
|
||||
from .domain import (
|
||||
DomainView,
|
||||
DomainAuthorizingOfficialView,
|
||||
|
|
|
@ -8,18 +8,18 @@ from django.utils.translation import gettext_lazy as _
|
|||
from django.views.generic import TemplateView
|
||||
from django.contrib import messages
|
||||
|
||||
from registrar.forms import application_wizard as forms
|
||||
from registrar.models import DomainApplication
|
||||
from registrar.forms import domain_request_wizard as forms
|
||||
from registrar.models import DomainRequest
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.models.user import User
|
||||
from registrar.utility import StrEnum
|
||||
from registrar.views.utility import StepsHelper
|
||||
from registrar.views.utility.permission_views import DomainApplicationPermissionDeleteView
|
||||
from registrar.views.utility.permission_views import DomainRequestPermissionDeleteView
|
||||
|
||||
from .utility import (
|
||||
DomainApplicationPermissionView,
|
||||
DomainApplicationPermissionWithdrawView,
|
||||
ApplicationWizardPermissionView,
|
||||
DomainRequestPermissionView,
|
||||
DomainRequestPermissionWithdrawView,
|
||||
DomainRequestWizardPermissionView,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
class Step(StrEnum):
|
||||
"""
|
||||
Names for each page of the application wizard.
|
||||
Names for each page of the domain request wizard.
|
||||
|
||||
As with Django's own `TextChoices` class, steps will
|
||||
appear in the order they are defined. (Order matters.)
|
||||
|
@ -50,15 +50,15 @@ class Step(StrEnum):
|
|||
REVIEW = "review"
|
||||
|
||||
|
||||
class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
||||
class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||
"""
|
||||
A common set of methods and configuration.
|
||||
|
||||
The registrar's domain application is several pages of "steps".
|
||||
The registrar's domain request is several pages of "steps".
|
||||
Together, these steps constitute a "wizard".
|
||||
|
||||
This base class sets up a shared state (stored in the user's session)
|
||||
between pages of the application and provides common methods for
|
||||
between pages of the domain request and provides common methods for
|
||||
processing form data.
|
||||
|
||||
Views for each step should inherit from this base class.
|
||||
|
@ -73,9 +73,9 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
# (this is not seen _in_ urls, only for Django's internal naming)
|
||||
# NB: this is included here for reference. Do not change it without
|
||||
# also changing the many places it is hardcoded in the HTML templates
|
||||
URL_NAMESPACE = "application"
|
||||
# name for accessing /application/<id>/edit
|
||||
EDIT_URL_NAME = "edit-application"
|
||||
URL_NAMESPACE = "domain-request"
|
||||
# name for accessing /domain-request/<id>/edit
|
||||
EDIT_URL_NAME = "edit-domain-request"
|
||||
NEW_URL_NAME = "/request/"
|
||||
# We need to pass our human-readable step titles as context to the templates.
|
||||
TITLES = {
|
||||
|
@ -108,28 +108,28 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
def __init__(self):
|
||||
super().__init__()
|
||||
self.steps = StepsHelper(self)
|
||||
self._application = None # for caching
|
||||
self._domain_request = None # for caching
|
||||
|
||||
def has_pk(self):
|
||||
"""Does this wizard know about a DomainApplication database record?"""
|
||||
return "application_id" in self.storage
|
||||
"""Does this wizard know about a DomainRequest database record?"""
|
||||
return "domain_request_id" in self.storage
|
||||
|
||||
@property
|
||||
def prefix(self):
|
||||
"""Namespace the wizard to avoid clashes in session variable names."""
|
||||
# this is a string literal but can be made dynamic if we'd like
|
||||
# users to have multiple applications open for editing simultaneously
|
||||
return "wizard_application"
|
||||
# users to have multiple domain requests open for editing simultaneously
|
||||
return "wizard_domain_request"
|
||||
|
||||
@property
|
||||
def application(self) -> DomainApplication:
|
||||
def domain_request(self) -> DomainRequest:
|
||||
"""
|
||||
Attempt to match the current wizard with a DomainApplication.
|
||||
Attempt to match the current wizard with a DomainRequest.
|
||||
|
||||
Will create an application if none exists.
|
||||
Will create a domain request if none exists.
|
||||
"""
|
||||
if self._application:
|
||||
return self._application
|
||||
if self._domain_request:
|
||||
return self._domain_request
|
||||
|
||||
# For linter. The else block should never be hit, but if it does,
|
||||
# there may be a UI consideration. That will need to be handled in another ticket.
|
||||
|
@ -140,20 +140,20 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
raise ValueError("Invalid value for User")
|
||||
|
||||
if self.has_pk():
|
||||
id = self.storage["application_id"]
|
||||
id = self.storage["domain_request_id"]
|
||||
try:
|
||||
self._application = DomainApplication.objects.get(
|
||||
self._domain_request = DomainRequest.objects.get(
|
||||
creator=creator,
|
||||
pk=id,
|
||||
)
|
||||
return self._application
|
||||
except DomainApplication.DoesNotExist:
|
||||
logger.debug("Application id %s did not have a DomainApplication" % id)
|
||||
return self._domain_request
|
||||
except DomainRequest.DoesNotExist:
|
||||
logger.debug("DomainRequest id %s did not have a DomainRequest" % id)
|
||||
|
||||
self._application = DomainApplication.objects.create(creator=self.request.user)
|
||||
self._domain_request = DomainRequest.objects.create(creator=self.request.user)
|
||||
|
||||
self.storage["application_id"] = self._application.id
|
||||
return self._application
|
||||
self.storage["domain_request_id"] = self._domain_request.id
|
||||
return self._domain_request
|
||||
|
||||
@property
|
||||
def storage(self):
|
||||
|
@ -179,9 +179,9 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
|
||||
def done(self):
|
||||
"""Called when the user clicks the submit button, if all forms are valid."""
|
||||
self.application.submit() # change the status to submitted
|
||||
self.application.save()
|
||||
logger.debug("Application object saved: %s", self.application.id)
|
||||
self.domain_request.submit() # change the status to submitted
|
||||
self.domain_request.save()
|
||||
logger.debug("Domain Request object saved: %s", self.domain_request.id)
|
||||
return redirect(reverse(f"{self.URL_NAMESPACE}:finished"))
|
||||
|
||||
def from_model(self, attribute: str, default, *args, **kwargs):
|
||||
|
@ -194,8 +194,8 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
in the database before the wizard has been saved.
|
||||
"""
|
||||
if self.has_pk():
|
||||
if hasattr(self.application, attribute):
|
||||
attr = getattr(self.application, attribute)
|
||||
if hasattr(self.domain_request, attribute):
|
||||
attr = getattr(self.domain_request, attribute)
|
||||
if callable(attr):
|
||||
return attr(*args, **kwargs)
|
||||
else:
|
||||
|
@ -210,24 +210,24 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
current_url = resolve(request.path_info).url_name
|
||||
|
||||
# if user visited via an "edit" url, associate the id of the
|
||||
# application they are trying to edit to this wizard instance
|
||||
# domain request they are trying to edit to this wizard instance
|
||||
# and remove any prior wizard data from their session
|
||||
if current_url == self.EDIT_URL_NAME and "id" in kwargs:
|
||||
del self.storage
|
||||
self.storage["application_id"] = kwargs["id"]
|
||||
self.storage["domain_request_id"] = kwargs["id"]
|
||||
self.storage["step_history"] = self.db_check_for_unlocking_steps()
|
||||
|
||||
# if accessing this class directly, redirect to the first step
|
||||
# in other words, if `ApplicationWizard` is called as view
|
||||
# in other words, if `DomainRequestWizard` is called as view
|
||||
# directly by some redirect or url handler, we'll send users
|
||||
# either to an acknowledgement page or to the first step in
|
||||
# the processes (if an edit rather than a new request); subclasses
|
||||
# will NOT be redirected. The purpose of this is to allow code to
|
||||
# send users "to the application wizard" without needing to
|
||||
# send users "to the domain request wizard" without needing to
|
||||
# know which view is first in the list of steps.
|
||||
if self.__class__ == ApplicationWizard:
|
||||
if self.__class__ == DomainRequestWizard:
|
||||
if request.path_info == self.NEW_URL_NAME:
|
||||
return render(request, "application_intro.html")
|
||||
return render(request, "domain_request_intro.html")
|
||||
else:
|
||||
return self.goto(self.steps.first)
|
||||
|
||||
|
@ -236,7 +236,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
context["forms"] = self.get_forms()
|
||||
|
||||
# if pending requests exist and user does not have approved domains,
|
||||
# present message that domain application cannot be submitted
|
||||
# present message that domain request cannot be submitted
|
||||
pending_requests = self.pending_requests()
|
||||
if len(pending_requests) > 0:
|
||||
message_header = "You cannot submit this request yet"
|
||||
|
@ -278,7 +278,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
kwargs = {
|
||||
"files": files,
|
||||
"prefix": self.steps.current,
|
||||
"application": self.application, # this is a property, not an object
|
||||
"domain_request": self.domain_request, # this is a property, not an object
|
||||
}
|
||||
|
||||
if step is None:
|
||||
|
@ -290,7 +290,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
instantiated = []
|
||||
|
||||
for form in forms:
|
||||
data = form.from_database(self.application) if self.has_pk() else None
|
||||
data = form.from_database(self.domain_request) if self.has_pk() else None
|
||||
if use_post:
|
||||
instantiated.append(form(self.request.POST, **kwargs))
|
||||
elif use_db:
|
||||
|
@ -303,72 +303,73 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
def pending_requests(self):
|
||||
"""return an array of pending requests if user has pending requests
|
||||
and no approved requests"""
|
||||
if self.approved_applications_exist() or self.approved_domains_exist():
|
||||
if self.approved_domain_requests_exist() or self.approved_domains_exist():
|
||||
return []
|
||||
else:
|
||||
return self.pending_applications()
|
||||
return self.pending_domain_requests()
|
||||
|
||||
def approved_applications_exist(self):
|
||||
"""Checks if user is creator of applications with ApplicationStatus.APPROVED status"""
|
||||
approved_application_count = DomainApplication.objects.filter(
|
||||
creator=self.request.user, status=DomainApplication.ApplicationStatus.APPROVED
|
||||
def approved_domain_requests_exist(self):
|
||||
"""Checks if user is creator of domain requests with DomainRequestStatus.APPROVED status"""
|
||||
approved_domain_request_count = DomainRequest.objects.filter(
|
||||
creator=self.request.user, status=DomainRequest.DomainRequestStatus.APPROVED
|
||||
).count()
|
||||
return approved_application_count > 0
|
||||
return approved_domain_request_count > 0
|
||||
|
||||
def approved_domains_exist(self):
|
||||
"""Checks if user has permissions on approved domains
|
||||
|
||||
This additional check is necessary to account for domains which were migrated
|
||||
and do not have an application"""
|
||||
and do not have a domain request"""
|
||||
return self.request.user.permissions.count() > 0
|
||||
|
||||
def pending_applications(self):
|
||||
"""Returns a List of user's applications with one of the following states:
|
||||
ApplicationStatus.SUBMITTED, ApplicationStatus.IN_REVIEW, ApplicationStatus.ACTION_NEEDED"""
|
||||
# if the current application has ApplicationStatus.ACTION_NEEDED status, this check should not be performed
|
||||
if self.application.status == DomainApplication.ApplicationStatus.ACTION_NEEDED:
|
||||
def pending_domain_requests(self):
|
||||
"""Returns a List of user's domain requests with one of the following states:
|
||||
DomainRequestStatus.SUBMITTED, DomainRequestStatus.IN_REVIEW, DomainRequestStatus.ACTION_NEEDED"""
|
||||
# if the current domain request has DomainRequestStatus.ACTION_NEEDED status, this check should not be performed
|
||||
if self.domain_request.status == DomainRequest.DomainRequestStatus.ACTION_NEEDED:
|
||||
return []
|
||||
check_statuses = [
|
||||
DomainApplication.ApplicationStatus.SUBMITTED,
|
||||
DomainApplication.ApplicationStatus.IN_REVIEW,
|
||||
DomainApplication.ApplicationStatus.ACTION_NEEDED,
|
||||
DomainRequest.DomainRequestStatus.SUBMITTED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
]
|
||||
return DomainApplication.objects.filter(creator=self.request.user, status__in=check_statuses)
|
||||
return DomainRequest.objects.filter(creator=self.request.user, status__in=check_statuses)
|
||||
|
||||
def db_check_for_unlocking_steps(self):
|
||||
"""Helper for get_context_data
|
||||
|
||||
Queries the DB for an application and returns a list of unlocked steps."""
|
||||
Queries the DB for a domain request and returns a list of unlocked steps."""
|
||||
history_dict = {
|
||||
"organization_type": self.application.organization_type is not None,
|
||||
"tribal_government": self.application.tribe_name is not None,
|
||||
"organization_federal": self.application.federal_type is not None,
|
||||
"organization_election": self.application.is_election_board is not None,
|
||||
"organization_type": self.domain_request.organization_type is not None,
|
||||
"tribal_government": self.domain_request.tribe_name is not None,
|
||||
"organization_federal": self.domain_request.federal_type is not None,
|
||||
"organization_election": self.domain_request.is_election_board is not None,
|
||||
"organization_contact": (
|
||||
self.application.federal_agency is not None
|
||||
or self.application.organization_name is not None
|
||||
or self.application.address_line1 is not None
|
||||
or self.application.city is not None
|
||||
or self.application.state_territory is not None
|
||||
or self.application.zipcode is not None
|
||||
or self.application.urbanization is not None
|
||||
self.domain_request.federal_agency is not None
|
||||
or self.domain_request.organization_name is not None
|
||||
or self.domain_request.address_line1 is not None
|
||||
or self.domain_request.city is not None
|
||||
or self.domain_request.state_territory is not None
|
||||
or self.domain_request.zipcode is not None
|
||||
or self.domain_request.urbanization is not None
|
||||
),
|
||||
"about_your_organization": self.application.about_your_organization is not None,
|
||||
"authorizing_official": self.application.authorizing_official is not None,
|
||||
"about_your_organization": self.domain_request.about_your_organization is not None,
|
||||
"authorizing_official": self.domain_request.authorizing_official is not None,
|
||||
"current_sites": (
|
||||
self.application.current_websites.exists() or self.application.requested_domain is not None
|
||||
self.domain_request.current_websites.exists() or self.domain_request.requested_domain is not None
|
||||
),
|
||||
"dotgov_domain": self.application.requested_domain is not None,
|
||||
"purpose": self.application.purpose is not None,
|
||||
"your_contact": self.application.submitter is not None,
|
||||
"dotgov_domain": self.domain_request.requested_domain is not None,
|
||||
"purpose": self.domain_request.purpose is not None,
|
||||
"your_contact": self.domain_request.submitter is not None,
|
||||
"other_contacts": (
|
||||
self.application.other_contacts.exists() or self.application.no_other_contacts_rationale is not None
|
||||
self.domain_request.other_contacts.exists()
|
||||
or self.domain_request.no_other_contacts_rationale is not None
|
||||
),
|
||||
"anything_else": (
|
||||
self.application.anything_else is not None or self.application.is_policy_acknowledged is not None
|
||||
self.domain_request.anything_else is not None or self.domain_request.is_policy_acknowledged is not None
|
||||
),
|
||||
"requirements": self.application.is_policy_acknowledged is not None,
|
||||
"review": self.application.is_policy_acknowledged is not None,
|
||||
"requirements": self.domain_request.is_policy_acknowledged is not None,
|
||||
"review": self.domain_request.is_policy_acknowledged is not None,
|
||||
}
|
||||
return [key for key, value in history_dict.items() if value]
|
||||
|
||||
|
@ -377,8 +378,8 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
# Build the submit button that we'll pass to the modal.
|
||||
modal_button = '<button type="submit" ' 'class="usa-button" ' ">Submit request</button>"
|
||||
# Concatenate the modal header that we'll pass to the modal.
|
||||
if self.application.requested_domain:
|
||||
modal_heading = "You are about to submit a domain request for " + str(self.application.requested_domain)
|
||||
if self.domain_request.requested_domain:
|
||||
modal_heading = "You are about to submit a domain request for " + str(self.domain_request.requested_domain)
|
||||
else:
|
||||
modal_heading = "You are about to submit an incomplete request"
|
||||
|
||||
|
@ -387,7 +388,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
"steps": self.steps,
|
||||
# Add information about which steps should be unlocked
|
||||
"visited": self.storage.get("step_history", []),
|
||||
"is_federal": self.application.is_federal(),
|
||||
"is_federal": self.domain_request.is_federal(),
|
||||
"modal_button": modal_button,
|
||||
"modal_heading": modal_heading,
|
||||
}
|
||||
|
@ -434,7 +435,7 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
return self.goto(self.steps.first)
|
||||
|
||||
# if accessing this class directly, redirect to the first step
|
||||
if self.__class__ == ApplicationWizard:
|
||||
if self.__class__ == DomainRequestWizard:
|
||||
return self.goto(self.steps.first)
|
||||
|
||||
forms = self.get_forms(use_post=True)
|
||||
|
@ -462,86 +463,86 @@ class ApplicationWizard(ApplicationWizardPermissionView, TemplateView):
|
|||
"""
|
||||
Unpack the form responses onto the model object properties.
|
||||
|
||||
Saves the application to the database.
|
||||
Saves the domain request to the database.
|
||||
"""
|
||||
for form in forms:
|
||||
if form is not None and hasattr(form, "to_database"):
|
||||
form.to_database(self.application)
|
||||
form.to_database(self.domain_request)
|
||||
|
||||
|
||||
class OrganizationType(ApplicationWizard):
|
||||
template_name = "application_org_type.html"
|
||||
class OrganizationType(DomainRequestWizard):
|
||||
template_name = "domain_request_org_type.html"
|
||||
forms = [forms.OrganizationTypeForm]
|
||||
|
||||
|
||||
class TribalGovernment(ApplicationWizard):
|
||||
template_name = "application_tribal_government.html"
|
||||
class TribalGovernment(DomainRequestWizard):
|
||||
template_name = "domain_request_tribal_government.html"
|
||||
forms = [forms.TribalGovernmentForm]
|
||||
|
||||
|
||||
class OrganizationFederal(ApplicationWizard):
|
||||
template_name = "application_org_federal.html"
|
||||
class OrganizationFederal(DomainRequestWizard):
|
||||
template_name = "domain_request_org_federal.html"
|
||||
forms = [forms.OrganizationFederalForm]
|
||||
|
||||
|
||||
class OrganizationElection(ApplicationWizard):
|
||||
template_name = "application_org_election.html"
|
||||
class OrganizationElection(DomainRequestWizard):
|
||||
template_name = "domain_request_org_election.html"
|
||||
forms = [forms.OrganizationElectionForm]
|
||||
|
||||
|
||||
class OrganizationContact(ApplicationWizard):
|
||||
template_name = "application_org_contact.html"
|
||||
class OrganizationContact(DomainRequestWizard):
|
||||
template_name = "domain_request_org_contact.html"
|
||||
forms = [forms.OrganizationContactForm]
|
||||
|
||||
|
||||
class AboutYourOrganization(ApplicationWizard):
|
||||
template_name = "application_about_your_organization.html"
|
||||
class AboutYourOrganization(DomainRequestWizard):
|
||||
template_name = "domain_request_about_your_organization.html"
|
||||
forms = [forms.AboutYourOrganizationForm]
|
||||
|
||||
|
||||
class AuthorizingOfficial(ApplicationWizard):
|
||||
template_name = "application_authorizing_official.html"
|
||||
class AuthorizingOfficial(DomainRequestWizard):
|
||||
template_name = "domain_request_authorizing_official.html"
|
||||
forms = [forms.AuthorizingOfficialForm]
|
||||
|
||||
def get_context_data(self):
|
||||
context = super().get_context_data()
|
||||
context["organization_type"] = self.application.organization_type
|
||||
context["federal_type"] = self.application.federal_type
|
||||
context["organization_type"] = self.domain_request.organization_type
|
||||
context["federal_type"] = self.domain_request.federal_type
|
||||
return context
|
||||
|
||||
|
||||
class CurrentSites(ApplicationWizard):
|
||||
template_name = "application_current_sites.html"
|
||||
class CurrentSites(DomainRequestWizard):
|
||||
template_name = "domain_request_current_sites.html"
|
||||
forms = [forms.CurrentSitesFormSet]
|
||||
|
||||
|
||||
class DotgovDomain(ApplicationWizard):
|
||||
template_name = "application_dotgov_domain.html"
|
||||
class DotgovDomain(DomainRequestWizard):
|
||||
template_name = "domain_request_dotgov_domain.html"
|
||||
forms = [forms.DotGovDomainForm, forms.AlternativeDomainFormSet]
|
||||
|
||||
def get_context_data(self):
|
||||
context = super().get_context_data()
|
||||
context["organization_type"] = self.application.organization_type
|
||||
context["federal_type"] = self.application.federal_type
|
||||
context["organization_type"] = self.domain_request.organization_type
|
||||
context["federal_type"] = self.domain_request.federal_type
|
||||
return context
|
||||
|
||||
|
||||
class Purpose(ApplicationWizard):
|
||||
template_name = "application_purpose.html"
|
||||
class Purpose(DomainRequestWizard):
|
||||
template_name = "domain_request_purpose.html"
|
||||
forms = [forms.PurposeForm]
|
||||
|
||||
|
||||
class YourContact(ApplicationWizard):
|
||||
template_name = "application_your_contact.html"
|
||||
class YourContact(DomainRequestWizard):
|
||||
template_name = "domain_request_your_contact.html"
|
||||
forms = [forms.YourContactForm]
|
||||
|
||||
|
||||
class OtherContacts(ApplicationWizard):
|
||||
template_name = "application_other_contacts.html"
|
||||
class OtherContacts(DomainRequestWizard):
|
||||
template_name = "domain_request_other_contacts.html"
|
||||
forms = [forms.OtherContactsYesNoForm, forms.OtherContactsFormSet, forms.NoOtherContactsForm]
|
||||
|
||||
def is_valid(self, forms: list) -> bool:
|
||||
"""Overrides default behavior defined in ApplicationWizard.
|
||||
"""Overrides default behavior defined in DomainRequestWizard.
|
||||
Depending on value in other_contacts_yes_no_form, marks forms in
|
||||
other_contacts or no_other_contacts for deletion. Then validates
|
||||
all forms.
|
||||
|
@ -580,24 +581,24 @@ class OtherContacts(ApplicationWizard):
|
|||
return all_forms_valid
|
||||
|
||||
|
||||
class AnythingElse(ApplicationWizard):
|
||||
template_name = "application_anything_else.html"
|
||||
class AnythingElse(DomainRequestWizard):
|
||||
template_name = "domain_request_anything_else.html"
|
||||
forms = [forms.AnythingElseForm]
|
||||
|
||||
|
||||
class Requirements(ApplicationWizard):
|
||||
template_name = "application_requirements.html"
|
||||
class Requirements(DomainRequestWizard):
|
||||
template_name = "domain_request_requirements.html"
|
||||
forms = [forms.RequirementsForm]
|
||||
|
||||
|
||||
class Review(ApplicationWizard):
|
||||
template_name = "application_review.html"
|
||||
class Review(DomainRequestWizard):
|
||||
template_name = "domain_request_review.html"
|
||||
forms = [] # type: ignore
|
||||
|
||||
def get_context_data(self):
|
||||
context = super().get_context_data()
|
||||
context["Step"] = Step.__members__
|
||||
context["application"] = self.application
|
||||
context["domain_request"] = self.domain_request
|
||||
return context
|
||||
|
||||
def goto_next_step(self):
|
||||
|
@ -623,33 +624,33 @@ class Review(ApplicationWizard):
|
|||
# return self.goto(self.steps.current)
|
||||
|
||||
|
||||
class Finished(ApplicationWizard):
|
||||
template_name = "application_done.html"
|
||||
class Finished(DomainRequestWizard):
|
||||
template_name = "domain_request_done.html"
|
||||
forms = [] # type: ignore
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
context = self.get_context_data()
|
||||
context["application_id"] = self.application.id
|
||||
context["domain_request_id"] = self.domain_request.id
|
||||
# clean up this wizard session, because we are done with it
|
||||
del self.storage
|
||||
return render(self.request, self.template_name, context)
|
||||
|
||||
|
||||
class ApplicationStatus(DomainApplicationPermissionView):
|
||||
template_name = "application_status.html"
|
||||
class DomainRequestStatus(DomainRequestPermissionView):
|
||||
template_name = "domain_request_status.html"
|
||||
|
||||
|
||||
class ApplicationWithdrawConfirmation(DomainApplicationPermissionWithdrawView):
|
||||
class DomainRequestWithdrawConfirmation(DomainRequestPermissionWithdrawView):
|
||||
"""This page will ask user to confirm if they want to withdraw
|
||||
|
||||
The DomainApplicationPermissionView restricts access so that only the
|
||||
`creator` of the application may withdraw it.
|
||||
The DomainRequestPermissionView restricts access so that only the
|
||||
`creator` of the domain request may withdraw it.
|
||||
"""
|
||||
|
||||
template_name = "application_withdraw_confirmation.html"
|
||||
template_name = "domain_request_withdraw_confirmation.html"
|
||||
|
||||
|
||||
class ApplicationWithdrawn(DomainApplicationPermissionWithdrawView):
|
||||
class DomainRequestWithdrawn(DomainRequestPermissionWithdrawView):
|
||||
# this view renders no template
|
||||
template_name = ""
|
||||
|
||||
|
@ -659,16 +660,16 @@ class ApplicationWithdrawn(DomainApplicationPermissionWithdrawView):
|
|||
If user click on withdraw confirm button, this view updates the status
|
||||
to withdraw and send back to homepage.
|
||||
"""
|
||||
application = DomainApplication.objects.get(id=self.kwargs["pk"])
|
||||
application.withdraw()
|
||||
application.save()
|
||||
domain_request = DomainRequest.objects.get(id=self.kwargs["pk"])
|
||||
domain_request.withdraw()
|
||||
domain_request.save()
|
||||
return HttpResponseRedirect(reverse("home"))
|
||||
|
||||
|
||||
class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
||||
"""Delete view for home that allows the end user to delete DomainApplications"""
|
||||
class DomainRequestDeleteView(DomainRequestPermissionDeleteView):
|
||||
"""Delete view for home that allows the end user to delete DomainRequests"""
|
||||
|
||||
object: DomainApplication # workaround for type mismatch in DeleteView
|
||||
object: DomainRequest # workaround for type mismatch in DeleteView
|
||||
|
||||
def has_permission(self):
|
||||
"""Custom override for has_permission to exclude all statuses, except WITHDRAWN and STARTED"""
|
||||
|
@ -677,7 +678,7 @@ class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
|||
return False
|
||||
|
||||
status = self.get_object().status
|
||||
valid_statuses = [DomainApplication.ApplicationStatus.WITHDRAWN, DomainApplication.ApplicationStatus.STARTED]
|
||||
valid_statuses = [DomainRequest.DomainRequestStatus.WITHDRAWN, DomainRequest.DomainRequestStatus.STARTED]
|
||||
if status not in valid_statuses:
|
||||
return False
|
||||
|
||||
|
@ -689,10 +690,10 @@ class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# Grab all orphaned contacts
|
||||
application: DomainApplication = self.get_object()
|
||||
contacts_to_delete, duplicates = self._get_orphaned_contacts(application)
|
||||
domain_request: DomainRequest = self.get_object()
|
||||
contacts_to_delete, duplicates = self._get_orphaned_contacts(domain_request)
|
||||
|
||||
# Delete the DomainApplication
|
||||
# Delete the DomainRequest
|
||||
response = super().post(request, *args, **kwargs)
|
||||
|
||||
# Delete orphaned contacts - but only for if they are not associated with a user
|
||||
|
@ -702,21 +703,21 @@ class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
|||
# This determines if any of these three fields share a contact, which is used for
|
||||
# the edge case where the same user may be an AO, and a submitter, for example.
|
||||
if len(duplicates) > 0:
|
||||
duplicates_to_delete, _ = self._get_orphaned_contacts(application, check_db=True)
|
||||
duplicates_to_delete, _ = self._get_orphaned_contacts(domain_request, check_db=True)
|
||||
Contact.objects.filter(id__in=duplicates_to_delete, user=None).delete()
|
||||
|
||||
return response
|
||||
|
||||
def _get_orphaned_contacts(self, application: DomainApplication, check_db=False):
|
||||
def _get_orphaned_contacts(self, domain_request: DomainRequest, check_db=False):
|
||||
"""
|
||||
Collects all orphaned contacts associated with a given DomainApplication object.
|
||||
Collects all orphaned contacts associated with a given DomainRequest object.
|
||||
|
||||
An orphaned contact is defined as a contact that is associated with the application,
|
||||
but not with any other application. This includes the authorizing official, the submitter,
|
||||
and any other contacts linked to the application.
|
||||
An orphaned contact is defined as a contact that is associated with the domain request,
|
||||
but not with any other domain_request. This includes the authorizing official, the submitter,
|
||||
and any other contacts linked to the domain_request.
|
||||
|
||||
Parameters:
|
||||
application (DomainApplication): The DomainApplication object for which to find orphaned contacts.
|
||||
domain_request (DomainRequest): The DomainRequest object for which to find orphaned contacts.
|
||||
check_db (bool, optional): A flag indicating whether to check the database for the existence of the contacts.
|
||||
Defaults to False.
|
||||
|
||||
|
@ -726,11 +727,11 @@ class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
|||
"""
|
||||
contacts_to_delete = []
|
||||
|
||||
# Get each contact object on the DomainApplication object
|
||||
ao = application.authorizing_official
|
||||
submitter = application.submitter
|
||||
other_contacts = list(application.other_contacts.all())
|
||||
other_contact_ids = application.other_contacts.all().values_list("id", flat=True)
|
||||
# Get each contact object on the DomainRequest object
|
||||
ao = domain_request.authorizing_official
|
||||
submitter = domain_request.submitter
|
||||
other_contacts = list(domain_request.other_contacts.all())
|
||||
other_contact_ids = domain_request.other_contacts.all().values_list("id", flat=True)
|
||||
|
||||
# Check if the desired item still exists in the DB
|
||||
if check_db:
|
||||
|
@ -739,8 +740,8 @@ class DomainApplicationDeleteView(DomainApplicationPermissionDeleteView):
|
|||
other_contacts = self._get_contacts_by_id(other_contact_ids)
|
||||
|
||||
# Pair each contact with its db related name for use in checking if it has joins
|
||||
checked_contacts = [(ao, "authorizing_official"), (submitter, "submitted_applications")]
|
||||
checked_contacts.extend((contact, "contact_applications") for contact in other_contacts)
|
||||
checked_contacts = [(ao, "authorizing_official"), (submitter, "submitted_domain_requests")]
|
||||
checked_contacts.extend((contact, "contact_domain_requests") for contact in other_contacts)
|
||||
|
||||
for contact, related_name in checked_contacts:
|
||||
if contact is not None and not contact.has_more_than_one_join(related_name):
|
|
@ -1,56 +1,56 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
from registrar.models import DomainApplication, Domain, UserDomainRole
|
||||
from registrar.models import DomainRequest, Domain, UserDomainRole
|
||||
|
||||
|
||||
def index(request):
|
||||
"""This page is available to anyone without logging in."""
|
||||
context = {}
|
||||
if request.user.is_authenticated:
|
||||
# Get all domain applications the user has access to
|
||||
applications, deletable_applications = _get_applications(request)
|
||||
# Get all domain requests the user has access to
|
||||
domain_requests, deletable_domain_requests = _get_domain_requests(request)
|
||||
|
||||
context["domain_applications"] = applications
|
||||
context["domain_requests"] = domain_requests
|
||||
|
||||
# Get all domains the user has access to
|
||||
domains = _get_domains(request)
|
||||
context["domains"] = domains
|
||||
|
||||
# Determine if the user will see applications that they can delete
|
||||
has_deletable_applications = deletable_applications.exists()
|
||||
context["has_deletable_applications"] = has_deletable_applications
|
||||
# Determine if the user will see domain requests that they can delete
|
||||
has_deletable_domain_requests = deletable_domain_requests.exists()
|
||||
context["has_deletable_domain_requests"] = has_deletable_domain_requests
|
||||
|
||||
# If they can delete applications, add the delete button to the context
|
||||
if has_deletable_applications:
|
||||
# If they can delete domain requests, add the delete button to the context
|
||||
if has_deletable_domain_requests:
|
||||
# Add the delete modal button to the context
|
||||
modal_button = (
|
||||
'<button type="submit" '
|
||||
'class="usa-button usa-button--secondary" '
|
||||
'name="delete-application">Yes, delete request</button>'
|
||||
'name="delete-domain-request">Yes, delete request</button>'
|
||||
)
|
||||
context["modal_button"] = modal_button
|
||||
|
||||
return render(request, "home.html", context)
|
||||
|
||||
|
||||
def _get_applications(request):
|
||||
def _get_domain_requests(request):
|
||||
"""Given the current request,
|
||||
get all DomainApplications that are associated with the UserDomainRole object.
|
||||
get all DomainRequests that are associated with the UserDomainRole object.
|
||||
|
||||
Returns a tuple of all applications, and those that are deletable by the user.
|
||||
Returns a tuple of all domain requests, and those that are deletable by the user.
|
||||
"""
|
||||
# Let's exclude the approved applications since our
|
||||
# domain_applications context will be used to populate
|
||||
# the active applications table
|
||||
applications = DomainApplication.objects.filter(creator=request.user).exclude(
|
||||
status=DomainApplication.ApplicationStatus.APPROVED
|
||||
# Let's exclude the approved domain requests since our
|
||||
# domain_requests context will be used to populate
|
||||
# the active domain requests table
|
||||
domain_requests = DomainRequest.objects.filter(creator=request.user).exclude(
|
||||
status=DomainRequest.DomainRequestStatus.APPROVED
|
||||
)
|
||||
|
||||
# Create a placeholder DraftDomain for each incomplete draft
|
||||
valid_statuses = [DomainApplication.ApplicationStatus.STARTED, DomainApplication.ApplicationStatus.WITHDRAWN]
|
||||
deletable_applications = applications.filter(status__in=valid_statuses)
|
||||
valid_statuses = [DomainRequest.DomainRequestStatus.STARTED, DomainRequest.DomainRequestStatus.WITHDRAWN]
|
||||
deletable_domain_requests = domain_requests.filter(status__in=valid_statuses)
|
||||
|
||||
return (applications, deletable_applications)
|
||||
return (domain_requests, deletable_domain_requests)
|
||||
|
||||
|
||||
def _get_domains(request):
|
||||
|
|
|
@ -3,8 +3,8 @@ from .always_404 import always_404
|
|||
|
||||
from .permission_views import (
|
||||
DomainPermissionView,
|
||||
DomainApplicationPermissionView,
|
||||
DomainApplicationPermissionWithdrawView,
|
||||
DomainRequestPermissionView,
|
||||
DomainRequestPermissionWithdrawView,
|
||||
DomainInvitationPermissionDeleteView,
|
||||
ApplicationWizardPermissionView,
|
||||
DomainRequestWizardPermissionView,
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
|
|||
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
DomainApplication,
|
||||
DomainRequest,
|
||||
DomainInvitation,
|
||||
DomainInformation,
|
||||
UserDomainRole,
|
||||
|
@ -230,10 +230,10 @@ class DomainPermission(PermissionsLoginMixin):
|
|||
|
||||
# Analysts may manage domains, when they are in these statuses:
|
||||
valid_domain_statuses = [
|
||||
DomainApplication.ApplicationStatus.APPROVED,
|
||||
DomainApplication.ApplicationStatus.IN_REVIEW,
|
||||
DomainApplication.ApplicationStatus.REJECTED,
|
||||
DomainApplication.ApplicationStatus.ACTION_NEEDED,
|
||||
DomainRequest.DomainRequestStatus.APPROVED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.REJECTED,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
# Edge case - some domains do not have
|
||||
# a status or DomainInformation... aka a status of 'None'.
|
||||
# It is necessary to access those to correct errors.
|
||||
|
@ -244,14 +244,14 @@ class DomainPermission(PermissionsLoginMixin):
|
|||
if DomainInformation.objects.filter(id=pk).exists():
|
||||
requested_domain = DomainInformation.objects.get(id=pk)
|
||||
|
||||
# if no domain information or application exist, the user
|
||||
# if no domain information or domain request exist, the user
|
||||
# should be able to manage the domain; however, if domain information
|
||||
# and domain application exist, and application is not in valid status,
|
||||
# and domain request exist, and domain request is not in valid status,
|
||||
# user should not be able to manage domain
|
||||
if (
|
||||
requested_domain
|
||||
and requested_domain.domain_application
|
||||
and requested_domain.domain_application.status not in valid_domain_statuses
|
||||
and requested_domain.domain_request
|
||||
and requested_domain.domain_request.status not in valid_domain_statuses
|
||||
):
|
||||
return False
|
||||
|
||||
|
@ -261,12 +261,12 @@ class DomainPermission(PermissionsLoginMixin):
|
|||
return True
|
||||
|
||||
|
||||
class DomainApplicationPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain application if user
|
||||
class DomainRequestPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain request if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain application.
|
||||
"""Check if this user has access to this domain request.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
|
@ -274,10 +274,10 @@ class DomainApplicationPermission(PermissionsLoginMixin):
|
|||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# user needs to be the creator of the application
|
||||
# this query is empty if there isn't a domain application with this
|
||||
# user needs to be the creator of the domain request
|
||||
# this query is empty if there isn't a domain request with this
|
||||
# id and this user as creator
|
||||
if not DomainApplication.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
if not DomainRequest.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -288,7 +288,7 @@ class UserDeleteDomainRolePermission(PermissionsLoginMixin):
|
|||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain application.
|
||||
"""Check if this user has access to this domain request.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
|
@ -319,19 +319,19 @@ class UserDeleteDomainRolePermission(PermissionsLoginMixin):
|
|||
return True
|
||||
|
||||
|
||||
class DomainApplicationPermissionWithdraw(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to withdraw action on domain application
|
||||
class DomainRequestPermissionWithdraw(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to withdraw action on domain request
|
||||
if user has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to withdraw this domain application."""
|
||||
"""Check if this user has access to withdraw this domain request."""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# user needs to be the creator of the application
|
||||
# this query is empty if there isn't a domain application with this
|
||||
# user needs to be the creator of the domain request
|
||||
# this query is empty if there isn't a domain request with this
|
||||
# id and this user as creator
|
||||
if not DomainApplication.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
if not DomainRequest.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
return False
|
||||
|
||||
# Restricted users should not be able to withdraw domain requests
|
||||
|
@ -341,12 +341,12 @@ class DomainApplicationPermissionWithdraw(PermissionsLoginMixin):
|
|||
return True
|
||||
|
||||
|
||||
class ApplicationWizardPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to start or edit domain application if
|
||||
class DomainRequestWizardPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to start or edit domain request if
|
||||
user has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has permission to start or edit an application.
|
||||
"""Check if this user has permission to start or edit a domain request.
|
||||
|
||||
The user is in self.request.user
|
||||
"""
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
import abc # abstract base class
|
||||
|
||||
from django.views.generic import DetailView, DeleteView, TemplateView
|
||||
from registrar.models import Domain, DomainApplication, DomainInvitation
|
||||
from registrar.models import Domain, DomainRequest, DomainInvitation
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
|
||||
from .mixins import (
|
||||
DomainPermission,
|
||||
DomainApplicationPermission,
|
||||
DomainApplicationPermissionWithdraw,
|
||||
DomainRequestPermission,
|
||||
DomainRequestPermissionWithdraw,
|
||||
DomainInvitationPermission,
|
||||
ApplicationWizardPermission,
|
||||
DomainRequestWizardPermission,
|
||||
UserDeleteDomainRolePermission,
|
||||
)
|
||||
import logging
|
||||
|
@ -56,17 +56,17 @@ class DomainPermissionView(DomainPermission, DetailView, abc.ABC):
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainApplicationPermissionView(DomainApplicationPermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain applications that enforces permissions
|
||||
class DomainRequestPermissionView(DomainRequestPermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain requests that enforces permissions
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = DomainApplication
|
||||
model = DomainRequest
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "domainapplication"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
|
@ -75,17 +75,17 @@ class DomainApplicationPermissionView(DomainApplicationPermission, DetailView, a
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainApplicationPermissionWithdrawView(DomainApplicationPermissionWithdraw, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain application withdraw function
|
||||
class DomainRequestPermissionWithdrawView(DomainRequestPermissionWithdraw, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain request withdraw function
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = DomainApplication
|
||||
model = DomainRequest
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "domainapplication"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
|
@ -94,8 +94,8 @@ class DomainApplicationPermissionWithdrawView(DomainApplicationPermissionWithdra
|
|||
raise NotImplementedError
|
||||
|
||||
|
||||
class ApplicationWizardPermissionView(ApplicationWizardPermission, TemplateView, abc.ABC):
|
||||
"""Abstract base view for the application form that enforces permissions
|
||||
class DomainRequestWizardPermissionView(DomainRequestWizardPermission, TemplateView, abc.ABC):
|
||||
"""Abstract base view for the domain request form that enforces permissions
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
|
@ -121,11 +121,11 @@ class DomainInvitationPermissionDeleteView(DomainInvitationPermission, DeleteVie
|
|||
object: DomainInvitation # workaround for type mismatch in DeleteView
|
||||
|
||||
|
||||
class DomainApplicationPermissionDeleteView(DomainApplicationPermission, DeleteView, abc.ABC):
|
||||
"""Abstract view for deleting a DomainApplication."""
|
||||
class DomainRequestPermissionDeleteView(DomainRequestPermission, DeleteView, abc.ABC):
|
||||
"""Abstract view for deleting a DomainRequest."""
|
||||
|
||||
model = DomainApplication
|
||||
object: DomainApplication
|
||||
model = DomainRequest
|
||||
object: DomainRequest
|
||||
|
||||
|
||||
class UserDomainRolePermissionDeleteView(UserDeleteDomainRolePermission, DeleteView, abc.ABC):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue