mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-23 03:06:01 +02:00
Merge branch 'main' of github.com:cisagov/manage.get.gov into es/1920-update-field-labels
This commit is contained in:
commit
ba40a6ea7b
17 changed files with 531 additions and 46 deletions
|
@ -779,6 +779,46 @@ class WebsiteAdmin(ListHeaderAdmin):
|
|||
]
|
||||
search_help_text = "Search by website."
|
||||
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
Return empty perms dict thus hiding the model from admin index.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
if analyst_perm and not superuser_perm:
|
||||
return {}
|
||||
return super().get_model_perms(request)
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
"""
|
||||
Allow analysts to access the change form directly via URL.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
if analyst_perm and not superuser_perm:
|
||||
return True
|
||||
return super().has_change_permission(request, obj)
|
||||
|
||||
def response_change(self, request, obj):
|
||||
"""
|
||||
Override to redirect users back to the previous page after saving.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
return_path = request.GET.get("return_path")
|
||||
|
||||
# First, call the super method to perform the standard operations and capture the response
|
||||
response = super().response_change(request, obj)
|
||||
|
||||
# Don't redirect to the website page on save if the user is an analyst.
|
||||
# Rather, just redirect back to the originating page.
|
||||
if (analyst_perm and not superuser_perm) and return_path:
|
||||
# Redirect to the return path if it exists
|
||||
return HttpResponseRedirect(return_path)
|
||||
|
||||
# If no redirection is needed, return the original response
|
||||
return response
|
||||
|
||||
|
||||
class UserDomainRoleAdmin(ListHeaderAdmin):
|
||||
"""Custom user domain role admin class."""
|
||||
|
@ -1466,7 +1506,10 @@ class DomainInformationInline(admin.StackedInline):
|
|||
def has_change_permission(self, request, obj=None):
|
||||
"""Custom has_change_permission override so that we can specify that
|
||||
analysts can edit this through this inline, but not through the model normally"""
|
||||
if request.user.has_perm("registrar.analyst_access_permission"):
|
||||
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
if analyst_perm and not superuser_perm:
|
||||
return True
|
||||
return super().has_change_permission(request, obj)
|
||||
|
||||
|
@ -1627,12 +1670,8 @@ class DomainAdmin(ListHeaderAdmin):
|
|||
# No expiration date was found. Return none.
|
||||
extra_context["extended_expiration_date"] = None
|
||||
return super().changeform_view(request, object_id, form_url, extra_context)
|
||||
|
||||
if curr_exp_date < date.today():
|
||||
extra_context["extended_expiration_date"] = date.today() + relativedelta(years=years_to_extend_by)
|
||||
else:
|
||||
new_date = domain.registry_expiration_date + relativedelta(years=years_to_extend_by)
|
||||
extra_context["extended_expiration_date"] = new_date
|
||||
new_date = curr_exp_date + relativedelta(years=years_to_extend_by)
|
||||
extra_context["extended_expiration_date"] = new_date
|
||||
else:
|
||||
extra_context["extended_expiration_date"] = None
|
||||
|
||||
|
@ -1896,6 +1935,46 @@ class DraftDomainAdmin(ListHeaderAdmin):
|
|||
# in autocomplete_fields for user
|
||||
ordering = ["name"]
|
||||
|
||||
def get_model_perms(self, request):
|
||||
"""
|
||||
Return empty perms dict thus hiding the model from admin index.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
if analyst_perm and not superuser_perm:
|
||||
return {}
|
||||
return super().get_model_perms(request)
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
"""
|
||||
Allow analysts to access the change form directly via URL.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
if analyst_perm and not superuser_perm:
|
||||
return True
|
||||
return super().has_change_permission(request, obj)
|
||||
|
||||
def response_change(self, request, obj):
|
||||
"""
|
||||
Override to redirect users back to the previous page after saving.
|
||||
"""
|
||||
superuser_perm = request.user.has_perm("registrar.full_access_permission")
|
||||
analyst_perm = request.user.has_perm("registrar.analyst_access_permission")
|
||||
return_path = request.GET.get("return_path")
|
||||
|
||||
# First, call the super method to perform the standard operations and capture the response
|
||||
response = super().response_change(request, obj)
|
||||
|
||||
# Don't redirect to the website page on save if the user is an analyst.
|
||||
# Rather, just redirect back to the originating page.
|
||||
if (analyst_perm and not superuser_perm) and return_path:
|
||||
# Redirect to the return path if it exists
|
||||
return HttpResponseRedirect(return_path)
|
||||
|
||||
# If no redirection is needed, return the original response
|
||||
return response
|
||||
|
||||
|
||||
class PublicContactAdmin(ListHeaderAdmin):
|
||||
"""Custom PublicContact admin class."""
|
||||
|
|
|
@ -536,6 +536,18 @@ address.dja-address-contact-list {
|
|||
}
|
||||
}
|
||||
|
||||
.dja-status-list {
|
||||
border-top: solid 1px var(--border-color);
|
||||
margin-left: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
padding-top: 10px;
|
||||
li {
|
||||
line-height: 1.5;
|
||||
font-family: "Source Sans Pro Web", "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif !important;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Make the clipboard button "float" inside of the input box
|
||||
.admin-icon-group {
|
||||
|
|
37
src/registrar/migrations/0084_create_groups_v11.py
Normal file
37
src/registrar/migrations/0084_create_groups_v11.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# This migration creates the create_full_access_group and create_cisa_analyst_group groups
|
||||
# It is dependent on 0079 (which populates federal agencies)
|
||||
# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS
|
||||
# in the user_group model then:
|
||||
# [NOT RECOMMENDED]
|
||||
# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions
|
||||
# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups
|
||||
# step 3: fake run the latest migration in the migrations list
|
||||
# [RECOMMENDED]
|
||||
# Alternatively:
|
||||
# step 1: duplicate the migration that loads data
|
||||
# step 2: docker-compose exec app ./manage.py migrate
|
||||
|
||||
from django.db import migrations
|
||||
from registrar.models import UserGroup
|
||||
from typing import Any
|
||||
|
||||
|
||||
# For linting: RunPython expects a function reference,
|
||||
# so let's give it one
|
||||
def create_groups(apps, schema_editor) -> Any:
|
||||
UserGroup.create_cisa_analyst_group(apps, schema_editor)
|
||||
UserGroup.create_full_access_group(apps, schema_editor)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("registrar", "0083_alter_contact_email_alter_publiccontact_email"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
create_groups,
|
||||
reverse_code=migrations.RunPython.noop,
|
||||
atomic=True,
|
||||
),
|
||||
]
|
|
@ -94,6 +94,9 @@ class Contact(TimeStampedModel):
|
|||
names = [n for n in [self.first_name, self.middle_name, self.last_name] if n]
|
||||
return " ".join(names) if names else "Unknown"
|
||||
|
||||
def has_contact_info(self):
|
||||
return bool(self.title or self.email or self.phone)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# Call the parent class's save method to perform the actual save
|
||||
super().save(*args, **kwargs)
|
||||
|
|
|
@ -9,6 +9,7 @@ from .domain_invitation import DomainInvitation
|
|||
from .transition_domain import TransitionDomain
|
||||
from .verified_by_staff import VerifiedByStaff
|
||||
from .domain import Domain
|
||||
from .domain_request import DomainRequest
|
||||
|
||||
from phonenumber_field.modelfields import PhoneNumberField # type: ignore
|
||||
|
||||
|
@ -68,6 +69,33 @@ class User(AbstractUser):
|
|||
def is_restricted(self):
|
||||
return self.status == self.RESTRICTED
|
||||
|
||||
def get_approved_domains_count(self):
|
||||
"""Return count of approved domains"""
|
||||
allowed_states = [Domain.State.UNKNOWN, Domain.State.DNS_NEEDED, Domain.State.READY, Domain.State.ON_HOLD]
|
||||
approved_domains_count = self.domains.filter(state__in=allowed_states).count()
|
||||
return approved_domains_count
|
||||
|
||||
def get_active_requests_count(self):
|
||||
"""Return count of active requests"""
|
||||
allowed_states = [
|
||||
DomainRequest.DomainRequestStatus.SUBMITTED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
]
|
||||
active_requests_count = self.domain_requests_created.filter(status__in=allowed_states).count()
|
||||
return active_requests_count
|
||||
|
||||
def get_rejected_requests_count(self):
|
||||
"""Return count of rejected requests"""
|
||||
return self.domain_requests_created.filter(status=DomainRequest.DomainRequestStatus.REJECTED).count()
|
||||
|
||||
def get_ineligible_requests_count(self):
|
||||
"""Return count of ineligible requests"""
|
||||
return self.domain_requests_created.filter(status=DomainRequest.DomainRequestStatus.INELIGIBLE).count()
|
||||
|
||||
def has_contact_info(self):
|
||||
return bool(self.contact.title or self.contact.email or self.contact.phone)
|
||||
|
||||
@classmethod
|
||||
def needs_identity_verification(cls, email, uuid):
|
||||
"""A method used by our oidc classes to test whether a user needs email/uuid verification
|
||||
|
|
|
@ -41,11 +41,6 @@ class UserGroup(Group):
|
|||
"model": "domain",
|
||||
"permissions": ["view_domain"],
|
||||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
"model": "draftdomain",
|
||||
"permissions": ["change_draftdomain"],
|
||||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
"model": "user",
|
||||
|
@ -56,11 +51,6 @@ class UserGroup(Group):
|
|||
"model": "domaininvitation",
|
||||
"permissions": ["add_domaininvitation", "view_domaininvitation"],
|
||||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
"model": "website",
|
||||
"permissions": ["change_website"],
|
||||
},
|
||||
{
|
||||
"app_label": "registrar",
|
||||
"model": "userdomainrole",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{% load i18n static %}
|
||||
|
||||
<address class="{% if no_title_top_padding %}margin-top-neg-1__detail-list{% endif %} dja-address-contact-list">
|
||||
<address class="{% if no_title_top_padding %}margin-top-neg-1__detail-list{% endif %} {% if user.has_contact_info %}margin-bottom-1{% endif %} dja-address-contact-list">
|
||||
|
||||
{% if show_formatted_name %}
|
||||
{% if contact.get_formatted_name %}
|
||||
|
@ -10,7 +10,7 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if user.title or user.contact.title or user.email or user.contact.email or user.phone or user.contact.phone %}
|
||||
{% if user.has_contact_info %}
|
||||
{# Title #}
|
||||
{% if user.title or user.contact.title %}
|
||||
{% if user.contact.title %}
|
||||
|
|
|
@ -27,6 +27,10 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
|
|||
</dl>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% elif field.field.name == "requested_domain" %}
|
||||
{% with current_path=request.get_full_path %}
|
||||
<a class="margin-top-05 padding-top-05" href="{% url 'admin:registrar_draftdomain_change' original.requested_domain.id %}?{{ 'return_path='|add:current_path }}">{{ original.requested_domain }}</a>
|
||||
{% endwith%}
|
||||
{% elif field.field.name == "current_websites" %}
|
||||
{% comment %}
|
||||
The "website" model is essentially just a text field.
|
||||
|
@ -49,9 +53,11 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
|
|||
</div>
|
||||
{% elif field.field.name == "alternative_domains" %}
|
||||
<div class="readonly">
|
||||
{% with current_path=request.get_full_path %}
|
||||
{% for alt_domain in original.alternative_domains.all %}
|
||||
<a href="{% url 'admin:registrar_website_change' alt_domain.id %}">{{ alt_domain }}</a>{% if not forloop.last %}, {% endif %}
|
||||
<a href="{% url 'admin:registrar_website_change' alt_domain.id %}?{{ 'return_path='|add:current_path }}">{{ alt_domain }}</a>{% if not forloop.last %}, {% endif %}
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="readonly">{{ field.contents }}</div>
|
||||
|
@ -65,6 +71,10 @@ This is using a custom implementation fieldset.html (see admin/fieldset.html)
|
|||
<label aria-label="Creator contact details"></label>
|
||||
{% include "django/admin/includes/contact_detail_list.html" with user=original.creator no_title_top_padding=field.is_readonly %}
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<label aria-label="User summary details"></label>
|
||||
{% include "django/admin/includes/user_detail_list.html" with user=original.creator no_title_top_padding=field.is_readonly %}
|
||||
</div>
|
||||
{% elif field.field.name == "submitter" %}
|
||||
<div class="flex-container">
|
||||
<label aria-label="Submitter contact details"></label>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{% load i18n static %}
|
||||
|
||||
{% with approved_domains_count=user.get_approved_domains_count %}
|
||||
{% with active_requests_count=user.get_active_requests_count %}
|
||||
{% with rejected_requests_count=user.get_rejected_requests_count %}
|
||||
{% with ineligible_requests_count=user.get_ineligible_requests_count %}
|
||||
{% if approved_domains_count|add:active_requests_count|add:rejected_requests_count|add:ineligible_requests_count > 0 %}
|
||||
<ul class="dja-status-list">
|
||||
{% if approved_domains_count > 0 %}
|
||||
{# Approved domains #}
|
||||
<li>Approved domains: {{ approved_domains_count }}</li>
|
||||
{% endif %}
|
||||
{% if active_requests_count > 0 %}
|
||||
{# Active requests #}
|
||||
<li>Active requests: {{ active_requests_count }}</li>
|
||||
{% endif %}
|
||||
{% if rejected_requests_count > 0 %}
|
||||
{# Rejected requests #}
|
||||
<li>Rejected requests: {{ rejected_requests_count }}</li>
|
||||
{% endif %}
|
||||
{% if ineligible_requests_count > 0 %}
|
||||
{# Ineligible requests #}
|
||||
<li>Ineligible requests: {{ ineligible_requests_count }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
|
@ -3,7 +3,7 @@
|
|||
<h2 class="margin-top-0 margin-bottom-2 text-primary-darker text-semibold" >
|
||||
Next steps in this process
|
||||
</h2>
|
||||
<p>We received your .gov domain request. Our next step is to review your request. This usually takes 20 business days. We’ll email you if we have questions and when we complete our review. <a class="usa-link" rel="noopener noreferrer" target="_blank" href="{% public_site_url 'contact' %}">Contact us with any questions</a>.</p>
|
||||
<p>We received your .gov domain request. Our next step is to review your request. This usually takes 30 business days. We’ll email you if we have questions and when we complete our review. <a class="usa-link" rel="noopener noreferrer" target="_blank" href="{% public_site_url 'contact' %}">Contact us with any questions</a>.</p>
|
||||
|
||||
<h2 class="margin-top-0 margin-bottom-2 text-primary-darker text-semibold">
|
||||
Need to make changes?
|
||||
|
|
|
@ -21,7 +21,16 @@ from registrar.admin import (
|
|||
UserDomainRoleAdmin,
|
||||
VerifiedByStaffAdmin,
|
||||
)
|
||||
from registrar.models import Domain, DomainRequest, DomainInformation, User, DomainInvitation, Contact, Website
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
DomainRequest,
|
||||
DomainInformation,
|
||||
User,
|
||||
DomainInvitation,
|
||||
Contact,
|
||||
Website,
|
||||
DraftDomain,
|
||||
)
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
from registrar.models.verified_by_staff import VerifiedByStaff
|
||||
from .common import (
|
||||
|
@ -76,11 +85,10 @@ class TestDomainAdmin(MockEppLib, WebTest):
|
|||
)
|
||||
super().setUp()
|
||||
|
||||
@skip("TODO for another ticket. This test case is grabbing old db data.")
|
||||
@patch("registrar.admin.DomainAdmin._get_current_date", return_value=date(2024, 1, 1))
|
||||
def test_extend_expiration_date_button(self, mock_date_today):
|
||||
"""
|
||||
Tests if extend_expiration_date button extends correctly
|
||||
Tests if extend_expiration_date modal gives an accurate date
|
||||
"""
|
||||
|
||||
# Create a ready domain with a preset expiration date
|
||||
|
@ -107,17 +115,11 @@ class TestDomainAdmin(MockEppLib, WebTest):
|
|||
# Follow the response
|
||||
response = response.follow()
|
||||
|
||||
# refresh_from_db() does not work for objects with protected=True.
|
||||
# https://github.com/viewflow/django-fsm/issues/89
|
||||
new_domain = Domain.objects.get(id=domain.id)
|
||||
|
||||
# Check that the current expiration date is what we expect
|
||||
self.assertEqual(new_domain.expiration_date, date(2025, 5, 25))
|
||||
|
||||
# Assert that everything on the page looks correct
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, domain.name)
|
||||
self.assertContains(response, "Extend expiration date")
|
||||
self.assertContains(response, "New expiration date: <b>May 25, 2025</b>")
|
||||
|
||||
# Ensure the message we recieve is in line with what we expect
|
||||
expected_message = "Successfully extended the expiration date."
|
||||
|
@ -129,6 +131,7 @@ class TestDomainAdmin(MockEppLib, WebTest):
|
|||
extra_tags="",
|
||||
fail_silently=False,
|
||||
)
|
||||
|
||||
mock_add_message.assert_has_calls([expected_call], 1)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -703,6 +706,126 @@ class TestDomainRequestAdmin(MockEppLib):
|
|||
)
|
||||
self.mock_client = MockSESClient()
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_analyst_can_see_and_edit_alternative_domain(self):
|
||||
"""Tests if an analyst can still see and edit the alternative domain field"""
|
||||
|
||||
# Create fake creator
|
||||
_creator = User.objects.create(
|
||||
username="MrMeoward",
|
||||
first_name="Meoward",
|
||||
last_name="Jones",
|
||||
)
|
||||
|
||||
# Create a fake domain request
|
||||
_domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||
|
||||
fake_website = Website.objects.create(website="thisisatest.gov")
|
||||
_domain_request.alternative_domains.add(fake_website)
|
||||
_domain_request.save()
|
||||
|
||||
p = "userpass"
|
||||
self.client.login(username="staffuser", password=p)
|
||||
response = self.client.get(
|
||||
"/admin/registrar/domainrequest/{}/change/".format(_domain_request.pk),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Make sure the page loaded, and that we're on the right page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, _domain_request.requested_domain.name)
|
||||
|
||||
# Test if the page has the alternative domain
|
||||
self.assertContains(response, "thisisatest.gov")
|
||||
|
||||
# Check that the page contains the url we expect
|
||||
expected_href = reverse("admin:registrar_website_change", args=[fake_website.id])
|
||||
self.assertContains(response, expected_href)
|
||||
|
||||
# Navigate to the website to ensure that we can still edit it
|
||||
response = self.client.get(
|
||||
"/admin/registrar/website/{}/change/".format(fake_website.pk),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Make sure the page loaded, and that we're on the right page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "thisisatest.gov")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_analyst_can_see_and_edit_requested_domain(self):
|
||||
"""Tests if an analyst can still see and edit the requested domain field"""
|
||||
|
||||
# Create fake creator
|
||||
_creator = User.objects.create(
|
||||
username="MrMeoward",
|
||||
first_name="Meoward",
|
||||
last_name="Jones",
|
||||
)
|
||||
|
||||
# Create a fake domain request
|
||||
_domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||
|
||||
p = "userpass"
|
||||
self.client.login(username="staffuser", password=p)
|
||||
response = self.client.get(
|
||||
"/admin/registrar/domainrequest/{}/change/".format(_domain_request.pk),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Filter to get the latest from the DB (rather than direct assignment)
|
||||
requested_domain = DraftDomain.objects.filter(name=_domain_request.requested_domain.name).get()
|
||||
|
||||
# Make sure the page loaded, and that we're on the right page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, requested_domain.name)
|
||||
|
||||
# Check that the page contains the url we expect
|
||||
expected_href = reverse("admin:registrar_draftdomain_change", args=[requested_domain.id])
|
||||
self.assertContains(response, expected_href)
|
||||
|
||||
# Navigate to the website to ensure that we can still edit it
|
||||
response = self.client.get(
|
||||
"/admin/registrar/draftdomain/{}/change/".format(requested_domain.pk),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Make sure the page loaded, and that we're on the right page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "city.gov")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_analyst_can_see_current_websites(self):
|
||||
"""Tests if an analyst can still see current website field"""
|
||||
|
||||
# Create fake creator
|
||||
_creator = User.objects.create(
|
||||
username="MrMeoward",
|
||||
first_name="Meoward",
|
||||
last_name="Jones",
|
||||
)
|
||||
|
||||
# Create a fake domain request
|
||||
_domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.IN_REVIEW, user=_creator)
|
||||
|
||||
fake_website = Website.objects.create(website="thisisatest.gov")
|
||||
_domain_request.current_websites.add(fake_website)
|
||||
_domain_request.save()
|
||||
|
||||
p = "userpass"
|
||||
self.client.login(username="staffuser", password=p)
|
||||
response = self.client.get(
|
||||
"/admin/registrar/domainrequest/{}/change/".format(_domain_request.pk),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Make sure the page loaded, and that we're on the right page
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, _domain_request.requested_domain.name)
|
||||
|
||||
# Test if the page has the current website
|
||||
self.assertContains(response, "thisisatest.gov")
|
||||
|
||||
def test_domain_sortable(self):
|
||||
"""Tests if the DomainRequest sorts by domain correctly"""
|
||||
with less_console_noise():
|
||||
|
@ -1553,6 +1676,10 @@ class TestDomainRequestAdmin(MockEppLib):
|
|||
# Test for the copy link
|
||||
self.assertContains(response, "usa-button__clipboard", count=4)
|
||||
|
||||
# Test that Creator counts display properly
|
||||
self.assertNotContains(response, "Approved domains")
|
||||
self.assertContains(response, "Active requests")
|
||||
|
||||
def test_save_model_sets_restricted_status_on_user(self):
|
||||
with less_console_noise():
|
||||
# make sure there is no user with this email
|
||||
|
|
|
@ -37,7 +37,6 @@ class TestGroups(TestCase):
|
|||
"add_domaininvitation",
|
||||
"view_domaininvitation",
|
||||
"change_domainrequest",
|
||||
"change_draftdomain",
|
||||
"add_federalagency",
|
||||
"change_federalagency",
|
||||
"delete_federalagency",
|
||||
|
@ -48,7 +47,6 @@ class TestGroups(TestCase):
|
|||
"add_verifiedbystaff",
|
||||
"change_verifiedbystaff",
|
||||
"delete_verifiedbystaff",
|
||||
"change_website",
|
||||
]
|
||||
|
||||
# Get the codenames of actual permissions associated with the group
|
||||
|
|
|
@ -1004,6 +1004,8 @@ class TestUser(TestCase):
|
|||
Domain.objects.all().delete()
|
||||
DomainInvitation.objects.all().delete()
|
||||
DomainInformation.objects.all().delete()
|
||||
DomainRequest.objects.all().delete()
|
||||
DraftDomain.objects.all().delete()
|
||||
TransitionDomain.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
UserDomainRole.objects.all().delete()
|
||||
|
@ -1060,6 +1062,91 @@ class TestUser(TestCase):
|
|||
# Domain Invitation, then save routine should be called exactly once
|
||||
save_mock.assert_called_once()
|
||||
|
||||
def test_approved_domains_count(self):
|
||||
"""Test that the correct approved domain count is returned for a user"""
|
||||
# with no associated approved domains, expect this to return 0
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 0)
|
||||
# with one approved domain, expect this to return 1
|
||||
UserDomainRole.objects.get_or_create(user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 1)
|
||||
# with one approved domain, expect this to return 1 (domain2 is deleted, so not considered approved)
|
||||
domain2, _ = Domain.objects.get_or_create(name="igorville2.gov", state=Domain.State.DELETED)
|
||||
UserDomainRole.objects.get_or_create(user=self.user, domain=domain2, role=UserDomainRole.Roles.MANAGER)
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 1)
|
||||
# with two approved domains, expect this to return 2
|
||||
domain3, _ = Domain.objects.get_or_create(name="igorville3.gov", state=Domain.State.DNS_NEEDED)
|
||||
UserDomainRole.objects.get_or_create(user=self.user, domain=domain3, role=UserDomainRole.Roles.MANAGER)
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 2)
|
||||
# with three approved domains, expect this to return 3
|
||||
domain4, _ = Domain.objects.get_or_create(name="igorville4.gov", state=Domain.State.ON_HOLD)
|
||||
UserDomainRole.objects.get_or_create(user=self.user, domain=domain4, role=UserDomainRole.Roles.MANAGER)
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 3)
|
||||
# with four approved domains, expect this to return 4
|
||||
domain5, _ = Domain.objects.get_or_create(name="igorville5.gov", state=Domain.State.READY)
|
||||
UserDomainRole.objects.get_or_create(user=self.user, domain=domain5, role=UserDomainRole.Roles.MANAGER)
|
||||
self.assertEquals(self.user.get_approved_domains_count(), 4)
|
||||
|
||||
def test_active_requests_count(self):
|
||||
"""Test that the correct active domain requests count is returned for a user"""
|
||||
# with no associated active requests, expect this to return 0
|
||||
self.assertEquals(self.user.get_active_requests_count(), 0)
|
||||
# with one active request, expect this to return 1
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville1.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.SUBMITTED
|
||||
)
|
||||
self.assertEquals(self.user.get_active_requests_count(), 1)
|
||||
# with two active requests, expect this to return 2
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville2.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.IN_REVIEW
|
||||
)
|
||||
self.assertEquals(self.user.get_active_requests_count(), 2)
|
||||
# with three active requests, expect this to return 3
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville3.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.ACTION_NEEDED
|
||||
)
|
||||
self.assertEquals(self.user.get_active_requests_count(), 3)
|
||||
# with three active requests, expect this to return 3 (STARTED is not considered active)
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville4.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.STARTED
|
||||
)
|
||||
self.assertEquals(self.user.get_active_requests_count(), 3)
|
||||
|
||||
def test_rejected_requests_count(self):
|
||||
"""Test that the correct rejected domain requests count is returned for a user"""
|
||||
# with no associated rejected requests, expect this to return 0
|
||||
self.assertEquals(self.user.get_rejected_requests_count(), 0)
|
||||
# with one rejected request, expect this to return 1
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville1.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.REJECTED
|
||||
)
|
||||
self.assertEquals(self.user.get_rejected_requests_count(), 1)
|
||||
|
||||
def test_ineligible_requests_count(self):
|
||||
"""Test that the correct ineligible domain requests count is returned for a user"""
|
||||
# with no associated ineligible requests, expect this to return 0
|
||||
self.assertEquals(self.user.get_ineligible_requests_count(), 0)
|
||||
# with one ineligible request, expect this to return 1
|
||||
draft_domain, _ = DraftDomain.objects.get_or_create(name="igorville1.gov")
|
||||
DomainRequest.objects.create(
|
||||
creator=self.user, requested_domain=draft_domain, status=DomainRequest.DomainRequestStatus.INELIGIBLE
|
||||
)
|
||||
self.assertEquals(self.user.get_ineligible_requests_count(), 1)
|
||||
|
||||
def test_has_contact_info(self):
|
||||
"""Test that has_contact_info properly returns"""
|
||||
# test with a user with contact info defined
|
||||
self.assertTrue(self.user.has_contact_info())
|
||||
# test with a user without contact info defined
|
||||
self.user.contact.title = None
|
||||
self.user.contact.email = None
|
||||
self.user.contact.phone = None
|
||||
self.assertFalse(self.user.has_contact_info())
|
||||
|
||||
|
||||
class TestContact(TestCase):
|
||||
def setUp(self):
|
||||
|
@ -1162,6 +1249,16 @@ class TestContact(TestCase):
|
|||
self.assertFalse(self.contact_as_ao.has_more_than_one_join("authorizing_official"))
|
||||
self.assertTrue(self.contact_as_ao.has_more_than_one_join("submitted_domain_requests"))
|
||||
|
||||
def test_has_contact_info(self):
|
||||
"""Test that has_contact_info properly returns"""
|
||||
# test with a contact with contact info defined
|
||||
self.assertTrue(self.contact.has_contact_info())
|
||||
# test with a contact without contact info defined
|
||||
self.contact.title = None
|
||||
self.contact.email = None
|
||||
self.contact.phone = None
|
||||
self.assertFalse(self.contact.has_contact_info())
|
||||
|
||||
|
||||
class TestDomainRequestCustomSave(TestCase):
|
||||
"""Tests custom save behaviour on the DomainRequest object"""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue