Update domain namerservers form

This commit is contained in:
Neil Martinsen-Burrell 2023-04-25 12:19:28 -05:00
parent 2c0dac98b5
commit 6e9a8c8792
No known key found for this signature in database
GPG key ID: 6A3C818CC10D0184
9 changed files with 149 additions and 3 deletions

View file

@ -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(),

View file

@ -1,2 +1,2 @@
from .application_wizard import * from .application_wizard import *
from .domain import DomainAddUserForm from .domain import DomainAddUserForm, DomainNameserverForm

View file

@ -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")

View file

@ -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")

View 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 #}

View file

@ -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 %}
> >

View file

@ -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):

View file

@ -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,

View file

@ -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."""