Implement domain security email page with stubs for EPP

This commit is contained in:
rachidatecs 2023-05-17 10:39:49 -04:00
parent c3f1fcba27
commit c01a0276e5
No known key found for this signature in database
GPG key ID: 3CEBBFA7325E5525
10 changed files with 143 additions and 3 deletions

View file

@ -83,6 +83,11 @@ urlpatterns = [
views.DomainNameserversView.as_view(), views.DomainNameserversView.as_view(),
name="domain-nameservers", name="domain-nameservers",
), ),
path(
"domain/<int:pk>/securityemail",
views.DomainSecurityEmailView.as_view(),
name="domain-security-email",
),
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, NameserverFormset from .domain import DomainAddUserForm, NameserverFormset, DomainSecurityEmailForm

View file

@ -22,3 +22,10 @@ NameserverFormset = formset_factory(
DomainNameserverForm, DomainNameserverForm,
extra=1, extra=1,
) )
class DomainSecurityEmailForm(forms.Form):
"""Form for adding or editing a security email to a domain."""
security_email = forms.EmailField(label="Security email")

View file

@ -235,6 +235,19 @@ class Domain(TimeStampedModel):
# nothing. # nothing.
logger.warn("TODO: Fake setting nameservers to %s", new_nameservers) logger.warn("TODO: Fake setting nameservers to %s", new_nameservers)
def security_email(self) -> str:
"""Get the security email for this domain.
TODO: call EPP to get this info instead of returning fake data.
"""
return "mayor@igorville.gov"
def set_security_email(self, new_security_email: str):
"""Set the security email for this domain."""
# TODO: call EPP to set these values in the registry instead of doing
# nothing.
logger.warn("TODO: Fake setting security email to %s", new_security_email)
@property @property
def roid(self): def roid(self):
return self._get_property("roid") return self._get_property("roid")

View file

@ -0,0 +1,27 @@
{% extends "domain_base.html" %}
{% load static field_helpers %}
{% block title %}Domain security email | {{ domain.name }} | {% endblock %}
{% block domain_content %}
<h1>Domain security email</h1>
<p>We strongly recommend that you provide a security email. This email will allow the public to report observed or suspected security issues on your domain. Security emails are made public and included in the <a href="https://federalist-877ab29f-16f6-4f12-961c-96cf064cf070.sites.pages.cloud.gov/site/cisagov/getgov-home/about/data/">.gov domain data</a> we provide.</p>
<p>A security contact should be capable of evaluating or triaging security reports for your entire domain. Use a team email address, not an individuals email. We recommend using an alias, like security@domain.gov.</p>
{% include "includes/required_fields.html" %}
<form class="usa-form usa-form--large" method="post" novalidate>
{% csrf_token %}
{% input_with_errors form.security_email %}
<button
type="submit"
class="usa-button"
>Add security email</button>
</form>
{% endblock %} {# domain_content #}

View file

@ -40,7 +40,7 @@
</li> </li>
<li class="usa-sidenav__item"> <li class="usa-sidenav__item">
{% url 'todo' as url %} {% url 'domain-security-email' 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

@ -1063,6 +1063,11 @@ class TestDomainPermissions(TestWithDomainPermissions):
) )
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
response = self.client.get(
reverse("domain-security-email", 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)
@ -1282,6 +1287,38 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
# the field. # the field.
self.assertContains(result, "This field is required", count=2, status_code=200) self.assertContains(result, "This field is required", count=2, status_code=200)
def test_domain_security_email(self):
"""Can load domain's security email page."""
page = self.client.get(
reverse("domain-security-email", kwargs={"pk": self.domain.id})
)
self.assertContains(page, "Domain security email")
def test_domain_security_email_form(self):
"""Adding a security email works.
Uses self.app WebTest because we need to interact with forms.
"""
security_email_page = self.app.get(
reverse("domain-security-email", kwargs={"pk": self.domain.id})
)
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
security_email_page.form["security_email"] = "mayor@igorville.gov"
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
with less_console_noise(): # swallow log warning message
result = security_email_page.form.submit()
self.assertEqual(result.status_code, 302)
self.assertEqual(
result["Location"],
reverse("domain-security-email", kwargs={"pk": self.domain.id}),
)
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
success_page = result.follow()
self.assertContains(
success_page, "The security email for this domain have been updated"
)
class TestApplicationStatus(TestWithUser, WebTest): class TestApplicationStatus(TestWithUser, WebTest):
def setUp(self): def setUp(self):

View file

@ -2,6 +2,7 @@ from .application import *
from .domain import ( from .domain import (
DomainView, DomainView,
DomainNameserversView, DomainNameserversView,
DomainSecurityEmailView,
DomainUsersView, DomainUsersView,
DomainAddUserView, DomainAddUserView,
DomainInvitationDeleteView, DomainInvitationDeleteView,

View file

@ -12,7 +12,7 @@ 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, NameserverFormset from ..forms import DomainAddUserForm, NameserverFormset, DomainSecurityEmailForm
from ..utility.email import send_templated_email, EmailSendingError from ..utility.email import send_templated_email, EmailSendingError
from .utility import DomainPermission from .utility import DomainPermission
@ -96,6 +96,55 @@ class DomainNameserversView(DomainPermission, FormMixin, DetailView):
return super().form_valid(formset) return super().form_valid(formset)
class DomainSecurityEmailView(DomainPermission, FormMixin, DetailView):
"""Domain security email editing view."""
model = Domain
template_name = "domain_security_email.html"
context_object_name = "domain"
form_class = DomainSecurityEmailForm
def get_initial(self):
"""The initial value for the form."""
domain = self.get_object()
initial = super().get_initial()
initial["security_email"] = domain.security_email()
return initial
def get_success_url(self):
"""Redirect to the overview page for the domain."""
return reverse("domain-security-email", kwargs={"pk": self.object.pk})
def post(self, request, *args, **kwargs):
"""Formset submission posts to this view."""
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
# there is a valid email address in the form
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
"""The form is valid, call setter in model."""
# Set the security email from the from
try:
new_email = form.cleaned_data["security_email"]
except KeyError:
# no server information in this field, skip it
pass
domain = self.get_object()
domain.set_security_email(new_email)
messages.success(
self.request, "The security email for this domain have been updated"
)
# superclass has the redirect
return redirect(self.get_success_url())
class DomainUsersView(DomainPermission, DetailView): class DomainUsersView(DomainPermission, DetailView):
"""User management page in the domain details.""" """User management page in the domain details."""

View file

@ -52,6 +52,7 @@
10038 OUTOFSCOPE http://app:8080/users 10038 OUTOFSCOPE http://app:8080/users
10038 OUTOFSCOPE http://app:8080/users/add 10038 OUTOFSCOPE http://app:8080/users/add
10038 OUTOFSCOPE http://app:8080/nameservers 10038 OUTOFSCOPE http://app:8080/nameservers
10038 OUTOFSCOPE http://app:8080/securityemail
10038 OUTOFSCOPE http://app:8080/delete 10038 OUTOFSCOPE http://app:8080/delete
10038 OUTOFSCOPE http://app:8080/withdraw 10038 OUTOFSCOPE http://app:8080/withdraw
10038 OUTOFSCOPE http://app:8080/withdrawconfirmed 10038 OUTOFSCOPE http://app:8080/withdrawconfirmed