mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-02 07:52:15 +02:00
Merge branch 'main' into sspj/domain-interface
This commit is contained in:
commit
66640ebafb
345 changed files with 350 additions and 19266 deletions
|
@ -23,8 +23,10 @@ requests = "*"
|
|||
django-fsm = "*"
|
||||
django-phonenumber-field = {extras = ["phonenumberslite"], version = "*"}
|
||||
boto3 = "*"
|
||||
typing-extensions ='*'
|
||||
fred-epplib = {git = "https://github.com/cisagov/epplib.git", ref = "master"}
|
||||
|
||||
|
||||
[dev-packages]
|
||||
django-debug-toolbar = "*"
|
||||
nplusone = "*"
|
||||
|
|
42
src/Pipfile.lock
generated
42
src/Pipfile.lock
generated
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "14b5ea3c520cf927e27ae76936802a586dc0ff78e91fefdeb71125a2a320c301"
|
||||
"sha256": "fd7d0efa9a87dfe4b2bb228ee0e7978fba16c7cfdd3c443870900cfe899e2cfd"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
|
@ -24,19 +24,19 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:2eb9e688aa86bf1fadcec0b6995b42ec9788e7cd5f1a9c8ac1b66a2506aa209f",
|
||||
"sha256:5b7e9f2674fe8aa99e2d168744023a3f66da12d9c51e0624489dd0db7aafe30d"
|
||||
"sha256:30f8ab1cf89d5864a80ba2d5eb5316dbd2a63c9469877e0cffb522630438aa85",
|
||||
"sha256:77e8fa7c257f9ed8bfe0c3ffc2ccc47b1cfa27058f99415b6003699d1202e0c0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.144"
|
||||
"version": "==1.26.145"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:c60b9158cbc7447411abdec77b87a71d86d9404064702e92d317dca6a1ec9a5b",
|
||||
"sha256:e2b970e68643cf4752cad4e45ba3319fc35707f1bff7f150f7ffcac1b1427b47"
|
||||
"sha256:264a3f19ed280d80711b7e278be09acff7ed379a96432fdf179b4e6e3a687e6a",
|
||||
"sha256:65e2a2b1cc70583225f87d6d63736215f93c6234721967bdab872270ba7a1f45"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.29.144"
|
||||
"version": "==1.29.145"
|
||||
},
|
||||
"cachetools": {
|
||||
"hashes": [
|
||||
|
@ -794,7 +794,7 @@
|
|||
"sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c",
|
||||
"sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"
|
||||
],
|
||||
"markers": "python_version < '3.11'",
|
||||
"index": "pypi",
|
||||
"version": "==4.6.2"
|
||||
},
|
||||
"urllib3": {
|
||||
|
@ -880,11 +880,11 @@
|
|||
},
|
||||
"boto3": {
|
||||
"hashes": [
|
||||
"sha256:2eb9e688aa86bf1fadcec0b6995b42ec9788e7cd5f1a9c8ac1b66a2506aa209f",
|
||||
"sha256:5b7e9f2674fe8aa99e2d168744023a3f66da12d9c51e0624489dd0db7aafe30d"
|
||||
"sha256:30f8ab1cf89d5864a80ba2d5eb5316dbd2a63c9469877e0cffb522630438aa85",
|
||||
"sha256:77e8fa7c257f9ed8bfe0c3ffc2ccc47b1cfa27058f99415b6003699d1202e0c0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.144"
|
||||
"version": "==1.26.145"
|
||||
},
|
||||
"boto3-mocking": {
|
||||
"hashes": [
|
||||
|
@ -896,27 +896,27 @@
|
|||
},
|
||||
"boto3-stubs": {
|
||||
"hashes": [
|
||||
"sha256:1062612f63f154f47a4f5b7b40c2cb15debe5f44774587110da76fd292f528f0",
|
||||
"sha256:bc0cc5067f55b2da628db8a73119ecccd74b27cf424af83e56526cd90beaf9f8"
|
||||
"sha256:9413cb395c803d5b85e9ec7b16fba855a613ecd78b2e0011e2f6b62cf0b4fc1e",
|
||||
"sha256:be2007f92138781288c7a22eba30b7d60742466fc28edd04637b31fabee854a5"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.26.144"
|
||||
"version": "==1.26.145"
|
||||
},
|
||||
"botocore": {
|
||||
"hashes": [
|
||||
"sha256:c60b9158cbc7447411abdec77b87a71d86d9404064702e92d317dca6a1ec9a5b",
|
||||
"sha256:e2b970e68643cf4752cad4e45ba3319fc35707f1bff7f150f7ffcac1b1427b47"
|
||||
"sha256:264a3f19ed280d80711b7e278be09acff7ed379a96432fdf179b4e6e3a687e6a",
|
||||
"sha256:65e2a2b1cc70583225f87d6d63736215f93c6234721967bdab872270ba7a1f45"
|
||||
],
|
||||
"markers": "python_version >= '3.7'",
|
||||
"version": "==1.29.144"
|
||||
"version": "==1.29.145"
|
||||
},
|
||||
"botocore-stubs": {
|
||||
"hashes": [
|
||||
"sha256:b9db32981b4deefb01784d9b196afeaca7df6f6f185d8ba7f96c02b1c3bc0d90",
|
||||
"sha256:d456543af79fbdd23df76a2d7a7525cd672b4bb5b057d7e060bc117d9af71694"
|
||||
"sha256:80ffab72ad428d20cb1cf538ee55fcd94f7d81315b77d84fec99e218c3974e8b",
|
||||
"sha256:928c58a434dd83bef956e3b5bb1e96278fff5eee9f8b8ab08d916cef1e9a2014"
|
||||
],
|
||||
"markers": "python_version >= '3.7' and python_version < '4.0'",
|
||||
"version": "==1.29.144"
|
||||
"version": "==1.29.145"
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
|
@ -1309,7 +1309,7 @@
|
|||
"sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c",
|
||||
"sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"
|
||||
],
|
||||
"markers": "python_version < '3.11'",
|
||||
"index": "pypi",
|
||||
"version": "==4.6.2"
|
||||
},
|
||||
"urllib3": {
|
||||
|
|
|
@ -27,6 +27,8 @@ services:
|
|||
- DJANGO_DEBUG=True
|
||||
# Tell Django where it is being hosted
|
||||
- DJANGO_BASE_URL=http://localhost:8080
|
||||
# Public site URL link
|
||||
- GETGOV_PUBLIC_SITE_URL=https://beta.get.gov
|
||||
# Set a username for accessing the registry
|
||||
- REGISTRY_CL_ID=nothing
|
||||
# Set a password for accessing the registry
|
||||
|
|
|
@ -77,6 +77,7 @@ h2 {
|
|||
font-weight: font-weight('semibold');
|
||||
line-height: line-height('heading', 3);
|
||||
margin: units(4) 0 units(1);
|
||||
color: color('primary-darker');
|
||||
}
|
||||
|
||||
.register-form-step > h1 {
|
||||
|
@ -431,4 +432,4 @@ abbr[title] {
|
|||
@include at-media('tablet') {
|
||||
height: units('mobile');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,8 @@ secret_registry_key = b64decode(secret("REGISTRY_KEY", ""))
|
|||
secret_registry_key_passphrase = secret("REGISTRY_KEY_PASSPHRASE", "")
|
||||
secret_registry_hostname = secret("REGISTRY_HOSTNAME")
|
||||
|
||||
secret_getgov_public_site_url = secret("GETGOV_PUBLIC_SITE_URL", "")
|
||||
|
||||
# region: Basic Django Config-----------------------------------------------###
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / "subdir".
|
||||
|
@ -505,6 +507,10 @@ ROOT_URLCONF = "registrar.config.urls"
|
|||
# Must be relative and end with "/"
|
||||
STATIC_URL = "public/"
|
||||
|
||||
# Base URL of our separate static public website. Used by the
|
||||
# {% public_site_url subdir/path %} template tag
|
||||
GETGOV_PUBLIC_SITE_URL = secret_getgov_public_site_url
|
||||
|
||||
# endregion
|
||||
# region: Registry----------------------------------------------------------###
|
||||
|
||||
|
|
|
@ -88,6 +88,11 @@ urlpatterns = [
|
|||
views.DomainYourContactInformationView.as_view(),
|
||||
name="domain-your-contact-information",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/authorizing-official",
|
||||
views.DomainAuthorizingOfficialView.as_view(),
|
||||
name="domain-authorizing-official",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/security-email",
|
||||
views.DomainSecurityEmailView.as_view(),
|
||||
|
|
|
@ -28,13 +28,6 @@ NameserverFormset = formset_factory(
|
|||
)
|
||||
|
||||
|
||||
class DomainSecurityEmailForm(forms.Form):
|
||||
|
||||
"""Form for adding or editing a security email to a domain."""
|
||||
|
||||
security_email = forms.EmailField(label="Security email")
|
||||
|
||||
|
||||
class ContactForm(forms.ModelForm):
|
||||
|
||||
"""Form for updating contacts."""
|
||||
|
@ -59,8 +52,15 @@ class ContactForm(forms.ModelForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# take off maxlength attribute for the phone number field
|
||||
# which interferes with our input_with_errors template tag
|
||||
# which interferes with out input_with_errors template tag
|
||||
self.fields["phone"].widget.attrs.pop("maxlength", None)
|
||||
|
||||
for field_name in self.required:
|
||||
self.fields[field_name].required = True
|
||||
|
||||
|
||||
class DomainSecurityEmailForm(forms.Form):
|
||||
|
||||
"""Form for adding or editing a security email to a domain."""
|
||||
|
||||
security_email = forms.EmailField(label="Security email")
|
||||
|
|
19
src/registrar/migrations/0024_alter_contact_email.py
Normal file
19
src/registrar/migrations/0024_alter_contact_email.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.1 on 2023-06-01 19:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("registrar", "0023_alter_contact_first_name_alter_contact_last_name_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="contact",
|
||||
name="email",
|
||||
field=models.EmailField(
|
||||
blank=True, db_index=True, help_text="Email", max_length=254, null=True
|
||||
),
|
||||
),
|
||||
]
|
|
@ -41,7 +41,7 @@ class Contact(TimeStampedModel):
|
|||
help_text="Title",
|
||||
verbose_name="title or role in your organization",
|
||||
)
|
||||
email = models.TextField(
|
||||
email = models.EmailField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="Email",
|
||||
|
|
|
@ -562,11 +562,13 @@ class DomainApplication(TimeStampedModel):
|
|||
"""Show this step if the answer to the first question implies it.
|
||||
|
||||
This shows for answers that aren't "Federal" or "Interstate".
|
||||
This also doesnt show if user selected "School District" as well (#524)
|
||||
"""
|
||||
user_choice = self.organization_type
|
||||
excluded = [
|
||||
DomainApplication.OrganizationChoices.FEDERAL,
|
||||
DomainApplication.OrganizationChoices.INTERSTATE,
|
||||
DomainApplication.OrganizationChoices.SCHOOL_DISTRICT,
|
||||
]
|
||||
return bool(user_choice and user_choice not in excluded)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends 'application_form.html' %}
|
||||
{% load field_helpers %}
|
||||
{% load field_helpers url_helpers %}
|
||||
|
||||
{% block form_instructions %}
|
||||
<p>.Gov domain names are for use on the internet. Don’t register a .gov to simply reserve a
|
||||
|
@ -8,7 +8,7 @@ domain name or for mainly internal use.</p>
|
|||
<p>Describe the reason for your domain request. Explain how you plan to use this domain.
|
||||
Who is your intended audience? Will you use it for a website and/or email? Are you moving
|
||||
your website from another top-level domain (like .com or .org)?
|
||||
Read about <a href="{% url 'todo' %}">activities that are prohibited on .gov domains.</a></p>
|
||||
Read about <a href="{% public_site_url 'domains/requirements/' %}">activities that are prohibited on .gov domains.</a></p>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
43
src/registrar/templates/domain_authorizing_official.html
Normal file
43
src/registrar/templates/domain_authorizing_official.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
{% extends "domain_base.html" %}
|
||||
{% load static field_helpers%}
|
||||
|
||||
{% block title %}Domain authorizing official | {{ domain.name }} | {% endblock %}
|
||||
|
||||
{% block domain_content %}
|
||||
{# this is right after the messages block in the parent template #}
|
||||
{% include "includes/form_errors.html" with form=form %}
|
||||
|
||||
<h1>Authorizing official</h1>
|
||||
|
||||
<p>Your authorizing official is the person within your organization who can
|
||||
authorize domain requests. This is generally the highest-ranking or
|
||||
highest-elected official in your organization. <a class="usa-link"
|
||||
href="https://federalist-877ab29f-16f6-4f12-961c-96cf064cf070.sites.pages.cloud.gov/site/cisagov/getgov-home/domains/eligibility/#you-must-have-approval-from-an-authorizing-official-within-your-organization">Read more about who can serve
|
||||
as an authorizing official.</a></p>
|
||||
|
||||
{% include "includes/required_fields.html" %}
|
||||
|
||||
<form class="usa-form usa-form--large" method="post" novalidate id="form-container">
|
||||
{% csrf_token %}
|
||||
|
||||
{% input_with_errors form.first_name %}
|
||||
|
||||
{% input_with_errors form.middle_name %}
|
||||
|
||||
{% input_with_errors form.last_name %}
|
||||
|
||||
{% input_with_errors form.title %}
|
||||
|
||||
{% input_with_errors form.email %}
|
||||
|
||||
{% input_with_errors form.phone %}
|
||||
|
||||
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="usa-button"
|
||||
>Save</button>
|
||||
</form>
|
||||
|
||||
{% endblock %} {# domain_content #}
|
|
@ -1,6 +1,33 @@
|
|||
{% extends "domain_base.html" %}
|
||||
{% load static url_helpers %}
|
||||
|
||||
{% block domain_content %}
|
||||
{{ block.super }}
|
||||
<p>Active: {% if domain.is_active %}Yes{% else %}No{% endif %}</p>
|
||||
<div class="margin-top-4 tablet:grid-col-10">
|
||||
|
||||
{% url 'domain-nameservers' pk=domain.id as url %}
|
||||
{% if domain.nameservers %}
|
||||
{% include "includes/summary_item.html" with title='DNS name servers' value=domain.nameservers list='true' edit_link=url %}
|
||||
{% else %}
|
||||
<h2 class="margin-top-neg-1"> DNS name servers </h2>
|
||||
<p> No DNS name servers have been added yet. Before your domain can be used we’ll need information about your domain name servers.</p>
|
||||
<a class="usa-button margin-bottom-1" href="{{url}}"> Add DNS name servers </a>
|
||||
{% endif %}
|
||||
|
||||
{% url 'todo' as url %}
|
||||
{% include "includes/summary_item.html" with title='Organization name and mailing address' value=domain.domain_info address='true' edit_link=url %}
|
||||
|
||||
{% url 'domain-authorizing-official' pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Authorizing official' value=domain.domain_info.authorizing_official contact='true' edit_link=url %}
|
||||
|
||||
{% url 'domain-your-contact-information' pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Your contact information' value=request.user.contact contact='true' edit_link=url %}
|
||||
|
||||
{% url 'domain-security-email' pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Security email' value=domain.security_email edit_link=url %}
|
||||
|
||||
{% url 'domain-users' pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='User management' users='true' list=True value=domain.permissions.all edit_link=url %}
|
||||
|
||||
</div>
|
||||
{% endblock %} {# domain_content #}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<a href="{{ url }}"
|
||||
{% if request.path == url %}class="usa-current"{% endif %}
|
||||
>
|
||||
Domain Overview
|
||||
Domain overview
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
</li>
|
||||
|
||||
<li class="usa-sidenav__item">
|
||||
{% url 'todo' as url %}
|
||||
{% url 'domain-authorizing-official' pk=domain.id as url %}
|
||||
<a href="{{ url }}"
|
||||
{% if request.path == url %}class="usa-current"{% endif %}
|
||||
>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
{% load static url_helpers %}
|
||||
|
||||
<section class="summary-item margin-top-3">
|
||||
<hr class="" />
|
||||
<p class="summary-item__title
|
||||
<hr class="" aria-hidden="true" />
|
||||
<h2 class="summary-item__title
|
||||
text-primary-dark text-semibold
|
||||
margin-top-0 margin-bottom-05"
|
||||
>
|
||||
{{ title }}
|
||||
</p>
|
||||
>
|
||||
{{ title }}
|
||||
</h2>
|
||||
{% if address %}
|
||||
{% include "includes/organization_address.html" with organization=value %}
|
||||
{% elif contact %}
|
||||
|
@ -30,11 +32,19 @@
|
|||
{% endif %}
|
||||
{% elif list %}
|
||||
{% if value|length == 1 %}
|
||||
<p class="margin-top-0">{{ value | first }} </p>
|
||||
{% if users %}
|
||||
<p class="margin-top-0">{{ value.0.user.email }} </p>
|
||||
{% else %}
|
||||
<p class="margin-top-0">{{ value | first }} </p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<ul class="usa-list margin-top-0">
|
||||
{% for item in value %}
|
||||
<li>{{ item }}</li>
|
||||
{% if users %}
|
||||
<li>{{ item.user.email }}</li>
|
||||
{% else %}
|
||||
<li>{{ item }}</li>
|
||||
{% endif %}
|
||||
{% empty %}
|
||||
<li>None</li>
|
||||
{% endfor %}</ul></p>
|
||||
|
@ -45,5 +55,13 @@
|
|||
{{ value }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if edit_link %}
|
||||
<a
|
||||
href="{{ edit_link }}"
|
||||
>
|
||||
Edit<span class="sr-only"> {{ title }}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
</section>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
from django import template
|
||||
from django.urls import reverse
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
|
@ -15,3 +17,16 @@ def startswith(text, starts):
|
|||
if isinstance(text, str):
|
||||
return text.startswith(starts)
|
||||
return False
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def public_site_url(url_path):
|
||||
"""Make a full URL for this path at our public site.
|
||||
|
||||
The public site base url is set by a GETGOV_PUBLIC_SITE_URL environment
|
||||
variable.
|
||||
"""
|
||||
base_url = settings.GETGOV_PUBLIC_SITE_URL
|
||||
# join the two halves with a single slash
|
||||
public_url = "/".join([base_url.rstrip("/"), url_path.lstrip("/")])
|
||||
return public_url
|
||||
|
|
|
@ -15,6 +15,7 @@ from registrar.forms.application_wizard import (
|
|||
AnythingElseForm,
|
||||
TypeOfWorkForm,
|
||||
)
|
||||
from registrar.forms.domain import ContactForm
|
||||
|
||||
|
||||
class TestFormValidation(TestCase):
|
||||
|
@ -277,3 +278,13 @@ class TestFormValidation(TestCase):
|
|||
for error in form.non_field_errors()
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class TestContactForm(TestCase):
|
||||
def test_contact_form_email_invalid(self):
|
||||
form = ContactForm(data={"email": "example.net"})
|
||||
self.assertEqual(form.errors["email"], ["Enter a valid email address."])
|
||||
|
||||
def test_contact_form_email_invalid2(self):
|
||||
form = ContactForm(data={"email": "@"})
|
||||
self.assertEqual(form.errors["email"], ["Enter a valid email address."])
|
||||
|
|
31
src/registrar/tests/test_templatetags.py
Normal file
31
src/registrar/tests/test_templatetags.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
"""Test template tags."""
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.template import Context, Template
|
||||
|
||||
|
||||
class TestTemplateTags(TestCase):
|
||||
def _render_template(self, string, context=None):
|
||||
"""Helper method to render a template given as a string.
|
||||
|
||||
Originally from https://stackoverflow.com/a/1690879
|
||||
"""
|
||||
context = context or {}
|
||||
context = Context(context)
|
||||
return Template(string).render(context)
|
||||
|
||||
def test_public_site_url(self):
|
||||
result = self._render_template(
|
||||
"{% load url_helpers %}{% public_site_url 'directory/page' %}"
|
||||
)
|
||||
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
||||
self.assertTrue(result.endswith("/directory/page"))
|
||||
|
||||
def test_public_site_url_leading_slash(self):
|
||||
result = self._render_template(
|
||||
"{% load url_helpers %}{% public_site_url '/directory/page' %}"
|
||||
)
|
||||
self.assertTrue(result.startswith(settings.GETGOV_PUBLIC_SITE_URL))
|
||||
# slash-slash host slash directory slash page
|
||||
self.assertEqual(result.count("/"), 4)
|
|
@ -1058,6 +1058,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
"domain-users",
|
||||
"domain-users-add",
|
||||
"domain-nameservers",
|
||||
"domain-authorizing-official",
|
||||
"domain-your-contact-information",
|
||||
"domain-security-email",
|
||||
]:
|
||||
|
@ -1077,6 +1078,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
"domain-users",
|
||||
"domain-users-add",
|
||||
"domain-nameservers",
|
||||
"domain-authorizing-official",
|
||||
"domain-your-contact-information",
|
||||
"domain-security-email",
|
||||
]:
|
||||
|
@ -1087,12 +1089,6 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
with less_console_noise():
|
||||
response = self.client.get(
|
||||
reverse("domain-security-email", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
||||
def setUp(self):
|
||||
|
@ -1301,6 +1297,24 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
|||
# the field.
|
||||
self.assertContains(result, "This field is required", count=2, status_code=200)
|
||||
|
||||
def test_domain_authorizing_official(self):
|
||||
"""Can load domain's authorizing official page."""
|
||||
page = self.client.get(
|
||||
reverse("domain-authorizing-official", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
# once on the sidebar, once in the title
|
||||
self.assertContains(page, "Authorizing official", count=2)
|
||||
|
||||
def test_domain_authorizing_official_content(self):
|
||||
"""Authorizing official information appears on the page."""
|
||||
self.domain_information.authorizing_official = Contact(first_name="Testy")
|
||||
self.domain_information.authorizing_official.save()
|
||||
self.domain_information.save()
|
||||
page = self.app.get(
|
||||
reverse("domain-authorizing-official", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
self.assertContains(page, "Testy")
|
||||
|
||||
def test_domain_your_contact_information(self):
|
||||
"""Can load domain's your contact information page."""
|
||||
page = self.client.get(
|
||||
|
@ -1309,10 +1323,9 @@ class TestDomainDetail(TestWithDomainPermissions, WebTest):
|
|||
self.assertContains(page, "Domain contact information")
|
||||
|
||||
def test_domain_your_contact_information_content(self):
|
||||
"""Your contact information appears on the page."""
|
||||
self.domain_information.submitter = Contact(first_name="Testy")
|
||||
self.domain_information.submitter.save()
|
||||
self.domain_information.save()
|
||||
"""Logged-in user's contact information appears on the page."""
|
||||
self.user.contact.first_name = "Testy"
|
||||
self.user.contact.save()
|
||||
page = self.app.get(
|
||||
reverse("domain-your-contact-information", kwargs={"pk": self.domain.id})
|
||||
)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from .application import *
|
||||
from .domain import (
|
||||
DomainView,
|
||||
DomainAuthorizingOfficialView,
|
||||
DomainNameserversView,
|
||||
DomainYourContactInformationView,
|
||||
DomainSecurityEmailView,
|
||||
|
|
|
@ -15,6 +15,7 @@ from django.urls import reverse
|
|||
from django.views.generic.edit import FormMixin
|
||||
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
DomainInvitation,
|
||||
User,
|
||||
UserDomainRole,
|
||||
|
@ -40,6 +41,48 @@ class DomainView(DomainPermissionView):
|
|||
template_name = "domain_detail.html"
|
||||
|
||||
|
||||
class DomainAuthorizingOfficialView(DomainPermissionView, FormMixin):
|
||||
|
||||
"""Domain authorizing official editing view."""
|
||||
|
||||
model = Domain
|
||||
template_name = "domain_authorizing_official.html"
|
||||
context_object_name = "domain"
|
||||
form_class = ContactForm
|
||||
|
||||
def get_form_kwargs(self, *args, **kwargs):
|
||||
"""Add domain_info.authorizing_official instance to make a bound form."""
|
||||
form_kwargs = super().get_form_kwargs(*args, **kwargs)
|
||||
form_kwargs["instance"] = self.get_object().domain_info.authorizing_official
|
||||
return form_kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the overview page for the domain."""
|
||||
return reverse("domain-authorizing-official", kwargs={"pk": self.object.pk})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Form submission posts to this view.
|
||||
|
||||
This post method harmonizes using DetailView and FormMixin together.
|
||||
"""
|
||||
self.object = self.get_object()
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
"""The form is valid, save the authorizing official."""
|
||||
form.save()
|
||||
|
||||
messages.success(
|
||||
self.request, "The authorizing official for this domain has been updated."
|
||||
)
|
||||
# superclass has the redirect
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class DomainNameserversView(DomainPermissionView, FormMixin):
|
||||
|
||||
"""Domain nameserver editing view."""
|
||||
|
@ -116,7 +159,7 @@ class DomainYourContactInformationView(DomainPermissionView, FormMixin):
|
|||
def get_form_kwargs(self, *args, **kwargs):
|
||||
"""Add domain_info.submitter instance to make a bound form."""
|
||||
form_kwargs = super().get_form_kwargs(*args, **kwargs)
|
||||
form_kwargs["instance"] = self.get_object().domain_info.submitter
|
||||
form_kwargs["instance"] = self.request.user.contact
|
||||
return form_kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
-i https://pypi.python.org/simple
|
||||
asgiref==3.6.0 ; python_version >= '3.7'
|
||||
boto3==1.26.69
|
||||
botocore==1.29.69 ; python_version >= '3.7'
|
||||
cachetools==5.3.0
|
||||
certifi==2022.12.7 ; python_version >= '3.6'
|
||||
asgiref==3.7.2 ; python_version >= '3.7'
|
||||
boto3==1.26.145
|
||||
botocore==1.29.145 ; python_version >= '3.7'
|
||||
cachetools==5.3.1
|
||||
certifi==2023.5.7 ; python_version >= '3.6'
|
||||
cfenv==0.5.3
|
||||
cffi==1.15.1
|
||||
charset-normalizer==3.0.1 ; python_version >= '3.6'
|
||||
cryptography==39.0.1 ; python_version >= '3.6'
|
||||
charset-normalizer==3.1.0 ; python_full_version >= '3.7.0'
|
||||
cryptography==41.0.1 ; python_version >= '3.7'
|
||||
defusedxml==0.7.1 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'
|
||||
dj-database-url==1.2.0
|
||||
dj-database-url==2.0.0
|
||||
dj-email-url==1.0.6
|
||||
django==4.1.6
|
||||
django==4.2.1
|
||||
django-allow-cidr==0.6.0
|
||||
django-auditlog==2.2.2
|
||||
django-auditlog==2.3.0
|
||||
django-cache-url==3.4.4
|
||||
django-csp==3.7
|
||||
django-fsm==2.8.1
|
||||
django-phonenumber-field[phonenumberslite]==7.0.2
|
||||
django-phonenumber-field[phonenumberslite]==7.1.0
|
||||
django-widget-tweaks==1.4.12
|
||||
environs[django]==9.5.0
|
||||
faker==17.0.0
|
||||
git+https://github.com/cisagov/epplib.git@master#egg=fred-epplib
|
||||
faker==18.10.0
|
||||
git+https://github.com/cisagov/epplib.git@f818cbf0b069a12f03e1d72e4b9f4900924b832d#egg=fred-epplib
|
||||
furl==2.1.3
|
||||
future==0.18.3 ; python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
gunicorn==20.1.0
|
||||
|
@ -31,21 +31,22 @@ lxml==4.9.2 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2,
|
|||
mako==1.2.4 ; python_version >= '3.7'
|
||||
markupsafe==2.1.2 ; python_version >= '3.7'
|
||||
marshmallow==3.19.0 ; python_version >= '3.7'
|
||||
oic==1.5.0
|
||||
oic==1.6.0
|
||||
orderedmultidict==1.0.1
|
||||
packaging==23.0 ; python_version >= '3.7'
|
||||
phonenumberslite==8.13.6
|
||||
psycopg2-binary==2.9.5
|
||||
packaging==23.1 ; python_version >= '3.7'
|
||||
phonenumberslite==8.13.13
|
||||
psycopg2-binary==2.9.6
|
||||
pycparser==2.21
|
||||
pycryptodomex==3.17
|
||||
pycryptodomex==3.18.0
|
||||
pydantic==1.10.8 ; python_version >= '3.7'
|
||||
pyjwkest==1.4.2
|
||||
python-dateutil==2.8.2 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
python-dotenv==0.21.1 ; python_version >= '3.7'
|
||||
requests==2.28.2
|
||||
s3transfer==0.6.0 ; python_version >= '3.7'
|
||||
setuptools==67.2.0 ; python_version >= '3.7'
|
||||
python-dotenv==1.0.0 ; python_version >= '3.8'
|
||||
requests==2.31.0
|
||||
s3transfer==0.6.1 ; python_version >= '3.7'
|
||||
setuptools==67.8.0 ; python_version >= '3.7'
|
||||
six==1.16.0 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'
|
||||
sqlparse==0.4.3 ; python_version >= '3.5'
|
||||
typing-extensions==4.4.0 ; python_version >= '3.7'
|
||||
urllib3==1.26.14 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
|
||||
whitenoise==6.3.0
|
||||
sqlparse==0.4.4 ; python_version >= '3.5'
|
||||
typing-extensions==4.6.2
|
||||
urllib3==1.26.16 ; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
|
||||
whitenoise==6.4.0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue