mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-17 18:09:25 +02:00
Merge branch 'main' into nl/1895-CISA-regions-questions-domain-req
This commit is contained in:
commit
1eb9b080a6
17 changed files with 683 additions and 46 deletions
|
@ -290,6 +290,13 @@ class CustomLogEntryAdmin(LogEntryAdmin):
|
|||
# Return the field value without a link
|
||||
return f"{obj.content_type} - {obj.object_repr}"
|
||||
|
||||
# We name the custom prop 'created_at' because linter
|
||||
# is not allowing a short_description attr on it
|
||||
# This gets around the linter limitation, for now.
|
||||
@admin.display(description=_("Created at"))
|
||||
def created(self, obj):
|
||||
return obj.timestamp
|
||||
|
||||
search_help_text = "Search by resource, changes, or user."
|
||||
|
||||
change_form_template = "admin/change_form_no_submit.html"
|
||||
|
@ -478,7 +485,7 @@ class MyUserAdmin(BaseUserAdmin):
|
|||
|
||||
list_display = (
|
||||
"username",
|
||||
"email",
|
||||
"overridden_email_field",
|
||||
"first_name",
|
||||
"last_name",
|
||||
# Group is a custom property defined within this file,
|
||||
|
@ -487,6 +494,18 @@ class MyUserAdmin(BaseUserAdmin):
|
|||
"status",
|
||||
)
|
||||
|
||||
# Renames inherited AbstractUser label 'email_address to 'email'
|
||||
def formfield_for_dbfield(self, dbfield, **kwargs):
|
||||
field = super().formfield_for_dbfield(dbfield, **kwargs)
|
||||
if dbfield.name == "email":
|
||||
field.label = "Email"
|
||||
return field
|
||||
|
||||
# Renames inherited AbstractUser column name 'email_address to 'email'
|
||||
@admin.display(description=_("Email"))
|
||||
def overridden_email_field(self, obj):
|
||||
return obj.email
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
|
@ -561,6 +580,7 @@ class MyUserAdmin(BaseUserAdmin):
|
|||
# this ordering effects the ordering of results
|
||||
# in autocomplete_fields for user
|
||||
ordering = ["first_name", "last_name", "email"]
|
||||
search_help_text = "Search by first name, last name, or email."
|
||||
|
||||
change_form_template = "django/admin/email_clipboard_change_form.html"
|
||||
|
||||
|
@ -651,7 +671,7 @@ class MyHostAdmin(AuditedAdmin):
|
|||
"""Custom host admin class to use our inlines."""
|
||||
|
||||
search_fields = ["name", "domain__name"]
|
||||
search_help_text = "Search by domain or hostname."
|
||||
search_help_text = "Search by domain or host name."
|
||||
inlines = [HostIPInline]
|
||||
|
||||
|
||||
|
@ -659,9 +679,9 @@ class ContactAdmin(ListHeaderAdmin):
|
|||
"""Custom contact admin class to add search."""
|
||||
|
||||
search_fields = ["email", "first_name", "last_name"]
|
||||
search_help_text = "Search by firstname, lastname or email."
|
||||
search_help_text = "Search by first name, last name or email."
|
||||
list_display = [
|
||||
"contact",
|
||||
"name",
|
||||
"email",
|
||||
"user_exists",
|
||||
]
|
||||
|
@ -690,7 +710,7 @@ class ContactAdmin(ListHeaderAdmin):
|
|||
# We name the custom prop 'contact' because linter
|
||||
# is not allowing a short_description attr on it
|
||||
# This gets around the linter limitation, for now.
|
||||
def contact(self, obj: models.Contact):
|
||||
def name(self, obj: models.Contact):
|
||||
"""Duplicate the contact _str_"""
|
||||
if obj.first_name or obj.last_name:
|
||||
return obj.get_formatted_name()
|
||||
|
@ -701,7 +721,7 @@ class ContactAdmin(ListHeaderAdmin):
|
|||
else:
|
||||
return ""
|
||||
|
||||
contact.admin_order_field = "first_name" # type: ignore
|
||||
name.admin_order_field = "first_name" # type: ignore
|
||||
|
||||
# Read only that we'll leverage for CISA Analysts
|
||||
analyst_readonly_fields = [
|
||||
|
@ -859,7 +879,7 @@ class UserDomainRoleAdmin(ListHeaderAdmin):
|
|||
"domain__name",
|
||||
"role",
|
||||
]
|
||||
search_help_text = "Search by firstname, lastname, email, domain, or role."
|
||||
search_help_text = "Search by first name, last name, email, or domain."
|
||||
|
||||
autocomplete_fields = ["user", "domain"]
|
||||
|
||||
|
@ -959,7 +979,9 @@ class DomainInformationAdmin(ListHeaderAdmin):
|
|||
"classes": ["collapse"],
|
||||
"fields": [
|
||||
"federal_type",
|
||||
"federal_agency",
|
||||
# "updated_federal_agency",
|
||||
# Above field commented out so it won't display
|
||||
"federal_agency", # TODO: remove later
|
||||
"tribe_name",
|
||||
"federally_recognized_tribe",
|
||||
"state_recognized_tribe",
|
||||
|
@ -1208,7 +1230,9 @@ class DomainRequestAdmin(ListHeaderAdmin):
|
|||
"classes": ["collapse"],
|
||||
"fields": [
|
||||
"federal_type",
|
||||
"federal_agency",
|
||||
# "updated_federal_agency",
|
||||
# Above field commented out so it won't display
|
||||
"federal_agency", # TODO: remove later
|
||||
"tribe_name",
|
||||
"federally_recognized_tribe",
|
||||
"state_recognized_tribe",
|
||||
|
@ -1665,6 +1689,7 @@ class DomainAdmin(ListHeaderAdmin):
|
|||
|
||||
city.admin_order_field = "domain_info__city" # type: ignore
|
||||
|
||||
@admin.display(description=_("State / territory"))
|
||||
def state_territory(self, obj):
|
||||
return obj.domain_info.state_territory if obj.domain_info else None
|
||||
|
||||
|
@ -1979,6 +2004,11 @@ class DraftDomainAdmin(ListHeaderAdmin):
|
|||
# this ordering effects the ordering of results
|
||||
# in autocomplete_fields for user
|
||||
ordering = ["name"]
|
||||
list_display = ["name"]
|
||||
|
||||
@admin.display(description=_("Requested domain"))
|
||||
def name(self, obj):
|
||||
return obj.name
|
||||
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
|
@ -2057,13 +2087,36 @@ class FederalAgencyAdmin(ListHeaderAdmin):
|
|||
ordering = ["agency"]
|
||||
|
||||
|
||||
class UserGroupAdmin(AuditedAdmin):
|
||||
"""Overwrite the generated UserGroup admin class"""
|
||||
|
||||
list_display = ["user_group"]
|
||||
|
||||
fieldsets = ((None, {"fields": ("name", "permissions")}),)
|
||||
|
||||
def formfield_for_dbfield(self, dbfield, **kwargs):
|
||||
field = super().formfield_for_dbfield(dbfield, **kwargs)
|
||||
if dbfield.name == "name":
|
||||
field.label = "Group name"
|
||||
if dbfield.name == "permissions":
|
||||
field.label = "User permissions"
|
||||
return field
|
||||
|
||||
# We name the custom prop 'Group' because linter
|
||||
# is not allowing a short_description attr on it
|
||||
# This gets around the linter limitation, for now.
|
||||
@admin.display(description=_("Group"))
|
||||
def user_group(self, obj):
|
||||
return obj.name
|
||||
|
||||
|
||||
admin.site.unregister(LogEntry) # Unregister the default registration
|
||||
admin.site.register(LogEntry, CustomLogEntryAdmin)
|
||||
admin.site.register(models.User, MyUserAdmin)
|
||||
# Unregister the built-in Group model
|
||||
admin.site.unregister(Group)
|
||||
# Register UserGroup
|
||||
admin.site.register(models.UserGroup)
|
||||
admin.site.register(models.UserGroup, UserGroupAdmin)
|
||||
admin.site.register(models.UserDomainRole, UserDomainRoleAdmin)
|
||||
admin.site.register(models.Contact, ContactAdmin)
|
||||
admin.site.register(models.DomainInvitation, DomainInvitationAdmin)
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
# Generated by Django 4.2.10 on 2024-04-18 18:01
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django_fsm
|
||||
import registrar.models.utility.domain_field
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0084_create_groups_v11"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="contact",
|
||||
name="first_name",
|
||||
field=models.CharField(blank=True, db_index=True, null=True, verbose_name="first name"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="contact",
|
||||
name="last_name",
|
||||
field=models.CharField(blank=True, db_index=True, null=True, verbose_name="last name"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="contact",
|
||||
name="title",
|
||||
field=models.CharField(blank=True, null=True, verbose_name="title / role"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domain",
|
||||
name="deleted",
|
||||
field=models.DateField(editable=False, help_text="Deleted at date", null=True, verbose_name="deleted on"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domain",
|
||||
name="first_ready",
|
||||
field=models.DateField(
|
||||
editable=False,
|
||||
help_text="The last time this domain moved into the READY state",
|
||||
null=True,
|
||||
verbose_name="first ready on",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domain",
|
||||
name="name",
|
||||
field=registrar.models.utility.domain_field.DomainField(
|
||||
default=None,
|
||||
help_text="Fully qualified domain name",
|
||||
max_length=253,
|
||||
unique=True,
|
||||
verbose_name="domain",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domain",
|
||||
name="state",
|
||||
field=django_fsm.FSMField(
|
||||
choices=[
|
||||
("unknown", "Unknown"),
|
||||
("dns needed", "Dns needed"),
|
||||
("ready", "Ready"),
|
||||
("on hold", "On hold"),
|
||||
("deleted", "Deleted"),
|
||||
],
|
||||
default="unknown",
|
||||
help_text="Very basic info about the lifecycle of this domain object",
|
||||
max_length=21,
|
||||
protected=True,
|
||||
verbose_name="domain state",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="address_line1",
|
||||
field=models.CharField(blank=True, help_text="Street address", null=True, verbose_name="address line 1"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="address_line2",
|
||||
field=models.CharField(
|
||||
blank=True, help_text="Street address line 2 (optional)", null=True, verbose_name="address line 2"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="is_election_board",
|
||||
field=models.BooleanField(
|
||||
blank=True,
|
||||
help_text="Is your organization an election office?",
|
||||
null=True,
|
||||
verbose_name="election office",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="state_territory",
|
||||
field=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,
|
||||
verbose_name="state / territory",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="urbanization",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="Urbanization (required for Puerto Rico only)",
|
||||
null=True,
|
||||
verbose_name="urbanization",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domaininformation",
|
||||
name="zipcode",
|
||||
field=models.CharField(
|
||||
blank=True, db_index=True, help_text="Zip code", max_length=10, null=True, verbose_name="zip code"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domainrequest",
|
||||
name="is_election_board",
|
||||
field=models.BooleanField(
|
||||
blank=True,
|
||||
help_text="Is your organization an election office?",
|
||||
null=True,
|
||||
verbose_name="election office",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domainrequest",
|
||||
name="state_territory",
|
||||
field=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,
|
||||
verbose_name="state / territory",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domainrequest",
|
||||
name="submission_date",
|
||||
field=models.DateField(
|
||||
blank=True, default=None, help_text="Date submitted", null=True, verbose_name="submitted at"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="domainrequest",
|
||||
name="zipcode",
|
||||
field=models.CharField(
|
||||
blank=True, db_index=True, help_text="Zip code", max_length=10, null=True, verbose_name="zip code"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="draftdomain",
|
||||
name="name",
|
||||
field=models.CharField(
|
||||
default=None, help_text="Fully qualified domain name", max_length=253, verbose_name="requested domain"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="host",
|
||||
name="name",
|
||||
field=models.CharField(
|
||||
default=None, help_text="Fully qualified domain name", max_length=253, verbose_name="host name"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="hostip",
|
||||
name="address",
|
||||
field=models.CharField(
|
||||
default=None,
|
||||
help_text="IP address",
|
||||
max_length=46,
|
||||
validators=[django.core.validators.validate_ipv46_address],
|
||||
verbose_name="IP address",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="domain_name",
|
||||
field=models.CharField(blank=True, null=True, verbose_name="domain"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="first_name",
|
||||
field=models.CharField(
|
||||
blank=True, db_index=True, help_text="First name / given name", null=True, verbose_name="first name"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="processed",
|
||||
field=models.BooleanField(
|
||||
default=True,
|
||||
help_text="Indicates whether this TransitionDomain was already processed",
|
||||
verbose_name="processed",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="state_territory",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="State, territory, or military post",
|
||||
max_length=2,
|
||||
null=True,
|
||||
verbose_name="state / territory",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="status",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[("ready", "Ready"), ("on hold", "On hold"), ("unknown", "Unknown")],
|
||||
default="ready",
|
||||
help_text="domain status during the transfer",
|
||||
max_length=255,
|
||||
verbose_name="status",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="title",
|
||||
field=models.CharField(blank=True, help_text="Title", null=True, verbose_name="title / role"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="username",
|
||||
field=models.CharField(help_text="Username - this will be an email address", verbose_name="username"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="transitiondomain",
|
||||
name="zipcode",
|
||||
field=models.CharField(
|
||||
blank=True, db_index=True, help_text="Zip code", max_length=10, null=True, verbose_name="zip code"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="status",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
choices=[("restricted", "restricted")],
|
||||
default=None,
|
||||
max_length=10,
|
||||
null=True,
|
||||
verbose_name="user status",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,36 @@
|
|||
# Generated by Django 4.2.10 on 2024-04-18 22:45
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("registrar", "0085_alter_contact_first_name_alter_contact_last_name_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="domaininformation",
|
||||
name="updated_federal_agency",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
help_text="Associated federal agency",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="registrar.federalagency",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="domainrequest",
|
||||
name="updated_federal_agency",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
help_text="Associated federal agency",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="registrar.federalagency",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -18,7 +18,7 @@ class Contact(TimeStampedModel):
|
|||
first_name = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="first name / given name",
|
||||
verbose_name="first name",
|
||||
db_index=True,
|
||||
)
|
||||
middle_name = models.CharField(
|
||||
|
@ -28,13 +28,13 @@ class Contact(TimeStampedModel):
|
|||
last_name = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="last name / family name",
|
||||
verbose_name="last name",
|
||||
db_index=True,
|
||||
)
|
||||
title = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="title or role in your organization",
|
||||
verbose_name="title / role",
|
||||
)
|
||||
email = models.EmailField(
|
||||
null=True,
|
||||
|
|
|
@ -992,6 +992,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
blank=False,
|
||||
default=None, # prevent saving without a value
|
||||
unique=True,
|
||||
verbose_name="domain",
|
||||
help_text="Fully qualified domain name",
|
||||
)
|
||||
|
||||
|
@ -1000,6 +1001,7 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
choices=State.choices,
|
||||
default=State.UNKNOWN,
|
||||
protected=True, # cannot change state directly, particularly in Django admin
|
||||
verbose_name="domain state",
|
||||
help_text="Very basic info about the lifecycle of this domain object",
|
||||
)
|
||||
|
||||
|
@ -1017,12 +1019,14 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
deleted = DateField(
|
||||
null=True,
|
||||
editable=False,
|
||||
verbose_name="deleted on",
|
||||
help_text="Deleted at date",
|
||||
)
|
||||
|
||||
first_ready = DateField(
|
||||
null=True,
|
||||
editable=False,
|
||||
verbose_name="first ready on",
|
||||
help_text="The last time this domain moved into the READY state",
|
||||
)
|
||||
|
||||
|
@ -1685,6 +1689,59 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
else:
|
||||
logger.error("Error _delete_hosts_if_not_used, code was %s error was %s" % (e.code, e))
|
||||
|
||||
def _fix_unknown_state(self, cleaned):
|
||||
"""
|
||||
_fix_unknown_state: Calls _add_missing_contacts_if_unknown
|
||||
to add contacts in as needed (or return an error). Otherwise
|
||||
if we are able to add contacts and the state is out of UNKNOWN
|
||||
and (and should be into DNS_NEEDED), we double check the
|
||||
current state and # of nameservers and update the state from there
|
||||
"""
|
||||
try:
|
||||
self._add_missing_contacts_if_unknown(cleaned)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"%s couldn't _add_missing_contacts_if_unknown, error was %s."
|
||||
"Domain will still be in UNKNOWN state." % (self.name, e)
|
||||
)
|
||||
if len(self.nameservers) >= 2 and (self.state != self.State.READY):
|
||||
self.ready()
|
||||
self.save()
|
||||
|
||||
@transition(field="state", source=State.UNKNOWN, target=State.DNS_NEEDED)
|
||||
def _add_missing_contacts_if_unknown(self, cleaned):
|
||||
"""
|
||||
_add_missing_contacts_if_unknown: Add contacts (SECURITY, TECHNICAL, and/or ADMINISTRATIVE)
|
||||
if they are missing, AND switch the state to DNS_NEEDED from UNKNOWN (if it
|
||||
is in an UNKNOWN state, that is an error state)
|
||||
Note: The transition state change happens at the end of the function
|
||||
"""
|
||||
|
||||
missingAdmin = True
|
||||
missingSecurity = True
|
||||
missingTech = True
|
||||
|
||||
if len(cleaned.get("_contacts")) < 3:
|
||||
for contact in cleaned.get("_contacts"):
|
||||
if contact.type == PublicContact.ContactTypeChoices.ADMINISTRATIVE:
|
||||
missingAdmin = False
|
||||
if contact.type == PublicContact.ContactTypeChoices.SECURITY:
|
||||
missingSecurity = False
|
||||
if contact.type == PublicContact.ContactTypeChoices.TECHNICAL:
|
||||
missingTech = False
|
||||
|
||||
# We are only creating if it doesn't exist so we don't overwrite
|
||||
if missingAdmin:
|
||||
administrative_contact = self.get_default_administrative_contact()
|
||||
administrative_contact.save()
|
||||
if missingSecurity:
|
||||
security_contact = self.get_default_security_contact()
|
||||
security_contact.save()
|
||||
if missingTech:
|
||||
technical_contact = self.get_default_technical_contact()
|
||||
technical_contact.save()
|
||||
|
||||
def _fetch_cache(self, fetch_hosts=False, fetch_contacts=False):
|
||||
"""Contact registry for info about a domain."""
|
||||
try:
|
||||
|
@ -1692,6 +1749,9 @@ class Domain(TimeStampedModel, DomainHelper):
|
|||
cache = self._extract_data_from_response(data_response)
|
||||
cleaned = self._clean_cache(cache, data_response)
|
||||
self._update_hosts_and_contacts(cleaned, fetch_hosts, fetch_contacts)
|
||||
|
||||
if self.state == self.State.UNKNOWN:
|
||||
self._fix_unknown_state(cleaned)
|
||||
if fetch_hosts:
|
||||
self._update_hosts_and_ips_in_db(cleaned)
|
||||
if fetch_contacts:
|
||||
|
|
|
@ -29,8 +29,18 @@ class DomainInformation(TimeStampedModel):
|
|||
|
||||
BranchChoices = DomainRequest.BranchChoices
|
||||
|
||||
# TODO for #1975: Delete this after we run the new migration
|
||||
AGENCY_CHOICES = DomainRequest.AGENCY_CHOICES
|
||||
|
||||
updated_federal_agency = models.ForeignKey(
|
||||
"registrar.FederalAgency",
|
||||
on_delete=models.PROTECT,
|
||||
help_text="Associated federal agency",
|
||||
unique=False,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
# 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(
|
||||
|
@ -62,6 +72,7 @@ class DomainInformation(TimeStampedModel):
|
|||
is_election_board = models.BooleanField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="election office",
|
||||
help_text="Is your organization an election office?",
|
||||
)
|
||||
|
||||
|
@ -108,6 +119,7 @@ class DomainInformation(TimeStampedModel):
|
|||
is_election_board = models.BooleanField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="election office",
|
||||
help_text="Is your organization an election office?",
|
||||
)
|
||||
|
||||
|
@ -121,13 +133,13 @@ class DomainInformation(TimeStampedModel):
|
|||
null=True,
|
||||
blank=True,
|
||||
help_text="Street address",
|
||||
verbose_name="Street address",
|
||||
verbose_name="address line 1",
|
||||
)
|
||||
address_line2 = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Street address line 2 (optional)",
|
||||
verbose_name="Street address line 2 (optional)",
|
||||
verbose_name="address line 2",
|
||||
)
|
||||
city = models.CharField(
|
||||
null=True,
|
||||
|
@ -139,21 +151,22 @@ class DomainInformation(TimeStampedModel):
|
|||
choices=StateTerritoryChoices.choices,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="state / territory",
|
||||
help_text="State, territory, or military post",
|
||||
verbose_name="State, territory, or military post",
|
||||
)
|
||||
zipcode = models.CharField(
|
||||
max_length=10,
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Zip code",
|
||||
verbose_name="zip code",
|
||||
db_index=True,
|
||||
)
|
||||
urbanization = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Urbanization (required for Puerto Rico only)",
|
||||
verbose_name="Urbanization (required for Puerto Rico only)",
|
||||
verbose_name="urbanization",
|
||||
)
|
||||
|
||||
about_your_organization = models.TextField(
|
||||
|
|
|
@ -449,6 +449,15 @@ class DomainRequest(TimeStampedModel):
|
|||
blank=True,
|
||||
)
|
||||
|
||||
updated_federal_agency = models.ForeignKey(
|
||||
"registrar.FederalAgency",
|
||||
on_delete=models.PROTECT,
|
||||
help_text="Associated federal agency",
|
||||
unique=False,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
# 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(
|
||||
|
@ -478,6 +487,7 @@ class DomainRequest(TimeStampedModel):
|
|||
is_election_board = models.BooleanField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="election office",
|
||||
help_text="Is your organization an election office?",
|
||||
)
|
||||
|
||||
|
@ -550,12 +560,14 @@ class DomainRequest(TimeStampedModel):
|
|||
choices=StateTerritoryChoices.choices,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="state / territory",
|
||||
help_text="State, territory, or military post",
|
||||
)
|
||||
zipcode = models.CharField(
|
||||
max_length=10,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="zip code",
|
||||
help_text="Zip code",
|
||||
db_index=True,
|
||||
)
|
||||
|
@ -683,6 +695,7 @@ class DomainRequest(TimeStampedModel):
|
|||
null=True,
|
||||
blank=True,
|
||||
default=None,
|
||||
verbose_name="submitted at",
|
||||
help_text="Date submitted",
|
||||
)
|
||||
|
||||
|
|
|
@ -18,5 +18,6 @@ class DraftDomain(TimeStampedModel, DomainHelper):
|
|||
max_length=253,
|
||||
blank=False,
|
||||
default=None, # prevent saving without a value
|
||||
verbose_name="requested domain",
|
||||
help_text="Fully qualified domain name",
|
||||
)
|
||||
|
|
|
@ -21,6 +21,7 @@ class Host(TimeStampedModel):
|
|||
blank=False,
|
||||
default=None, # prevent saving without a value
|
||||
unique=False,
|
||||
verbose_name="host name",
|
||||
help_text="Fully qualified domain name",
|
||||
)
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class HostIP(TimeStampedModel):
|
|||
blank=False,
|
||||
default=None, # prevent saving without a value
|
||||
validators=[validate_ipv46_address],
|
||||
verbose_name="IP address",
|
||||
help_text="IP address",
|
||||
)
|
||||
|
||||
|
|
|
@ -20,13 +20,13 @@ class TransitionDomain(TimeStampedModel):
|
|||
username = models.CharField(
|
||||
null=False,
|
||||
blank=False,
|
||||
verbose_name="Username",
|
||||
verbose_name="username",
|
||||
help_text="Username - this will be an email address",
|
||||
)
|
||||
domain_name = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="Domain name",
|
||||
verbose_name="domain",
|
||||
)
|
||||
status = models.CharField(
|
||||
max_length=255,
|
||||
|
@ -34,7 +34,7 @@ class TransitionDomain(TimeStampedModel):
|
|||
blank=True,
|
||||
default=StatusChoices.READY,
|
||||
choices=StatusChoices.choices,
|
||||
verbose_name="Status",
|
||||
verbose_name="status",
|
||||
help_text="domain status during the transfer",
|
||||
)
|
||||
email_sent = models.BooleanField(
|
||||
|
@ -46,7 +46,7 @@ class TransitionDomain(TimeStampedModel):
|
|||
processed = models.BooleanField(
|
||||
null=False,
|
||||
default=True,
|
||||
verbose_name="Processed",
|
||||
verbose_name="processed",
|
||||
help_text="Indicates whether this TransitionDomain was already processed",
|
||||
)
|
||||
generic_org_type = models.CharField(
|
||||
|
@ -83,8 +83,8 @@ class TransitionDomain(TimeStampedModel):
|
|||
first_name = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="First name",
|
||||
verbose_name="first name / given name",
|
||||
help_text="First name / given name",
|
||||
verbose_name="first name",
|
||||
db_index=True,
|
||||
)
|
||||
middle_name = models.CharField(
|
||||
|
@ -100,6 +100,7 @@ class TransitionDomain(TimeStampedModel):
|
|||
title = models.CharField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="title / role",
|
||||
help_text="Title",
|
||||
)
|
||||
email = models.EmailField(
|
||||
|
@ -126,12 +127,14 @@ class TransitionDomain(TimeStampedModel):
|
|||
max_length=2,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="state / territory",
|
||||
help_text="State, territory, or military post",
|
||||
)
|
||||
zipcode = models.CharField(
|
||||
max_length=10,
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name="zip code",
|
||||
help_text="Zip code",
|
||||
db_index=True,
|
||||
)
|
||||
|
|
|
@ -33,6 +33,7 @@ class User(AbstractUser):
|
|||
default=None, # Set the default value to None
|
||||
null=True, # Allow the field to be null
|
||||
blank=True, # Allow the field to be blank
|
||||
verbose_name="user status",
|
||||
)
|
||||
|
||||
domains = models.ManyToManyField(
|
||||
|
|
|
@ -545,7 +545,6 @@ class MockDb(TestCase):
|
|||
self.domain_2, _ = Domain.objects.get_or_create(name="adomain2.gov", state=Domain.State.DNS_NEEDED)
|
||||
self.domain_3, _ = Domain.objects.get_or_create(name="ddomain3.gov", state=Domain.State.ON_HOLD)
|
||||
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||
self.domain_4, _ = Domain.objects.get_or_create(name="bdomain4.gov", state=Domain.State.UNKNOWN)
|
||||
self.domain_5, _ = Domain.objects.get_or_create(
|
||||
name="bdomain5.gov", state=Domain.State.DELETED, deleted=timezone.make_aware(datetime(2023, 11, 1))
|
||||
)
|
||||
|
@ -979,7 +978,20 @@ class MockEppLib(TestCase):
|
|||
mockDataInfoDomain = fakedEppObject(
|
||||
"fakePw",
|
||||
cr_date=make_aware(datetime(2023, 5, 25, 19, 45, 35)),
|
||||
contacts=[common.DomainContact(contact="123", type=PublicContact.ContactTypeChoices.SECURITY)],
|
||||
contacts=[
|
||||
common.DomainContact(
|
||||
contact="securityContact",
|
||||
type=PublicContact.ContactTypeChoices.SECURITY,
|
||||
),
|
||||
common.DomainContact(
|
||||
contact="technicalContact",
|
||||
type=PublicContact.ContactTypeChoices.TECHNICAL,
|
||||
),
|
||||
common.DomainContact(
|
||||
contact="adminContact",
|
||||
type=PublicContact.ContactTypeChoices.ADMINISTRATIVE,
|
||||
),
|
||||
],
|
||||
hosts=["fake.host.com"],
|
||||
statuses=[
|
||||
common.Status(state="serverTransferProhibited", description="", lang="en"),
|
||||
|
@ -1049,10 +1061,13 @@ class MockEppLib(TestCase):
|
|||
ex_date=date(2023, 11, 15),
|
||||
)
|
||||
mockDataInfoContact = mockDataInfoDomain.dummyInfoContactResultData(
|
||||
"123", "123@mail.gov", datetime(2023, 5, 25, 19, 45, 35), "lastPw"
|
||||
id="123", email="123@mail.gov", cr_date=datetime(2023, 5, 25, 19, 45, 35), pw="lastPw"
|
||||
)
|
||||
mockDataSecurityContact = mockDataInfoDomain.dummyInfoContactResultData(
|
||||
id="securityContact", email="security@mail.gov", cr_date=datetime(2023, 5, 25, 19, 45, 35), pw="lastPw"
|
||||
)
|
||||
InfoDomainWithContacts = fakedEppObject(
|
||||
"fakepw",
|
||||
"fakePw",
|
||||
cr_date=make_aware(datetime(2023, 5, 25, 19, 45, 35)),
|
||||
contacts=[
|
||||
common.DomainContact(
|
||||
|
@ -1074,6 +1089,7 @@ class MockEppLib(TestCase):
|
|||
common.Status(state="inactive", description="", lang="en"),
|
||||
],
|
||||
registrant="regContact",
|
||||
ex_date=date(2023, 11, 15),
|
||||
)
|
||||
|
||||
InfoDomainWithDefaultSecurityContact = fakedEppObject(
|
||||
|
@ -1500,6 +1516,8 @@ class MockEppLib(TestCase):
|
|||
"meow.gov": (self.mockDataInfoDomainSubdomainAndIPAddress, None),
|
||||
"fakemeow.gov": (self.mockDataInfoDomainNotSubdomainNoIP, None),
|
||||
"subdomainwoip.gov": (self.mockDataInfoDomainSubdomainNoIP, None),
|
||||
"ddomain3.gov": (self.InfoDomainWithContacts, None),
|
||||
"igorville.gov": (self.InfoDomainWithContacts, None),
|
||||
}
|
||||
|
||||
# Retrieve the corresponding values from the dictionary
|
||||
|
|
|
@ -25,11 +25,13 @@ from registrar.models import (
|
|||
Domain,
|
||||
DomainRequest,
|
||||
DomainInformation,
|
||||
DraftDomain,
|
||||
User,
|
||||
DomainInvitation,
|
||||
Contact,
|
||||
PublicContact,
|
||||
Host,
|
||||
Website,
|
||||
DraftDomain,
|
||||
)
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
from registrar.models.verified_by_staff import VerifiedByStaff
|
||||
|
@ -690,6 +692,8 @@ class TestDomainAdmin(MockEppLib, WebTest):
|
|||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
PublicContact.objects.all().delete()
|
||||
Host.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
DomainInformation.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
|
@ -1858,6 +1862,8 @@ class TestDomainRequestAdmin(MockEppLib):
|
|||
"updated_at",
|
||||
"status",
|
||||
"rejection_reason",
|
||||
"updated_federal_agency",
|
||||
# TODO: once approved, we'll have to remove above from test
|
||||
"creator",
|
||||
"investigator",
|
||||
"generic_org_type",
|
||||
|
|
|
@ -107,9 +107,9 @@ class TestDomainCache(MockEppLib):
|
|||
common.DomainContact(contact="123", type="security"),
|
||||
]
|
||||
expectedContactsDict = {
|
||||
PublicContact.ContactTypeChoices.ADMINISTRATIVE: None,
|
||||
PublicContact.ContactTypeChoices.SECURITY: "123",
|
||||
PublicContact.ContactTypeChoices.TECHNICAL: None,
|
||||
PublicContact.ContactTypeChoices.ADMINISTRATIVE: "adminContact",
|
||||
PublicContact.ContactTypeChoices.SECURITY: "securityContact",
|
||||
PublicContact.ContactTypeChoices.TECHNICAL: "technicalContact",
|
||||
}
|
||||
expectedHostsDict = {
|
||||
"name": self.mockDataInfoDomain.hosts[0],
|
||||
|
@ -129,6 +129,7 @@ class TestDomainCache(MockEppLib):
|
|||
# The contact list should not contain what is sent by the registry by default,
|
||||
# as _fetch_cache will transform the type to PublicContact
|
||||
self.assertNotEqual(domain._cache["contacts"], expectedUnfurledContactsList)
|
||||
|
||||
self.assertEqual(domain._cache["contacts"], expectedContactsDict)
|
||||
|
||||
# get and check hosts is set correctly
|
||||
|
@ -203,19 +204,20 @@ class TestDomainCache(MockEppLib):
|
|||
def test_map_epp_contact_to_public_contact(self):
|
||||
# Tests that the mapper is working how we expect
|
||||
with less_console_noise():
|
||||
domain, _ = Domain.objects.get_or_create(name="registry.gov")
|
||||
domain, _ = Domain.objects.get_or_create(name="registry.gov", state=Domain.State.DNS_NEEDED)
|
||||
security = PublicContact.ContactTypeChoices.SECURITY
|
||||
mapped = domain.map_epp_contact_to_public_contact(
|
||||
self.mockDataInfoContact,
|
||||
self.mockDataInfoContact.id,
|
||||
self.mockDataSecurityContact,
|
||||
self.mockDataSecurityContact.id,
|
||||
security,
|
||||
)
|
||||
|
||||
# id, registry_id, and contact are the same thing
|
||||
expected_contact = PublicContact(
|
||||
domain=domain,
|
||||
contact_type=security,
|
||||
registry_id="123",
|
||||
email="123@mail.gov",
|
||||
registry_id="securityContact",
|
||||
email="security@mail.gov",
|
||||
voice="+1.8882820870",
|
||||
fax="+1-212-9876543",
|
||||
pw="lastPw",
|
||||
|
@ -232,7 +234,6 @@ class TestDomainCache(MockEppLib):
|
|||
# two duplicate objects. We would expect
|
||||
# these not to have the same state.
|
||||
expected_contact._state = mapped._state
|
||||
|
||||
# Mapped object is what we expect
|
||||
self.assertEqual(mapped.__dict__, expected_contact.__dict__)
|
||||
|
||||
|
@ -243,9 +244,9 @@ class TestDomainCache(MockEppLib):
|
|||
registry_id=domain.security_contact.registry_id,
|
||||
contact_type=security,
|
||||
).get()
|
||||
|
||||
# DB Object is the same as the mapped object
|
||||
self.assertEqual(db_object, in_db)
|
||||
|
||||
domain.security_contact = in_db
|
||||
# Trigger the getter
|
||||
_ = domain.security_contact
|
||||
|
@ -309,6 +310,40 @@ class TestDomainCache(MockEppLib):
|
|||
)
|
||||
self.assertEqual(context.exception.code, desired_error)
|
||||
|
||||
def test_fix_unknown_to_ready_state(self):
|
||||
"""
|
||||
Scenario: A error occurred and the domain's state is in UNKONWN
|
||||
which shouldn't happen. The biz logic and test is to make sure
|
||||
we resolve that UNKNOWN state to READY because it has 2 nameservers.
|
||||
Note:
|
||||
* Default state when you do get_or_create is UNKNOWN
|
||||
* justnameserver.com has 2 nameservers which is why we are using it
|
||||
* justnameserver.com also has all 3 contacts hence 0 count
|
||||
"""
|
||||
with less_console_noise():
|
||||
domain, _ = Domain.objects.get_or_create(name="justnameserver.com")
|
||||
# trigger the getter
|
||||
_ = domain.nameservers
|
||||
self.assertEqual(domain.state, Domain.State.READY)
|
||||
self.assertEqual(PublicContact.objects.filter(domain=domain.id).count(), 0)
|
||||
|
||||
def test_fix_unknown_to_dns_needed_state(self):
|
||||
"""
|
||||
Scenario: A error occurred and the domain's state is in UNKONWN
|
||||
which shouldn't happen. The biz logic and test is to make sure
|
||||
we resolve that UNKNOWN state to DNS_NEEDED because it has 1 nameserver.
|
||||
Note:
|
||||
* Default state when you do get_or_create is UNKNOWN
|
||||
* defaulttechnical.gov has 1 nameservers which is why we are using it
|
||||
* defaulttechnical.gov already has a security contact (1) hence 2 count
|
||||
"""
|
||||
with less_console_noise():
|
||||
domain, _ = Domain.objects.get_or_create(name="defaulttechnical.gov")
|
||||
# trigger the getter
|
||||
_ = domain.nameservers
|
||||
self.assertEqual(domain.state, Domain.State.DNS_NEEDED)
|
||||
self.assertEqual(PublicContact.objects.filter(domain=domain.id).count(), 2)
|
||||
|
||||
|
||||
class TestDomainCreation(MockEppLib):
|
||||
"""Rule: An approved domain request must result in a domain"""
|
||||
|
@ -346,7 +381,7 @@ class TestDomainCreation(MockEppLib):
|
|||
Given that no domain object exists in the registry
|
||||
When a property is accessed
|
||||
Then Domain sends `commands.CreateDomain` to the registry
|
||||
And `domain.state` is set to `UNKNOWN`
|
||||
And `domain.state` is set to `DNS_NEEDED`
|
||||
And `domain.is_active()` returns False
|
||||
"""
|
||||
with less_console_noise():
|
||||
|
@ -375,7 +410,7 @@ class TestDomainCreation(MockEppLib):
|
|||
any_order=False, # Ensure calls are in the specified order
|
||||
)
|
||||
|
||||
self.assertEqual(domain.state, Domain.State.UNKNOWN)
|
||||
self.assertEqual(domain.state, Domain.State.DNS_NEEDED)
|
||||
self.assertEqual(domain.is_active(), False)
|
||||
|
||||
@skip("assertion broken with mock addition")
|
||||
|
@ -400,6 +435,7 @@ class TestDomainCreation(MockEppLib):
|
|||
DomainInformation.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
PublicContact.objects.all().delete()
|
||||
Host.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
DraftDomain.objects.all().delete()
|
||||
|
@ -485,6 +521,7 @@ class TestDomainStatuses(MockEppLib):
|
|||
|
||||
def tearDown(self) -> None:
|
||||
PublicContact.objects.all().delete()
|
||||
Host.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
super().tearDown()
|
||||
|
||||
|
@ -624,6 +661,7 @@ class TestRegistrantContacts(MockEppLib):
|
|||
self.domain._invalidate_cache()
|
||||
self.domain_contact._invalidate_cache()
|
||||
PublicContact.objects.all().delete()
|
||||
Host.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
|
||||
def test_no_security_email(self):
|
||||
|
@ -998,10 +1036,10 @@ class TestRegistrantContacts(MockEppLib):
|
|||
And the field `disclose` is set to true for DF.EMAIL
|
||||
"""
|
||||
with less_console_noise():
|
||||
domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
||||
domain, _ = Domain.objects.get_or_create(name="igorville.gov", state=Domain.State.DNS_NEEDED)
|
||||
expectedSecContact = PublicContact.get_default_security()
|
||||
expectedSecContact.domain = domain
|
||||
expectedSecContact.email = "123@mail.gov"
|
||||
expectedSecContact.email = "security@mail.gov"
|
||||
domain.security_contact = expectedSecContact
|
||||
expectedCreateCommand = self._convertPublicContactToEpp(expectedSecContact, disclose_email=True)
|
||||
self.mockedSendFunction.assert_any_call(expectedCreateCommand, cleaned=True)
|
||||
|
@ -1847,6 +1885,8 @@ class TestRegistrantDNSSEC(MockEppLib):
|
|||
self.domain, _ = Domain.objects.get_or_create(name="fake.gov")
|
||||
|
||||
def tearDown(self):
|
||||
PublicContact.objects.all().delete()
|
||||
Host.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
super().tearDown()
|
||||
|
||||
|
@ -1904,6 +1944,7 @@ class TestRegistrantDNSSEC(MockEppLib):
|
|||
),
|
||||
cleaned=True,
|
||||
),
|
||||
call(commands.InfoHost(name="fake.host.com"), cleaned=True),
|
||||
call(
|
||||
commands.UpdateDomain(
|
||||
name="dnssec-dsdata.gov",
|
||||
|
@ -1976,6 +2017,13 @@ class TestRegistrantDNSSEC(MockEppLib):
|
|||
),
|
||||
cleaned=True,
|
||||
),
|
||||
call(
|
||||
commands.InfoDomain(
|
||||
name="dnssec-dsdata.gov",
|
||||
),
|
||||
cleaned=True,
|
||||
),
|
||||
call(commands.InfoHost(name="fake.host.com"), cleaned=True),
|
||||
call(
|
||||
commands.UpdateDomain(
|
||||
name="dnssec-dsdata.gov",
|
||||
|
@ -2129,6 +2177,7 @@ class TestRegistrantDNSSEC(MockEppLib):
|
|||
),
|
||||
cleaned=True,
|
||||
),
|
||||
call(commands.InfoHost(name="fake.host.com"), cleaned=True),
|
||||
call(
|
||||
commands.UpdateDomain(
|
||||
name="dnssec-dsdata.gov",
|
||||
|
|
|
@ -263,7 +263,7 @@ class ExportDataTest(MockDb, MockEppLib):
|
|||
"adomain10.gov,Federal,Armed Forces Retirement Home,Ready\n"
|
||||
"adomain2.gov,Interstate,(blank),Dns needed\n"
|
||||
"cdomain11.govFederal-ExecutiveWorldWarICentennialCommissionReady\n"
|
||||
"ddomain3.gov,Federal,Armed Forces Retirement Home,123@mail.gov,On hold,2023-05-25\n"
|
||||
"ddomain3.gov,Federal,Armed Forces Retirement Home,security@mail.gov,On hold,2023-11-15\n"
|
||||
"defaultsecurity.gov,Federal - Executive,World War I Centennial Commission,(blank),Ready\n"
|
||||
"zdomain12.govInterstateReady\n"
|
||||
)
|
||||
|
|
|
@ -243,7 +243,7 @@ class TestDomainDetail(TestDomainOverview):
|
|||
self.assertContains(home_page, "DNS needed")
|
||||
|
||||
def test_unknown_domain_does_not_show_as_expired_on_detail_page(self):
|
||||
"""An UNKNOWN domain does not show as expired on the detail page.
|
||||
"""An UNKNOWN domain should not exist on the detail_page anymore.
|
||||
It shows as 'DNS needed'"""
|
||||
# At the time of this test's writing, there are 6 UNKNOWN domains inherited
|
||||
# from constructors. Let's reset.
|
||||
|
@ -262,9 +262,9 @@ class TestDomainDetail(TestDomainOverview):
|
|||
igorville = Domain.objects.get(name="igorville.gov")
|
||||
self.assertEquals(igorville.state, Domain.State.UNKNOWN)
|
||||
detail_page = home_page.click("Manage", index=0)
|
||||
self.assertNotContains(detail_page, "Expired")
|
||||
self.assertContains(detail_page, "Expired")
|
||||
|
||||
self.assertContains(detail_page, "DNS needed")
|
||||
self.assertNotContains(detail_page, "DNS needed")
|
||||
|
||||
def test_domain_detail_blocked_for_ineligible_user(self):
|
||||
"""We could easily duplicate this test for all domain management
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue