mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-04 17:01:56 +02:00
Merge branch 'dk/1091-dnssec' of https://github.com/cisagov/getgov into dk/1091-dnssec
This commit is contained in:
commit
45429eef71
9 changed files with 246 additions and 208 deletions
|
@ -1,7 +1,8 @@
|
|||
# common.py
|
||||
#
|
||||
#
|
||||
# ALGORITHM_CHOICES are options for alg attribute in DS Data and Key Data
|
||||
# reference: https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||
# reference:
|
||||
# https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
|
||||
ALGORITHM_CHOICES = [
|
||||
(1, "(1) ERSA/MD5 [RSAMD5]"),
|
||||
(2, "(2) Diffie-Hellman [DH]"),
|
||||
|
|
|
@ -7,7 +7,13 @@ from django.forms import formset_factory
|
|||
from phonenumber_field.widgets import RegionalPhoneNumberWidget
|
||||
|
||||
from ..models import Contact, DomainInformation
|
||||
from .common import ALGORITHM_CHOICES, DIGEST_TYPE_CHOICES, FLAG_CHOICES, PROTOCOL_CHOICES
|
||||
from .common import (
|
||||
ALGORITHM_CHOICES,
|
||||
DIGEST_TYPE_CHOICES,
|
||||
FLAG_CHOICES,
|
||||
PROTOCOL_CHOICES,
|
||||
)
|
||||
|
||||
|
||||
class DomainAddUserForm(forms.Form):
|
||||
|
||||
|
@ -157,35 +163,27 @@ class DomainDsdataForm(forms.Form):
|
|||
MinValueValidator(0, message="Value must be between 0 and 65535"),
|
||||
MaxValueValidator(65535, message="Value must be between 0 and 65535"),
|
||||
],
|
||||
error_messages={
|
||||
"required": ("Key tag is required.")
|
||||
},
|
||||
error_messages={"required": ("Key tag is required.")},
|
||||
)
|
||||
|
||||
|
||||
algorithm = forms.TypedChoiceField(
|
||||
required=True,
|
||||
label="Algorithm",
|
||||
choices=[(None, "--Select--")] + ALGORITHM_CHOICES,
|
||||
error_messages={
|
||||
"required": ("Algorithm is required.")
|
||||
},
|
||||
choices=[(None, "--Select--")] + ALGORITHM_CHOICES, # type: ignore
|
||||
error_messages={"required": ("Algorithm is required.")},
|
||||
)
|
||||
|
||||
digest_type = forms.TypedChoiceField(
|
||||
required=True,
|
||||
label="Digest Type",
|
||||
choices=[(None, "--Select--")] + DIGEST_TYPE_CHOICES,
|
||||
error_messages={
|
||||
"required": ("Digest Type is required.")
|
||||
},
|
||||
choices=[(None, "--Select--")] + DIGEST_TYPE_CHOICES, # type: ignore
|
||||
error_messages={"required": ("Digest Type is required.")},
|
||||
)
|
||||
|
||||
digest = forms.CharField(
|
||||
required=True,
|
||||
label="Digest",
|
||||
error_messages={
|
||||
"required": ("Digest is required.")
|
||||
},
|
||||
error_messages={"required": ("Digest is required.")},
|
||||
)
|
||||
|
||||
|
||||
|
@ -204,35 +202,27 @@ class DomainKeydataForm(forms.Form):
|
|||
required=True,
|
||||
label="Flag",
|
||||
choices=FLAG_CHOICES,
|
||||
error_messages={
|
||||
"required": ("Flag is required.")
|
||||
},
|
||||
error_messages={"required": ("Flag is required.")},
|
||||
)
|
||||
|
||||
protocol = forms.TypedChoiceField(
|
||||
required=True,
|
||||
label="Protocol",
|
||||
choices=PROTOCOL_CHOICES,
|
||||
error_messages={
|
||||
"required": ("Protocol is required.")
|
||||
},
|
||||
error_messages={"required": ("Protocol is required.")},
|
||||
)
|
||||
|
||||
algorithm = forms.TypedChoiceField(
|
||||
required=True,
|
||||
label="Algorithm",
|
||||
choices=[(None, "--Select--")] + ALGORITHM_CHOICES,
|
||||
error_messages={
|
||||
"required": ("Algorithm is required.")
|
||||
},
|
||||
choices=[(None, "--Select--")] + ALGORITHM_CHOICES, # type: ignore
|
||||
error_messages={"required": ("Algorithm is required.")},
|
||||
)
|
||||
|
||||
|
||||
pub_key = forms.CharField(
|
||||
required=True,
|
||||
label="Pub key",
|
||||
error_messages={
|
||||
"required": ("Pub key is required.")
|
||||
},
|
||||
error_messages={"required": ("Pub key is required.")},
|
||||
)
|
||||
|
||||
|
||||
|
@ -240,4 +230,4 @@ DomainKeydataFormset = formset_factory(
|
|||
DomainKeydataForm,
|
||||
extra=0,
|
||||
can_delete=True,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<p>The Domain Name System (DNS) is the internet service that translates your domain name into an IP address. Before your .gov domain can be used, you'll need to connect it to your DNS hosting service and provide us with your name server information.</p>
|
||||
|
||||
<p>You can enter your name services, as well as other DNS-related information, in the following sections:</p>
|
||||
<p>You can enter your name servers, as well as other DNS-related information, in the following sections:</p>
|
||||
|
||||
{% url 'domain-dns-nameservers' pk=domain.id as url %}
|
||||
<p><a href="{{ url }}">DNS name servers</a></p>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<h1>{% if dnssec_enabled %}Set up {% endif %}DNSSEC</h1>
|
||||
|
||||
<p>DNSSEC, or DNS Security Extensions, is additional security layer to protect your website. Enabling DNSSEC ensures that when someone visits your website, they can be certain that it's connecting to the correct server, preventing potential hijacking or tampering with your domain's records.</p>
|
||||
<p>DNSSEC, or DNS Security Extensions, is additional security layer to protect your domain. Enabling DNSSEC ensures that when someone visits your domain, they can be certain that it's connecting to the correct server, preventing potential hijacking or tampering with your domain's records.</p>
|
||||
|
||||
<form class="usa-form usa-form--large" method="post">
|
||||
{% csrf_token %}
|
||||
|
@ -43,7 +43,7 @@
|
|||
<div id="enable-dnssec">
|
||||
<div class="usa-alert usa-alert--info usa-alert--slim margin-bottom-3">
|
||||
<div class="usa-alert__body">
|
||||
It is strongly recommended that you do not enable this unless you fully understand DNSSEC and know how to set it up properly. If you make a mistake, it could cause your domain name to stop working.
|
||||
It is strongly recommended that you only enable DNSSEC if you know how to set it up properly at your hosting service. If you make a mistake, it could cause your domain name to stop working.
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
|
|
|
@ -18,12 +18,14 @@ def startswith(text, starts):
|
|||
return text.startswith(starts)
|
||||
return False
|
||||
|
||||
|
||||
@register.filter("endswith")
|
||||
def endswith(text, ends):
|
||||
if isinstance(text, str):
|
||||
return text.endswith(ends)
|
||||
return False
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def public_site_url(url_path):
|
||||
"""Make a full URL for this path at our public site.
|
||||
|
|
|
@ -689,18 +689,18 @@ class MockEppLib(TestCase):
|
|||
"alg": 1,
|
||||
"pubKey": "AQPJ////4Q==",
|
||||
}
|
||||
dnssecExtensionWithDsData: Mapping[str, Any] = {
|
||||
"dsData": [common.DSData(**addDsData1)]
|
||||
dnssecExtensionWithDsData: Mapping[Any, Any] = {
|
||||
"dsData": [common.DSData(**addDsData1)] # type: ignore
|
||||
}
|
||||
dnssecExtensionWithMultDsData: Mapping[str, Any] = {
|
||||
"dsData": [
|
||||
common.DSData(**addDsData1),
|
||||
common.DSData(**addDsData2),
|
||||
common.DSData(**addDsData1), # type: ignore
|
||||
common.DSData(**addDsData2), # type: ignore
|
||||
],
|
||||
}
|
||||
dnssecExtensionWithKeyData: Mapping[str, Any] = {
|
||||
"maxSigLife": 3215,
|
||||
"keyData": [common.DNSSECKeyData(**keyDataDict)],
|
||||
"keyData": [common.DNSSECKeyData(**keyDataDict)], # type: ignore
|
||||
}
|
||||
|
||||
def mockSend(self, _request, cleaned):
|
||||
|
@ -709,54 +709,9 @@ class MockEppLib(TestCase):
|
|||
returns objects that simulate what would be in a epp response
|
||||
but only relevant pieces for tests"""
|
||||
if isinstance(_request, commands.InfoDomain):
|
||||
if getattr(_request, "name", None) == "security.gov":
|
||||
return MagicMock(res_data=[self.infoDomainNoContact])
|
||||
elif getattr(_request, "name", None) == "dnssec-dsdata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithDsData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-multdsdata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithMultDsData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-keydata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithKeyData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-none.gov":
|
||||
# this case is not necessary, but helps improve readability
|
||||
return MagicMock(res_data=[self.mockDataInfoDomain])
|
||||
elif getattr(_request, "name", None) == "freeman.gov":
|
||||
return MagicMock(res_data=[self.InfoDomainWithContacts])
|
||||
else:
|
||||
return MagicMock(res_data=[self.mockDataInfoDomain])
|
||||
return self.mockInfoDomainCommands(_request, cleaned)
|
||||
elif isinstance(_request, commands.InfoContact):
|
||||
mocked_result: info.InfoContactResultData
|
||||
|
||||
# For testing contact types
|
||||
match getattr(_request, "id", None):
|
||||
case "securityContact":
|
||||
mocked_result = self.mockSecurityContact
|
||||
case "technicalContact":
|
||||
mocked_result = self.mockTechnicalContact
|
||||
case "adminContact":
|
||||
mocked_result = self.mockAdministrativeContact
|
||||
case "regContact":
|
||||
mocked_result = self.mockRegistrantContact
|
||||
case _:
|
||||
# Default contact return
|
||||
mocked_result = self.mockDataInfoContact
|
||||
|
||||
return MagicMock(res_data=[mocked_result])
|
||||
return self.mockInfoContactCommands(_request, cleaned)
|
||||
elif (
|
||||
isinstance(_request, commands.CreateContact)
|
||||
and getattr(_request, "id", None) == "fail"
|
||||
|
@ -782,6 +737,57 @@ class MockEppLib(TestCase):
|
|||
raise RegistryError(code=ErrorCode.PARAMETER_VALUE_RANGE_ERROR)
|
||||
return MagicMock(res_data=[self.mockDataInfoHosts])
|
||||
|
||||
def mockInfoDomainCommands(self, _request, cleaned):
|
||||
if getattr(_request, "name", None) == "security.gov":
|
||||
return MagicMock(res_data=[self.infoDomainNoContact])
|
||||
elif getattr(_request, "name", None) == "dnssec-dsdata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithDsData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-multdsdata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithMultDsData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-keydata.gov":
|
||||
return MagicMock(
|
||||
res_data=[self.mockDataInfoDomain],
|
||||
extensions=[
|
||||
extensions.DNSSECExtension(**self.dnssecExtensionWithKeyData)
|
||||
],
|
||||
)
|
||||
elif getattr(_request, "name", None) == "dnssec-none.gov":
|
||||
# this case is not necessary, but helps improve readability
|
||||
return MagicMock(res_data=[self.mockDataInfoDomain])
|
||||
elif getattr(_request, "name", None) == "freeman.gov":
|
||||
return MagicMock(res_data=[self.InfoDomainWithContacts])
|
||||
else:
|
||||
return MagicMock(res_data=[self.mockDataInfoDomain])
|
||||
|
||||
def mockInfoContactCommands(self, _request, cleaned):
|
||||
mocked_result: info.InfoContactResultData
|
||||
|
||||
# For testing contact types
|
||||
match getattr(_request, "id", None):
|
||||
case "securityContact":
|
||||
mocked_result = self.mockSecurityContact
|
||||
case "technicalContact":
|
||||
mocked_result = self.mockTechnicalContact
|
||||
case "adminContact":
|
||||
mocked_result = self.mockAdministrativeContact
|
||||
case "regContact":
|
||||
mocked_result = self.mockRegistrantContact
|
||||
case _:
|
||||
# Default contact return
|
||||
mocked_result = self.mockDataInfoContact
|
||||
|
||||
return MagicMock(res_data=[mocked_result])
|
||||
|
||||
def setUp(self):
|
||||
"""mock epp send function as this will fail locally"""
|
||||
self.mockSendPatch = patch("registrar.models.domain.registry.send")
|
||||
|
|
|
@ -1003,7 +1003,6 @@ class TestRegistrantDNSSEC(MockEppLib):
|
|||
super().setUp()
|
||||
# for the tests, need a domain in the unknown state
|
||||
self.domain, _ = Domain.objects.get_or_create(name="fake.gov")
|
||||
|
||||
|
||||
def tearDown(self):
|
||||
Domain.objects.all().delete()
|
||||
|
|
|
@ -18,6 +18,7 @@ from registrar.models import (
|
|||
DraftDomain,
|
||||
DomainInvitation,
|
||||
Contact,
|
||||
PublicContact,
|
||||
Website,
|
||||
UserDomainRole,
|
||||
User,
|
||||
|
@ -1071,11 +1072,15 @@ class TestWithDomainPermissions(TestWithUser):
|
|||
super().setUp()
|
||||
self.domain, _ = Domain.objects.get_or_create(name="igorville.gov")
|
||||
self.domain_dsdata, _ = Domain.objects.get_or_create(name="dnssec-dsdata.gov")
|
||||
self.domain_multdsdata, _ = Domain.objects.get_or_create(name="dnssec-multdsdata.gov")
|
||||
self.domain_multdsdata, _ = Domain.objects.get_or_create(
|
||||
name="dnssec-multdsdata.gov"
|
||||
)
|
||||
self.domain_keydata, _ = Domain.objects.get_or_create(name="dnssec-keydata.gov")
|
||||
# We could simply use domain (igoreville) but this will be more readable in tests
|
||||
# We could simply use domain (igorville) but this will be more readable in tests
|
||||
# that inherit this setUp
|
||||
self.domain_dnssec_none, _ = Domain.objects.get_or_create(name="dnssec-none.gov")
|
||||
self.domain_dnssec_none, _ = Domain.objects.get_or_create(
|
||||
name="dnssec-none.gov"
|
||||
)
|
||||
self.domain_information, _ = DomainInformation.objects.get_or_create(
|
||||
creator=self.user, domain=self.domain
|
||||
)
|
||||
|
@ -1098,13 +1103,17 @@ class TestWithDomainPermissions(TestWithUser):
|
|||
user=self.user, domain=self.domain_dsdata, role=UserDomainRole.Roles.ADMIN
|
||||
)
|
||||
UserDomainRole.objects.get_or_create(
|
||||
user=self.user, domain=self.domain_multdsdata, role=UserDomainRole.Roles.ADMIN
|
||||
user=self.user,
|
||||
domain=self.domain_multdsdata,
|
||||
role=UserDomainRole.Roles.ADMIN,
|
||||
)
|
||||
UserDomainRole.objects.get_or_create(
|
||||
user=self.user, domain=self.domain_keydata, role=UserDomainRole.Roles.ADMIN
|
||||
)
|
||||
UserDomainRole.objects.get_or_create(
|
||||
user=self.user, domain=self.domain_dnssec_none, role=UserDomainRole.Roles.ADMIN
|
||||
user=self.user,
|
||||
domain=self.domain_dnssec_none,
|
||||
role=UserDomainRole.Roles.ADMIN,
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
|
@ -1113,6 +1122,7 @@ class TestWithDomainPermissions(TestWithUser):
|
|||
if hasattr(self.domain, "contacts"):
|
||||
self.domain.contacts.all().delete()
|
||||
DomainApplication.objects.all().delete()
|
||||
PublicContact.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
UserDomainRole.objects.all().delete()
|
||||
except ValueError: # pass if already deleted
|
||||
|
@ -1175,7 +1185,7 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
|||
detail_page = home_page.click("Manage", index=0)
|
||||
self.assertContains(detail_page, "igorville.gov")
|
||||
self.assertContains(detail_page, "Status")
|
||||
|
||||
|
||||
def test_domain_overview_blocked_for_ineligible_user(self):
|
||||
"""We could easily duplicate this test for all domain management
|
||||
views, but a single url test should be solid enough since all domain
|
||||
|
@ -1190,7 +1200,6 @@ class TestDomainOverview(TestWithDomainPermissions, WebTest):
|
|||
|
||||
|
||||
class TestDomainUserManagement(TestDomainOverview):
|
||||
|
||||
def test_domain_user_management(self):
|
||||
response = self.client.get(
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id})
|
||||
|
@ -1348,9 +1357,9 @@ class TestDomainUserManagement(TestDomainOverview):
|
|||
# Now load the home page and make sure our domain appears there
|
||||
home_page = self.app.get(reverse("home"))
|
||||
self.assertContains(home_page, self.domain.name)
|
||||
|
||||
class TestDomainNameservers(TestDomainOverview):
|
||||
|
||||
|
||||
class TestDomainNameservers(TestDomainOverview):
|
||||
def test_domain_nameservers(self):
|
||||
"""Can load domain's nameservers page."""
|
||||
page = self.client.get(
|
||||
|
@ -1401,9 +1410,9 @@ class TestDomainNameservers(TestDomainOverview):
|
|||
# error text appears twice, once at the top of the page, once around
|
||||
# the field.
|
||||
self.assertContains(result, "This field is required", count=2, status_code=200)
|
||||
|
||||
class TestDomainAuthorizingOfficial(TestDomainOverview):
|
||||
|
||||
|
||||
class TestDomainAuthorizingOfficial(TestDomainOverview):
|
||||
def test_domain_authorizing_official(self):
|
||||
"""Can load domain's authorizing official page."""
|
||||
page = self.client.get(
|
||||
|
@ -1421,9 +1430,9 @@ class TestDomainAuthorizingOfficial(TestDomainOverview):
|
|||
reverse("domain-authorizing-official", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertContains(page, "Testy")
|
||||
|
||||
class TestDomainOrganization(TestDomainOverview):
|
||||
|
||||
|
||||
class TestDomainOrganization(TestDomainOverview):
|
||||
def test_domain_org_name_address(self):
|
||||
"""Can load domain's org name and mailing address page."""
|
||||
page = self.client.get(
|
||||
|
@ -1459,9 +1468,9 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
|
||||
self.assertContains(success_result_page, "Not igorville")
|
||||
self.assertContains(success_result_page, "Faketown")
|
||||
|
||||
class TestDomainContactInformation(TestDomainOverview):
|
||||
|
||||
|
||||
class TestDomainContactInformation(TestDomainOverview):
|
||||
def test_domain_your_contact_information(self):
|
||||
"""Can load domain's your contact information page."""
|
||||
page = self.client.get(
|
||||
|
@ -1477,9 +1486,9 @@ class TestDomainContactInformation(TestDomainOverview):
|
|||
reverse("domain-your-contact-information", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertContains(page, "Testy")
|
||||
|
||||
class TestDomainSecurityEmail(TestDomainOverview):
|
||||
|
||||
|
||||
class TestDomainSecurityEmail(TestDomainOverview):
|
||||
def test_domain_security_email_existing_security_contact(self):
|
||||
"""Can load domain's security email page."""
|
||||
self.mockSendPatch = patch("registrar.models.domain.registry.send")
|
||||
|
@ -1544,47 +1553,50 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
self.assertContains(
|
||||
success_page, "The security email for this domain has been updated"
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
class TestDomainDNSSEC(TestDomainOverview):
|
||||
|
||||
|
||||
"""MockEPPLib is already inherited."""
|
||||
|
||||
|
||||
def test_dnssec_page_refreshes_enable_button(self):
|
||||
"""DNSSEC overview page loads when domain has no DNSSEC data
|
||||
and shows a 'Enable DNSSEC' button. When button is clicked the template
|
||||
updates. When user navigates away then comes back to the page, the
|
||||
'Enable DNSSEC' button is shown again."""
|
||||
# home_page = self.app.get("/")
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertContains(page, "Enable DNSSEC")
|
||||
|
||||
|
||||
# Prepare the data for the POST request
|
||||
post_data = {
|
||||
'enable_dnssec': 'Enable DNSSEC', # Replace with the actual form field and value
|
||||
# Add other form fields as needed
|
||||
"enable_dnssec": "Enable DNSSEC",
|
||||
}
|
||||
updated_page = self.client.post(reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}), post_data, follow=True)
|
||||
|
||||
updated_page = self.client.post(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}),
|
||||
post_data,
|
||||
follow=True,
|
||||
)
|
||||
|
||||
self.assertEqual(updated_page.status_code, 200)
|
||||
|
||||
|
||||
self.assertContains(updated_page, "Add DS Data")
|
||||
self.assertContains(updated_page, "Add Key Data")
|
||||
|
||||
|
||||
self.app.get("/")
|
||||
|
||||
|
||||
back_to_page = self.client.get(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertContains(back_to_page, "Enable DNSSEC")
|
||||
|
||||
|
||||
def test_dnssec_page_loads_with_data_in_domain(self):
|
||||
"""DNSSEC overview page loads when domain has DNSSEC data
|
||||
and the template contains a button to disable DNSSEC."""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain_multdsdata.id})
|
||||
)
|
||||
|
@ -1592,63 +1604,71 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
# Prepare the data for the POST request
|
||||
post_data = {
|
||||
'disable_dnssec': 'Disable DNSSEC', # Replace with the actual form field and value
|
||||
"disable_dnssec": "Disable DNSSEC",
|
||||
}
|
||||
updated_page = self.client.post(reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}), post_data, follow=True)
|
||||
|
||||
updated_page = self.client.post(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}),
|
||||
post_data,
|
||||
follow=True,
|
||||
)
|
||||
|
||||
self.assertEqual(updated_page.status_code, 200)
|
||||
|
||||
|
||||
self.assertContains(updated_page, "Enable DNSSEC")
|
||||
|
||||
|
||||
def test_ds_form_loads_with_no_domain_data(self):
|
||||
"""DNSSEC Add DS Data page loads when there is no
|
||||
domain DNSSEC data and shows a button to Add DS Data record"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dnssec_none.id})
|
||||
reverse(
|
||||
"domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dnssec_none.id}
|
||||
)
|
||||
)
|
||||
self.assertContains(page, "Add DS Data record")
|
||||
|
||||
|
||||
def test_ds_form_loads_with_ds_data(self):
|
||||
"""DNSSEC Add DS Data page loads when there is
|
||||
domain DNSSEC DS data and shows the data"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id})
|
||||
)
|
||||
self.assertContains(page, "DS Data record 1")
|
||||
|
||||
|
||||
def test_ds_form_loads_with_key_data(self):
|
||||
"""DNSSEC Add DS Data page loads when there is
|
||||
domain DNSSEC KEY data and shows an alert"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_keydata.id})
|
||||
)
|
||||
self.assertContains(page, "Warning, you cannot add DS Data")
|
||||
|
||||
|
||||
def test_key_form_loads_with_no_domain_data(self):
|
||||
"""DNSSEC Add Key Data page loads when there is no
|
||||
domain DNSSEC data and shows a button to Add DS Key record"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-keydata", kwargs={"pk": self.domain_dnssec_none.id})
|
||||
reverse(
|
||||
"domain-dns-dnssec-keydata", kwargs={"pk": self.domain_dnssec_none.id}
|
||||
)
|
||||
)
|
||||
self.assertContains(page, "Add DS Key record")
|
||||
|
||||
|
||||
def test_key_form_loads_with_key_data(self):
|
||||
"""DNSSEC Add Key Data page loads when there is
|
||||
domain DNSSEC Key data and shows the data"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-keydata", kwargs={"pk": self.domain_keydata.id})
|
||||
)
|
||||
self.assertContains(page, "DS Data record 1")
|
||||
|
||||
|
||||
def test_key_form_loads_with_ds_data(self):
|
||||
"""DNSSEC Add Key Data page loads when there is
|
||||
domain DNSSEC DS data and shows an alert"""
|
||||
|
||||
|
||||
page = self.client.get(
|
||||
reverse("domain-dns-dnssec-keydata", kwargs={"pk": self.domain_dsdata.id})
|
||||
)
|
||||
|
@ -1674,7 +1694,9 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
page = result.follow()
|
||||
self.assertContains(page, "The DS Data records for this domain have been updated.")
|
||||
self.assertContains(
|
||||
page, "The DS Data records for this domain have been updated."
|
||||
)
|
||||
|
||||
def test_ds_data_form_invalid(self):
|
||||
"""DS Data form errors with invalid data
|
||||
|
@ -1716,7 +1738,9 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
page = result.follow()
|
||||
self.assertContains(page, "The Key Data records for this domain have been updated.")
|
||||
self.assertContains(
|
||||
page, "The Key Data records for this domain have been updated."
|
||||
)
|
||||
|
||||
def test_key_data_form_invalid(self):
|
||||
"""Key Data form errors with invalid data
|
||||
|
@ -1737,8 +1761,8 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
# error text appears twice, once at the top of the page, once around
|
||||
# the field.
|
||||
self.assertContains(result, "Pub key is required", count=2, status_code=200)
|
||||
|
||||
|
||||
|
||||
|
||||
class TestApplicationStatus(TestWithUser, WebTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
|
|
|
@ -233,20 +233,24 @@ class DomainDNSSECView(DomainPermissionView, FormMixin):
|
|||
|
||||
template_name = "domain_dnssec.html"
|
||||
form_class = DomainDnssecForm
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
"""The initial value for the form (which is a formset here)."""
|
||||
self.domain = self.get_object()
|
||||
|
||||
has_dnssec_records = self.domain.dnssecdata is not None
|
||||
|
||||
# Create HTML for the modal button
|
||||
modal_button = '<button type="submit" class="usa-button" name="disable_dnssec">Disable DNSSEC</button>'
|
||||
|
||||
context['modal_button'] = modal_button
|
||||
context['has_dnssec_records'] = has_dnssec_records
|
||||
context['dnssec_enabled'] = self.request.session.pop('dnssec_enabled', False)
|
||||
has_dnssec_records = self.domain.dnssecdata is not None
|
||||
|
||||
# Create HTML for the modal button
|
||||
modal_button = (
|
||||
'<button type="submit" '
|
||||
'class="usa-button" '
|
||||
'name="disable_dnssec">Disable DNSSEC</button>'
|
||||
)
|
||||
|
||||
context["modal_button"] = modal_button
|
||||
context["has_dnssec_records"] = has_dnssec_records
|
||||
context["dnssec_enabled"] = self.request.session.pop("dnssec_enabled", False)
|
||||
|
||||
return context
|
||||
|
||||
|
@ -255,27 +259,24 @@ class DomainDNSSECView(DomainPermissionView, FormMixin):
|
|||
return reverse("domain-dns-dnssec", kwargs={"pk": self.domain.pk})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Form submission posts to this view.
|
||||
"""
|
||||
"""Form submission posts to this view."""
|
||||
self.domain = self.get_object()
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
if 'disable_dnssec' in request.POST:
|
||||
if form.is_valid():
|
||||
if "disable_dnssec" in request.POST:
|
||||
try:
|
||||
self.domain.dnssecdata = {}
|
||||
except RegistryError as err:
|
||||
errmsg = "Error removing existing DNSSEC record(s)."
|
||||
logger.error(errmsg + ": " + err)
|
||||
messages.error(
|
||||
self.request, errmsg
|
||||
)
|
||||
request.session['dnssec_ds_confirmed'] = False
|
||||
request.session['dnssec_key_confirmed'] = False
|
||||
elif 'enable_dnssec' in request.POST:
|
||||
request.session['dnssec_enabled'] = True
|
||||
request.session['dnssec_ds_confirmed'] = False
|
||||
request.session['dnssec_key_confirmed'] = False
|
||||
|
||||
messages.error(self.request, errmsg)
|
||||
request.session["dnssec_ds_confirmed"] = False
|
||||
request.session["dnssec_key_confirmed"] = False
|
||||
elif "enable_dnssec" in request.POST:
|
||||
request.session["dnssec_enabled"] = True
|
||||
request.session["dnssec_ds_confirmed"] = False
|
||||
request.session["dnssec_key_confirmed"] = False
|
||||
|
||||
return self.form_valid(form)
|
||||
|
||||
|
||||
|
@ -292,21 +293,28 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
domain = self.get_object()
|
||||
dnssecdata: extensions.DNSSECExtension = domain.dnssecdata
|
||||
initial_data = []
|
||||
|
||||
if dnssecdata is not None:
|
||||
|
||||
if dnssecdata is not None:
|
||||
if dnssecdata.keyData is not None:
|
||||
# TODO: Throw an error
|
||||
pass
|
||||
|
||||
if dnssecdata.dsData is not None:
|
||||
# Add existing nameservers as initial data
|
||||
initial_data.extend({"key_tag": record.keyTag, "algorithm": record.alg, "digest_type": record.digestType, "digest": record.digest} for record in dnssecdata.dsData)
|
||||
|
||||
initial_data.extend(
|
||||
{
|
||||
"key_tag": record.keyTag,
|
||||
"algorithm": record.alg,
|
||||
"digest_type": record.digestType,
|
||||
"digest": record.digest,
|
||||
}
|
||||
for record in dnssecdata.dsData
|
||||
)
|
||||
|
||||
# Ensure at least 3 fields, filled or empty
|
||||
while len(initial_data) == 0:
|
||||
initial_data.append({})
|
||||
|
||||
|
||||
return initial_data
|
||||
|
||||
def get_success_url(self):
|
||||
|
@ -319,16 +327,18 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
# use "formset" instead of "form" for the key
|
||||
context["formset"] = context.pop("form")
|
||||
|
||||
# set the dnssec_ds_confirmed flag in the context for this view
|
||||
# set the dnssec_ds_confirmed flag in the context for this view
|
||||
# based either on the existence of DS Data in the domain,
|
||||
# or on the flag stored in the session
|
||||
domain = self.get_object()
|
||||
dnssecdata: extensions.DNSSECExtension = domain.dnssecdata
|
||||
|
||||
if dnssecdata is not None and dnssecdata.dsData is not None:
|
||||
self.request.session['dnssec_ds_confirmed'] = True
|
||||
self.request.session["dnssec_ds_confirmed"] = True
|
||||
|
||||
context['dnssec_ds_confirmed'] = self.request.session.get('dnssec_ds_confirmed', False)
|
||||
context["dnssec_ds_confirmed"] = self.request.session.get(
|
||||
"dnssec_ds_confirmed", False
|
||||
)
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
@ -336,14 +346,14 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
self.object = self.get_object()
|
||||
formset = self.get_form()
|
||||
|
||||
if 'confirm-ds' in request.POST:
|
||||
request.session['dnssec_ds_confirmed'] = True
|
||||
request.session['dnssec_key_confirmed'] = False
|
||||
if "confirm-ds" in request.POST:
|
||||
request.session["dnssec_ds_confirmed"] = True
|
||||
request.session["dnssec_key_confirmed"] = False
|
||||
return super().form_valid(formset)
|
||||
|
||||
if 'btn-cancel-click' in request.POST:
|
||||
return redirect('/', {'formset': formset},RequestContext(request))
|
||||
|
||||
|
||||
if "btn-cancel-click" in request.POST:
|
||||
return redirect("/", {"formset": formset}, RequestContext(request))
|
||||
|
||||
if formset.is_valid():
|
||||
return self.form_valid(formset)
|
||||
else:
|
||||
|
@ -353,11 +363,12 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
"""The formset is valid, perform something with it."""
|
||||
|
||||
# Set the nameservers from the formset
|
||||
dnssecdata = {"dsData":[]}
|
||||
dnssecdata = {"dsData": []}
|
||||
|
||||
for form in formset:
|
||||
try:
|
||||
# if 'delete' not in form.cleaned_data or form.cleaned_data['delete'] == False:
|
||||
# if 'delete' not in form.cleaned_data
|
||||
# or form.cleaned_data['delete'] == False:
|
||||
dsrecord = {
|
||||
"keyTag": form.cleaned_data["key_tag"],
|
||||
"alg": form.cleaned_data["algorithm"],
|
||||
|
@ -378,9 +389,7 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
errmsg = "Error updating DNSSEC data in the registry."
|
||||
logger.error(errmsg)
|
||||
logger.error(err)
|
||||
messages.error(
|
||||
self.request, errmsg
|
||||
)
|
||||
messages.error(self.request, errmsg)
|
||||
return self.form_invalid(formset)
|
||||
else:
|
||||
messages.success(
|
||||
|
@ -388,7 +397,6 @@ class DomainDsdataView(DomainPermissionView, FormMixin):
|
|||
)
|
||||
# superclass has the redirect
|
||||
return super().form_valid(formset)
|
||||
|
||||
|
||||
|
||||
class DomainKeydataView(DomainPermissionView, FormMixin):
|
||||
|
@ -404,21 +412,28 @@ class DomainKeydataView(DomainPermissionView, FormMixin):
|
|||
domain = self.get_object()
|
||||
dnssecdata: extensions.DNSSECExtension = domain.dnssecdata
|
||||
initial_data = []
|
||||
|
||||
if dnssecdata is not None:
|
||||
|
||||
if dnssecdata is not None:
|
||||
if dnssecdata.dsData is not None:
|
||||
# TODO: Throw an error
|
||||
pass
|
||||
|
||||
if dnssecdata.keyData is not None:
|
||||
# Add existing keydata as initial data
|
||||
initial_data.extend({"flag": record.flags, "protocol": record.protocol, "algorithm": record.alg, "pub_key": record.pubKey} for record in dnssecdata.keyData)
|
||||
|
||||
initial_data.extend(
|
||||
{
|
||||
"flag": record.flags,
|
||||
"protocol": record.protocol,
|
||||
"algorithm": record.alg,
|
||||
"pub_key": record.pubKey,
|
||||
}
|
||||
for record in dnssecdata.keyData
|
||||
)
|
||||
|
||||
# Ensure at least 3 fields, filled or empty
|
||||
while len(initial_data) == 0:
|
||||
initial_data.append({})
|
||||
|
||||
|
||||
return initial_data
|
||||
|
||||
def get_success_url(self):
|
||||
|
@ -431,32 +446,34 @@ class DomainKeydataView(DomainPermissionView, FormMixin):
|
|||
# use "formset" instead of "form" for the key
|
||||
context["formset"] = context.pop("form")
|
||||
|
||||
# set the dnssec_key_confirmed flag in the context for this view
|
||||
# set the dnssec_key_confirmed flag in the context for this view
|
||||
# based either on the existence of Key Data in the domain,
|
||||
# or on the flag stored in the session
|
||||
domain = self.get_object()
|
||||
dnssecdata: extensions.DNSSECExtension = domain.dnssecdata
|
||||
|
||||
if dnssecdata is not None and dnssecdata.keyData is not None:
|
||||
self.request.session['dnssec_key_confirmed'] = True
|
||||
self.request.session["dnssec_key_confirmed"] = True
|
||||
|
||||
context['dnssec_key_confirmed'] = self.request.session.get('dnssec_key_confirmed', False)
|
||||
context["dnssec_key_confirmed"] = self.request.session.get(
|
||||
"dnssec_key_confirmed", False
|
||||
)
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Formset submission posts to this view."""
|
||||
self.object = self.get_object()
|
||||
formset = self.get_form()
|
||||
|
||||
if 'confirm-key' in request.POST:
|
||||
request.session['dnssec_key_confirmed'] = True
|
||||
request.session['dnssec_ds_confirmed'] = False
|
||||
|
||||
if "confirm-key" in request.POST:
|
||||
request.session["dnssec_key_confirmed"] = True
|
||||
request.session["dnssec_ds_confirmed"] = False
|
||||
self.object.save()
|
||||
return super().form_valid(formset)
|
||||
|
||||
if 'btn-cancel-click' in request.POST:
|
||||
return redirect('/', {'formset': formset},RequestContext(request))
|
||||
|
||||
|
||||
if "btn-cancel-click" in request.POST:
|
||||
return redirect("/", {"formset": formset}, RequestContext(request))
|
||||
|
||||
if formset.is_valid():
|
||||
return self.form_valid(formset)
|
||||
else:
|
||||
|
@ -466,11 +483,12 @@ class DomainKeydataView(DomainPermissionView, FormMixin):
|
|||
"""The formset is valid, perform something with it."""
|
||||
|
||||
# Set the nameservers from the formset
|
||||
dnssecdata = {"keyData":[]}
|
||||
dnssecdata = {"keyData": []}
|
||||
|
||||
for form in formset:
|
||||
try:
|
||||
# if 'delete' not in form.cleaned_data or form.cleaned_data['delete'] == False:
|
||||
# if 'delete' not in form.cleaned_data
|
||||
# or form.cleaned_data['delete'] == False:
|
||||
keyrecord = {
|
||||
"flags": form.cleaned_data["flag"],
|
||||
"protocol": form.cleaned_data["protocol"],
|
||||
|
@ -490,9 +508,7 @@ class DomainKeydataView(DomainPermissionView, FormMixin):
|
|||
errmsg = "Error updating DNSSEC data in the registry."
|
||||
logger.error(errmsg)
|
||||
logger.error(err)
|
||||
messages.error(
|
||||
self.request, errmsg
|
||||
)
|
||||
messages.error(self.request, errmsg)
|
||||
return self.form_invalid(formset)
|
||||
else:
|
||||
messages.success(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue