mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-22 01:01:08 +02:00
Update domain namerservers form
This commit is contained in:
parent
2c0dac98b5
commit
6e9a8c8792
9 changed files with 149 additions and 3 deletions
|
@ -78,6 +78,11 @@ urlpatterns = [
|
||||||
),
|
),
|
||||||
path("domain/<int:pk>", views.DomainView.as_view(), name="domain"),
|
path("domain/<int:pk>", views.DomainView.as_view(), name="domain"),
|
||||||
path("domain/<int:pk>/users", views.DomainUsersView.as_view(), name="domain-users"),
|
path("domain/<int:pk>/users", views.DomainUsersView.as_view(), name="domain-users"),
|
||||||
|
path(
|
||||||
|
"domain/<int:pk>/nameservers",
|
||||||
|
views.DomainNameserversView.as_view(),
|
||||||
|
name="domain-nameservers",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"domain/<int:pk>/users/add",
|
"domain/<int:pk>/users/add",
|
||||||
views.DomainAddUserView.as_view(),
|
views.DomainAddUserView.as_view(),
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
from .application_wizard import *
|
from .application_wizard import *
|
||||||
from .domain import DomainAddUserForm
|
from .domain import DomainAddUserForm, DomainNameserverForm
|
||||||
|
|
|
@ -8,3 +8,10 @@ class DomainAddUserForm(forms.Form):
|
||||||
"""Form for adding a user to a domain."""
|
"""Form for adding a user to a domain."""
|
||||||
|
|
||||||
email = forms.EmailField(label="Email")
|
email = forms.EmailField(label="Email")
|
||||||
|
|
||||||
|
|
||||||
|
class DomainNameserverForm(forms.Form):
|
||||||
|
|
||||||
|
"""Form for changing nameservers."""
|
||||||
|
|
||||||
|
server = forms.CharField(label="Name server")
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
@ -216,6 +218,24 @@ class Domain(TimeStampedModel):
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def nameservers(self):
|
||||||
|
"""A list of the nameservers for this domain.
|
||||||
|
|
||||||
|
TODO: call EPP to get this info instead of returning fake data.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
# reserved example IPs
|
||||||
|
"192.0.2.1",
|
||||||
|
"198.51.100.2",
|
||||||
|
"203.0.113.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
def set_nameservers(self, new_nameservers: List[str]):
|
||||||
|
"""Set the nameservers for this domain."""
|
||||||
|
# TODO: call EPP to set these values in the registry instead of doing
|
||||||
|
# nothing.
|
||||||
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def roid(self):
|
def roid(self):
|
||||||
return self._get_property("roid")
|
return self._get_property("roid")
|
||||||
|
|
23
src/registrar/templates/domain_nameservers.html
Normal file
23
src/registrar/templates/domain_nameservers.html
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{% extends "domain_base.html" %}
|
||||||
|
{% load static field_helpers%}
|
||||||
|
|
||||||
|
{% block title %}Domain name servers | {{ domain.name }} | {% endblock %}
|
||||||
|
|
||||||
|
{% block domain_content %}
|
||||||
|
<h1>Domain name servers</h1>
|
||||||
|
|
||||||
|
<form class="usa-form usa-form--large" method="post" novalidate>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ formset.management_form }}
|
||||||
|
|
||||||
|
{% for form in formset %}
|
||||||
|
{% input_with_errors form.server %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="usa-button"
|
||||||
|
>Save</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% endblock %} {# domain_content #}
|
|
@ -13,7 +13,7 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="usa-sidenav__item">
|
<li class="usa-sidenav__item">
|
||||||
{% url 'todo' as url %}
|
{% url 'domain-nameservers' pk=domain.id as url %}
|
||||||
<a href="{{ url }}"
|
<a href="{{ url }}"
|
||||||
{% if request.path == url %}class="usa-current"{% endif %}
|
{% if request.path == url %}class="usa-current"{% endif %}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1058,6 +1058,11 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("domain-nameservers", kwargs={"pk": self.domain.id})
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
def test_no_domain_role(self):
|
def test_no_domain_role(self):
|
||||||
"""Logged in but no role gets 403 Forbidden."""
|
"""Logged in but no role gets 403 Forbidden."""
|
||||||
self.client.force_login(self.user)
|
self.client.force_login(self.user)
|
||||||
|
@ -1079,6 +1084,12 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
with less_console_noise():
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("domain-nameservers", kwargs={"pk": self.domain.id})
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
|
|
||||||
class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -1222,6 +1233,13 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
||||||
home_page = self.app.get(reverse("home"))
|
home_page = self.app.get(reverse("home"))
|
||||||
self.assertContains(home_page, self.domain.name)
|
self.assertContains(home_page, self.domain.name)
|
||||||
|
|
||||||
|
def test_domain_nameservers(self):
|
||||||
|
"""Can load domain's namerservers page."""
|
||||||
|
page = self.client.get(
|
||||||
|
reverse("domain-nameservers", kwargs={"pk": self.domain.id})
|
||||||
|
)
|
||||||
|
self.assertContains(page, "Domain name servers")
|
||||||
|
|
||||||
|
|
||||||
class TestApplicationStatus(TestWithUser, WebTest):
|
class TestApplicationStatus(TestWithUser, WebTest):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from .application import *
|
from .application import *
|
||||||
from .domain import (
|
from .domain import (
|
||||||
DomainView,
|
DomainView,
|
||||||
|
DomainNameserversView,
|
||||||
DomainUsersView,
|
DomainUsersView,
|
||||||
DomainAddUserView,
|
DomainAddUserView,
|
||||||
DomainInvitationDeleteView,
|
DomainInvitationDeleteView,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import logging
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
|
from django.forms import formset_factory
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.views.generic import DetailView
|
from django.views.generic import DetailView
|
||||||
|
@ -12,13 +13,15 @@ from django.views.generic.edit import DeleteView, FormMixin
|
||||||
|
|
||||||
from registrar.models import Domain, DomainInvitation, User, UserDomainRole
|
from registrar.models import Domain, DomainInvitation, User, UserDomainRole
|
||||||
|
|
||||||
from ..forms import DomainAddUserForm
|
from ..forms import DomainAddUserForm, DomainNameserverForm
|
||||||
from ..utility.email import send_templated_email, EmailSendingError
|
from ..utility.email import send_templated_email, EmailSendingError
|
||||||
from .utility import DomainPermission
|
from .utility import DomainPermission
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
NameserverFormset = formset_factory(DomainNameserverForm)
|
||||||
|
|
||||||
|
|
||||||
class DomainView(DomainPermission, DetailView):
|
class DomainView(DomainPermission, DetailView):
|
||||||
|
|
||||||
|
@ -29,6 +32,75 @@ class DomainView(DomainPermission, DetailView):
|
||||||
context_object_name = "domain"
|
context_object_name = "domain"
|
||||||
|
|
||||||
|
|
||||||
|
class DomainNameserversView(DomainPermission, FormMixin, DetailView):
|
||||||
|
|
||||||
|
"""Domain nameserver editing view."""
|
||||||
|
|
||||||
|
model = Domain
|
||||||
|
template_name = "domain_nameservers.html"
|
||||||
|
context_object_name = "domain"
|
||||||
|
form_class = NameserverFormset
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
"""The initial value for the form (which is a formset here)."""
|
||||||
|
domain = self.get_object()
|
||||||
|
return [{"server": server} for server in domain.nameservers()]
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
"""Redirect to the overview page for the domain."""
|
||||||
|
return reverse("domain-nameservers", kwargs={"pk": self.object.pk})
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
"""Adjust context from FormMixin for formsets."""
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
# use "formset" instead of "form" for the key
|
||||||
|
context["formset"] = context.pop("form")
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_form(self, **kwargs):
|
||||||
|
"""Override the labels and required fields every time we get a formset."""
|
||||||
|
formset = super().get_form(**kwargs)
|
||||||
|
for i, form in enumerate(formset):
|
||||||
|
form.fields["server"].label += f" {i+1}"
|
||||||
|
if i < 2:
|
||||||
|
form.fields["server"].required = True
|
||||||
|
else:
|
||||||
|
form.fields["server"].required = False
|
||||||
|
return formset
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
"""Formset submission posts to this view."""
|
||||||
|
self.object = self.get_object()
|
||||||
|
formset = self.get_form()
|
||||||
|
print([form.fields["server"].required for form in formset])
|
||||||
|
if formset.is_valid():
|
||||||
|
return self.form_valid(formset)
|
||||||
|
else:
|
||||||
|
return self.form_invalid(formset)
|
||||||
|
|
||||||
|
def form_valid(self, formset):
|
||||||
|
"""The formset is valid, perform something with it."""
|
||||||
|
|
||||||
|
# Set the nameservers from the formset
|
||||||
|
nameservers = []
|
||||||
|
for form in formset:
|
||||||
|
print(form.cleaned_data)
|
||||||
|
try:
|
||||||
|
nameservers.append(form.cleaned_data["server"])
|
||||||
|
except KeyError:
|
||||||
|
# no server information in this field, skip it
|
||||||
|
pass
|
||||||
|
print("Valid form, got nameservers:", nameservers)
|
||||||
|
domain = self.get_object()
|
||||||
|
domain.set_nameservers(nameservers)
|
||||||
|
|
||||||
|
messages.success(
|
||||||
|
self.request, "The name servers for this domain have been updated"
|
||||||
|
)
|
||||||
|
# superclass has the redirect
|
||||||
|
return super().form_valid(formset)
|
||||||
|
|
||||||
|
|
||||||
class DomainUsersView(DomainPermission, DetailView):
|
class DomainUsersView(DomainPermission, DetailView):
|
||||||
|
|
||||||
"""User management page in the domain details."""
|
"""User management page in the domain details."""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue