mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-23 19:20:47 +02:00
Merge pull request #3513 from cisagov/dk/3440-permissions
#3440: Opt-out permissions
This commit is contained in:
commit
9eefda35da
50 changed files with 1397 additions and 1569 deletions
|
@ -201,6 +201,8 @@ MIDDLEWARE = [
|
|||
"waffle.middleware.WaffleMiddleware",
|
||||
"registrar.registrar_middleware.CheckUserProfileMiddleware",
|
||||
"registrar.registrar_middleware.CheckPortfolioMiddleware",
|
||||
# Restrict access using Opt-Out approach
|
||||
"registrar.registrar_middleware.RestrictAccessMiddleware",
|
||||
]
|
||||
|
||||
# application object used by Django's built-in servers (e.g. `runserver`)
|
||||
|
|
|
@ -68,7 +68,7 @@ for step, view in [
|
|||
(PortfolioDomainRequestStep.REQUESTING_ENTITY, views.RequestingEntity),
|
||||
(PortfolioDomainRequestStep.ADDITIONAL_DETAILS, views.PortfolioAdditionalDetails),
|
||||
]:
|
||||
domain_request_urls.append(path(f"<int:id>/{step}/", view.as_view(), name=step))
|
||||
domain_request_urls.append(path(f"<int:domain_request_pk>/{step}/", view.as_view(), name=step))
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -260,27 +260,27 @@ urlpatterns = [
|
|||
name="export_data_type_user",
|
||||
),
|
||||
path(
|
||||
"domain-request/<int:id>/edit/",
|
||||
"domain-request/<int:domain_request_pk>/edit/",
|
||||
views.DomainRequestWizard.as_view(),
|
||||
name=views.DomainRequestWizard.EDIT_URL_NAME,
|
||||
),
|
||||
path(
|
||||
"domain-request/<int:pk>",
|
||||
"domain-request/<int:domain_request_pk>",
|
||||
views.DomainRequestStatus.as_view(),
|
||||
name="domain-request-status",
|
||||
),
|
||||
path(
|
||||
"domain-request/viewonly/<int:pk>",
|
||||
"domain-request/viewonly/<int:domain_request_pk>",
|
||||
views.PortfolioDomainRequestStatusViewOnly.as_view(),
|
||||
name="domain-request-status-viewonly",
|
||||
),
|
||||
path(
|
||||
"domain-request/<int:pk>/withdraw",
|
||||
"domain-request/<int:domain_request_pk>/withdraw",
|
||||
views.DomainRequestWithdrawConfirmation.as_view(),
|
||||
name="domain-request-withdraw-confirmation",
|
||||
),
|
||||
path(
|
||||
"domain-request/<int:pk>/withdrawconfirmed",
|
||||
"domain-request/<int:domain_request_pk>/withdrawconfirmed",
|
||||
views.DomainRequestWithdrawn.as_view(),
|
||||
name="domain-request-withdrawn",
|
||||
),
|
||||
|
@ -296,56 +296,60 @@ urlpatterns = [
|
|||
lambda r: always_404(r, "We forgot to include this link, sorry."),
|
||||
name="todo",
|
||||
),
|
||||
path("domain/<int:pk>", views.DomainView.as_view(), name="domain"),
|
||||
path("domain/<int:pk>/prototype-dns", views.PrototypeDomainDNSRecordView.as_view(), name="prototype-domain-dns"),
|
||||
path("domain/<int:pk>/users", views.DomainUsersView.as_view(), name="domain-users"),
|
||||
path("domain/<int:domain_pk>", views.DomainView.as_view(), name="domain"),
|
||||
path(
|
||||
"domain/<int:pk>/dns",
|
||||
"domain/<int:domain_pk>/prototype-dns",
|
||||
views.PrototypeDomainDNSRecordView.as_view(),
|
||||
name="prototype-domain-dns",
|
||||
),
|
||||
path("domain/<int:domain_pk>/users", views.DomainUsersView.as_view(), name="domain-users"),
|
||||
path(
|
||||
"domain/<int:domain_pk>/dns",
|
||||
views.DomainDNSView.as_view(),
|
||||
name="domain-dns",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/dns/nameservers",
|
||||
"domain/<int:domain_pk>/dns/nameservers",
|
||||
views.DomainNameserversView.as_view(),
|
||||
name="domain-dns-nameservers",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/dns/dnssec",
|
||||
"domain/<int:domain_pk>/dns/dnssec",
|
||||
views.DomainDNSSECView.as_view(),
|
||||
name="domain-dns-dnssec",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/dns/dnssec/dsdata",
|
||||
"domain/<int:domain_pk>/dns/dnssec/dsdata",
|
||||
views.DomainDsDataView.as_view(),
|
||||
name="domain-dns-dnssec-dsdata",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/org-name-address",
|
||||
"domain/<int:domain_pk>/org-name-address",
|
||||
views.DomainOrgNameAddressView.as_view(),
|
||||
name="domain-org-name-address",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/suborganization",
|
||||
"domain/<int:domain_pk>/suborganization",
|
||||
views.DomainSubOrganizationView.as_view(),
|
||||
name="domain-suborganization",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/senior-official",
|
||||
"domain/<int:domain_pk>/senior-official",
|
||||
views.DomainSeniorOfficialView.as_view(),
|
||||
name="domain-senior-official",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/security-email",
|
||||
"domain/<int:domain_pk>/security-email",
|
||||
views.DomainSecurityEmailView.as_view(),
|
||||
name="domain-security-email",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/renewal",
|
||||
"domain/<int:domain_pk>/renewal",
|
||||
views.DomainRenewalView.as_view(),
|
||||
name="domain-renewal",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/users/add",
|
||||
"domain/<int:domain_pk>/users/add",
|
||||
views.DomainAddUserView.as_view(),
|
||||
name="domain-users-add",
|
||||
),
|
||||
|
@ -360,17 +364,17 @@ urlpatterns = [
|
|||
name="user-profile",
|
||||
),
|
||||
path(
|
||||
"invitation/<int:pk>/cancel",
|
||||
"invitation/<int:domain_invitation_pk>/cancel",
|
||||
views.DomainInvitationCancelView.as_view(http_method_names=["post"]),
|
||||
name="invitation-cancel",
|
||||
),
|
||||
path(
|
||||
"domain-request/<int:pk>/delete",
|
||||
"domain-request/<int:domain_request_pk>/delete",
|
||||
views.DomainRequestDeleteView.as_view(http_method_names=["post"]),
|
||||
name="domain-request-delete",
|
||||
),
|
||||
path(
|
||||
"domain/<int:pk>/users/<int:user_pk>/delete",
|
||||
"domain/<int:domain_pk>/users/<int:user_pk>/delete",
|
||||
views.DomainDeleteUserView.as_view(http_method_names=["post"]),
|
||||
name="domain-user-delete",
|
||||
),
|
||||
|
@ -392,6 +396,7 @@ urlpatterns = [
|
|||
# This way, we can share a view for djangooidc, and other pages as we see fit.
|
||||
handler500 = "registrar.views.utility.error_views.custom_500_error_view"
|
||||
handler403 = "registrar.views.utility.error_views.custom_403_error_view"
|
||||
handler404 = "registrar.views.utility.error_views.custom_404_error_view"
|
||||
|
||||
# we normally would guard these with `if settings.DEBUG` but tests run with
|
||||
# DEBUG = False even when these apps have been loaded because settings.DEBUG
|
||||
|
|
300
src/registrar/decorators.py
Normal file
300
src/registrar/decorators.py
Normal file
|
@ -0,0 +1,300 @@
|
|||
import functools
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.decorators import method_decorator
|
||||
from registrar.models import Domain, DomainInformation, DomainInvitation, DomainRequest, UserDomainRole
|
||||
|
||||
# Constants for clarity
|
||||
ALL = "all"
|
||||
IS_STAFF = "is_staff"
|
||||
IS_DOMAIN_MANAGER = "is_domain_manager"
|
||||
IS_DOMAIN_REQUEST_CREATOR = "is_domain_request_creator"
|
||||
IS_STAFF_MANAGING_DOMAIN = "is_staff_managing_domain"
|
||||
IS_PORTFOLIO_MEMBER = "is_portfolio_member"
|
||||
IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER = "is_portfolio_member_and_domain_manager"
|
||||
IS_DOMAIN_MANAGER_AND_NOT_PORTFOLIO_MEMBER = "is_domain_manager_and_not_portfolio_member"
|
||||
HAS_PORTFOLIO_DOMAINS_ANY_PERM = "has_portfolio_domains_any_perm"
|
||||
HAS_PORTFOLIO_DOMAINS_VIEW_ALL = "has_portfolio_domains_view_all"
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM = "has_portfolio_domain_requests_any_perm"
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_VIEW_ALL = "has_portfolio_domain_requests_view_all"
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT = "has_portfolio_domain_requests_edit"
|
||||
HAS_PORTFOLIO_MEMBERS_ANY_PERM = "has_portfolio_members_any_perm"
|
||||
HAS_PORTFOLIO_MEMBERS_EDIT = "has_portfolio_members_edit"
|
||||
HAS_PORTFOLIO_MEMBERS_VIEW = "has_portfolio_members_view"
|
||||
|
||||
|
||||
def grant_access(*rules):
|
||||
"""
|
||||
A decorator that enforces access control based on specified rules.
|
||||
|
||||
Usage:
|
||||
- Multiple rules in a single decorator:
|
||||
@grant_access(IS_STAFF, IS_SUPERUSER, IS_DOMAIN_MANAGER)
|
||||
|
||||
- Stacked decorators for separate rules:
|
||||
@grant_access(IS_SUPERUSER)
|
||||
@grant_access(IS_DOMAIN_MANAGER)
|
||||
|
||||
The decorator supports both function-based views (FBVs) and class-based views (CBVs).
|
||||
"""
|
||||
|
||||
def decorator(view):
|
||||
if isinstance(view, type): # Check if decorating a class-based view (CBV)
|
||||
original_dispatch = view.dispatch # Store the original dispatch method
|
||||
|
||||
@method_decorator(grant_access(*rules)) # Apply the decorator to dispatch
|
||||
def wrapped_dispatch(self, request, *args, **kwargs):
|
||||
if not _user_has_permission(request.user, request, rules, **kwargs):
|
||||
raise PermissionDenied # Deny access if the user lacks permission
|
||||
return original_dispatch(self, request, *args, **kwargs)
|
||||
|
||||
view.dispatch = wrapped_dispatch # Replace the dispatch method
|
||||
return view
|
||||
|
||||
else: # If decorating a function-based view (FBV)
|
||||
view.has_explicit_access = True # Mark the view as having explicit access control
|
||||
existing_rules = getattr(view, "_access_rules", set()) # Retrieve existing rules
|
||||
existing_rules.update(rules) # Merge with new rules
|
||||
view._access_rules = existing_rules # Store updated rules
|
||||
|
||||
@functools.wraps(view)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
if not _user_has_permission(request.user, request, rules, **kwargs):
|
||||
raise PermissionDenied # Deny access if the user lacks permission
|
||||
return view(request, *args, **kwargs) # Proceed with the original view
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def _user_has_permission(user, request, rules, **kwargs):
|
||||
"""
|
||||
Determines if the user meets the required permission rules.
|
||||
|
||||
This function evaluates a set of predefined permission rules to check whether a user has access
|
||||
to a specific view. It supports various access control conditions, including staff status,
|
||||
domain management roles, and portfolio-related permissions.
|
||||
|
||||
Parameters:
|
||||
- user: The user requesting access.
|
||||
- request: The HTTP request object.
|
||||
- rules: A set of access control rules to evaluate.
|
||||
- **kwargs: Additional keyword arguments used in specific permission checks.
|
||||
|
||||
Returns:
|
||||
- True if the user satisfies any of the specified rules.
|
||||
- False otherwise.
|
||||
"""
|
||||
|
||||
# Skip authentication if @login_not_required is applied
|
||||
if getattr(request, "login_not_required", False):
|
||||
return True
|
||||
|
||||
# Allow everyone if `ALL` is in rules
|
||||
if ALL in rules:
|
||||
return True
|
||||
|
||||
# Ensure user is authenticated and not restricted
|
||||
if not user.is_authenticated or user.is_restricted():
|
||||
return False
|
||||
|
||||
# Define permission checks
|
||||
permission_checks = [
|
||||
(IS_STAFF, lambda: user.is_staff),
|
||||
(IS_DOMAIN_MANAGER, lambda: _is_domain_manager(user, **kwargs)),
|
||||
(IS_STAFF_MANAGING_DOMAIN, lambda: _is_staff_managing_domain(request, **kwargs)),
|
||||
(IS_PORTFOLIO_MEMBER, lambda: user.is_org_user(request)),
|
||||
(
|
||||
HAS_PORTFOLIO_DOMAINS_VIEW_ALL,
|
||||
lambda: _has_portfolio_view_all_domains(request, kwargs.get("domain_pk")),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_DOMAINS_ANY_PERM,
|
||||
lambda: user.is_org_user(request)
|
||||
and user.has_any_domains_portfolio_permission(request.session.get("portfolio")),
|
||||
),
|
||||
(
|
||||
IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER,
|
||||
lambda: _is_domain_manager(user, **kwargs) and _is_portfolio_member(request),
|
||||
),
|
||||
(
|
||||
IS_DOMAIN_MANAGER_AND_NOT_PORTFOLIO_MEMBER,
|
||||
lambda: _is_domain_manager(user, **kwargs) and not _is_portfolio_member(request),
|
||||
),
|
||||
(
|
||||
IS_DOMAIN_REQUEST_CREATOR,
|
||||
lambda: _is_domain_request_creator(user, kwargs.get("domain_request_pk"))
|
||||
and not _is_portfolio_member(request),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM,
|
||||
lambda: user.is_org_user(request)
|
||||
and user.has_any_requests_portfolio_permission(request.session.get("portfolio")),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_VIEW_ALL,
|
||||
lambda: user.is_org_user(request)
|
||||
and user.has_view_all_domain_requests_portfolio_permission(request.session.get("portfolio")),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT,
|
||||
lambda: _has_portfolio_domain_requests_edit(user, request, kwargs.get("domain_request_pk")),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_MEMBERS_ANY_PERM,
|
||||
lambda: user.is_org_user(request)
|
||||
and (
|
||||
user.has_view_members_portfolio_permission(request.session.get("portfolio"))
|
||||
or user.has_edit_members_portfolio_permission(request.session.get("portfolio"))
|
||||
),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_MEMBERS_EDIT,
|
||||
lambda: user.is_org_user(request)
|
||||
and user.has_edit_members_portfolio_permission(request.session.get("portfolio")),
|
||||
),
|
||||
(
|
||||
HAS_PORTFOLIO_MEMBERS_VIEW,
|
||||
lambda: user.is_org_user(request)
|
||||
and user.has_view_members_portfolio_permission(request.session.get("portfolio")),
|
||||
),
|
||||
]
|
||||
|
||||
# Check conditions iteratively
|
||||
return any(check() for rule, check in permission_checks if rule in rules)
|
||||
|
||||
|
||||
def _has_portfolio_domain_requests_edit(user, request, domain_request_id):
|
||||
if domain_request_id and not _is_domain_request_creator(user, domain_request_id):
|
||||
return False
|
||||
return user.is_org_user(request) and user.has_edit_request_portfolio_permission(request.session.get("portfolio"))
|
||||
|
||||
|
||||
def _is_domain_manager(user, **kwargs):
|
||||
"""
|
||||
Determines if the given user is a domain manager for a specified domain.
|
||||
|
||||
- First, it checks if 'domain_pk' is present in the URL parameters.
|
||||
- If 'domain_pk' exists, it verifies if the user has a domain role for that domain.
|
||||
- If 'domain_pk' is absent, it checks for 'domain_invitation_pk' to determine if the user
|
||||
has domain permissions through an invitation.
|
||||
|
||||
Returns:
|
||||
bool: True if the user is a domain manager, False otherwise.
|
||||
"""
|
||||
domain_id = kwargs.get("domain_pk")
|
||||
if domain_id:
|
||||
return UserDomainRole.objects.filter(user=user, domain_id=domain_id).exists()
|
||||
domain_invitation_id = kwargs.get("domain_invitation_pk")
|
||||
if domain_invitation_id:
|
||||
return DomainInvitation.objects.filter(id=domain_invitation_id, domain__permissions__user=user).exists()
|
||||
return False
|
||||
|
||||
|
||||
def _is_domain_request_creator(user, domain_request_pk):
|
||||
"""Checks to see if the user is the creator of a domain request
|
||||
with domain_request_pk."""
|
||||
if domain_request_pk:
|
||||
return DomainRequest.objects.filter(creator=user, id=domain_request_pk).exists()
|
||||
return True
|
||||
|
||||
|
||||
def _is_portfolio_member(request):
|
||||
"""Checks to see if the user in the request is a member of the
|
||||
portfolio in the request's session."""
|
||||
return request.user.is_org_user(request)
|
||||
|
||||
|
||||
def _is_staff_managing_domain(request, **kwargs):
|
||||
"""
|
||||
Determines whether a staff user (analyst or superuser) has permission to manage a domain
|
||||
that they did not create or were not invited to.
|
||||
|
||||
The function enforces:
|
||||
1. **User Authorization** - The user must have `analyst_access_permission` or `full_access_permission`.
|
||||
2. **Valid Session Context** - The user must have explicitly selected the domain for management
|
||||
via an 'analyst action' (e.g., by clicking 'Manage Domain' in the admin interface).
|
||||
3. **Domain Status Check** - Only domains in specific statuses (e.g., APPROVED, IN_REVIEW, etc.)
|
||||
can be managed, except in cases where the domain lacks a status due to errors.
|
||||
|
||||
Process:
|
||||
- First, the function retrieves the `domain_pk` from the URL parameters.
|
||||
- If `domain_pk` is not provided, it attempts to resolve the domain via `domain_invitation_pk`.
|
||||
- It checks if the user has the required permissions.
|
||||
- It verifies that the user has an active 'analyst action' session for the domain.
|
||||
- Finally, it ensures that the domain is in a status that allows management.
|
||||
|
||||
Returns:
|
||||
bool: True if the user is allowed to manage the domain, False otherwise.
|
||||
"""
|
||||
|
||||
domain_id = kwargs.get("domain_pk")
|
||||
if not domain_id:
|
||||
domain_invitation_id = kwargs.get("domain_invitation_pk")
|
||||
domain_invitation = DomainInvitation.objects.filter(id=domain_invitation_id).first()
|
||||
if domain_invitation:
|
||||
domain_id = domain_invitation.domain_id
|
||||
|
||||
# Check if the request user is permissioned...
|
||||
user_is_analyst_or_superuser = request.user.has_perm(
|
||||
"registrar.analyst_access_permission"
|
||||
) or request.user.has_perm("registrar.full_access_permission")
|
||||
|
||||
if not user_is_analyst_or_superuser:
|
||||
return False
|
||||
|
||||
# Check if the user is attempting a valid edit action.
|
||||
# In other words, if the analyst/admin did not click
|
||||
# the 'Manage Domain' button in /admin,
|
||||
# then they cannot access this page.
|
||||
session = request.session
|
||||
can_do_action = (
|
||||
"analyst_action" in session
|
||||
and "analyst_action_location" in session
|
||||
and session["analyst_action_location"] == domain_id
|
||||
)
|
||||
|
||||
if not can_do_action:
|
||||
return False
|
||||
|
||||
# Analysts may manage domains, when they are in these statuses:
|
||||
valid_domain_statuses = [
|
||||
DomainRequest.DomainRequestStatus.APPROVED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.REJECTED,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
# Edge case - some domains do not have
|
||||
# a status or DomainInformation... aka a status of 'None'.
|
||||
# It is necessary to access those to correct errors.
|
||||
None,
|
||||
]
|
||||
|
||||
requested_domain = DomainInformation.objects.filter(domain_id=domain_id).first()
|
||||
|
||||
# if no domain information or domain request exist, the user
|
||||
# should be able to manage the domain; however, if domain information
|
||||
# and domain request exist, and domain request is not in valid status,
|
||||
# user should not be able to manage domain
|
||||
if (
|
||||
requested_domain
|
||||
and requested_domain.domain_request
|
||||
and requested_domain.domain_request.status not in valid_domain_statuses
|
||||
):
|
||||
return False
|
||||
|
||||
# Valid session keys exist,
|
||||
# the user is permissioned,
|
||||
# and it is in a valid status
|
||||
return True
|
||||
|
||||
|
||||
def _has_portfolio_view_all_domains(request, domain_pk):
|
||||
"""Returns whether the user in the request can access the domain
|
||||
via portfolio view all domains permission."""
|
||||
portfolio = request.session.get("portfolio")
|
||||
if request.user.has_view_all_domains_portfolio_permission(portfolio):
|
||||
if Domain.objects.filter(id=domain_pk).exists():
|
||||
domain = Domain.objects.get(id=domain_pk)
|
||||
if domain.domain_info.portfolio == portfolio:
|
||||
return True
|
||||
return False
|
|
@ -3,9 +3,13 @@ Contains middleware used in settings.py
|
|||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
from urllib.parse import parse_qs
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.urls import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import resolve
|
||||
from registrar.models import User
|
||||
from waffle.decorators import flag_is_active
|
||||
|
||||
|
@ -170,3 +174,51 @@ class CheckPortfolioMiddleware:
|
|||
request.session["portfolio"] = request.user.get_first_portfolio()
|
||||
else:
|
||||
request.session["portfolio"] = request.user.get_first_portfolio()
|
||||
|
||||
|
||||
class RestrictAccessMiddleware:
|
||||
"""
|
||||
Middleware that blocks access to all views unless explicitly permitted.
|
||||
|
||||
This middleware enforces authentication by default. Views must explicitly allow access
|
||||
using access control mechanisms such as the `@grant_access` decorator. Exceptions are made
|
||||
for Django admin views, explicitly ignored paths, and views that opt out of login requirements.
|
||||
"""
|
||||
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
# Compile regex patterns from settings to identify paths that bypass login requirements
|
||||
self.ignored_paths = [re.compile(pattern) for pattern in getattr(settings, "LOGIN_REQUIRED_IGNORE_PATHS", [])]
|
||||
|
||||
def __call__(self, request):
|
||||
|
||||
# Allow requests to Django Debug Toolbar
|
||||
if request.path.startswith("/__debug__/"):
|
||||
return self.get_response(request)
|
||||
|
||||
# Allow requests matching configured ignored paths
|
||||
if any(pattern.match(request.path) for pattern in self.ignored_paths):
|
||||
return self.get_response(request)
|
||||
|
||||
# Attempt to resolve the request path to a view function
|
||||
try:
|
||||
resolver_match = resolve(request.path_info)
|
||||
view_func = resolver_match.func
|
||||
app_name = resolver_match.app_name # Get the app name of the resolved view
|
||||
except Exception:
|
||||
# If resolution fails, allow the request to proceed (avoid blocking non-view routes)
|
||||
return self.get_response(request)
|
||||
|
||||
# Automatically allow access to Django's built-in admin views (excluding custom /admin/* views)
|
||||
if app_name == "admin":
|
||||
return self.get_response(request)
|
||||
|
||||
# Allow access if the view explicitly opts out of login requirements
|
||||
if getattr(view_func, "login_required", True) is False:
|
||||
return self.get_response(request)
|
||||
|
||||
# Restrict access to views that do not explicitly declare access rules
|
||||
if not getattr(view_func, "has_explicit_access", False):
|
||||
raise PermissionDenied # Deny access if the view lacks explicit permission handling
|
||||
|
||||
return self.get_response(request)
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain-users' pk=domain.id %}" class="usa-breadcrumb__link"><span>Domain managers</span></a>
|
||||
<a href="{% url 'domain-users' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>Domain managers</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>Add a domain manager</span>
|
||||
|
@ -27,7 +27,7 @@
|
|||
</ol>
|
||||
</nav>
|
||||
{% else %}
|
||||
{% url 'domain-users' pk=domain.id as url %}
|
||||
{% url 'domain-users' domain_pk=domain.id as url %}
|
||||
<nav class="usa-breadcrumb padding-top-0" aria-label="Domain manager breadcrumb">
|
||||
<ol class="usa-breadcrumb__list">
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
|
|
|
@ -48,11 +48,11 @@
|
|||
<p class="margin-y-0 text-primary-darker">
|
||||
{% if domain.is_expired and is_domain_manager %}
|
||||
This domain has expired, but it is still online.
|
||||
{% url 'domain-renewal' pk=domain.id as url %}
|
||||
{% url 'domain-renewal' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}" class="usa-link">Renew to maintain access.</a>
|
||||
{% elif domain.is_expiring and is_domain_manager %}
|
||||
This domain will expire soon.
|
||||
{% url 'domain-renewal' pk=domain.id as url %}
|
||||
{% url 'domain-renewal' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}" class="usa-link">Renew to maintain access.</a>
|
||||
{% elif domain.is_expiring and is_portfolio_user %}
|
||||
This domain will expire soon. Contact one of the listed domain managers to renew the domain.
|
||||
|
@ -82,7 +82,7 @@
|
|||
{% endif %}
|
||||
|
||||
|
||||
{% url 'domain-dns-nameservers' pk=domain.id as url %}
|
||||
{% url 'domain-dns-nameservers' domain_pk=domain.id as url %}
|
||||
{% if domain.nameservers|length > 0 %}
|
||||
{% include "includes/summary_item.html" with title='DNS name servers' domains='true' value=domain.nameservers list='true' edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
|
@ -95,7 +95,7 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% url 'domain-dns-dnssec' pk=domain.id as url %}
|
||||
{% url 'domain-dns-dnssec' domain_pk=domain.id as url %}
|
||||
{% if domain.dnssecdata is not None %}
|
||||
{% include "includes/summary_item.html" with title='DNSSEC' value='Enabled' edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
|
@ -104,26 +104,26 @@
|
|||
|
||||
{% if portfolio %}
|
||||
{% if has_any_domains_portfolio_permission and has_edit_portfolio_permission %}
|
||||
{% url 'domain-suborganization' pk=domain.id as url %}
|
||||
{% url 'domain-suborganization' domain_pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Suborganization' value=domain.domain_info.sub_organization edit_link=url editable=is_editable|and:has_edit_portfolio_permission %}
|
||||
{% elif has_any_domains_portfolio_permission and has_view_portfolio_permission %}
|
||||
{% url 'domain-suborganization' pk=domain.id as url %}
|
||||
{% url 'domain-suborganization' domain_pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Suborganization' value=domain.domain_info.sub_organization edit_link=url editable=is_editable|and:has_view_portfolio_permission view_button=True %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% url 'domain-org-name-address' pk=domain.id as url %}
|
||||
{% url 'domain-org-name-address' domain_pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Organization' value=domain.domain_info address='true' edit_link=url editable=is_editable %}
|
||||
{% url 'domain-senior-official' pk=domain.id as url %}
|
||||
{% url 'domain-senior-official' domain_pk=domain.id as url %}
|
||||
{% include "includes/summary_item.html" with title='Senior official' value=domain.domain_info.senior_official contact='true' edit_link=url editable=is_editable %}
|
||||
{% endif %}
|
||||
|
||||
{% url 'domain-security-email' pk=domain.id as url %}
|
||||
{% url 'domain-security-email' domain_pk=domain.id as url %}
|
||||
{% if security_email is not None and security_email not in hidden_security_emails%}
|
||||
{% include "includes/summary_item.html" with title='Security email' value=security_email edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
{% include "includes/summary_item.html" with title='Security email' value='None provided' edit_link=url editable=is_editable %}
|
||||
{% endif %}
|
||||
{% url 'domain-users' pk=domain.id as url %}
|
||||
{% url 'domain-users' domain_pk=domain.id as url %}
|
||||
{% if portfolio %}
|
||||
{% include "includes/summary_item.html" with title='Domain managers' domain_permissions=True value=domain edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>DNS</span>
|
||||
|
@ -30,14 +30,14 @@
|
|||
<p>You can enter your name servers, as well as other DNS-related information, in the following sections:</p>
|
||||
|
||||
|
||||
{% url 'domain-dns-nameservers' pk=domain.id as url %}
|
||||
{% url 'domain-dns-nameservers' domain_pk=domain.id as url %}
|
||||
<ul class="usa-list">
|
||||
<li><a href="{{ url }}">Name servers</a></li>
|
||||
|
||||
{% url 'domain-dns-dnssec' pk=domain.id as url %}
|
||||
{% url 'domain-dns-dnssec' domain_pk=domain.id as url %}
|
||||
<li><a href="{{ url }}">DNSSEC</a></li>
|
||||
{% if dns_prototype_flag and is_valid_domain %}
|
||||
<li><a href="{% url 'prototype-domain-dns' pk=domain.id %}">Prototype DNS record creator</a></li>
|
||||
<li><a href="{% url 'prototype-domain-dns' domain_pk=domain.id %}">Prototype DNS record creator</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain-dns' pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
<a href="{% url 'domain-dns' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>DNSSEC</span>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<p class="margin-y-0">It is strongly recommended that you only enable DNSSEC if you know how to set it up properly at your hosting service. If you make a mistake, it could cause your domain name to stop working.</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{% url 'domain-dns-dnssec-dsdata' pk=domain.id %}" class="usa-button">Enable DNSSEC</a>
|
||||
<a href="{% url 'domain-dns-dnssec-dsdata' domain_pk=domain.id %}" class="usa-button">Enable DNSSEC</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain-dns' pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
<a href="{% url 'domain-dns' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain-dns-dnssec' pk=domain.id %}" class="usa-breadcrumb__link"><span>DNSSEC</span></a>
|
||||
<a href="{% url 'domain-dns-dnssec' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>DNSSEC</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>DS data</span>
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain-dns' pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
<a href="{% url 'domain-dns' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>DNS</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>DNS name servers</span>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{domain.name}}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{domain.name}}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>Renewal Form</span>
|
||||
|
@ -63,14 +63,14 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% url 'domain-security-email' pk=domain.id as url %}
|
||||
{% url 'domain-security-email' domain_pk=domain.id as url %}
|
||||
{% if security_email is not None and security_email not in hidden_security_emails%}
|
||||
{% include "includes/summary_item.html" with title='Security email' value=security_email custom_text_for_value_none='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.' edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
{% include "includes/summary_item.html" with title='Security email' value='None provided' custom_text_for_value_none='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.' edit_link=url editable=is_editable %}
|
||||
{% endif %}
|
||||
|
||||
{% url 'domain-users' pk=domain.id as url %}
|
||||
{% url 'domain-users' domain_pk=domain.id as url %}
|
||||
{% if portfolio %}
|
||||
{% include "includes/summary_item.html" with title='Domain managers' domain_permissions=True value=domain edit_link=url editable=is_editable %}
|
||||
{% else %}
|
||||
|
@ -91,7 +91,7 @@
|
|||
Acknowledgement of .gov domain requirements </h3>
|
||||
</legend>
|
||||
|
||||
<form method="post" action="{% url 'domain-renewal' pk=domain.id %}">
|
||||
<form method="post" action="{% url 'domain-renewal' domain_pk=domain.id %}">
|
||||
{% csrf_token %}
|
||||
<div class="usa-checkbox">
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
</ol>
|
||||
</nav>
|
||||
{% elif steps.prev %}
|
||||
<a href="{% namespaced_url 'domain-request' steps.prev id=domain_request_id %}" class="breadcrumb__back">
|
||||
<a href="{% namespaced_url 'domain-request' steps.prev domain_request_pk=domain_request_id %}" class="breadcrumb__back">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#arrow_back"></use>
|
||||
</svg><span class="margin-left-05">Previous step</span>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</svg>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a href="{% namespaced_url 'domain-request' this_step id=domain_request_id %}"
|
||||
<a href="{% namespaced_url 'domain-request' this_step domain_request_pk=domain_request_id %}"
|
||||
{% if this_step == steps.current %}
|
||||
class="usa-current"
|
||||
{% else %}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
<p>If you withdraw your request, we won't review it. Once you withdraw your request, you can edit it and submit it again. </p>
|
||||
|
||||
<p><a href="{% url 'domain-request-withdrawn' DomainRequest.id %}" class="usa-button withdraw">Withdraw request</a>
|
||||
<a href="{% url 'domain-request-status' DomainRequest.id %}">Cancel</a></p>
|
||||
<p><a href="{% url 'domain-request-withdrawn' domain_request_pk=DomainRequest.id %}" class="usa-button withdraw">Withdraw request</a>
|
||||
<a href="{% url 'domain-request-status' domain_request_pk=DomainRequest.id %}">Cancel</a></p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>Security email</span>
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
{% endif %}
|
||||
|
||||
<li class="usa-sidenav__item">
|
||||
{% url 'domain-dns' pk=domain.id as url %}
|
||||
{% url 'domain-dns' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}" {% if request.path|startswith:url %}class="usa-current"{% endif %}">
|
||||
DNS
|
||||
</a>
|
||||
{% if request.path|startswith:url %}
|
||||
<ul class="usa-sidenav__sublist">
|
||||
<li class="usa-sidenav__item">
|
||||
{% url 'domain-dns-nameservers' pk=domain.id as url %}
|
||||
{% url 'domain-dns-nameservers' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}"
|
||||
{% if request.path == url %}class="usa-current"{% endif %}
|
||||
>
|
||||
|
@ -33,7 +33,7 @@
|
|||
</li>
|
||||
|
||||
<li class="usa-sidenav__item">
|
||||
{% url 'domain-dns-dnssec' pk=domain.id as url %}
|
||||
{% url 'domain-dns-dnssec' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}"
|
||||
{% if request.path|startswith:url %}class="usa-current"{% endif %}
|
||||
>
|
||||
|
@ -43,7 +43,7 @@
|
|||
{% if domain.dnssecdata is not None or request.path|startswith:url and request.path|endswith:'dsdata' %}
|
||||
<ul class="usa-sidenav__sublist">
|
||||
<li class="usa-sidenav__item">
|
||||
{% url 'domain-dns-dnssec-dsdata' pk=domain.id as url %}
|
||||
{% url 'domain-dns-dnssec-dsdata' domain_pk=domain.id as url %}
|
||||
<a href="{{ url }}"
|
||||
{% if request.path == url %}class="usa-current"{% endif %}
|
||||
>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>Suborganization</span>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<a href="{% url 'domains' %}" class="usa-breadcrumb__link"><span>Domains</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item">
|
||||
<a href="{% url 'domain' pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
<a href="{% url 'domain' domain_pk=domain.id %}" class="usa-breadcrumb__link"><span>{{ domain.name }}</span></a>
|
||||
</li>
|
||||
<li class="usa-breadcrumb__list-item usa-current" aria-current="page">
|
||||
<span>Domain managers</span>
|
||||
|
@ -93,7 +93,7 @@
|
|||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to remove yourself as a domain manager?" modal_description="You will no longer be able to manage the domain <strong>"|add:domain_name|add:"</strong>."|safe modal_button_id="user-delete-button-"|add:counter_str|safe modal_button_text="Yes, remove myself" modal_button_class="usa-button--secondary" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
<form method="POST" id="user-delete-form-{{ forloop.counter }}" action="{% url "domain-user-delete" pk=domain.id user_pk=item.permission.user.id %}" >
|
||||
<form method="POST" id="user-delete-form-{{ forloop.counter }}" action="{% url "domain-user-delete" domain_pk=domain.id user_pk=item.permission.user.id %}" >
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
{% else %}
|
||||
|
@ -108,7 +108,7 @@
|
|||
{% include 'includes/modal.html' with modal_heading="Are you sure you want to remove " heading_value=email|add:"?" modal_description="<strong>"|add:email|add:"</strong> will no longer be able to manage the domain <strong>"|add:domain_name|add:"</strong>."|safe modal_button_id="user-delete-button-"|add:counter_str|safe modal_button_text="Yes, remove domain manager" modal_button_class="usa-button--secondary" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
<form method="POST" id="user-delete-form-{{ forloop.counter }}" action="{% url "domain-user-delete" pk=domain.id user_pk=item.permission.user.id %}">
|
||||
<form method="POST" id="user-delete-form-{{ forloop.counter }}" action="{% url "domain-user-delete" domain_pk=domain.id user_pk=item.permission.user.id %}">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
{% endif %}
|
||||
|
@ -123,7 +123,7 @@
|
|||
></div>
|
||||
{% endif %}
|
||||
|
||||
<a class="usa-button usa-button--unstyled usa-button--with-icon" href="{% url 'domain-users-add' pk=domain.id %}">
|
||||
<a class="usa-button usa-button--unstyled usa-button--with-icon" href="{% url 'domain-users-add' domain_pk=domain.id %}">
|
||||
<svg class="usa-icon" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||
<use xlink:href="{%static 'img/sprite.svg'%}#add_circle"></use>
|
||||
</svg><span class="margin-left-05">Add a domain manager</span>
|
||||
|
@ -154,7 +154,7 @@
|
|||
{% if not portfolio %}<td data-label="Status">{{ invitation.domain_invitation.status|title }}</td>{% endif %}
|
||||
<td>
|
||||
{% if invitation.domain_invitation.status == invitation.domain_invitation.DomainInvitationStatus.INVITED %}
|
||||
<form method="POST" action="{% url "invitation-cancel" pk=invitation.domain_invitation.id %}">
|
||||
<form method="POST" action="{% url "invitation-cancel" domain_invitation_pk=invitation.domain_invitation.id %}">
|
||||
{% csrf_token %}<input type="submit" class="usa-button--unstyled text-no-underline cursor-pointer" value="Cancel">
|
||||
</form>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<li class="usa-sidenav__item">
|
||||
{% if url_name %}
|
||||
{% url url_name pk=domain.id as url %}
|
||||
{% url url_name domain_pk=domain.id as url %}
|
||||
{% endif %}
|
||||
<a href="{{ url }}"
|
||||
{% if request.path == url %}class="usa-current"{% endif %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% for step in steps %}
|
||||
<section class="summary-item margin-top-3">
|
||||
{% if is_editable %}
|
||||
{% namespaced_url 'domain-request' step id=domain_request_id as domain_request_url %}
|
||||
{% namespaced_url 'domain-request' step domain_request_pk=domain_request_id as domain_request_url %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.REQUESTING_ENTITY %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% for step in steps %}
|
||||
<section class="summary-item margin-top-3">
|
||||
{% if is_editable %}
|
||||
{% namespaced_url 'domain-request' step id=domain_request_id as domain_request_url %}
|
||||
{% namespaced_url 'domain-request' step domain_request_pk=domain_request_id as domain_request_url %}
|
||||
{% endif %}
|
||||
|
||||
{% if step == Step.ORGANIZATION_TYPE %}
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
|
||||
{% block modify_request %}
|
||||
{% if DomainRequest.is_withdrawable %}
|
||||
<p><a href="{% url 'domain-request-withdraw-confirmation' pk=DomainRequest.id %}" class="usa-button usa-button--outline withdraw_outline">
|
||||
<p><a href="{% url 'domain-request-withdraw-confirmation' domain_request_pk=DomainRequest.id %}" class="usa-button usa-button--outline withdraw_outline">
|
||||
Withdraw request</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
|
|
@ -3834,8 +3834,6 @@ class TestTransferUser(WebTest):
|
|||
|
||||
self.assertContains(after_submit, "<h1>Change user</h1>")
|
||||
|
||||
print(mock_success_message.call_args_list)
|
||||
|
||||
mock_success_message.assert_any_call(
|
||||
ANY,
|
||||
(
|
||||
|
|
|
@ -224,7 +224,7 @@ class TestDomainAdminAsStaff(MockEppLib):
|
|||
|
||||
self.assertEqual(domain.state, Domain.State.DELETED)
|
||||
|
||||
# @less_console_noise_decorator
|
||||
@less_console_noise_decorator
|
||||
def test_deletion_is_unsuccessful(self):
|
||||
"""
|
||||
Scenario: Domain deletion is unsuccessful
|
||||
|
|
|
@ -62,7 +62,7 @@ class GetSeniorOfficialJsonTest(TestCase):
|
|||
p = "password"
|
||||
self.client.login(username="testuser", password=p)
|
||||
response = self.client.get(self.api_url, {"agency_name": "Test Agency"})
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_get_senior_official_json_not_found(self):
|
||||
|
@ -138,7 +138,7 @@ class GetPortfolioJsonTest(TestCase):
|
|||
"""Test that an unauthenticated user receives a 403 with an error message."""
|
||||
self.client.force_login(self.user)
|
||||
response = self.client.get(self.api_url, {"id": self.portfolio.id})
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_get_portfolio_json_not_found(self):
|
||||
|
@ -181,7 +181,7 @@ class GetFederalPortfolioTypeJsonTest(TestCase):
|
|||
p = "password"
|
||||
self.client.login(username="testuser", password=p)
|
||||
response = self.client.get(self.api_url, {"agency_name": "Test Agency", "organization_type": "federal"})
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
class GetActionNeededEmailForUserJsonTest(TestCase):
|
||||
|
|
|
@ -38,7 +38,6 @@ from epplibwrapper import commands, common
|
|||
|
||||
from .common import (
|
||||
MockEppLib,
|
||||
less_console_noise,
|
||||
completed_domain_request,
|
||||
MockSESClient,
|
||||
MockDbForIndividualTests,
|
||||
|
@ -454,6 +453,7 @@ class TestPopulateFirstReady(TestCase):
|
|||
# Delete domains
|
||||
Domain.objects.all().delete()
|
||||
|
||||
@less_console_noise_decorator
|
||||
def run_populate_first_ready(self):
|
||||
"""
|
||||
This method executes the populate_first_ready command.
|
||||
|
@ -461,103 +461,102 @@ class TestPopulateFirstReady(TestCase):
|
|||
The 'call_command' function from Django's management framework is then used to
|
||||
execute the populate_first_ready command with the specified arguments.
|
||||
"""
|
||||
with less_console_noise():
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("populate_first_ready")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("populate_first_ready")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_populate_first_ready_state_ready(self):
|
||||
"""
|
||||
Tests that the populate_first_ready works as expected for the state 'ready'
|
||||
"""
|
||||
with less_console_noise():
|
||||
# Set the created at date
|
||||
self.ready_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.ready_domain.save()
|
||||
desired_domain = copy.deepcopy(self.ready_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
self.assertEqual(desired_domain, self.ready_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakeready.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
# Set the created at date
|
||||
self.ready_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.ready_domain.save()
|
||||
desired_domain = copy.deepcopy(self.ready_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
self.assertEqual(desired_domain, self.ready_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakeready.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_populate_first_ready_state_deleted(self):
|
||||
"""
|
||||
Tests that the populate_first_ready works as expected for the state 'deleted'
|
||||
"""
|
||||
with less_console_noise():
|
||||
# Set the created at date
|
||||
self.deleted_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.deleted_domain.save()
|
||||
desired_domain = copy.deepcopy(self.deleted_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
self.assertEqual(desired_domain, self.deleted_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakedeleted.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
# Set the created at date
|
||||
self.deleted_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.deleted_domain.save()
|
||||
desired_domain = copy.deepcopy(self.deleted_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
self.assertEqual(desired_domain, self.deleted_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakedeleted.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_populate_first_ready_state_dns_needed(self):
|
||||
"""
|
||||
Tests that the populate_first_ready doesn't make changes when a domain's state is 'dns_needed'
|
||||
"""
|
||||
with less_console_noise():
|
||||
# Set the created at date
|
||||
self.dns_needed_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.dns_needed_domain.save()
|
||||
desired_domain = copy.deepcopy(self.dns_needed_domain)
|
||||
desired_domain.first_ready = None
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.dns_needed_domain
|
||||
# The object should largely be unaltered (does not test first_ready)
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
first_ready = Domain.objects.filter(name="fakedns.gov").get().first_ready
|
||||
# Explicitly test the first_ready date
|
||||
self.assertNotEqual(first_ready, self.ready_at_date)
|
||||
self.assertEqual(first_ready, None)
|
||||
# Set the created at date
|
||||
self.dns_needed_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.dns_needed_domain.save()
|
||||
desired_domain = copy.deepcopy(self.dns_needed_domain)
|
||||
desired_domain.first_ready = None
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.dns_needed_domain
|
||||
# The object should largely be unaltered (does not test first_ready)
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
first_ready = Domain.objects.filter(name="fakedns.gov").get().first_ready
|
||||
# Explicitly test the first_ready date
|
||||
self.assertNotEqual(first_ready, self.ready_at_date)
|
||||
self.assertEqual(first_ready, None)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_populate_first_ready_state_on_hold(self):
|
||||
"""
|
||||
Tests that the populate_first_ready works as expected for the state 'on_hold'
|
||||
"""
|
||||
with less_console_noise():
|
||||
self.hold_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.hold_domain.save()
|
||||
desired_domain = copy.deepcopy(self.hold_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the update first ready_at script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.hold_domain
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakehold.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
self.hold_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.hold_domain.save()
|
||||
desired_domain = copy.deepcopy(self.hold_domain)
|
||||
desired_domain.first_ready = self.ready_at_date
|
||||
# Run the update first ready_at script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.hold_domain
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakehold.gov").get().first_ready
|
||||
self.assertEqual(first_ready, self.ready_at_date)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_populate_first_ready_state_unknown(self):
|
||||
"""
|
||||
Tests that the populate_first_ready works as expected for the state 'unknown'
|
||||
"""
|
||||
with less_console_noise():
|
||||
# Set the created at date
|
||||
self.unknown_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.unknown_domain.save()
|
||||
desired_domain = copy.deepcopy(self.unknown_domain)
|
||||
desired_domain.first_ready = None
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.unknown_domain
|
||||
# The object should largely be unaltered (does not test first_ready)
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakeunknown.gov").get().first_ready
|
||||
self.assertNotEqual(first_ready, self.ready_at_date)
|
||||
self.assertEqual(first_ready, None)
|
||||
# Set the created at date
|
||||
self.unknown_domain.created_at = self.ready_at_date_tz_aware
|
||||
self.unknown_domain.save()
|
||||
desired_domain = copy.deepcopy(self.unknown_domain)
|
||||
desired_domain.first_ready = None
|
||||
# Run the expiration date script
|
||||
self.run_populate_first_ready()
|
||||
current_domain = self.unknown_domain
|
||||
# The object should largely be unaltered (does not test first_ready)
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the first_ready date
|
||||
first_ready = Domain.objects.filter(name="fakeunknown.gov").get().first_ready
|
||||
self.assertNotEqual(first_ready, self.ready_at_date)
|
||||
self.assertEqual(first_ready, None)
|
||||
|
||||
|
||||
class TestPatchAgencyInfo(TestCase):
|
||||
|
@ -578,10 +577,10 @@ class TestPatchAgencyInfo(TestCase):
|
|||
TransitionDomain.objects.all().delete()
|
||||
|
||||
@patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", return_value=True)
|
||||
@less_console_noise_decorator
|
||||
def call_patch_federal_agency_info(self, mock_prompt):
|
||||
"""Calls the patch_federal_agency_info command and mimics a keypress"""
|
||||
with less_console_noise():
|
||||
call_command("patch_federal_agency_info", "registrar/tests/data/fake_current_full.csv", debug=True)
|
||||
call_command("patch_federal_agency_info", "registrar/tests/data/fake_current_full.csv", debug=True)
|
||||
|
||||
|
||||
class TestExtendExpirationDates(MockEppLib):
|
||||
|
@ -637,6 +636,7 @@ class TestExtendExpirationDates(MockEppLib):
|
|||
User.objects.all().delete()
|
||||
UserDomainRole.objects.all().delete()
|
||||
|
||||
@less_console_noise_decorator
|
||||
def run_extend_expiration_dates(self):
|
||||
"""
|
||||
This method executes the extend_expiration_dates command.
|
||||
|
@ -644,83 +644,83 @@ class TestExtendExpirationDates(MockEppLib):
|
|||
The 'call_command' function from Django's management framework is then used to
|
||||
execute the extend_expiration_dates command with the specified arguments.
|
||||
"""
|
||||
with less_console_noise():
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("extend_expiration_dates")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("extend_expiration_dates")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_extends_expiration_date_correctly(self):
|
||||
"""
|
||||
Tests that the extend_expiration_dates method extends dates as expected
|
||||
"""
|
||||
with less_console_noise():
|
||||
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 11, 15)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date
|
||||
self.assertEqual(current_domain.expiration_date, date(2024, 11, 15))
|
||||
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 11, 15)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date
|
||||
self.assertEqual(current_domain.expiration_date, date(2024, 11, 15))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_extends_expiration_date_skips_non_current(self):
|
||||
"""
|
||||
Tests that the extend_expiration_dates method correctly skips domains
|
||||
with an expiration date less than a certain threshold.
|
||||
"""
|
||||
with less_console_noise():
|
||||
desired_domain = Domain.objects.filter(name="fake.gov").get()
|
||||
desired_domain.expiration_date = date(2022, 5, 25)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="fake.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2022, 5, 25))
|
||||
desired_domain = Domain.objects.filter(name="fake.gov").get()
|
||||
desired_domain.expiration_date = date(2022, 5, 25)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="fake.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2022, 5, 25))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_extends_expiration_date_skips_maximum_date(self):
|
||||
"""
|
||||
Tests that the extend_expiration_dates method correctly skips domains
|
||||
with an expiration date more than a certain threshold.
|
||||
"""
|
||||
with less_console_noise():
|
||||
desired_domain = Domain.objects.filter(name="fakemaximum.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 12, 31)
|
||||
desired_domain = Domain.objects.filter(name="fakemaximum.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 12, 31)
|
||||
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
|
||||
current_domain = Domain.objects.filter(name="fakemaximum.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
current_domain = Domain.objects.filter(name="fakemaximum.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2024, 12, 31))
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2024, 12, 31))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_extends_expiration_date_skips_non_ready(self):
|
||||
"""
|
||||
Tests that the extend_expiration_dates method correctly skips domains not in the state "ready"
|
||||
"""
|
||||
with less_console_noise():
|
||||
desired_domain = Domain.objects.filter(name="fakeneeded.gov").get()
|
||||
desired_domain.expiration_date = date(2023, 11, 15)
|
||||
desired_domain = Domain.objects.filter(name="fakeneeded.gov").get()
|
||||
desired_domain.expiration_date = date(2023, 11, 15)
|
||||
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
|
||||
current_domain = Domain.objects.filter(name="fakeneeded.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
current_domain = Domain.objects.filter(name="fakeneeded.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2023, 11, 15))
|
||||
# Explicitly test the expiration date. The extend_expiration_dates script
|
||||
# will skip all dates less than date(2023, 11, 15), meaning that this domain
|
||||
# should not be affected by the change.
|
||||
self.assertEqual(current_domain.expiration_date, date(2023, 11, 15))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_extends_expiration_date_idempotent(self):
|
||||
"""
|
||||
Tests the idempotency of the extend_expiration_dates command.
|
||||
|
@ -728,21 +728,20 @@ class TestExtendExpirationDates(MockEppLib):
|
|||
Verifies that running the method multiple times does not change the expiration date
|
||||
of a domain beyond the initial extension.
|
||||
"""
|
||||
with less_console_noise():
|
||||
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 11, 15)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date
|
||||
self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
|
||||
# Run the expiration date script again
|
||||
self.run_extend_expiration_dates()
|
||||
# The old domain shouldn't have changed
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date - should be the same
|
||||
self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
|
||||
desired_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
desired_domain.expiration_date = date(2024, 11, 15)
|
||||
# Run the expiration date script
|
||||
self.run_extend_expiration_dates()
|
||||
current_domain = Domain.objects.filter(name="waterbutpurple.gov").get()
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date
|
||||
self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
|
||||
# Run the expiration date script again
|
||||
self.run_extend_expiration_dates()
|
||||
# The old domain shouldn't have changed
|
||||
self.assertEqual(desired_domain, current_domain)
|
||||
# Explicitly test the expiration date - should be the same
|
||||
self.assertEqual(desired_domain.expiration_date, date(2024, 11, 15))
|
||||
|
||||
|
||||
class TestDiscloseEmails(MockEppLib):
|
||||
|
@ -754,6 +753,7 @@ class TestDiscloseEmails(MockEppLib):
|
|||
PublicContact.objects.all().delete()
|
||||
Domain.objects.all().delete()
|
||||
|
||||
@less_console_noise_decorator
|
||||
def run_disclose_security_emails(self):
|
||||
"""
|
||||
This method executes the disclose_security_emails command.
|
||||
|
@ -761,44 +761,43 @@ class TestDiscloseEmails(MockEppLib):
|
|||
The 'call_command' function from Django's management framework is then used to
|
||||
execute the disclose_security_emails command.
|
||||
"""
|
||||
with less_console_noise():
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("disclose_security_emails")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("disclose_security_emails")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_disclose_security_emails(self):
|
||||
"""
|
||||
Tests that command disclose_security_emails runs successfully with
|
||||
appropriate EPP calll to UpdateContact.
|
||||
"""
|
||||
with less_console_noise():
|
||||
domain, _ = Domain.objects.get_or_create(name="testdisclose.gov", state=Domain.State.READY)
|
||||
expectedSecContact = PublicContact.get_default_security()
|
||||
expectedSecContact.domain = domain
|
||||
expectedSecContact.email = "123@mail.gov"
|
||||
# set domain security email to 123@mail.gov instead of default email
|
||||
domain.security_contact = expectedSecContact
|
||||
self.run_disclose_security_emails()
|
||||
domain, _ = Domain.objects.get_or_create(name="testdisclose.gov", state=Domain.State.READY)
|
||||
expectedSecContact = PublicContact.get_default_security()
|
||||
expectedSecContact.domain = domain
|
||||
expectedSecContact.email = "123@mail.gov"
|
||||
# set domain security email to 123@mail.gov instead of default email
|
||||
domain.security_contact = expectedSecContact
|
||||
self.run_disclose_security_emails()
|
||||
|
||||
# running disclose_security_emails sends EPP call UpdateContact with disclose
|
||||
self.mockedSendFunction.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
commands.UpdateContact(
|
||||
id=domain.security_contact.registry_id,
|
||||
postal_info=domain._make_epp_contact_postal_info(contact=domain.security_contact),
|
||||
email=domain.security_contact.email,
|
||||
voice=domain.security_contact.voice,
|
||||
fax=domain.security_contact.fax,
|
||||
auth_info=common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
||||
disclose=domain._disclose_fields(contact=domain.security_contact),
|
||||
),
|
||||
cleaned=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
# running disclose_security_emails sends EPP call UpdateContact with disclose
|
||||
self.mockedSendFunction.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
commands.UpdateContact(
|
||||
id=domain.security_contact.registry_id,
|
||||
postal_info=domain._make_epp_contact_postal_info(contact=domain.security_contact),
|
||||
email=domain.security_contact.email,
|
||||
voice=domain.security_contact.voice,
|
||||
fax=domain.security_contact.fax,
|
||||
auth_info=common.ContactAuthInfo(pw="2fooBAR123fooBaz"),
|
||||
disclose=domain._disclose_fields(contact=domain.security_contact),
|
||||
),
|
||||
cleaned=True,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestCleanTables(TestCase):
|
||||
|
@ -813,17 +812,18 @@ class TestCleanTables(TestCase):
|
|||
self.logger_patcher.stop()
|
||||
|
||||
@override_settings(IS_PRODUCTION=True)
|
||||
@less_console_noise_decorator
|
||||
def test_command_logs_error_in_production(self):
|
||||
"""Test that the handle method does not process in production"""
|
||||
with less_console_noise():
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("clean_tables")
|
||||
self.logger_mock.error.assert_called_with("clean_tables cannot be run in production")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("clean_tables")
|
||||
self.logger_mock.error.assert_called_with("clean_tables cannot be run in production")
|
||||
|
||||
@override_settings(IS_PRODUCTION=False)
|
||||
@less_console_noise_decorator
|
||||
def test_command_cleans_tables(self):
|
||||
"""test that the handle method functions properly to clean tables"""
|
||||
|
||||
|
@ -891,61 +891,61 @@ class TestCleanTables(TestCase):
|
|||
raise
|
||||
|
||||
@override_settings(IS_PRODUCTION=False)
|
||||
@less_console_noise_decorator
|
||||
def test_command_handles_nonexistent_model(self):
|
||||
"""Test that exceptions for non existent models are handled properly within the handle method"""
|
||||
with less_console_noise():
|
||||
with patch("django.apps.apps.get_model", side_effect=LookupError):
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("clean_tables")
|
||||
# Assert that the error message was logged for any of the table names
|
||||
self.logger_mock.error.assert_any_call("Model for table DomainInformation not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table DomainRequest not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table PublicContact not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Domain not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table User not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Contact not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Website not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table DraftDomain not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table HostIp not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Host not found.")
|
||||
with patch("django.apps.apps.get_model", side_effect=LookupError):
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("clean_tables")
|
||||
# Assert that the error message was logged for any of the table names
|
||||
self.logger_mock.error.assert_any_call("Model for table DomainInformation not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table DomainRequest not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table PublicContact not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Domain not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table User not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Contact not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Website not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table DraftDomain not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table HostIp not found.")
|
||||
self.logger_mock.error.assert_any_call("Model for table Host not found.")
|
||||
|
||||
@override_settings(IS_PRODUCTION=False)
|
||||
@less_console_noise_decorator
|
||||
def test_command_logs_other_exceptions(self):
|
||||
"""Test that generic exceptions are handled properly in the handle method"""
|
||||
with less_console_noise():
|
||||
with patch("django.apps.apps.get_model") as get_model_mock:
|
||||
model_mock = MagicMock()
|
||||
get_model_mock.return_value = model_mock
|
||||
with patch("django.apps.apps.get_model") as get_model_mock:
|
||||
model_mock = MagicMock()
|
||||
get_model_mock.return_value = model_mock
|
||||
|
||||
# Mock the values_list so that DomainInformation attempts a delete
|
||||
pk_batches = [[1, 2, 3, 4, 5, 6], []]
|
||||
# Mock the values_list so that DomainInformation attempts a delete
|
||||
pk_batches = [[1, 2, 3, 4, 5, 6], []]
|
||||
|
||||
def values_list_side_effect(*args, **kwargs):
|
||||
if args == ("pk",) and kwargs.get("flat", False):
|
||||
return pk_batches.pop(0)
|
||||
return []
|
||||
def values_list_side_effect(*args, **kwargs):
|
||||
if args == ("pk",) and kwargs.get("flat", False):
|
||||
return pk_batches.pop(0)
|
||||
return []
|
||||
|
||||
model_mock.objects.values_list.side_effect = values_list_side_effect
|
||||
model_mock.objects.values_list.side_effect = values_list_side_effect
|
||||
|
||||
# Mock delete to raise a generic exception
|
||||
model_mock.objects.filter.return_value.delete.side_effect = Exception("Mocked delete exception")
|
||||
# Mock delete to raise a generic exception
|
||||
model_mock.objects.filter.return_value.delete.side_effect = Exception("Mocked delete exception")
|
||||
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit",
|
||||
return_value=True,
|
||||
):
|
||||
with self.assertRaises(Exception) as context:
|
||||
# Execute the command
|
||||
call_command("clean_tables")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit",
|
||||
return_value=True,
|
||||
):
|
||||
with self.assertRaises(Exception) as context:
|
||||
# Execute the command
|
||||
call_command("clean_tables")
|
||||
|
||||
# Check the exception message
|
||||
self.assertEqual(str(context.exception), "Custom delete error")
|
||||
# Check the exception message
|
||||
self.assertEqual(str(context.exception), "Custom delete error")
|
||||
|
||||
# Assert that delete was called
|
||||
model_mock.objects.filter.return_value.delete.assert_called()
|
||||
# Assert that delete was called
|
||||
model_mock.objects.filter.return_value.delete.assert_called()
|
||||
|
||||
|
||||
class TestExportTables(MockEppLib):
|
||||
|
@ -1030,34 +1030,34 @@ class TestExportTables(MockEppLib):
|
|||
self.logger_mock.info.assert_any_call(f"Removed {table_name}_1.csv")
|
||||
|
||||
@patch("registrar.management.commands.export_tables.getattr")
|
||||
@less_console_noise_decorator
|
||||
def test_export_table_handles_missing_resource_class(self, mock_getattr):
|
||||
"""Test that missing resource classes are handled properly in the handle method"""
|
||||
with less_console_noise():
|
||||
mock_getattr.side_effect = AttributeError
|
||||
mock_getattr.side_effect = AttributeError
|
||||
|
||||
# Import the command to avoid any locale or gettext issues
|
||||
command_class = import_string("registrar.management.commands.export_tables.Command")
|
||||
command_instance = command_class()
|
||||
command_instance.export_table("NonExistentTable")
|
||||
# Import the command to avoid any locale or gettext issues
|
||||
command_class = import_string("registrar.management.commands.export_tables.Command")
|
||||
command_instance = command_class()
|
||||
command_instance.export_table("NonExistentTable")
|
||||
|
||||
self.logger_mock.error.assert_called_with(
|
||||
"Resource class NonExistentTableResource not found in registrar.admin"
|
||||
)
|
||||
self.logger_mock.error.assert_called_with(
|
||||
"Resource class NonExistentTableResource not found in registrar.admin"
|
||||
)
|
||||
|
||||
@patch("registrar.management.commands.export_tables.getattr")
|
||||
@less_console_noise_decorator
|
||||
def test_export_table_handles_generic_exception(self, mock_getattr):
|
||||
"""Test that general exceptions in the handle method are handled correctly"""
|
||||
with less_console_noise():
|
||||
mock_resource_class = MagicMock()
|
||||
mock_resource_class().export.side_effect = Exception("Test Exception")
|
||||
mock_getattr.return_value = mock_resource_class
|
||||
mock_resource_class = MagicMock()
|
||||
mock_resource_class().export.side_effect = Exception("Test Exception")
|
||||
mock_getattr.return_value = mock_resource_class
|
||||
|
||||
# Import the command to avoid any locale or gettext issues
|
||||
command_class = import_string("registrar.management.commands.export_tables.Command")
|
||||
command_instance = command_class()
|
||||
command_instance.export_table("TestTable")
|
||||
# Import the command to avoid any locale or gettext issues
|
||||
command_class = import_string("registrar.management.commands.export_tables.Command")
|
||||
command_instance = command_class()
|
||||
command_instance.export_table("TestTable")
|
||||
|
||||
self.logger_mock.error.assert_called_with("Failed to export TestTable: Test Exception")
|
||||
self.logger_mock.error.assert_called_with("Failed to export TestTable: Test Exception")
|
||||
|
||||
|
||||
class TestImportTables(TestCase):
|
||||
|
@ -1073,6 +1073,7 @@ class TestImportTables(TestCase):
|
|||
@patch("registrar.management.commands.import_tables.getattr")
|
||||
@patch("django.apps.apps.get_model")
|
||||
@patch("os.listdir")
|
||||
@less_console_noise_decorator
|
||||
def test_handle(
|
||||
self,
|
||||
mock_listdir,
|
||||
|
@ -1087,105 +1088,104 @@ class TestImportTables(TestCase):
|
|||
mock_makedirs,
|
||||
):
|
||||
"""Test that the handle method properly imports tables"""
|
||||
with less_console_noise():
|
||||
# Mock os.makedirs to do nothing
|
||||
mock_makedirs.return_value = None
|
||||
# Mock os.makedirs to do nothing
|
||||
mock_makedirs.return_value = None
|
||||
|
||||
# Mock os.path.exists to always return True
|
||||
mock_path_exists.return_value = True
|
||||
# Mock os.path.exists to always return True
|
||||
mock_path_exists.return_value = True
|
||||
|
||||
# Mock the zipfile to have extractall return None
|
||||
mock_zipfile_instance = mock_zipfile.return_value.__enter__.return_value
|
||||
mock_zipfile_instance.extractall.return_value = None
|
||||
# Mock the zipfile to have extractall return None
|
||||
mock_zipfile_instance = mock_zipfile.return_value.__enter__.return_value
|
||||
mock_zipfile_instance.extractall.return_value = None
|
||||
|
||||
# Check that the import_table function was called for each table
|
||||
table_names = [
|
||||
"User",
|
||||
"Contact",
|
||||
"Domain",
|
||||
"DomainRequest",
|
||||
"DomainInformation",
|
||||
"UserDomainRole",
|
||||
"DraftDomain",
|
||||
"Website",
|
||||
"HostIp",
|
||||
"Host",
|
||||
"PublicContact",
|
||||
]
|
||||
# Check that the import_table function was called for each table
|
||||
table_names = [
|
||||
"User",
|
||||
"Contact",
|
||||
"Domain",
|
||||
"DomainRequest",
|
||||
"DomainInformation",
|
||||
"UserDomainRole",
|
||||
"DraftDomain",
|
||||
"Website",
|
||||
"HostIp",
|
||||
"Host",
|
||||
"PublicContact",
|
||||
]
|
||||
|
||||
# Mock directory listing
|
||||
mock_listdir.side_effect = lambda path: [f"{table}_1.csv" for table in table_names]
|
||||
# Mock directory listing
|
||||
mock_listdir.side_effect = lambda path: [f"{table}_1.csv" for table in table_names]
|
||||
|
||||
# Mock the CSV file content
|
||||
csv_content = b"mock_csv_data"
|
||||
# Mock the CSV file content
|
||||
csv_content = b"mock_csv_data"
|
||||
|
||||
# Mock the open function to return a mock file
|
||||
mock_open.return_value.__enter__.return_value.read.return_value = csv_content
|
||||
# Mock the open function to return a mock file
|
||||
mock_open.return_value.__enter__.return_value.read.return_value = csv_content
|
||||
|
||||
# Mock the Dataset class and its load method to return a dataset
|
||||
mock_dataset_instance = MagicMock(spec=tablib.Dataset)
|
||||
with patch(
|
||||
"registrar.management.commands.import_tables.tablib.Dataset.load", return_value=mock_dataset_instance
|
||||
):
|
||||
# Mock the resource class and its import method
|
||||
mock_resource_class = MagicMock()
|
||||
mock_resource_instance = MagicMock()
|
||||
mock_result = MagicMock()
|
||||
mock_result.has_errors.return_value = False
|
||||
mock_resource_instance.import_data.return_value = mock_result
|
||||
mock_resource_class.return_value = mock_resource_instance
|
||||
mock_getattr.return_value = mock_resource_class
|
||||
# Mock the Dataset class and its load method to return a dataset
|
||||
mock_dataset_instance = MagicMock(spec=tablib.Dataset)
|
||||
with patch(
|
||||
"registrar.management.commands.import_tables.tablib.Dataset.load", return_value=mock_dataset_instance
|
||||
):
|
||||
# Mock the resource class and its import method
|
||||
mock_resource_class = MagicMock()
|
||||
mock_resource_instance = MagicMock()
|
||||
mock_result = MagicMock()
|
||||
mock_result.has_errors.return_value = False
|
||||
mock_resource_instance.import_data.return_value = mock_result
|
||||
mock_resource_class.return_value = mock_resource_instance
|
||||
mock_getattr.return_value = mock_resource_class
|
||||
|
||||
# Call the command
|
||||
call_command("import_tables")
|
||||
# Call the command
|
||||
call_command("import_tables")
|
||||
|
||||
# Check that os.makedirs was called once to create the tmp directory
|
||||
mock_makedirs.assert_called_once_with("tmp", exist_ok=True)
|
||||
# Check that os.makedirs was called once to create the tmp directory
|
||||
mock_makedirs.assert_called_once_with("tmp", exist_ok=True)
|
||||
|
||||
# Check that os.path.exists was called once for the zip file
|
||||
mock_path_exists.assert_any_call("tmp/exported_tables.zip")
|
||||
# Check that os.path.exists was called once for the zip file
|
||||
mock_path_exists.assert_any_call("tmp/exported_tables.zip")
|
||||
|
||||
# Check that pyzipper.AESZipFile was called once to open the zip file
|
||||
mock_zipfile.assert_called_once_with("tmp/exported_tables.zip", "r")
|
||||
# Check that pyzipper.AESZipFile was called once to open the zip file
|
||||
mock_zipfile.assert_called_once_with("tmp/exported_tables.zip", "r")
|
||||
|
||||
# Check that extractall was called once to extract the zip file contents
|
||||
mock_zipfile_instance.extractall.assert_called_once_with("tmp")
|
||||
# Check that extractall was called once to extract the zip file contents
|
||||
mock_zipfile_instance.extractall.assert_called_once_with("tmp")
|
||||
|
||||
# Check that os.path.exists was called for each table
|
||||
for table_name in table_names:
|
||||
mock_path_exists.assert_any_call(f"{table_name}_1.csv")
|
||||
# Check that os.path.exists was called for each table
|
||||
for table_name in table_names:
|
||||
mock_path_exists.assert_any_call(f"{table_name}_1.csv")
|
||||
|
||||
# Check that logger.info was called for each successful import
|
||||
for table_name in table_names:
|
||||
mock_logger.info.assert_any_call(f"Successfully imported {table_name}_1.csv into {table_name}")
|
||||
# Check that logger.info was called for each successful import
|
||||
for table_name in table_names:
|
||||
mock_logger.info.assert_any_call(f"Successfully imported {table_name}_1.csv into {table_name}")
|
||||
|
||||
# Check that logger.error was not called for resource class not found
|
||||
mock_logger.error.assert_not_called()
|
||||
# Check that logger.error was not called for resource class not found
|
||||
mock_logger.error.assert_not_called()
|
||||
|
||||
# Check that os.remove was called for each CSV file
|
||||
for table_name in table_names:
|
||||
mock_remove.assert_any_call(f"{table_name}_1.csv")
|
||||
# Check that os.remove was called for each CSV file
|
||||
for table_name in table_names:
|
||||
mock_remove.assert_any_call(f"{table_name}_1.csv")
|
||||
|
||||
# Check that logger.info was called for each CSV file removal
|
||||
for table_name in table_names:
|
||||
mock_logger.info.assert_any_call(f"Removed temporary file {table_name}_1.csv")
|
||||
# Check that logger.info was called for each CSV file removal
|
||||
for table_name in table_names:
|
||||
mock_logger.info.assert_any_call(f"Removed temporary file {table_name}_1.csv")
|
||||
|
||||
@patch("registrar.management.commands.import_tables.logger")
|
||||
@patch("registrar.management.commands.import_tables.os.makedirs")
|
||||
@patch("registrar.management.commands.import_tables.os.path.exists")
|
||||
@less_console_noise_decorator
|
||||
def test_handle_zip_file_not_found(self, mock_path_exists, mock_makedirs, mock_logger):
|
||||
"""Test the handle method when the zip file doesn't exist"""
|
||||
with less_console_noise():
|
||||
# Mock os.makedirs to do nothing
|
||||
mock_makedirs.return_value = None
|
||||
# Mock os.makedirs to do nothing
|
||||
mock_makedirs.return_value = None
|
||||
|
||||
# Mock os.path.exists to return False
|
||||
mock_path_exists.return_value = False
|
||||
# Mock os.path.exists to return False
|
||||
mock_path_exists.return_value = False
|
||||
|
||||
call_command("import_tables")
|
||||
call_command("import_tables")
|
||||
|
||||
# Check that logger.error was called with the correct message
|
||||
mock_logger.error.assert_called_once_with("Zip file tmp/exported_tables.zip does not exist.")
|
||||
# Check that logger.error was called with the correct message
|
||||
mock_logger.error.assert_called_once_with("Zip file tmp/exported_tables.zip does not exist.")
|
||||
|
||||
|
||||
class TestTransferFederalAgencyType(TestCase):
|
||||
|
@ -1255,6 +1255,7 @@ class TestTransferFederalAgencyType(TestCase):
|
|||
id__in=[self.amtrak.id, self.legislative_branch.id, self.library_of_congress.id, self.gov_admin.id]
|
||||
).delete()
|
||||
|
||||
@less_console_noise_decorator
|
||||
def run_transfer_federal_agency_type(self):
|
||||
"""
|
||||
This method executes the transfer_federal_agency_type command.
|
||||
|
@ -1262,12 +1263,11 @@ class TestTransferFederalAgencyType(TestCase):
|
|||
The 'call_command' function from Django's management framework is then used to
|
||||
execute the populate_first_ready command with the specified arguments.
|
||||
"""
|
||||
with less_console_noise():
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("transfer_federal_agency_type")
|
||||
with patch(
|
||||
"registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no_exit", # noqa
|
||||
return_value=True,
|
||||
):
|
||||
call_command("transfer_federal_agency_type")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_transfer_federal_agency_type_script(self):
|
||||
|
@ -1630,6 +1630,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
# Test the senior official
|
||||
self.assertEqual(portfolio.senior_official, self.senior_official)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_create_multiple_portfolios_for_branch_judicial(self):
|
||||
"""Tests creating all portfolios under a given branch"""
|
||||
federal_choice = DomainRequest.OrganizationChoices.FEDERAL
|
||||
|
@ -1657,6 +1658,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertTrue(all([creator == User.get_default_user() for creator in creators]))
|
||||
self.assertTrue(all([note == "Auto-generated record" for note in notes]))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_create_multiple_portfolios_for_branch_legislative(self):
|
||||
"""Tests creating all portfolios under a given branch"""
|
||||
federal_choice = DomainRequest.OrganizationChoices.FEDERAL
|
||||
|
@ -1684,6 +1686,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertTrue(all([creator == User.get_default_user() for creator in creators]))
|
||||
self.assertTrue(all([note == "Auto-generated record" for note in notes]))
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_script_adds_requested_suborganization_information(self):
|
||||
"""Tests that the script adds the requested suborg fields for domain requests"""
|
||||
# Create a new domain request with some errant spacing
|
||||
|
@ -1712,6 +1715,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
custom_suborg_request.suborganization_state_territory, DomainRequest.StateTerritoryChoices.TEXAS
|
||||
)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_create_multiple_portfolios_for_branch_executive(self):
|
||||
"""Tests creating all portfolios under a given branch"""
|
||||
federal_choice = DomainRequest.OrganizationChoices.FEDERAL
|
||||
|
@ -1774,6 +1778,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertEqual(expected_requests.count(), 2)
|
||||
self.assertEqual(expected_domain_infos.count(), 2)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_handle_portfolio_requests(self):
|
||||
"""Verify portfolio association with domain requests."""
|
||||
self.run_create_federal_portfolio(agency_name="Test Federal Agency", parse_requests=True)
|
||||
|
@ -1783,6 +1788,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertEqual(self.domain_request.portfolio.federal_agency, self.federal_agency)
|
||||
self.assertEqual(self.domain_request.sub_organization.name, "Testorg")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_handle_portfolio_domains(self):
|
||||
"""Check portfolio association with domain information."""
|
||||
self.run_create_federal_portfolio(agency_name="Test Federal Agency", parse_domains=True)
|
||||
|
@ -1792,6 +1798,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertEqual(self.domain_info.portfolio.federal_agency, self.federal_agency)
|
||||
self.assertEqual(self.domain_info.sub_organization.name, "Testorg")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_handle_parse_both(self):
|
||||
"""Ensure correct parsing of both requests and domains."""
|
||||
self.run_create_federal_portfolio(agency_name="Test Federal Agency", parse_requests=True, parse_domains=True)
|
||||
|
@ -1802,6 +1809,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
self.assertIsNotNone(self.domain_info.portfolio)
|
||||
self.assertEqual(self.domain_request.portfolio, self.domain_info.portfolio)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_command_error_parse_options(self):
|
||||
"""Verify error when bad parse options are provided."""
|
||||
# The command should enforce either --branch or --agency_name
|
||||
|
@ -1823,6 +1831,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
):
|
||||
self.run_create_federal_portfolio(agency_name="test")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_command_error_agency_not_found(self):
|
||||
"""Check error handling for non-existent agency."""
|
||||
expected_message = (
|
||||
|
@ -1832,6 +1841,7 @@ class TestCreateFederalPortfolio(TestCase):
|
|||
with self.assertRaisesRegex(CommandError, expected_message):
|
||||
self.run_create_federal_portfolio(agency_name="Non-existent Agency", parse_requests=True)
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_does_not_update_existing_portfolio(self):
|
||||
"""Tests that an existing portfolio is not updated when"""
|
||||
# Create an existing portfolio
|
||||
|
@ -2433,6 +2443,7 @@ class TestRemovePortfolios(TestCase):
|
|||
Portfolio.objects.all().delete()
|
||||
User.objects.all().delete()
|
||||
|
||||
@less_console_noise_decorator
|
||||
@patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no")
|
||||
def test_delete_unlisted_portfolios(self, mock_query_yes_no):
|
||||
"""Test that portfolios not on the allowed list are deleted."""
|
||||
|
@ -2450,6 +2461,7 @@ class TestRemovePortfolios(TestCase):
|
|||
self.assertFalse(Portfolio.objects.filter(organization_name="Test with suborg").exists())
|
||||
self.assertTrue(Portfolio.objects.filter(organization_name="Department of Veterans Affairs").exists())
|
||||
|
||||
@less_console_noise_decorator
|
||||
@patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no")
|
||||
def test_delete_entries_with_related_objects(self, mock_query_yes_no):
|
||||
"""Test deletion with related objects being handled properly."""
|
||||
|
@ -2473,6 +2485,7 @@ class TestRemovePortfolios(TestCase):
|
|||
# Check that the portfolio was deleted
|
||||
self.assertFalse(Portfolio.objects.filter(organization_name="Test with orphaned objects").exists())
|
||||
|
||||
@less_console_noise_decorator
|
||||
@patch("registrar.management.commands.utility.terminal_helper.TerminalHelper.query_yes_no")
|
||||
def test_delete_entries_with_suborganizations(self, mock_query_yes_no):
|
||||
"""Test that suborganizations and their related objects are deleted along with the portfolio."""
|
||||
|
|
|
@ -2039,7 +2039,7 @@ class TestDomainRequestIncomplete(TestCase):
|
|||
self.wizard = DomainRequestWizard()
|
||||
self.wizard._domain_request = self.domain_request
|
||||
self.wizard.request = Mock(user=self.user, session={})
|
||||
self.wizard.kwargs = {"id": self.domain_request.id}
|
||||
self.wizard.kwargs = {"domain_request_pk": self.domain_request.id}
|
||||
|
||||
# We use both of these flags in the test. In the normal app these are generated normally.
|
||||
# The alternative syntax is adding the decorator to each test.
|
||||
|
|
|
@ -18,6 +18,9 @@ from .common import less_console_noise
|
|||
# request on the view.
|
||||
SAMPLE_KWARGS = {
|
||||
"app_label": "registrar",
|
||||
"domain_pk": "1",
|
||||
"domain_request_pk": "1",
|
||||
"domain_invitation_pk": "1",
|
||||
"pk": "1",
|
||||
"id": "1",
|
||||
"content_type_id": "2",
|
||||
|
@ -82,7 +85,6 @@ def iter_sample_urls(urlconf):
|
|||
if not viewname:
|
||||
continue
|
||||
if viewname == "auth_user_password_change":
|
||||
print(route)
|
||||
break
|
||||
named_groups = route.regex.groupindex.keys()
|
||||
kwargs = {}
|
||||
|
|
|
@ -126,7 +126,7 @@ class TestEnvironmentVariablesEffects(TestCase):
|
|||
with patch.object(DomainNameserversView, "get_initial", side_effect=self.side_effect_raise_value_error):
|
||||
with self.assertRaises(ValueError):
|
||||
contact_page_500 = self.client.get(
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": fake_domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": fake_domain.id}),
|
||||
)
|
||||
|
||||
# Check that a 500 response is returned
|
||||
|
@ -147,7 +147,7 @@ class TestEnvironmentVariablesEffects(TestCase):
|
|||
with patch.object(DomainNameserversView, "get_initial", side_effect=self.side_effect_raise_value_error):
|
||||
with self.assertRaises(ValueError):
|
||||
contact_page_500 = self.client.get(
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": fake_domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": fake_domain.id}),
|
||||
)
|
||||
|
||||
# Check that a 500 response is returned
|
||||
|
@ -292,7 +292,9 @@ class HomeTests(TestWithUser):
|
|||
)
|
||||
|
||||
# Trigger the delete logic
|
||||
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}), follow=True
|
||||
)
|
||||
|
||||
self.assertNotContains(response, "igorville.gov")
|
||||
|
||||
|
@ -309,7 +311,9 @@ class HomeTests(TestWithUser):
|
|||
)
|
||||
|
||||
# Trigger the delete logic
|
||||
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}), follow=True
|
||||
)
|
||||
|
||||
self.assertNotContains(response, "igorville.gov")
|
||||
|
||||
|
@ -335,7 +339,8 @@ class HomeTests(TestWithUser):
|
|||
|
||||
# Trigger the delete logic
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}),
|
||||
follow=True,
|
||||
)
|
||||
|
||||
# Check for a 403 error - the end user should not be allowed to do this
|
||||
|
@ -392,7 +397,7 @@ class HomeTests(TestWithUser):
|
|||
self.assertTrue(igorville.exists())
|
||||
|
||||
# Trigger the delete logic
|
||||
self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}))
|
||||
self.client.post(reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
|
||||
# igorville is now deleted
|
||||
igorville = DomainRequest.objects.filter(requested_domain__name="igorville.gov")
|
||||
|
@ -462,7 +467,7 @@ class HomeTests(TestWithUser):
|
|||
self.assertTrue(teaville.exists())
|
||||
|
||||
# Trigger the delete logic
|
||||
self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request_2.pk}))
|
||||
self.client.post(reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request_2.pk}))
|
||||
|
||||
teaville = DomainRequest.objects.filter(requested_domain__name="teaville.gov")
|
||||
self.assertFalse(teaville.exists())
|
||||
|
@ -935,7 +940,7 @@ class UserProfileTests(TestWithUser, WebTest):
|
|||
@less_console_noise_decorator
|
||||
def test_domain_detail_contains_your_profile(self):
|
||||
"""Tests that the domain detail view contains 'your profile' rather than 'your contact information'"""
|
||||
response = self.client.get(reverse("domain", args=[self.domain.pk]))
|
||||
response = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.pk}))
|
||||
self.assertContains(response, "Your profile")
|
||||
self.assertNotContains(response, "Your contact information")
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
"domain-security-email",
|
||||
]:
|
||||
with self.subTest(view_name=view_name):
|
||||
response = self.client.get(reverse(view_name, kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse(view_name, kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -194,7 +194,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
"domain-security-email",
|
||||
]:
|
||||
with self.subTest(view_name=view_name):
|
||||
response = self.client.get(reverse(view_name, kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse(view_name, kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -218,7 +218,7 @@ class TestDomainPermissions(TestWithDomainPermissions):
|
|||
self.domain_deleted,
|
||||
]:
|
||||
with self.subTest(view_name=view_name, domain=domain):
|
||||
response = self.client.get(reverse(view_name, kwargs={"pk": domain.id}))
|
||||
response = self.client.get(reverse(view_name, kwargs={"domain_pk": domain.id}))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
|
@ -271,20 +271,20 @@ class TestDomainDetail(TestDomainOverview):
|
|||
with less_console_noise():
|
||||
self.user.status = User.RESTRICTED
|
||||
self.user.save()
|
||||
response = self.client.get(reverse("domain", kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_domain_detail_allowed_for_on_hold(self):
|
||||
"""Test that the domain overview page displays for on hold domain"""
|
||||
with less_console_noise():
|
||||
# View domain overview page
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"pk": self.domain_on_hold.id}))
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain_on_hold.id}))
|
||||
self.assertNotContains(detail_page, "Edit")
|
||||
|
||||
def test_domain_detail_see_just_nameserver(self):
|
||||
with less_console_noise():
|
||||
# View nameserver on Domain Overview page
|
||||
detail_page = self.app.get(reverse("domain", kwargs={"pk": self.domain_just_nameserver.id}))
|
||||
detail_page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain_just_nameserver.id}))
|
||||
|
||||
self.assertContains(detail_page, "justnameserver.com")
|
||||
self.assertContains(detail_page, "ns1.justnameserver.com")
|
||||
|
@ -293,7 +293,7 @@ class TestDomainDetail(TestDomainOverview):
|
|||
def test_domain_detail_see_nameserver_and_ip(self):
|
||||
with less_console_noise():
|
||||
# View nameserver on Domain Overview page
|
||||
detail_page = self.app.get(reverse("domain", kwargs={"pk": self.domain_with_ip.id}))
|
||||
detail_page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}))
|
||||
|
||||
self.assertContains(detail_page, "nameserverwithip.gov")
|
||||
|
||||
|
@ -321,7 +321,7 @@ class TestDomainDetail(TestDomainOverview):
|
|||
session["analyst_action_location"] = self.domain_no_information.id
|
||||
session.save()
|
||||
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"pk": self.domain_no_information.id}))
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain_no_information.id}))
|
||||
|
||||
self.assertContains(detail_page, "noinformation.gov")
|
||||
self.assertContains(detail_page, "Domain missing domain information")
|
||||
|
@ -341,7 +341,7 @@ class TestDomainDetail(TestDomainOverview):
|
|||
session["analyst_action_location"] = self.domain.id
|
||||
session.save()
|
||||
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"pk": self.domain.id}))
|
||||
detail_page = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
self.assertNotContains(
|
||||
detail_page, "If you need to make updates, contact one of the listed domain managers."
|
||||
|
@ -486,7 +486,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
):
|
||||
self.assertEquals(self.domain_to_renew.state, Domain.State.UNKNOWN)
|
||||
detail_page = self.client.get(
|
||||
reverse("domain", kwargs={"pk": self.domain_to_renew.id}),
|
||||
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
||||
)
|
||||
self.assertContains(detail_page, "Expiring soon")
|
||||
|
||||
|
@ -528,7 +528,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
Domain, "is_expired", self.custom_is_expired_false
|
||||
):
|
||||
detail_page = self.client.get(
|
||||
reverse("domain", kwargs={"pk": domain_to_renew2.id}),
|
||||
reverse("domain", kwargs={"domain_pk": domain_to_renew2.id}),
|
||||
)
|
||||
self.assertContains(detail_page, "Contact one of the listed domain managers to renew the domain.")
|
||||
|
||||
|
@ -548,7 +548,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
Domain, "is_expired", self.custom_is_expired_false
|
||||
):
|
||||
detail_page = self.client.get(
|
||||
reverse("domain", kwargs={"pk": domain_to_renew3.id}),
|
||||
reverse("domain", kwargs={"domain_pk": domain_to_renew3.id}),
|
||||
)
|
||||
self.assertContains(detail_page, "Renew to maintain access")
|
||||
|
||||
|
@ -561,7 +561,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
):
|
||||
# Grab the detail page
|
||||
detail_page = self.client.get(
|
||||
reverse("domain", kwargs={"pk": self.domain_to_renew.id}),
|
||||
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
||||
)
|
||||
|
||||
# Make sure we see the link as a domain manager
|
||||
|
@ -571,7 +571,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
self.assertContains(detail_page, "Renewal form")
|
||||
|
||||
# Grab link to the renewal page
|
||||
renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domain_to_renew.id})
|
||||
renewal_form_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_to_renew.id})
|
||||
self.assertContains(detail_page, f'href="{renewal_form_url}"')
|
||||
|
||||
# Simulate clicking the link
|
||||
|
@ -590,7 +590,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
):
|
||||
# Grab the detail page
|
||||
detail_page = self.client.get(
|
||||
reverse("domain", kwargs={"pk": self.domain_to_renew.id}),
|
||||
reverse("domain", kwargs={"domain_pk": self.domain_to_renew.id}),
|
||||
)
|
||||
|
||||
# Make sure we see the link as a domain manager
|
||||
|
@ -600,7 +600,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
self.assertContains(detail_page, "Renewal form")
|
||||
|
||||
# Grab link to the renewal page
|
||||
renewal_form_url = reverse("domain-renewal", kwargs={"pk": self.domain_to_renew.id})
|
||||
renewal_form_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_to_renew.id})
|
||||
self.assertContains(detail_page, f'href="{renewal_form_url}"')
|
||||
|
||||
# Simulate clicking the link
|
||||
|
@ -614,7 +614,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
Your Profile portion of the Renewal Form."""
|
||||
with less_console_noise():
|
||||
# Start on the Renewal page for the domain
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id}))
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
||||
|
||||
# Verify we see "Your contact information" on the renewal form
|
||||
self.assertContains(renewal_page, "Your contact information")
|
||||
|
@ -633,7 +633,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
Security Email portion of the Renewal Form."""
|
||||
with less_console_noise():
|
||||
# Start on the Renewal page for the domain
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id}))
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
||||
|
||||
# Verify we see "Security email" on the renewal form
|
||||
self.assertContains(renewal_page, "Security email")
|
||||
|
@ -642,7 +642,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
self.assertContains(renewal_page, "We strongly recommend that you provide a security email.")
|
||||
|
||||
# Verify that the "Edit" button for Security email is there and links to correct URL
|
||||
edit_button_url = reverse("domain-security-email", kwargs={"pk": self.domain_with_ip.id})
|
||||
edit_button_url = reverse("domain-security-email", kwargs={"domain_pk": self.domain_with_ip.id})
|
||||
self.assertContains(renewal_page, f'href="{edit_button_url}"')
|
||||
|
||||
# Simulate clicking on edit button
|
||||
|
@ -655,13 +655,13 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
Domain Manager portion of the Renewal Form."""
|
||||
with less_console_noise():
|
||||
# Start on the Renewal page for the domain
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id}))
|
||||
renewal_page = self.app.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id}))
|
||||
|
||||
# Verify we see "Domain managers" on the renewal form
|
||||
self.assertContains(renewal_page, "Domain managers")
|
||||
|
||||
# Verify that the "Edit" button for Domain managers is there and links to correct URL
|
||||
edit_button_url = reverse("domain-users", kwargs={"pk": self.domain_with_ip.id})
|
||||
edit_button_url = reverse("domain-users", kwargs={"domain_pk": self.domain_with_ip.id})
|
||||
self.assertContains(renewal_page, f'href="{edit_button_url}"')
|
||||
|
||||
# Simulate clicking on edit button
|
||||
|
@ -674,7 +674,7 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
to access /renewal and that it should receive a 403."""
|
||||
with less_console_noise():
|
||||
# Start on the Renewal page for the domain
|
||||
renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domain_not_expiring.id}))
|
||||
renewal_page = self.client.get(reverse("domain-renewal", kwargs={"domain_pk": self.domain_not_expiring.id}))
|
||||
self.assertEqual(renewal_page.status_code, 403)
|
||||
|
||||
def test_domain_renewal_form_does_not_appear_if_not_domain_manager(self):
|
||||
|
@ -682,13 +682,15 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
with patch.object(Domain, "is_expired", self.custom_is_expired_true), patch.object(
|
||||
Domain, "is_expired", self.custom_is_expired_true
|
||||
):
|
||||
renewal_page = self.client.get(reverse("domain-renewal", kwargs={"pk": self.domain_no_domain_manager.id}))
|
||||
renewal_page = self.client.get(
|
||||
reverse("domain-renewal", kwargs={"domain_pk": self.domain_no_domain_manager.id})
|
||||
)
|
||||
self.assertEqual(renewal_page.status_code, 403)
|
||||
|
||||
def test_ack_checkbox_not_checked(self):
|
||||
"""If user don't check the checkbox, user should receive an error message."""
|
||||
# Grab the renewal URL
|
||||
renewal_url = reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})
|
||||
renewal_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id})
|
||||
|
||||
# Test that the checkbox is not checked
|
||||
response = self.client.post(renewal_url, data={"submit_button": "next"})
|
||||
|
@ -701,17 +703,19 @@ class TestDomainDetailDomainRenewal(TestDomainOverview):
|
|||
user should be redirected Domain Over page with an updated by 1 year expiration date"""
|
||||
# Grab the renewal URL
|
||||
with patch.object(Domain, "renew_domain", self.custom_renew_domain):
|
||||
renewal_url = reverse("domain-renewal", kwargs={"pk": self.domain_with_ip.id})
|
||||
renewal_url = reverse("domain-renewal", kwargs={"domain_pk": self.domain_with_ip.id})
|
||||
|
||||
# Click the check, and submit
|
||||
response = self.client.post(renewal_url, data={"is_policy_acknowledged": "on", "submit_button": "next"})
|
||||
|
||||
# Check that it redirects after a successfully submits
|
||||
self.assertRedirects(response, reverse("domain", kwargs={"pk": self.domain_with_ip.id}))
|
||||
self.assertRedirects(response, reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}))
|
||||
|
||||
# Check for the updated expiration
|
||||
formatted_new_expiration_date = self.expiration_date_one_year_out().strftime("%b. %-d, %Y")
|
||||
redirect_response = self.client.get(reverse("domain", kwargs={"pk": self.domain_with_ip.id}), follow=True)
|
||||
redirect_response = self.client.get(
|
||||
reverse("domain", kwargs={"domain_pk": self.domain_with_ip.id}), follow=True
|
||||
)
|
||||
self.assertContains(redirect_response, formatted_new_expiration_date)
|
||||
|
||||
|
||||
|
@ -754,7 +758,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
|
||||
@less_console_noise_decorator
|
||||
def test_domain_managers(self):
|
||||
response = self.client.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse("domain-users", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(response, "Domain managers")
|
||||
self.assertContains(response, "Add a domain manager")
|
||||
# assert that the non-portfolio view contains Role column and doesn't contain Admin
|
||||
|
@ -765,7 +769,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
@less_console_noise_decorator
|
||||
@override_flag("organization_feature", active=True)
|
||||
def test_domain_managers_portfolio_view(self):
|
||||
response = self.client.get(reverse("domain-users", kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse("domain-users", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(response, "Domain managers")
|
||||
self.assertContains(response, "Add a domain manager")
|
||||
# assert that the portfolio view doesn't contain Role column and does contain Admin
|
||||
|
@ -775,7 +779,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
|
||||
@less_console_noise_decorator
|
||||
def test_domain_user_add(self):
|
||||
response = self.client.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(response, "Add a domain manager")
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -784,7 +788,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
"""Adding an existing user works."""
|
||||
get_user_model().objects.get_or_create(email="mayor@igorville.gov")
|
||||
user = User.objects.filter(email="mayor@igorville.gov").first()
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "mayor@igorville.gov"
|
||||
|
@ -804,7 +808,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -820,7 +824,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
"""Adding an existing user works and sends portfolio invitation when
|
||||
user is not member of portfolio."""
|
||||
get_user_model().objects.get_or_create(email="mayor@igorville.gov")
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "mayor@igorville.gov"
|
||||
|
@ -832,7 +836,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
# Verify that the invitation emails were sent
|
||||
|
@ -877,7 +881,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self, mock_send_domain_email, mock_send_portfolio_email
|
||||
):
|
||||
"""Adding an email not associated with a user works and sends portfolio invitation."""
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "notauser@igorville.gov"
|
||||
|
@ -889,7 +893,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
# Verify that the invitation emails were sent
|
||||
|
@ -928,7 +932,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
):
|
||||
"""Adding an email not associated with a user works and sends portfolio invitation,
|
||||
and when domain managers email(s) fail to send, assert proper warning displayed."""
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "notauser@igorville.gov"
|
||||
|
@ -942,7 +946,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
# Verify that the invitation emails were sent
|
||||
|
@ -967,7 +971,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
UserPortfolioPermission.objects.get_or_create(
|
||||
user=other_user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
||||
)
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "mayor@igorville.gov"
|
||||
|
@ -979,7 +983,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
# Verify that the invitation emails were sent
|
||||
|
@ -1015,7 +1019,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
user is not member of portfolio and send raises an error."""
|
||||
mock_send_portfolio_email.side_effect = EmailSendingError("Failed to send email.")
|
||||
get_user_model().objects.get_or_create(email="mayor@igorville.gov")
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
add_page.form["email"] = "mayor@igorville.gov"
|
||||
|
@ -1027,7 +1031,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.assertEqual(success_result.status_code, 302)
|
||||
self.assertEqual(
|
||||
success_result["Location"],
|
||||
reverse("domain-users", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-users", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
# Verify that the invitation emails were sent
|
||||
|
@ -1058,7 +1062,9 @@ class TestDomainManagers(TestDomainOverview):
|
|||
"""Removing a domain manager sends notification email to other domain managers."""
|
||||
self.manager, _ = User.objects.get_or_create(email="mayor@igorville.com", first_name="Hello", last_name="World")
|
||||
self.manager_domain_permission, _ = UserDomainRole.objects.get_or_create(user=self.manager, domain=self.domain)
|
||||
self.client.post(reverse("domain-user-delete", kwargs={"pk": self.domain.id, "user_pk": self.manager.id}))
|
||||
self.client.post(
|
||||
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.manager.id})
|
||||
)
|
||||
|
||||
# Verify that the notification emails were sent to domain manager
|
||||
mock_send_templated_email.assert_called_once_with(
|
||||
|
@ -1082,7 +1088,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
|
||||
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1115,7 +1121,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
|
||||
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = caps_email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1147,7 +1153,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
mock_client = MagicMock()
|
||||
mock_client_instance = mock_client.return_value
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1175,7 +1181,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
mock_client_instance = mock_client.return_value
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1214,7 +1220,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
mock_client_instance = mock_client.return_value
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1258,7 +1264,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
mock_client_instance = mock_client.return_value
|
||||
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1289,7 +1295,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
email_address = "mayor"
|
||||
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1313,7 +1319,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||
|
||||
with patch("django.contrib.messages.error") as mock_error:
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
add_page.form["email"] = email_address
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -1332,7 +1338,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
"""Posting to the delete view deletes an invitation."""
|
||||
email_address = "mayor@igorville.gov"
|
||||
invitation, _ = DomainInvitation.objects.get_or_create(domain=self.domain, email=email_address)
|
||||
self.client.post(reverse("invitation-cancel", kwargs={"pk": invitation.id}))
|
||||
self.client.post(reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}))
|
||||
invitation = DomainInvitation.objects.get(id=invitation.id)
|
||||
self.assertEqual(invitation.status, DomainInvitation.DomainInvitationStatus.CANCELED)
|
||||
|
||||
|
@ -1343,7 +1349,9 @@ class TestDomainManagers(TestDomainOverview):
|
|||
invitation, _ = DomainInvitation.objects.get_or_create(
|
||||
domain=self.domain, email=email_address, status=DomainInvitation.DomainInvitationStatus.RETRIEVED
|
||||
)
|
||||
response = self.client.post(reverse("invitation-cancel", kwargs={"pk": invitation.id}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}), follow=True
|
||||
)
|
||||
# Assert that an error message is displayed to the user
|
||||
self.assertContains(response, f"Invitation to {email_address} has already been retrieved.")
|
||||
# Assert that the Cancel link (form) is not displayed
|
||||
|
@ -1363,7 +1371,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
self.client.force_login(other_user)
|
||||
mock_client = MagicMock()
|
||||
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||
result = self.client.post(reverse("invitation-cancel", kwargs={"pk": invitation.id}))
|
||||
result = self.client.post(reverse("invitation-cancel", kwargs={"domain_invitation_pk": invitation.id}))
|
||||
|
||||
self.assertEqual(result.status_code, 403)
|
||||
|
||||
|
@ -1380,7 +1388,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
title = "title"
|
||||
User.objects.filter(email=email_address).delete()
|
||||
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"pk": self.domain.id}))
|
||||
add_page = self.app.get(reverse("domain-users-add", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
self.domain_information, _ = DomainInformation.objects.get_or_create(creator=self.user, domain=self.domain)
|
||||
|
||||
|
@ -1418,7 +1426,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
)
|
||||
UserDomainRole.objects.create(user=new_user_2, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
||||
response = self.client.post(
|
||||
reverse("domain-user-delete", kwargs={"pk": self.domain.id, "user_pk": new_user.id}), follow=True
|
||||
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": new_user.id}), follow=True
|
||||
)
|
||||
# Assert that a success message is displayed to the user
|
||||
self.assertContains(response, f"Removed {email_address} as a manager for this domain.")
|
||||
|
@ -1432,7 +1440,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
"""Posting to the delete view attempts to delete a user domain role when there is only one manager."""
|
||||
# self.user is the only domain manager, so attempt to delete it
|
||||
response = self.client.post(
|
||||
reverse("domain-user-delete", kwargs={"pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
||||
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
||||
)
|
||||
# Assert that an error message is displayed to the user
|
||||
self.assertContains(response, "Domains must have at least one domain manager.")
|
||||
|
@ -1449,7 +1457,7 @@ class TestDomainManagers(TestDomainOverview):
|
|||
new_user = User.objects.create(email=email_address, username="mayor")
|
||||
UserDomainRole.objects.create(user=new_user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
||||
response = self.client.post(
|
||||
reverse("domain-user-delete", kwargs={"pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
||||
reverse("domain-user-delete", kwargs={"domain_pk": self.domain.id, "user_pk": self.user.id}), follow=True
|
||||
)
|
||||
# Assert that a success message is displayed to the user
|
||||
self.assertContains(response, f"You are no longer managing the domain {self.domain}.")
|
||||
|
@ -1461,7 +1469,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
@less_console_noise_decorator
|
||||
def test_domain_nameservers(self):
|
||||
"""Can load domain's nameservers page."""
|
||||
page = self.client.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "DNS name servers")
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -1471,7 +1479,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form with only one nameserver, should error
|
||||
|
@ -1494,7 +1502,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without two hosts, both subdomains,
|
||||
|
@ -1519,7 +1527,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without two hosts, both subdomains,
|
||||
|
@ -1543,7 +1551,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form with duplicate host names of fake.host.com
|
||||
|
@ -1571,7 +1579,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
valid_ip = "1.1. 1.1"
|
||||
valid_ip_2 = "2.2. 2.2"
|
||||
# have to throw an error in order to test that the whitespace has been stripped from ip
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without one host and an ip with whitespace
|
||||
|
@ -1585,7 +1593,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
page = result.follow()
|
||||
|
@ -1604,7 +1612,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
nameserver2 = "ns2.igorville.com"
|
||||
valid_ip = "127.0.0.1"
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without two hosts, both subdomains,
|
||||
|
@ -1632,7 +1640,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
nameserver = "ns2.igorville.gov"
|
||||
invalid_ip = "123"
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without two hosts, both subdomains,
|
||||
|
@ -1659,7 +1667,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
nameserver = "invalid-nameserver.gov"
|
||||
valid_ip = "123.2.45.111"
|
||||
# initial nameservers page has one server with two ips
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# attempt to submit the form without two hosts, both subdomains,
|
||||
|
@ -1687,7 +1695,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
nameserver2 = "ns2.igorville.gov"
|
||||
valid_ip = "127.0.0.1"
|
||||
valid_ip_2 = "128.0.0.2"
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
nameservers_page.form["form-0-server"] = nameserver1
|
||||
|
@ -1699,7 +1707,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
page = result.follow()
|
||||
|
@ -1719,7 +1727,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
valid_ip = ""
|
||||
valid_ip_2 = "128.0.0.2"
|
||||
valid_ip_3 = "128.0.0.3"
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
nameservers_page.form["form-0-server"] = nameserver1
|
||||
|
@ -1734,7 +1742,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
nameservers_page = result.follow()
|
||||
|
@ -1760,7 +1768,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
nameservers_page = result.follow()
|
||||
|
@ -1785,7 +1793,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
valid_ip_3 = ""
|
||||
valid_ip_4 = ""
|
||||
nameservers_page = self.app.get(
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain_with_four_nameservers.id})
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_with_four_nameservers.id})
|
||||
)
|
||||
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
@ -1809,7 +1817,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-nameservers", kwargs={"pk": self.domain_with_four_nameservers.id}),
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_with_four_nameservers.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
nameservers_page = result.follow()
|
||||
|
@ -1821,7 +1829,7 @@ class TestDomainNameservers(TestDomainOverview, MockEppLib):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain.id}))
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# first two nameservers are required, so if we empty one out we should
|
||||
|
@ -1843,7 +1851,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
@less_console_noise_decorator
|
||||
def test_domain_senior_official(self):
|
||||
"""Can load domain's senior official page."""
|
||||
page = self.client.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "Senior official", count=4)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -1852,7 +1860,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
self.domain_information.senior_official = Contact(first_name="Testy")
|
||||
self.domain_information.senior_official.save()
|
||||
self.domain_information.save()
|
||||
page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "Testy")
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -1864,7 +1872,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
)
|
||||
self.domain_information.senior_official.save()
|
||||
self.domain_information.save()
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
so_form = so_page.forms[0]
|
||||
|
@ -1922,7 +1930,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
self.domain_information.senior_official.save()
|
||||
self.domain_information.save()
|
||||
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(so_page, "Apple Tester")
|
||||
self.assertContains(so_page, "CIO")
|
||||
self.assertContains(so_page, "nobody@igorville.gov")
|
||||
|
@ -1943,7 +1951,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
self.domain_information.senior_official.save()
|
||||
self.domain_information.save()
|
||||
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(so_page, "Apple Tester")
|
||||
self.assertContains(so_page, "CIO")
|
||||
self.assertContains(so_page, "nobody@igorville.gov")
|
||||
|
@ -1962,7 +1970,7 @@ class TestDomainSeniorOfficial(TestDomainOverview):
|
|||
self.domain_information.other_contacts.add(self.domain_information.senior_official)
|
||||
self.domain_information.save()
|
||||
# load the Senior Official in the web form
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
so_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
so_form = so_page.forms[0]
|
||||
|
@ -1990,7 +1998,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
@less_console_noise_decorator
|
||||
def test_domain_org_name_address(self):
|
||||
"""Can load domain's org name and mailing address page."""
|
||||
page = self.client.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
# once on the sidebar, once in the page title, once as H1
|
||||
self.assertContains(page, "/org-name-address")
|
||||
self.assertContains(page, "Organization name and mailing address")
|
||||
|
@ -2001,7 +2009,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
"""Org name and address information appears on the page."""
|
||||
self.domain_information.organization_name = "Town of Igorville"
|
||||
self.domain_information.save()
|
||||
page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "Town of Igorville")
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -2009,7 +2017,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
"""Submitting changes works on the org name address page."""
|
||||
self.domain_information.organization_name = "Town of Igorville"
|
||||
self.domain_information.save()
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
org_name_page.form["organization_name"] = "Not igorville"
|
||||
|
@ -2041,7 +2049,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
|
||||
self.assertEqual(self.domain_information.generic_org_type, tribal_org_type)
|
||||
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
form = org_name_page.forms[0]
|
||||
# Check the value of the input field
|
||||
|
@ -2098,7 +2106,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
|
||||
self.assertEqual(self.domain_information.generic_org_type, fed_org_type)
|
||||
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
form = org_name_page.forms[0]
|
||||
# Check the value of the input field
|
||||
|
@ -2160,7 +2168,7 @@ class TestDomainOrganization(TestDomainOverview):
|
|||
|
||||
new_value = ("Department of State", "Department of State")
|
||||
self.client.post(
|
||||
reverse("domain-org-name-address", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}),
|
||||
{
|
||||
"federal_agency": new_value,
|
||||
},
|
||||
|
@ -2202,7 +2210,7 @@ class TestDomainSuborganization(TestDomainOverview):
|
|||
self.assertEqual(self.domain_information.sub_organization, suborg)
|
||||
|
||||
# Navigate to the suborganization page
|
||||
page = self.app.get(reverse("domain-suborganization", kwargs={"pk": self.domain.id}))
|
||||
page = self.app.get(reverse("domain-suborganization", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
# The page should contain the choices Vanilla and Chocolate
|
||||
self.assertContains(page, "Vanilla")
|
||||
|
@ -2260,7 +2268,7 @@ class TestDomainSuborganization(TestDomainOverview):
|
|||
self.assertEqual(self.domain_information.sub_organization, suborg)
|
||||
|
||||
# Navigate to the suborganization page
|
||||
page = self.app.get(reverse("domain-suborganization", kwargs={"pk": self.domain.id}))
|
||||
page = self.app.get(reverse("domain-suborganization", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
# The page should display the readonly option
|
||||
self.assertContains(page, "Vanilla")
|
||||
|
@ -2299,7 +2307,7 @@ class TestDomainSuborganization(TestDomainOverview):
|
|||
self.user.refresh_from_db()
|
||||
|
||||
# Navigate to the domain overview page
|
||||
page = self.app.get(reverse("domain", kwargs={"pk": self.domain.id}))
|
||||
page = self.app.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
# Test for the title change
|
||||
self.assertContains(page, "Suborganization")
|
||||
|
@ -2328,7 +2336,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
domain_contact, _ = Domain.objects.get_or_create(name="freeman.gov")
|
||||
# Add current user to this domain
|
||||
_ = UserDomainRole(user=self.user, domain=domain_contact, role="admin").save()
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"pk": domain_contact.id}))
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": domain_contact.id}))
|
||||
|
||||
# Loads correctly
|
||||
self.assertContains(page, "Security email")
|
||||
|
@ -2343,7 +2351,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
self.mockedSendFunction = self.mockSendPatch.start()
|
||||
self.mockedSendFunction.side_effect = self.mockSend
|
||||
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
||||
|
||||
# Loads correctly
|
||||
self.assertContains(page, "Security email")
|
||||
|
@ -2353,7 +2361,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
def test_domain_security_email(self):
|
||||
"""Can load domain's security email page."""
|
||||
with less_console_noise():
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "Security email")
|
||||
|
||||
def test_domain_security_email_form(self):
|
||||
|
@ -2361,7 +2369,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
with less_console_noise():
|
||||
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"domain_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)
|
||||
|
@ -2372,7 +2380,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-security-email", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}),
|
||||
)
|
||||
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -2415,7 +2423,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
]
|
||||
for test_name, data, expected_message in test_cases:
|
||||
response = self.client.post(
|
||||
reverse("domain-security-email", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}),
|
||||
data=data,
|
||||
follow=True,
|
||||
)
|
||||
|
@ -2443,7 +2451,7 @@ class TestDomainSecurityEmail(TestDomainOverview):
|
|||
management pages share the same permissions class"""
|
||||
self.user.status = User.RESTRICTED
|
||||
self.user.save()
|
||||
response = self.client.get(reverse("domain", kwargs={"pk": self.domain.id}))
|
||||
response = self.client.get(reverse("domain", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
|
||||
|
@ -2455,7 +2463,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
"""DNSSEC overview page loads when domain has no DNSSEC data
|
||||
and shows a 'Enable DNSSEC' button."""
|
||||
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}))
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}))
|
||||
self.assertContains(page, "Enable DNSSEC")
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -2463,7 +2471,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
"""DNSSEC overview page loads when domain has DNSSEC data
|
||||
and the template contains a button to disable DNSSEC."""
|
||||
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"pk": self.domain_multdsdata.id}))
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain_multdsdata.id}))
|
||||
self.assertContains(page, "Disable DNSSEC")
|
||||
|
||||
# Prepare the data for the POST request
|
||||
|
@ -2471,7 +2479,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
"disable_dnssec": "Disable DNSSEC",
|
||||
}
|
||||
updated_page = self.client.post(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}),
|
||||
post_data,
|
||||
follow=True,
|
||||
)
|
||||
|
@ -2485,7 +2493,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
"""DNSSEC Add DS data page loads when there is no
|
||||
domain DNSSEC data and shows a button to Add new record"""
|
||||
|
||||
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dnssec_none.id}))
|
||||
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dnssec_none.id}))
|
||||
self.assertContains(page, "You have no DS data added")
|
||||
self.assertContains(page, "Add new record")
|
||||
|
||||
|
@ -2494,13 +2502,13 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
"""DNSSEC Add DS data page loads when there is
|
||||
domain DNSSEC DS data and shows the data"""
|
||||
|
||||
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
page = self.client.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
self.assertContains(page, "DS data record 1")
|
||||
|
||||
@less_console_noise_decorator
|
||||
def test_ds_data_form_modal(self):
|
||||
"""When user clicks on save, a modal pops up."""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
# Assert that a hidden trigger for the modal does not exist.
|
||||
# This hidden trigger will pop on the page when certain condition are met:
|
||||
# 1) Initial form contained DS data, 2) All data is deleted and form is
|
||||
|
@ -2509,7 +2517,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
# Simulate a delete all data
|
||||
form_data = {}
|
||||
response = self.client.post(
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}),
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}),
|
||||
data=form_data,
|
||||
)
|
||||
self.assertEqual(response.status_code, 200) # Adjust status code as needed
|
||||
|
@ -2522,7 +2530,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
result = add_data_page.forms[0].submit()
|
||||
|
@ -2530,7 +2538,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
self.assertEqual(result.status_code, 302)
|
||||
self.assertEqual(
|
||||
result["Location"],
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}),
|
||||
reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}),
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
page = result.follow()
|
||||
|
@ -2542,7 +2550,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# all four form fields are required, so will test with each blank
|
||||
|
@ -2565,7 +2573,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# first two nameservers are required, so if we empty one out we should
|
||||
|
@ -2588,7 +2596,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# first two nameservers are required, so if we empty one out we should
|
||||
|
@ -2611,7 +2619,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# first two nameservers are required, so if we empty one out we should
|
||||
|
@ -2634,7 +2642,7 @@ class TestDomainDNSSEC(TestDomainOverview):
|
|||
|
||||
Uses self.app WebTest because we need to interact with forms.
|
||||
"""
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain_dsdata.id}))
|
||||
add_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain_dsdata.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
# first two nameservers are required, so if we empty one out we should
|
||||
|
@ -2688,7 +2696,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
self.domain_information.zipcode = "62052"
|
||||
self.domain_information.save()
|
||||
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
org_name_page.form["organization_name"] = "Not igorville"
|
||||
|
@ -2729,7 +2737,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
self.domain_information.portfolio = portfolio
|
||||
self.domain_information.save()
|
||||
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
org_name_page.form["organization_name"] = "Not igorville"
|
||||
|
@ -2756,7 +2764,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
self.domain_information.portfolio = portfolio
|
||||
self.domain_information.save()
|
||||
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"pk": self.domain.id}))
|
||||
org_name_page = self.app.get(reverse("domain-org-name-address", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
session = self.app.session
|
||||
|
@ -2778,7 +2786,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
def test_notification_on_security_email_change(self):
|
||||
"""Test that an email is sent when the security email is changed."""
|
||||
|
||||
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"pk": self.domain.id}))
|
||||
security_email_page = self.app.get(reverse("domain-security-email", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
security_email_page.form["security_email"] = "new_security@example.com"
|
||||
|
@ -2801,7 +2809,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
def test_notification_on_dnssec_enable(self):
|
||||
"""Test that an email is sent when DNSSEC is enabled."""
|
||||
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"pk": self.domain_multdsdata.id}))
|
||||
page = self.client.get(reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain_multdsdata.id}))
|
||||
self.assertContains(page, "Disable DNSSEC")
|
||||
|
||||
# Prepare the data for the POST request
|
||||
|
@ -2811,7 +2819,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
|
||||
with boto3_mocking.clients.handler_for("sesv2", self.mock_client_class):
|
||||
updated_page = self.client.post(
|
||||
reverse("domain-dns-dnssec", kwargs={"pk": self.domain.id}),
|
||||
reverse("domain-dns-dnssec", kwargs={"domain_pk": self.domain.id}),
|
||||
post_data,
|
||||
follow=True,
|
||||
)
|
||||
|
@ -2834,7 +2842,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
def test_notification_on_ds_data_change(self):
|
||||
"""Test that an email is sent when DS data is changed."""
|
||||
|
||||
ds_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.domain.id}))
|
||||
ds_data_page = self.app.get(reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
# Add DS data
|
||||
|
@ -2868,7 +2876,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
)
|
||||
self.domain_information.save()
|
||||
|
||||
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
senior_official_page.form["first_name"] = "New"
|
||||
|
@ -2905,7 +2913,7 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
self.domain_information.portfolio = portfolio
|
||||
self.domain_information.save()
|
||||
|
||||
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"pk": self.domain.id}))
|
||||
senior_official_page = self.app.get(reverse("domain-senior-official", kwargs={"domain_pk": self.domain.id}))
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
senior_official_page.form["first_name"] = "New"
|
||||
|
@ -2924,7 +2932,9 @@ class TestDomainChangeNotifications(TestDomainOverview):
|
|||
def test_no_notification_when_dns_needed(self):
|
||||
"""Test that an email is not sent when nameservers are changed while the state is DNS_NEEDED."""
|
||||
|
||||
nameservers_page = self.app.get(reverse("domain-dns-nameservers", kwargs={"pk": self.domain_dns_needed.id}))
|
||||
nameservers_page = self.app.get(
|
||||
reverse("domain-dns-nameservers", kwargs={"domain_pk": self.domain_dns_needed.id})
|
||||
)
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
|
||||
# add nameservers
|
||||
|
|
|
@ -104,7 +104,7 @@ class GetDomainsJsonTest(TestWithUser, WebTest):
|
|||
self.assertEqual(expected_domain.state_display(), state_displays[i])
|
||||
self.assertEqual(expected_domain.get_state_help_text(), get_state_help_texts[i])
|
||||
|
||||
self.assertEqual(reverse("domain", kwargs={"pk": expected_domain.id}), action_urls[i])
|
||||
self.assertEqual(reverse("domain", kwargs={"domain_pk": expected_domain.id}), action_urls[i])
|
||||
|
||||
# Check action_label
|
||||
action_label_expected = (
|
||||
|
@ -185,7 +185,7 @@ class GetDomainsJsonTest(TestWithUser, WebTest):
|
|||
self.assertEqual(expected_domain.state_display(), state_displays[i])
|
||||
self.assertEqual(expected_domain.get_state_help_text(), get_state_help_texts[i])
|
||||
|
||||
self.assertEqual(reverse("domain", kwargs={"pk": expected_domain.id}), action_urls[i])
|
||||
self.assertEqual(reverse("domain", kwargs={"domain_pk": expected_domain.id}), action_urls[i])
|
||||
|
||||
# Check action_label
|
||||
user_domain_role_exists = UserDomainRole.objects.filter(
|
||||
|
@ -272,7 +272,7 @@ class GetDomainsJsonTest(TestWithUser, WebTest):
|
|||
self.assertEqual(expected_domain.state_display(), state_displays[i])
|
||||
self.assertEqual(expected_domain.get_state_help_text(), get_state_help_texts[i])
|
||||
|
||||
self.assertEqual(reverse("domain", kwargs={"pk": expected_domain.id}), action_urls[i])
|
||||
self.assertEqual(reverse("domain", kwargs={"domain_pk": expected_domain.id}), action_urls[i])
|
||||
|
||||
# Check action_label
|
||||
user_domain_role_exists = UserDomainRole.objects.filter(
|
||||
|
|
|
@ -1320,7 +1320,9 @@ class TestPortfolio(WebTest):
|
|||
|
||||
self.client.force_login(self.user)
|
||||
# Perform delete
|
||||
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}), follow=True
|
||||
)
|
||||
|
||||
# Check that the response is 200
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
@ -1354,7 +1356,9 @@ class TestPortfolio(WebTest):
|
|||
|
||||
self.client.force_login(self.user)
|
||||
# Attempt to delete
|
||||
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}), follow=True
|
||||
)
|
||||
|
||||
# Check response is 403 Forbidden
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
@ -1389,7 +1393,9 @@ class TestPortfolio(WebTest):
|
|||
|
||||
self.client.force_login(self.user)
|
||||
# Perform delete as self.user
|
||||
response = self.client.post(reverse("domain-request-delete", kwargs={"pk": domain_request.pk}), follow=True)
|
||||
response = self.client.post(
|
||||
reverse("domain-request-delete", kwargs={"domain_request_pk": domain_request.pk}), follow=True
|
||||
)
|
||||
|
||||
# Check response is 403 Forbidden
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
@ -3244,7 +3250,9 @@ class TestRequestingEntity(WebTest):
|
|||
def test_requesting_entity_page_errors(self):
|
||||
"""Tests that we get the expected form errors on requesting entity"""
|
||||
domain_request = completed_domain_request(user=self.user, portfolio=self.portfolio)
|
||||
response = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk})).follow()
|
||||
response = self.app.get(
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk})
|
||||
).follow()
|
||||
form = response.forms[0]
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
@ -3334,7 +3342,9 @@ class TestRequestingEntity(WebTest):
|
|||
|
||||
domain_request.submit()
|
||||
|
||||
response = self.app.get(reverse("domain-request-status-viewonly", kwargs={"pk": domain_request.pk}))
|
||||
response = self.app.get(
|
||||
reverse("domain-request-status-viewonly", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.assertContains(response, "Requesting entity")
|
||||
self.assertContains(response, "moon")
|
||||
self.assertContains(response, "kepler, AL")
|
||||
|
@ -3359,7 +3369,7 @@ class TestRequestingEntity(WebTest):
|
|||
|
||||
domain_request.submit()
|
||||
|
||||
response = self.app.get(reverse("domain-request-status", kwargs={"pk": domain_request.pk}))
|
||||
response = self.app.get(reverse("domain-request-status", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
self.assertContains(response, "Requesting entity")
|
||||
self.assertContains(response, "moon")
|
||||
self.assertContains(response, "kepler, AL")
|
||||
|
|
|
@ -809,7 +809,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
# type_page = home_page.click("Edit")
|
||||
|
||||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
url = reverse("edit-domain-request", kwargs={"id": domain_request.pk})
|
||||
url = reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk})
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
# TODO: The following line results in a django error on middleware
|
||||
|
@ -1106,7 +1106,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
def test_yes_no_contact_form_inits_blank_for_new_domain_request(self):
|
||||
"""On the Other Contacts page, the yes/no form gets initialized with nothing selected for
|
||||
new domain requests"""
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": 0}))
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"domain_request_pk": 0}))
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
self.assertEquals(other_contacts_form["other_contacts-has_other_contacts"].value, None)
|
||||
|
||||
|
@ -1114,7 +1114,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
def test_yes_no_additional_form_inits_blank_for_new_domain_request(self):
|
||||
"""On the Additional Details page, the yes/no form gets initialized with nothing selected for
|
||||
new domain requests"""
|
||||
additional_details_page = self.app.get(reverse("domain-request:additional_details", kwargs={"id": 0}))
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": 0})
|
||||
)
|
||||
additional_form = additional_details_page.forms[0]
|
||||
|
||||
# Check the cisa representative yes/no field
|
||||
|
@ -1130,7 +1132,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
# Domain Request has other contacts by default
|
||||
domain_request = completed_domain_request(user=self.user)
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1138,7 +1140,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1155,7 +1159,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.save()
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1164,7 +1168,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1187,7 +1191,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.no_other_contacts_rationale = "Hello!"
|
||||
domain_request.save()
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1195,7 +1199,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1216,7 +1222,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.save()
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1225,7 +1231,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1256,7 +1262,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.assertEqual(domain_request.cisa_representative_email, "fake@faketown.gov")
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1265,7 +1271,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1320,7 +1326,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.assertEqual(domain_request.has_cisa_representative, None)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1329,7 +1335,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1367,7 +1373,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1376,7 +1382,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1400,7 +1406,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request = completed_domain_request(name="cisareps.gov", user=self.user, has_anything_else=False)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1409,7 +1415,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.pk})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1439,7 +1445,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.assertEqual(domain_request.has_cisa_representative, None)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1448,7 +1454,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
additional_details_page = self.app.get(
|
||||
reverse("domain-request:additional_details", kwargs={"id": domain_request.id})
|
||||
reverse("domain-request:additional_details", kwargs={"domain_request_pk": domain_request.id})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
|
@ -1472,7 +1478,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.no_other_contacts_rationale = "Hello!"
|
||||
domain_request.save()
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1480,7 +1486,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1520,7 +1528,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
# Domain request has other contacts by default
|
||||
domain_request = completed_domain_request(user=self.user)
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1528,7 +1536,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1604,7 +1614,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_info.other_contacts.set([other])
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1612,7 +1622,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1653,7 +1665,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
@less_console_noise_decorator
|
||||
def test_if_yes_no_form_is_no_then_no_other_contacts_required(self):
|
||||
"""Applicants with no other contacts have to give a reason."""
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": 0}))
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"domain_request_pk": 0}))
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
other_contacts_form["other_contacts-has_other_contacts"] = "False"
|
||||
response = other_contacts_page.forms[0].submit()
|
||||
|
@ -1669,7 +1681,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
@less_console_noise_decorator
|
||||
def test_if_yes_no_form_is_yes_then_other_contacts_required(self):
|
||||
"""Applicants with other contacts do not have to give a reason."""
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": 0}))
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"domain_request_pk": 0}))
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
other_contacts_form["other_contacts-has_other_contacts"] = "True"
|
||||
response = other_contacts_page.forms[0].submit()
|
||||
|
@ -1737,7 +1749,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.other_contacts.add(other2)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1745,7 +1757,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.id}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.id})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1810,7 +1824,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.other_contacts.add(other)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1818,7 +1832,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.id}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.id})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1887,7 +1903,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.other_contacts.add(other)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1895,7 +1911,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.id}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.id})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -1967,7 +1985,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
other_contact_pk = other.id
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -1975,7 +1993,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -2043,7 +2063,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
other_contact_pk = so.id
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -2051,7 +2071,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_page = self.app.get(reverse("domain-request:other_contacts", kwargs={"id": domain_request.pk}))
|
||||
other_contacts_page = self.app.get(
|
||||
reverse("domain-request:other_contacts", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
other_contacts_form = other_contacts_page.forms[0]
|
||||
|
@ -2113,7 +2135,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
so_pk = so.id
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -2121,7 +2143,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
so_page = self.app.get(reverse("domain-request:senior_official", kwargs={"id": domain_request.pk}))
|
||||
so_page = self.app.get(
|
||||
reverse("domain-request:senior_official", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
so_form = so_page.forms[0]
|
||||
|
@ -2182,7 +2206,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
so_pk = so.id
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -2190,7 +2214,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
session_id = self.app.cookies[settings.SESSION_COOKIE_NAME]
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
so_page = self.app.get(reverse("domain-request:senior_official", kwargs={"id": domain_request.pk}))
|
||||
so_page = self.app.get(
|
||||
reverse("domain-request:senior_official", kwargs={"domain_request_pk": domain_request.pk})
|
||||
)
|
||||
self.app.set_cookie(settings.SESSION_COOKIE_NAME, session_id)
|
||||
|
||||
so_form = so_page.forms[0]
|
||||
|
@ -2240,7 +2266,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
creator_pk = self.user.id
|
||||
|
||||
# prime the form by visiting /edit
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}))
|
||||
self.app.get(reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}))
|
||||
# django-webtest does not handle cookie-based sessions well because it keeps
|
||||
# resetting the session key on each new request, thus destroying the concept
|
||||
# of a "session". We are going to do it manually, saving the session ID here
|
||||
|
@ -2539,7 +2565,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
new_domain_request_id = all_domain_requests.first().id
|
||||
|
||||
# Skip to the current sites page
|
||||
current_sites_page = self.app.get(reverse("domain-request:current_sites", kwargs={"id": new_domain_request_id}))
|
||||
current_sites_page = self.app.get(
|
||||
reverse("domain-request:current_sites", kwargs={"domain_request_pk": new_domain_request_id})
|
||||
)
|
||||
# fill in the form field
|
||||
current_sites_form = current_sites_page.forms[0]
|
||||
self.assertIn("current_sites-0-website", current_sites_form.fields)
|
||||
|
@ -2614,7 +2642,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
domain_request.alternative_domains.add(alt)
|
||||
|
||||
# prime the form by visiting /edit
|
||||
url = reverse("edit-domain-request", kwargs={"id": domain_request.pk})
|
||||
url = reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk})
|
||||
response = self.client.get(url)
|
||||
|
||||
# TODO: this is a sketch of each page in the wizard which needs to be tested
|
||||
|
@ -2724,7 +2752,7 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
NOTE: This may be a moot point if we implement a more solid pattern in the
|
||||
future, like not a submit action at all on the review page."""
|
||||
|
||||
review_page = self.app.get(reverse("domain-request:review", kwargs={"id": 0}))
|
||||
review_page = self.app.get(reverse("domain-request:review", kwargs={"domain_request_pk": 0}))
|
||||
self.assertContains(review_page, "toggle-submit-domain-request")
|
||||
self.assertContains(review_page, "Your request form is incomplete")
|
||||
|
||||
|
@ -2742,7 +2770,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
|
||||
# This user should also be forbidden from editing existing ones
|
||||
domain_request = completed_domain_request(user=self.user)
|
||||
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}), expect_errors=True)
|
||||
edit_page = self.app.get(
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}), expect_errors=True
|
||||
)
|
||||
self.assertEqual(edit_page.status_code, 403)
|
||||
|
||||
# Cleanup
|
||||
|
@ -2767,7 +2797,9 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
|
||||
# This user should also be allowed to edit existing ones
|
||||
domain_request = completed_domain_request(user=self.user)
|
||||
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk})).follow()
|
||||
edit_page = self.app.get(
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk})
|
||||
).follow()
|
||||
self.assertEqual(edit_page.status_code, 200)
|
||||
|
||||
def test_non_creator_access(self):
|
||||
|
@ -2776,14 +2808,18 @@ class DomainRequestTests(TestWithUser, WebTest):
|
|||
other_user = User.objects.create_user(username="other_user", password=p)
|
||||
domain_request = completed_domain_request(user=other_user)
|
||||
|
||||
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk}), expect_errors=True)
|
||||
edit_page = self.app.get(
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk}), expect_errors=True
|
||||
)
|
||||
self.assertEqual(edit_page.status_code, 403)
|
||||
|
||||
def test_creator_access(self):
|
||||
"""Tests that a user can edit a domain request they created"""
|
||||
domain_request = completed_domain_request(user=self.user)
|
||||
|
||||
edit_page = self.app.get(reverse("edit-domain-request", kwargs={"id": domain_request.pk})).follow()
|
||||
edit_page = self.app.get(
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.pk})
|
||||
).follow()
|
||||
self.assertEqual(edit_page.status_code, 200)
|
||||
|
||||
|
||||
|
@ -2898,12 +2934,8 @@ class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
|||
domain_request = completed_domain_request(status=DomainRequest.DomainRequestStatus.SUBMITTED, user=self.user)
|
||||
domain_request.save()
|
||||
|
||||
detail_page = self.app.get(f"/domain-request/{domain_request.id}")
|
||||
self.assertContains(detail_page, "city.gov")
|
||||
self.assertContains(detail_page, "city1.gov")
|
||||
self.assertContains(detail_page, "Chief Tester")
|
||||
self.assertContains(detail_page, "testy@town.com")
|
||||
self.assertContains(detail_page, "Status:")
|
||||
detail_page = self.client.get(f"/domain-request/{domain_request.id}")
|
||||
self.assertEqual(detail_page.status_code, 403)
|
||||
# Restricted user trying to withdraw results in 403 error
|
||||
with less_console_noise():
|
||||
for url_name in [
|
||||
|
@ -2911,7 +2943,7 @@ class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
|||
"domain-request-withdrawn",
|
||||
]:
|
||||
with self.subTest(url_name=url_name):
|
||||
page = self.client.get(reverse(url_name, kwargs={"pk": domain_request.pk}))
|
||||
page = self.client.get(reverse(url_name, kwargs={"domain_request_pk": domain_request.pk}))
|
||||
self.assertEqual(page.status_code, 403)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -2931,7 +2963,7 @@ class DomainRequestTestDifferentStatuses(TestWithUser, WebTest):
|
|||
"domain-request-withdrawn",
|
||||
]:
|
||||
with self.subTest(url_name=url_name):
|
||||
page = self.client.get(reverse(url_name, kwargs={"pk": domain_request.pk}))
|
||||
page = self.client.get(reverse(url_name, kwargs={"domain_request_pk": domain_request.pk}))
|
||||
self.assertEqual(page.status_code, 403)
|
||||
|
||||
@less_console_noise_decorator
|
||||
|
@ -3206,7 +3238,9 @@ class TestDomainRequestWizard(TestWithUser, WebTest):
|
|||
self.assertContains(detail_page, "usa-current", count=2)
|
||||
|
||||
# We default to the requesting entity page
|
||||
expected_url = reverse("domain-request:portfolio_requesting_entity", kwargs={"id": domain_request.id})
|
||||
expected_url = reverse(
|
||||
"domain-request:portfolio_requesting_entity", kwargs={"domain_request_pk": domain_request.id}
|
||||
)
|
||||
# This returns the entire url, thus "in"
|
||||
self.assertIn(expected_url, detail_page.request.url)
|
||||
else:
|
||||
|
|
|
@ -199,14 +199,14 @@ class GetRequestsJsonTest(TestWithUser, WebTest):
|
|||
|
||||
# Check action_url
|
||||
action_url_expected = (
|
||||
reverse("edit-domain-request", kwargs={"id": self.domain_requests[i].id})
|
||||
reverse("edit-domain-request", kwargs={"domain_request_pk": self.domain_requests[i].id})
|
||||
if self.domain_requests[i].status
|
||||
in [
|
||||
DomainRequest.DomainRequestStatus.STARTED,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
DomainRequest.DomainRequestStatus.WITHDRAWN,
|
||||
]
|
||||
else reverse("domain-request-status", kwargs={"pk": self.domain_requests[i].id})
|
||||
else reverse("domain-request-status", kwargs={"domain_request_pk": self.domain_requests[i].id})
|
||||
)
|
||||
self.assertEqual(action_url_expected, action_urls[i])
|
||||
|
||||
|
@ -342,7 +342,8 @@ class GetRequestsJsonTest(TestWithUser, WebTest):
|
|||
# Test case where action is View
|
||||
self.assertEqual("View", action_labels[i])
|
||||
self.assertEqual(
|
||||
reverse("domain-request-status-viewonly", kwargs={"pk": expected_domain_request.id}), action_urls[i]
|
||||
reverse("domain-request-status-viewonly", kwargs={"domain_request_pk": expected_domain_request.id}),
|
||||
action_urls[i],
|
||||
)
|
||||
self.assertEqual("visibility", svg_icons[i])
|
||||
elif status[i] in [
|
||||
|
@ -360,7 +361,8 @@ class GetRequestsJsonTest(TestWithUser, WebTest):
|
|||
# Test case where action is Manage
|
||||
self.assertEqual("Manage", action_labels[i])
|
||||
self.assertEqual(
|
||||
reverse("domain-request-status", kwargs={"pk": expected_domain_request.id}), action_urls[i]
|
||||
reverse("domain-request-status", kwargs={"domain_request_pk": expected_domain_request.id}),
|
||||
action_urls[i],
|
||||
)
|
||||
self.assertEqual("settings", svg_icons[i])
|
||||
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
"""Views for a single Domain.
|
||||
|
||||
Authorization is handled by the `DomainPermissionView`. To ensure that only
|
||||
authorized users can see information on a domain, every view here should
|
||||
inherit from `DomainPermissionView` (or DomainInvitationPermissionCancelView).
|
||||
"""
|
||||
|
||||
from datetime import date
|
||||
import logging
|
||||
import requests
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import redirect, render, get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.views.generic import DeleteView, DetailView, UpdateView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django.conf import settings
|
||||
from registrar.decorators import (
|
||||
HAS_PORTFOLIO_DOMAINS_VIEW_ALL,
|
||||
IS_DOMAIN_MANAGER,
|
||||
IS_DOMAIN_MANAGER_AND_NOT_PORTFOLIO_MEMBER,
|
||||
IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER,
|
||||
IS_STAFF_MANAGING_DOMAIN,
|
||||
grant_access,
|
||||
)
|
||||
from registrar.forms.domain import DomainSuborganizationForm, DomainRenewalForm
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
|
@ -40,7 +43,6 @@ from registrar.utility.errors import (
|
|||
SecurityEmailErrorCodes,
|
||||
)
|
||||
from registrar.models.utility.contact_error import ContactError
|
||||
from registrar.views.utility.permission_views import UserDomainRolePermissionDeleteView
|
||||
from registrar.utility.waffle import flag_is_active_for_user
|
||||
from registrar.views.utility.invitation_helper import (
|
||||
get_org_membership,
|
||||
|
@ -67,19 +69,22 @@ from epplibwrapper import (
|
|||
|
||||
from ..utility.email import send_templated_email, EmailSendingError
|
||||
from ..utility.email_invitations import send_domain_invitation_email, send_portfolio_invitation_email
|
||||
from .utility import DomainPermissionView, DomainInvitationPermissionCancelView
|
||||
from django import forms
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DomainBaseView(DomainPermissionView):
|
||||
class DomainBaseView(PermissionRequiredMixin, DetailView):
|
||||
"""
|
||||
Base View for the Domain. Handles getting and setting the domain
|
||||
in session cache on GETs. Also provides methods for getting
|
||||
and setting the domain in cache
|
||||
"""
|
||||
|
||||
model = Domain
|
||||
pk_url_kwarg = "domain_pk"
|
||||
context_object_name = "domain"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self._get_domain(request)
|
||||
context = self.get_context_data(object=self.object)
|
||||
|
@ -95,7 +100,7 @@ class DomainBaseView(DomainPermissionView):
|
|||
self.session = request.session
|
||||
# domain:private_key is the session key to use for
|
||||
# caching the domain in the session
|
||||
domain_pk = "domain:" + str(self.kwargs.get("pk"))
|
||||
domain_pk = "domain:" + str(self.kwargs.get("domain_pk"))
|
||||
cached_domain = self.session.get(domain_pk)
|
||||
|
||||
if cached_domain:
|
||||
|
@ -108,9 +113,136 @@ class DomainBaseView(DomainPermissionView):
|
|||
"""
|
||||
update domain in the session cache
|
||||
"""
|
||||
domain_pk = "domain:" + str(self.kwargs.get("pk"))
|
||||
domain_pk = "domain:" + str(self.kwargs.get("domain_pk"))
|
||||
self.session[domain_pk] = self.object
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
user = self.request.user
|
||||
context["is_analyst_or_superuser"] = user.has_perm("registrar.analyst_access_permission") or user.has_perm(
|
||||
"registrar.full_access_permission"
|
||||
)
|
||||
context["is_domain_manager"] = UserDomainRole.objects.filter(user=user, domain=self.object).exists()
|
||||
context["is_portfolio_user"] = self.can_access_domain_via_portfolio(self.object.pk)
|
||||
context["is_editable"] = self.is_editable()
|
||||
# Stored in a variable for the linter
|
||||
action = "analyst_action"
|
||||
action_location = "analyst_action_location"
|
||||
# Flag to see if an analyst is attempting to make edits
|
||||
if action in self.request.session:
|
||||
context[action] = self.request.session[action]
|
||||
if action_location in self.request.session:
|
||||
context[action_location] = self.request.session[action_location]
|
||||
|
||||
return context
|
||||
|
||||
def is_editable(self):
|
||||
"""Returns whether domain is editable in the context of the view"""
|
||||
domain_editable = self.object.is_editable()
|
||||
if not domain_editable:
|
||||
return False
|
||||
|
||||
# if user is domain manager or analyst or admin, return True
|
||||
if (
|
||||
self.can_access_other_user_domains(self.object.id)
|
||||
or UserDomainRole.objects.filter(user=self.request.user, domain=self.object).exists()
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def can_access_domain_via_portfolio(self, pk):
|
||||
"""Most views should not allow permission to portfolio users.
|
||||
If particular views allow access to the domain pages, they will need to override
|
||||
this function.
|
||||
"""
|
||||
return False
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["domain_pk"]
|
||||
"""
|
||||
pk = self.kwargs["domain_pk"]
|
||||
|
||||
# test if domain in editable state
|
||||
if not self.in_editable_state(pk):
|
||||
return False
|
||||
|
||||
# if we need to check more about the nature of role, do it here.
|
||||
return True
|
||||
|
||||
def in_editable_state(self, pk):
|
||||
"""Is the domain in an editable state"""
|
||||
requested_domain = None
|
||||
if Domain.objects.filter(id=pk).exists():
|
||||
requested_domain = Domain.objects.get(id=pk)
|
||||
|
||||
# if domain is editable return true
|
||||
if requested_domain and requested_domain.is_editable():
|
||||
return True
|
||||
return False
|
||||
|
||||
def can_access_other_user_domains(self, pk):
|
||||
"""Checks to see if an authorized user (staff or superuser)
|
||||
can access a domain that they did not create or was invited to.
|
||||
"""
|
||||
|
||||
# Check if the user is permissioned...
|
||||
user_is_analyst_or_superuser = self.request.user.has_perm(
|
||||
"registrar.analyst_access_permission"
|
||||
) or self.request.user.has_perm("registrar.full_access_permission")
|
||||
|
||||
if not user_is_analyst_or_superuser:
|
||||
return False
|
||||
|
||||
# Check if the user is attempting a valid edit action.
|
||||
# In other words, if the analyst/admin did not click
|
||||
# the 'Manage Domain' button in /admin,
|
||||
# then they cannot access this page.
|
||||
session = self.request.session
|
||||
can_do_action = (
|
||||
"analyst_action" in session
|
||||
and "analyst_action_location" in session
|
||||
and session["analyst_action_location"] == pk
|
||||
)
|
||||
|
||||
if not can_do_action:
|
||||
return False
|
||||
|
||||
# Analysts may manage domains, when they are in these statuses:
|
||||
valid_domain_statuses = [
|
||||
DomainRequest.DomainRequestStatus.APPROVED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.REJECTED,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
# Edge case - some domains do not have
|
||||
# a status or DomainInformation... aka a status of 'None'.
|
||||
# It is necessary to access those to correct errors.
|
||||
None,
|
||||
]
|
||||
|
||||
requested_domain = None
|
||||
if DomainInformation.objects.filter(id=pk).exists():
|
||||
requested_domain = DomainInformation.objects.get(id=pk)
|
||||
|
||||
# if no domain information or domain request exist, the user
|
||||
# should be able to manage the domain; however, if domain information
|
||||
# and domain request exist, and domain request is not in valid status,
|
||||
# user should not be able to manage domain
|
||||
if (
|
||||
requested_domain
|
||||
and requested_domain.domain_request
|
||||
and requested_domain.domain_request.status not in valid_domain_statuses
|
||||
):
|
||||
return False
|
||||
|
||||
# Valid session keys exist,
|
||||
# the user is permissioned,
|
||||
# and it is in a valid status
|
||||
return True
|
||||
|
||||
|
||||
class DomainFormBaseView(DomainBaseView, FormMixin):
|
||||
"""
|
||||
|
@ -257,6 +389,7 @@ class DomainFormBaseView(DomainBaseView, FormMixin):
|
|||
)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN, HAS_PORTFOLIO_DOMAINS_VIEW_ALL)
|
||||
class DomainView(DomainBaseView):
|
||||
"""Domain detail overview page."""
|
||||
|
||||
|
@ -311,6 +444,7 @@ class DomainView(DomainBaseView):
|
|||
self._update_session_with_domain()
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainRenewalView(DomainBaseView):
|
||||
"""Domain detail overview page."""
|
||||
|
||||
|
@ -344,9 +478,9 @@ class DomainRenewalView(DomainBaseView):
|
|||
and (requested_domain.is_expiring() or requested_domain.is_expired())
|
||||
)
|
||||
|
||||
def post(self, request, pk):
|
||||
def post(self, request, domain_pk):
|
||||
|
||||
domain = get_object_or_404(Domain, id=pk)
|
||||
domain = get_object_or_404(Domain, id=domain_pk)
|
||||
|
||||
form = DomainRenewalForm(request.POST)
|
||||
|
||||
|
@ -363,7 +497,7 @@ class DomainRenewalView(DomainBaseView):
|
|||
"This domain has not been renewed for one year, "
|
||||
"please email help@get.gov if this problem persists.",
|
||||
)
|
||||
return HttpResponseRedirect(reverse("domain", kwargs={"pk": pk}))
|
||||
return HttpResponseRedirect(reverse("domain", kwargs={"domain_pk": domain_pk}))
|
||||
|
||||
# if not valid, render the template with error messages
|
||||
# passing editable and is_editable for re-render
|
||||
|
@ -379,6 +513,7 @@ class DomainRenewalView(DomainBaseView):
|
|||
)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainOrgNameAddressView(DomainFormBaseView):
|
||||
"""Organization view"""
|
||||
|
||||
|
@ -395,7 +530,7 @@ class DomainOrgNameAddressView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the overview page for the domain."""
|
||||
return reverse("domain-org-name-address", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-org-name-address", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""The form is valid, save the organization name and mailing address."""
|
||||
|
@ -420,6 +555,7 @@ class DomainOrgNameAddressView(DomainFormBaseView):
|
|||
return super().has_permission()
|
||||
|
||||
|
||||
@grant_access(IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainSubOrganizationView(DomainFormBaseView):
|
||||
"""Suborganization view"""
|
||||
|
||||
|
@ -454,7 +590,7 @@ class DomainSubOrganizationView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the overview page for the domain."""
|
||||
return reverse("domain-suborganization", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-suborganization", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""The form is valid, save the organization name and mailing address."""
|
||||
|
@ -466,6 +602,7 @@ class DomainSubOrganizationView(DomainFormBaseView):
|
|||
return super().form_valid(form)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER_AND_NOT_PORTFOLIO_MEMBER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainSeniorOfficialView(DomainFormBaseView):
|
||||
"""Domain senior official editing view."""
|
||||
|
||||
|
@ -493,7 +630,7 @@ class DomainSeniorOfficialView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the overview page for the domain."""
|
||||
return reverse("domain-senior-official", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-senior-official", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""The form is valid, save the senior official."""
|
||||
|
@ -523,6 +660,7 @@ class DomainSeniorOfficialView(DomainFormBaseView):
|
|||
return super().has_permission()
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainDNSView(DomainBaseView):
|
||||
"""DNS Information View."""
|
||||
|
||||
|
@ -586,7 +724,7 @@ class PrototypeDomainDNSRecordView(DomainFormBaseView):
|
|||
return True
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("prototype-domain-dns", kwargs={"pk": self.object.pk})
|
||||
return reverse("prototype-domain-dns", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def find_by_name(self, items, name):
|
||||
"""Find an item by name in a list of dictionaries."""
|
||||
|
@ -739,6 +877,7 @@ class PrototypeDomainDNSRecordView(DomainFormBaseView):
|
|||
return super().post(request)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainNameserversView(DomainFormBaseView):
|
||||
"""Domain nameserver editing view."""
|
||||
|
||||
|
@ -763,7 +902,7 @@ class DomainNameserversView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the nameservers page for the domain."""
|
||||
return reverse("domain-dns-nameservers", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-dns-nameservers", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Adjust context from FormMixin for formsets."""
|
||||
|
@ -866,6 +1005,7 @@ class DomainNameserversView(DomainFormBaseView):
|
|||
return super().form_valid(formset)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainDNSSECView(DomainFormBaseView):
|
||||
"""Domain DNSSEC editing view."""
|
||||
|
||||
|
@ -884,7 +1024,7 @@ class DomainDNSSECView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the DNSSEC page for the domain."""
|
||||
return reverse("domain-dns-dnssec", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-dns-dnssec", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Form submission posts to this view."""
|
||||
|
@ -903,6 +1043,7 @@ class DomainDNSSECView(DomainFormBaseView):
|
|||
return self.form_valid(form)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainDsDataView(DomainFormBaseView):
|
||||
"""Domain DNSSEC ds data editing view."""
|
||||
|
||||
|
@ -935,7 +1076,7 @@ class DomainDsDataView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the DS data page for the domain."""
|
||||
return reverse("domain-dns-dnssec-dsdata", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-dns-dnssec-dsdata", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Adjust context from FormMixin for formsets."""
|
||||
|
@ -1021,6 +1162,7 @@ class DomainDsDataView(DomainFormBaseView):
|
|||
return super().form_valid(formset)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainSecurityEmailView(DomainFormBaseView):
|
||||
"""Domain security email editing view."""
|
||||
|
||||
|
@ -1041,7 +1183,7 @@ class DomainSecurityEmailView(DomainFormBaseView):
|
|||
|
||||
def get_success_url(self):
|
||||
"""Redirect to the security email page for the domain."""
|
||||
return reverse("domain-security-email", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-security-email", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""The form is valid, call setter in model."""
|
||||
|
@ -1092,6 +1234,7 @@ class DomainSecurityEmailView(DomainFormBaseView):
|
|||
return redirect(self.get_success_url())
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainUsersView(DomainBaseView):
|
||||
"""Domain managers page in the domain details."""
|
||||
|
||||
|
@ -1187,6 +1330,7 @@ class DomainUsersView(DomainBaseView):
|
|||
return context
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainAddUserView(DomainFormBaseView):
|
||||
"""Inside of a domain's user management, a form for adding users.
|
||||
|
||||
|
@ -1198,7 +1342,7 @@ class DomainAddUserView(DomainFormBaseView):
|
|||
form_class = DomainAddUserForm
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("domain-users", kwargs={"pk": self.object.pk})
|
||||
return reverse("domain-users", kwargs={"domain_pk": self.object.pk})
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Add the specified user to this domain."""
|
||||
|
@ -1284,8 +1428,10 @@ class DomainAddUserView(DomainFormBaseView):
|
|||
messages.success(self.request, f"Added user {email}.")
|
||||
|
||||
|
||||
class DomainInvitationCancelView(SuccessMessageMixin, DomainInvitationPermissionCancelView):
|
||||
object: DomainInvitation
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainInvitationCancelView(SuccessMessageMixin, UpdateView):
|
||||
model = DomainInvitation
|
||||
pk_url_kwarg = "domain_invitation_pk"
|
||||
fields = []
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
@ -1303,26 +1449,29 @@ class DomainInvitationCancelView(SuccessMessageMixin, DomainInvitationPermission
|
|||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("domain-users", kwargs={"pk": self.object.domain.id})
|
||||
return reverse("domain-users", kwargs={"domain_pk": self.object.domain.id})
|
||||
|
||||
def get_success_message(self, cleaned_data):
|
||||
return f"Canceled invitation to {self.object.email}."
|
||||
|
||||
|
||||
class DomainDeleteUserView(UserDomainRolePermissionDeleteView):
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainDeleteUserView(DeleteView):
|
||||
"""Inside of a domain's user management, a form for deleting users."""
|
||||
|
||||
object: UserDomainRole # workaround for type mismatch in DeleteView
|
||||
object: UserDomainRole
|
||||
model = UserDomainRole
|
||||
context_object_name = "userdomainrole"
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
"""Custom get_object definition to grab a UserDomainRole object from a domain_id and user_id"""
|
||||
domain_id = self.kwargs.get("pk")
|
||||
domain_id = self.kwargs.get("domain_pk")
|
||||
user_id = self.kwargs.get("user_pk")
|
||||
return UserDomainRole.objects.get(domain=domain_id, user=user_id)
|
||||
|
||||
def get_success_url(self):
|
||||
"""Refreshes the page after a delete is successful"""
|
||||
return reverse("domain-users", kwargs={"pk": self.object.domain.id})
|
||||
return reverse("domain-users", kwargs={"domain_pk": self.object.domain.id})
|
||||
|
||||
def get_success_message(self):
|
||||
"""Returns confirmation content for the deletion event"""
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
import logging
|
||||
from collections import defaultdict
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import resolve, reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import TemplateView
|
||||
from django.contrib import messages
|
||||
from django.views.generic import DeleteView, DetailView, TemplateView
|
||||
from registrar.decorators import (
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT,
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_VIEW_ALL,
|
||||
IS_DOMAIN_REQUEST_CREATOR,
|
||||
grant_access,
|
||||
)
|
||||
from registrar.forms import domain_request_wizard as forms
|
||||
from registrar.forms.utility.wizard_form_helper import request_step_list
|
||||
from registrar.models import DomainRequest
|
||||
from registrar.models.contact import Contact
|
||||
from registrar.models.user import User
|
||||
from registrar.views.utility import StepsHelper
|
||||
from registrar.views.utility.permission_views import DomainRequestPermissionDeleteView
|
||||
from registrar.utility.enums import Step, PortfolioDomainRequestStep
|
||||
|
||||
from .utility import (
|
||||
DomainRequestPermissionView,
|
||||
DomainRequestPermissionWithdrawView,
|
||||
DomainRequestWizardPermissionView,
|
||||
DomainRequestPortfolioViewonlyView,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||
@grant_access(IS_DOMAIN_REQUEST_CREATOR, HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT)
|
||||
class DomainRequestWizard(TemplateView):
|
||||
"""
|
||||
A common set of methods and configuration.
|
||||
|
||||
|
@ -51,7 +51,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
# NB: this is included here for reference. Do not change it without
|
||||
# also changing the many places it is hardcoded in the HTML templates
|
||||
URL_NAMESPACE = "domain-request"
|
||||
# name for accessing /domain-request/<id>/edit
|
||||
# name for accessing /domain-request/<domain_request_pk>/edit
|
||||
EDIT_URL_NAME = "edit-domain-request"
|
||||
NEW_URL_NAME = "start"
|
||||
FINISHED_URL_NAME = "finished"
|
||||
|
@ -174,7 +174,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
|
||||
def has_pk(self):
|
||||
"""Does this wizard know about a DomainRequest database record?"""
|
||||
return bool(self.kwargs.get("id") is not None)
|
||||
return bool(self.kwargs.get("domain_request_pk") is not None)
|
||||
|
||||
def get_step_enum(self):
|
||||
"""Determines which step enum we should use for the wizard"""
|
||||
|
@ -209,11 +209,11 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
try:
|
||||
self._domain_request = DomainRequest.objects.get(
|
||||
creator=creator,
|
||||
pk=self.kwargs.get("id"),
|
||||
pk=self.kwargs.get("domain_request_pk"),
|
||||
)
|
||||
return self._domain_request
|
||||
except DomainRequest.DoesNotExist:
|
||||
logger.debug("DomainRequest id %s did not have a DomainRequest" % id)
|
||||
logger.debug("DomainRequest id %s did not have a DomainRequest" % self.kwargs.get("domain_request_pk"))
|
||||
|
||||
# If a user is creating a request, we assume that perms are handled upstream
|
||||
if self.request.user.is_org_user(self.request):
|
||||
|
@ -292,10 +292,10 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
|
||||
current_url = resolve(request.path_info).url_name
|
||||
|
||||
# if user visited via an "edit" url, associate the id of the
|
||||
# if user visited via an "edit" url, associate the pk of the
|
||||
# domain request they are trying to edit to this wizard instance
|
||||
# and remove any prior wizard data from their session
|
||||
if current_url == self.EDIT_URL_NAME and "id" in kwargs:
|
||||
if current_url == self.EDIT_URL_NAME and "domain_request_pk" in kwargs:
|
||||
del self.storage
|
||||
|
||||
# if accessing this class directly, redirect to either to an acknowledgement
|
||||
|
@ -474,7 +474,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
|||
|
||||
def goto(self, step):
|
||||
self.steps.current = step
|
||||
return redirect(reverse(f"{self.URL_NAMESPACE}:{step}", kwargs={"id": self.domain_request.id}))
|
||||
return redirect(reverse(f"{self.URL_NAMESPACE}:{step}", kwargs={"domain_request_pk": self.domain_request.id}))
|
||||
|
||||
def goto_next_step(self):
|
||||
"""Redirects to the next step."""
|
||||
|
@ -823,23 +823,12 @@ class Finished(DomainRequestWizard):
|
|||
return render(self.request, self.template_name, context)
|
||||
|
||||
|
||||
class DomainRequestStatus(DomainRequestPermissionView):
|
||||
@grant_access(IS_DOMAIN_REQUEST_CREATOR, HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT)
|
||||
class DomainRequestStatus(DetailView):
|
||||
template_name = "domain_request_status.html"
|
||||
|
||||
def has_permission(self):
|
||||
"""
|
||||
Override of the base has_permission class to account for portfolio permissions
|
||||
"""
|
||||
has_base_perms = super().has_permission()
|
||||
if not has_base_perms:
|
||||
return False
|
||||
|
||||
if self.request.user.is_org_user(self.request):
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_edit_request_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return True
|
||||
model = DomainRequest
|
||||
pk_url_kwarg = "domain_request_pk"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Context override to add a step list to the context"""
|
||||
|
@ -854,19 +843,27 @@ class DomainRequestStatus(DomainRequestPermissionView):
|
|||
return context
|
||||
|
||||
|
||||
class DomainRequestWithdrawConfirmation(DomainRequestPermissionWithdrawView):
|
||||
@grant_access(IS_DOMAIN_REQUEST_CREATOR, HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT)
|
||||
class DomainRequestWithdrawConfirmation(DetailView):
|
||||
"""This page will ask user to confirm if they want to withdraw
|
||||
|
||||
The DomainRequestPermissionView restricts access so that only the
|
||||
Access is restricted so that only the
|
||||
`creator` of the domain request may withdraw it.
|
||||
"""
|
||||
|
||||
template_name = "domain_request_withdraw_confirmation.html"
|
||||
template_name = "domain_request_withdraw_confirmation.html" # DetailView property for what model this is viewing
|
||||
model = DomainRequest
|
||||
pk_url_kwarg = "domain_request_pk"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
|
||||
class DomainRequestWithdrawn(DomainRequestPermissionWithdrawView):
|
||||
@grant_access(IS_DOMAIN_REQUEST_CREATOR, HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT)
|
||||
class DomainRequestWithdrawn(DetailView):
|
||||
# this view renders no template
|
||||
template_name = ""
|
||||
model = DomainRequest
|
||||
pk_url_kwarg = "domain_request_pk"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
"""View class that does the actual withdrawing.
|
||||
|
@ -874,7 +871,7 @@ class DomainRequestWithdrawn(DomainRequestPermissionWithdrawView):
|
|||
If user click on withdraw confirm button, this view updates the status
|
||||
to withdraw and send back to homepage.
|
||||
"""
|
||||
domain_request = DomainRequest.objects.get(id=self.kwargs["pk"])
|
||||
domain_request = DomainRequest.objects.get(id=self.kwargs["domain_request_pk"])
|
||||
domain_request.withdraw()
|
||||
domain_request.save()
|
||||
if self.request.user.is_org_user(self.request):
|
||||
|
@ -883,16 +880,16 @@ class DomainRequestWithdrawn(DomainRequestPermissionWithdrawView):
|
|||
return HttpResponseRedirect(reverse("home"))
|
||||
|
||||
|
||||
class DomainRequestDeleteView(DomainRequestPermissionDeleteView):
|
||||
@grant_access(IS_DOMAIN_REQUEST_CREATOR, HAS_PORTFOLIO_DOMAIN_REQUESTS_EDIT)
|
||||
class DomainRequestDeleteView(PermissionRequiredMixin, DeleteView):
|
||||
"""Delete view for home that allows the end user to delete DomainRequests"""
|
||||
|
||||
object: DomainRequest # workaround for type mismatch in DeleteView
|
||||
model = DomainRequest
|
||||
pk_url_kwarg = "domain_request_pk"
|
||||
|
||||
def has_permission(self):
|
||||
"""Custom override for has_permission to exclude all statuses, except WITHDRAWN and STARTED"""
|
||||
has_perm = super().has_permission()
|
||||
if not has_perm:
|
||||
return False
|
||||
|
||||
status = self.get_object().status
|
||||
valid_statuses = [DomainRequest.DomainRequestStatus.WITHDRAWN, DomainRequest.DomainRequestStatus.STARTED]
|
||||
|
@ -989,8 +986,12 @@ class DomainRequestDeleteView(DomainRequestPermissionDeleteView):
|
|||
|
||||
|
||||
# region Portfolio views
|
||||
class PortfolioDomainRequestStatusViewOnly(DomainRequestPortfolioViewonlyView):
|
||||
@grant_access(HAS_PORTFOLIO_DOMAIN_REQUESTS_VIEW_ALL)
|
||||
class PortfolioDomainRequestStatusViewOnly(DetailView):
|
||||
template_name = "portfolio_domain_request_status_viewonly.html"
|
||||
model = DomainRequest
|
||||
pk_url_kwarg = "domain_request_pk"
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
from django.http import JsonResponse
|
||||
from django.core.paginator import Paginator
|
||||
from registrar.decorators import grant_access, ALL
|
||||
from registrar.models import DomainRequest
|
||||
from django.utils.dateformat import format
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
|
||||
|
||||
@login_required
|
||||
@grant_access(ALL)
|
||||
def get_domain_requests_json(request):
|
||||
"""Given the current request,
|
||||
get all domain requests that are associated with the request user and exclude the APPROVED ones.
|
||||
If we are on the portfolio requests page, limit the response to only those requests associated with
|
||||
the given portfolio."""
|
||||
|
||||
domain_request_ids = get_domain_request_ids_from_request(request)
|
||||
domain_request_ids = _get_domain_request_ids_from_request(request)
|
||||
|
||||
objects = DomainRequest.objects.filter(id__in=domain_request_ids)
|
||||
unfiltered_total = objects.count()
|
||||
|
||||
objects = apply_search(objects, request)
|
||||
objects = apply_status_filter(objects, request)
|
||||
objects = apply_sorting(objects, request)
|
||||
objects = _apply_search(objects, request)
|
||||
objects = _apply_status_filter(objects, request)
|
||||
objects = _apply_sorting(objects, request)
|
||||
|
||||
paginator = Paginator(objects, 10)
|
||||
page_number = request.GET.get("page", 1)
|
||||
page_obj = paginator.get_page(page_number)
|
||||
domain_requests = [
|
||||
serialize_domain_request(request, domain_request, request.user) for domain_request in page_obj.object_list
|
||||
_serialize_domain_request(request, domain_request, request.user) for domain_request in page_obj.object_list
|
||||
]
|
||||
|
||||
return JsonResponse(
|
||||
|
@ -43,7 +43,7 @@ def get_domain_requests_json(request):
|
|||
)
|
||||
|
||||
|
||||
def get_domain_request_ids_from_request(request):
|
||||
def _get_domain_request_ids_from_request(request):
|
||||
"""Get domain request ids from request.
|
||||
|
||||
If portfolio specified, return domain request ids associated with portfolio.
|
||||
|
@ -62,7 +62,7 @@ def get_domain_request_ids_from_request(request):
|
|||
return domain_requests.values_list("id", flat=True)
|
||||
|
||||
|
||||
def apply_search(queryset, request):
|
||||
def _apply_search(queryset, request):
|
||||
search_term = request.GET.get("search_term")
|
||||
is_portfolio = request.GET.get("portfolio")
|
||||
|
||||
|
@ -90,7 +90,7 @@ def apply_search(queryset, request):
|
|||
return queryset
|
||||
|
||||
|
||||
def apply_status_filter(queryset, request):
|
||||
def _apply_status_filter(queryset, request):
|
||||
status_param = request.GET.get("status")
|
||||
if status_param:
|
||||
status_list = status_param.split(",")
|
||||
|
@ -105,7 +105,7 @@ def apply_status_filter(queryset, request):
|
|||
return queryset
|
||||
|
||||
|
||||
def apply_sorting(queryset, request):
|
||||
def _apply_sorting(queryset, request):
|
||||
sort_by = request.GET.get("sort_by", "id") # Default to 'id'
|
||||
order = request.GET.get("order", "asc") # Default to 'asc'
|
||||
|
||||
|
@ -118,7 +118,7 @@ def apply_sorting(queryset, request):
|
|||
return queryset.order_by(sort_by)
|
||||
|
||||
|
||||
def serialize_domain_request(request, domain_request, user):
|
||||
def _serialize_domain_request(request, domain_request, user):
|
||||
|
||||
deletable_statuses = [
|
||||
DomainRequest.DomainRequestStatus.STARTED,
|
||||
|
@ -154,9 +154,9 @@ def serialize_domain_request(request, domain_request, user):
|
|||
|
||||
# Map the action label to corresponding URLs and icons
|
||||
action_url_map = {
|
||||
"Edit": reverse("edit-domain-request", kwargs={"id": domain_request.id}),
|
||||
"Manage": reverse("domain-request-status", kwargs={"pk": domain_request.id}),
|
||||
"View": reverse("domain-request-status-viewonly", kwargs={"pk": domain_request.id}),
|
||||
"Edit": reverse("edit-domain-request", kwargs={"domain_request_pk": domain_request.id}),
|
||||
"Manage": reverse("domain-request-status", kwargs={"domain_request_pk": domain_request.id}),
|
||||
"View": reverse("domain-request-status-viewonly", kwargs={"domain_request_pk": domain_request.id}),
|
||||
}
|
||||
|
||||
svg_icon_map = {"Edit": "edit", "Manage": "settings", "View": "visibility"}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import logging
|
||||
from django.http import JsonResponse
|
||||
from django.core.paginator import Paginator
|
||||
from registrar.decorators import grant_access, ALL
|
||||
from registrar.models import UserDomainRole, Domain, DomainInformation, User
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@login_required
|
||||
@grant_access(ALL)
|
||||
def get_domains_json(request):
|
||||
"""Given the current request,
|
||||
get all domains that are associated with the UserDomainRole object"""
|
||||
|
@ -142,7 +142,7 @@ def serialize_domain(domain, request):
|
|||
"state": domain.state,
|
||||
"state_display": domain.state_display(request),
|
||||
"get_state_help_text": domain.get_state_help_text(),
|
||||
"action_url": reverse("domain", kwargs={"pk": domain.id}),
|
||||
"action_url": reverse("domain", kwargs={"domain_pk": domain.id}),
|
||||
"action_label": ("View" if view_only else "Manage"),
|
||||
"svg_icon": ("visibility" if view_only else "settings"),
|
||||
"domain_info__sub_organization": suborganization_name,
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
from registrar.decorators import grant_access, ALL
|
||||
|
||||
|
||||
@grant_access(ALL)
|
||||
def index(request):
|
||||
"""This page is available to anyone without logging in."""
|
||||
context = {}
|
||||
|
|
|
@ -4,37 +4,38 @@ from django.http import JsonResponse
|
|||
from django.core.paginator import Paginator
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views import View
|
||||
from registrar.decorators import HAS_PORTFOLIO_MEMBERS_ANY_PERM, grant_access
|
||||
from registrar.models import UserDomainRole, Domain, DomainInformation, User
|
||||
from django.urls import reverse
|
||||
from django.db.models import Q
|
||||
|
||||
from registrar.models.domain_invitation import DomainInvitation
|
||||
from registrar.views.utility.mixins import PortfolioMemberDomainsPermission
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMemberDomainsJson(View):
|
||||
|
||||
def get(self, request):
|
||||
"""Given the current request,
|
||||
get all domains that are associated with the portfolio, or
|
||||
associated with the member/invited member"""
|
||||
|
||||
domain_ids = self.get_domain_ids_from_request(request)
|
||||
domain_ids = self._get_domain_ids_from_request(request)
|
||||
|
||||
objects = Domain.objects.filter(id__in=domain_ids).select_related("domain_info__sub_organization")
|
||||
unfiltered_total = objects.count()
|
||||
|
||||
objects = self.apply_search(objects, request)
|
||||
objects = self.apply_sorting(objects, request)
|
||||
objects = self._apply_search(objects, request)
|
||||
objects = self._apply_sorting(objects, request)
|
||||
|
||||
paginator = Paginator(objects, self.get_page_size(request))
|
||||
paginator = Paginator(objects, self._get_page_size(request))
|
||||
page_number = request.GET.get("page")
|
||||
page_obj = paginator.get_page(page_number)
|
||||
|
||||
member_id = request.GET.get("member_id")
|
||||
domains = [self.serialize_domain(domain, member_id, request.user) for domain in page_obj.object_list]
|
||||
domains = [self._serialize_domain(domain, member_id, request.user) for domain in page_obj.object_list]
|
||||
|
||||
return JsonResponse(
|
||||
{
|
||||
|
@ -48,7 +49,7 @@ class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
|||
}
|
||||
)
|
||||
|
||||
def get_page_size(self, request):
|
||||
def _get_page_size(self, request):
|
||||
"""Gets the page size.
|
||||
|
||||
If member_only, need to return the entire result set every time, so need
|
||||
|
@ -65,7 +66,7 @@ class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
|||
# later
|
||||
return 1000
|
||||
|
||||
def get_domain_ids_from_request(self, request):
|
||||
def _get_domain_ids_from_request(self, request):
|
||||
"""Get domain ids from request.
|
||||
|
||||
request.get.email - email address of invited member
|
||||
|
@ -100,13 +101,13 @@ class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
|||
logger.warning("Invalid search criteria, returning empty results list")
|
||||
return []
|
||||
|
||||
def apply_search(self, queryset, request):
|
||||
def _apply_search(self, queryset, request):
|
||||
search_term = request.GET.get("search_term")
|
||||
if search_term:
|
||||
queryset = queryset.filter(Q(name__icontains=search_term))
|
||||
return queryset
|
||||
|
||||
def apply_sorting(self, queryset, request):
|
||||
def _apply_sorting(self, queryset, request):
|
||||
# Get the sorting parameters from the request
|
||||
sort_by = request.GET.get("sort_by", "name")
|
||||
order = request.GET.get("order", "asc")
|
||||
|
@ -141,7 +142,7 @@ class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
|||
|
||||
return queryset
|
||||
|
||||
def serialize_domain(self, domain, member_id, user):
|
||||
def _serialize_domain(self, domain, member_id, user):
|
||||
suborganization_name = None
|
||||
try:
|
||||
domain_info = domain.domain_info
|
||||
|
@ -176,7 +177,7 @@ class PortfolioMemberDomainsJson(PortfolioMemberDomainsPermission, View):
|
|||
"state": domain.state,
|
||||
"state_display": domain.state_display(),
|
||||
"get_state_help_text": domain.get_state_help_text(),
|
||||
"action_url": reverse("domain", kwargs={"pk": domain.id}),
|
||||
"action_url": reverse("domain", kwargs={"domain_pk": domain.id}),
|
||||
"action_label": ("View" if view_only else "Manage"),
|
||||
"svg_icon": ("visibility" if view_only else "settings"),
|
||||
"domain_info__sub_organization": suborganization_name,
|
||||
|
|
|
@ -6,16 +6,17 @@ from django.contrib.postgres.aggregates import ArrayAgg
|
|||
from django.urls import reverse
|
||||
from django.views import View
|
||||
|
||||
from registrar.decorators import HAS_PORTFOLIO_MEMBERS_ANY_PERM, grant_access
|
||||
from registrar.models.domain_invitation import DomainInvitation
|
||||
from registrar.models.portfolio_invitation import PortfolioInvitation
|
||||
from registrar.models.user_portfolio_permission import UserPortfolioPermission
|
||||
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
|
||||
from registrar.views.utility.mixins import PortfolioMembersPermission
|
||||
from registrar.models.utility.orm_helper import ArrayRemoveNull
|
||||
from django.contrib.postgres.aggregates import StringAgg
|
||||
|
||||
|
||||
class PortfolioMembersJson(PortfolioMembersPermission, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMembersJson(View):
|
||||
|
||||
def get(self, request):
|
||||
"""Fetch members (permissions and invitations) for the given portfolio."""
|
||||
|
@ -236,7 +237,7 @@ class PortfolioMembersJson(PortfolioMembersPermission, View):
|
|||
),
|
||||
# split domain_info array values into ids to form urls, and names
|
||||
"domain_urls": [
|
||||
reverse("domain", kwargs={"pk": domain_info.split(":")[0]}) for domain_info in domain_info_list
|
||||
reverse("domain", kwargs={"domain_pk": domain_info.split(":")[0]}) for domain_info in domain_info_list
|
||||
],
|
||||
"domain_names": [domain_info.split(":")[1] for domain_info in domain_info_list],
|
||||
"is_admin": is_admin,
|
||||
|
|
|
@ -5,14 +5,26 @@ from django.http import Http404, JsonResponse
|
|||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import DetailView
|
||||
from django.contrib import messages
|
||||
from registrar.decorators import (
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM,
|
||||
HAS_PORTFOLIO_DOMAINS_ANY_PERM,
|
||||
HAS_PORTFOLIO_MEMBERS_ANY_PERM,
|
||||
HAS_PORTFOLIO_MEMBERS_EDIT,
|
||||
IS_PORTFOLIO_MEMBER,
|
||||
grant_access,
|
||||
)
|
||||
from registrar.forms import portfolio as portfolioForms
|
||||
from registrar.models import Portfolio, User
|
||||
from registrar.models.domain import Domain
|
||||
from registrar.models.domain_invitation import DomainInvitation
|
||||
from registrar.models.portfolio_invitation import PortfolioInvitation
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
from registrar.models.user_portfolio_permission import UserPortfolioPermission
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
DomainInvitation,
|
||||
Portfolio,
|
||||
PortfolioInvitation,
|
||||
User,
|
||||
UserDomainRole,
|
||||
UserPortfolioPermission,
|
||||
)
|
||||
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
|
||||
from registrar.utility.email import EmailSendingError
|
||||
from registrar.utility.email_invitations import (
|
||||
|
@ -24,18 +36,6 @@ from registrar.utility.email_invitations import (
|
|||
)
|
||||
from registrar.utility.errors import MissingEmailError
|
||||
from registrar.utility.enums import DefaultUserValues
|
||||
from registrar.views.utility.mixins import PortfolioMemberPermission
|
||||
from registrar.views.utility.permission_views import (
|
||||
PortfolioDomainRequestsPermissionView,
|
||||
PortfolioDomainsPermissionView,
|
||||
PortfolioBasePermissionView,
|
||||
NoPortfolioDomainsPermissionView,
|
||||
PortfolioMemberDomainsPermissionView,
|
||||
PortfolioMemberDomainsEditPermissionView,
|
||||
PortfolioMemberEditPermissionView,
|
||||
PortfolioMemberPermissionView,
|
||||
PortfolioMembersPermissionView,
|
||||
)
|
||||
from django.views.generic import View
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django.db import IntegrityError
|
||||
|
@ -46,7 +46,8 @@ from registrar.views.utility.invitation_helper import get_org_membership
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_DOMAINS_ANY_PERM)
|
||||
class PortfolioDomainsView(View):
|
||||
|
||||
template_name = "portfolio_domains.html"
|
||||
|
||||
|
@ -59,7 +60,8 @@ class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
|||
return render(request, "portfolio_domains.html", context)
|
||||
|
||||
|
||||
class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM)
|
||||
class PortfolioDomainRequestsView(View):
|
||||
|
||||
template_name = "portfolio_requests.html"
|
||||
|
||||
|
@ -67,8 +69,10 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
|||
return render(request, "portfolio_requests.html")
|
||||
|
||||
|
||||
class PortfolioMemberView(PortfolioMemberPermissionView, View):
|
||||
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMemberView(DetailView, View):
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member.html"
|
||||
|
||||
def get(self, request, pk):
|
||||
|
@ -109,7 +113,8 @@ class PortfolioMemberView(PortfolioMemberPermissionView, View):
|
|||
)
|
||||
|
||||
|
||||
class PortfolioMemberDeleteView(PortfolioMemberPermission, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMemberDeleteView(View):
|
||||
|
||||
def post(self, request, pk):
|
||||
"""
|
||||
|
@ -186,8 +191,10 @@ class PortfolioMemberDeleteView(PortfolioMemberPermission, View):
|
|||
messages.warning(self.request, "Could not send email notification to existing organization admins.")
|
||||
|
||||
|
||||
class PortfolioMemberEditView(PortfolioMemberEditPermissionView, View):
|
||||
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT)
|
||||
class PortfolioMemberEditView(DetailView, View):
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member_permissions.html"
|
||||
form_class = portfolioForms.PortfolioMemberForm
|
||||
|
||||
|
@ -266,7 +273,8 @@ class PortfolioMemberEditView(PortfolioMemberEditPermissionView, View):
|
|||
messages.warning(self.request, "Could not send email notification to existing organization admins.")
|
||||
|
||||
|
||||
class PortfolioMemberDomainsView(PortfolioMemberDomainsPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMemberDomainsView(View):
|
||||
|
||||
template_name = "portfolio_member_domains.html"
|
||||
|
||||
|
@ -284,8 +292,10 @@ class PortfolioMemberDomainsView(PortfolioMemberDomainsPermissionView, View):
|
|||
)
|
||||
|
||||
|
||||
class PortfolioMemberDomainsEditView(PortfolioMemberDomainsEditPermissionView, View):
|
||||
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT)
|
||||
class PortfolioMemberDomainsEditView(DetailView, View):
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member_domains_edit.html"
|
||||
|
||||
def get(self, request, pk):
|
||||
|
@ -394,8 +404,10 @@ class PortfolioMemberDomainsEditView(PortfolioMemberDomainsEditPermissionView, V
|
|||
UserDomainRole.objects.filter(domain_id__in=removed_domain_ids, user=member).delete()
|
||||
|
||||
|
||||
class PortfolioInvitedMemberView(PortfolioMemberPermissionView, View):
|
||||
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioInvitedMemberView(DetailView, View):
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member.html"
|
||||
# form_class = PortfolioInvitedMemberForm
|
||||
|
||||
|
@ -436,7 +448,8 @@ class PortfolioInvitedMemberView(PortfolioMemberPermissionView, View):
|
|||
)
|
||||
|
||||
|
||||
class PortfolioInvitedMemberDeleteView(PortfolioMemberPermission, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioInvitedMemberDeleteView(View):
|
||||
|
||||
def post(self, request, pk):
|
||||
"""
|
||||
|
@ -479,8 +492,10 @@ class PortfolioInvitedMemberDeleteView(PortfolioMemberPermission, View):
|
|||
messages.warning(self.request, "Could not send email notification to existing organization admins.")
|
||||
|
||||
|
||||
class PortfolioInvitedMemberEditView(PortfolioMemberEditPermissionView, View):
|
||||
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT)
|
||||
class PortfolioInvitedMemberEditView(DetailView, View):
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member_permissions.html"
|
||||
form_class = portfolioForms.PortfolioInvitedMemberForm
|
||||
|
||||
|
@ -548,7 +563,8 @@ class PortfolioInvitedMemberEditView(PortfolioMemberEditPermissionView, View):
|
|||
messages.warning(self.request, "Could not send email notification to existing organization admins.")
|
||||
|
||||
|
||||
class PortfolioInvitedMemberDomainsView(PortfolioMemberDomainsPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioInvitedMemberDomainsView(View):
|
||||
|
||||
template_name = "portfolio_member_domains.html"
|
||||
|
||||
|
@ -564,8 +580,11 @@ class PortfolioInvitedMemberDomainsView(PortfolioMemberDomainsPermissionView, Vi
|
|||
)
|
||||
|
||||
|
||||
class PortfolioInvitedMemberDomainsEditView(PortfolioMemberDomainsEditPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT)
|
||||
class PortfolioInvitedMemberDomainsEditView(DetailView, View):
|
||||
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
template_name = "portfolio_member_domains_edit.html"
|
||||
|
||||
def get(self, request, pk):
|
||||
|
@ -690,7 +709,8 @@ class PortfolioInvitedMemberDomainsEditView(PortfolioMemberDomainsEditPermission
|
|||
).update(status=DomainInvitation.DomainInvitationStatus.CANCELED)
|
||||
|
||||
|
||||
class PortfolioNoDomainsView(NoPortfolioDomainsPermissionView, View):
|
||||
@grant_access(IS_PORTFOLIO_MEMBER)
|
||||
class PortfolioNoDomainsView(View):
|
||||
"""Some users have access to the underlying portfolio, but not any domains.
|
||||
This is a custom view which explains that to the user - and denotes who to contact.
|
||||
"""
|
||||
|
@ -719,7 +739,8 @@ class PortfolioNoDomainsView(NoPortfolioDomainsPermissionView, View):
|
|||
return context
|
||||
|
||||
|
||||
class PortfolioNoDomainRequestsView(NoPortfolioDomainsPermissionView, View):
|
||||
@grant_access(IS_PORTFOLIO_MEMBER)
|
||||
class PortfolioNoDomainRequestsView(View):
|
||||
"""Some users have access to the underlying portfolio, but not any domain requests.
|
||||
This is a custom view which explains that to the user - and denotes who to contact.
|
||||
"""
|
||||
|
@ -748,7 +769,8 @@ class PortfolioNoDomainRequestsView(NoPortfolioDomainsPermissionView, View):
|
|||
return context
|
||||
|
||||
|
||||
class PortfolioOrganizationView(PortfolioBasePermissionView, FormMixin):
|
||||
@grant_access(IS_PORTFOLIO_MEMBER)
|
||||
class PortfolioOrganizationView(DetailView, FormMixin):
|
||||
"""
|
||||
View to handle displaying and updating the portfolio's organization details.
|
||||
"""
|
||||
|
@ -810,7 +832,8 @@ class PortfolioOrganizationView(PortfolioBasePermissionView, FormMixin):
|
|||
return reverse("organization")
|
||||
|
||||
|
||||
class PortfolioSeniorOfficialView(PortfolioBasePermissionView, FormMixin):
|
||||
@grant_access(IS_PORTFOLIO_MEMBER)
|
||||
class PortfolioSeniorOfficialView(DetailView, FormMixin):
|
||||
"""
|
||||
View to handle displaying and updating the portfolio's senior official details.
|
||||
For now, this view is readonly.
|
||||
|
@ -841,7 +864,8 @@ class PortfolioSeniorOfficialView(PortfolioBasePermissionView, FormMixin):
|
|||
return self.render_to_response(self.get_context_data(form=form))
|
||||
|
||||
|
||||
class PortfolioMembersView(PortfolioMembersPermissionView, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioMembersView(View):
|
||||
|
||||
template_name = "portfolio_members.html"
|
||||
|
||||
|
@ -850,10 +874,13 @@ class PortfolioMembersView(PortfolioMembersPermissionView, View):
|
|||
return render(request, "portfolio_members.html")
|
||||
|
||||
|
||||
class PortfolioAddMemberView(PortfolioMembersPermissionView, FormMixin):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM)
|
||||
class PortfolioAddMemberView(DetailView, FormMixin):
|
||||
|
||||
template_name = "portfolio_members_add_new.html"
|
||||
form_class = portfolioForms.PortfolioNewMemberForm
|
||||
model = Portfolio
|
||||
context_object_name = "portfolio"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Handle GET requests to display the form."""
|
||||
|
|
|
@ -6,19 +6,17 @@ from django.shortcuts import render
|
|||
from django.contrib import admin
|
||||
from django.db.models import Avg, F
|
||||
|
||||
from registrar.views.utility.mixins import DomainAndRequestsReportsPermission, PortfolioReportsPermission
|
||||
from registrar.decorators import ALL, HAS_PORTFOLIO_MEMBERS_VIEW, IS_STAFF, grant_access
|
||||
from .. import models
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from registrar.utility import csv_export
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class AnalyticsView(View):
|
||||
def get(self, request):
|
||||
thirty_days_ago = datetime.datetime.today() - datetime.timedelta(days=30)
|
||||
|
@ -178,7 +176,7 @@ class AnalyticsView(View):
|
|||
return render(request, "admin/analytics.html", context)
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataType(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
# match the CSV example with all the fields
|
||||
|
@ -188,7 +186,8 @@ class ExportDataType(View):
|
|||
return response
|
||||
|
||||
|
||||
class ExportDataTypeUser(DomainAndRequestsReportsPermission, View):
|
||||
@grant_access(ALL)
|
||||
class ExportDataTypeUser(View):
|
||||
"""Returns a domain report for a given user on the request"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
@ -199,7 +198,8 @@ class ExportDataTypeUser(DomainAndRequestsReportsPermission, View):
|
|||
return response
|
||||
|
||||
|
||||
class ExportMembersPortfolio(PortfolioReportsPermission, View):
|
||||
@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW)
|
||||
class ExportMembersPortfolio(View):
|
||||
"""Returns a members report for a given portfolio"""
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
@ -227,7 +227,7 @@ class ExportMembersPortfolio(PortfolioReportsPermission, View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataFull(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Smaller export based on 1
|
||||
|
@ -237,7 +237,7 @@ class ExportDataFull(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataFederal(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Federal only
|
||||
|
@ -247,7 +247,7 @@ class ExportDataFederal(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDomainRequestDataFull(View):
|
||||
"""Generates a downloaded report containing all Domain Requests (except started)"""
|
||||
|
||||
|
@ -259,7 +259,7 @@ class ExportDomainRequestDataFull(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataDomainsGrowth(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
start_date = request.GET.get("start_date", "")
|
||||
|
@ -272,7 +272,7 @@ class ExportDataDomainsGrowth(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataRequestsGrowth(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
start_date = request.GET.get("start_date", "")
|
||||
|
@ -285,7 +285,7 @@ class ExportDataRequestsGrowth(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataManagedDomains(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
start_date = request.GET.get("start_date", "")
|
||||
|
@ -297,7 +297,7 @@ class ExportDataManagedDomains(View):
|
|||
return response
|
||||
|
||||
|
||||
@method_decorator(staff_member_required, name="dispatch")
|
||||
@grant_access(IS_STAFF)
|
||||
class ExportDataUnmanagedDomains(View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
start_date = request.GET.get("start_date", "")
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.db.models import ForeignKey, OneToOneField, ManyToManyField, ManyToO
|
|||
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.views import View
|
||||
from registrar.decorators import IS_STAFF, grant_access
|
||||
from registrar.models.domain import Domain
|
||||
from registrar.models.domain_request import DomainRequest
|
||||
from registrar.models.user import User
|
||||
|
@ -18,6 +19,7 @@ from registrar.utility.db_helpers import ignore_unique_violation
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@grant_access(IS_STAFF)
|
||||
class TransferUserView(View):
|
||||
"""Transfer user methods that set up the transfer_user template and handle the forms on it."""
|
||||
|
||||
|
|
|
@ -5,22 +5,25 @@ import logging
|
|||
|
||||
from django.contrib import messages
|
||||
from django.http import QueryDict
|
||||
from django.views.generic import DetailView
|
||||
from django.views.generic.edit import FormMixin
|
||||
from registrar.decorators import ALL, grant_access
|
||||
from registrar.forms.user_profile import UserProfileForm, FinishSetupProfileForm
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from registrar.models.user import User
|
||||
from registrar.models.utility.generic_helper import replace_url_queryparams
|
||||
from registrar.views.utility.permission_views import UserProfilePermissionView
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UserProfileView(UserProfilePermissionView, FormMixin):
|
||||
@grant_access(ALL)
|
||||
class UserProfileView(DetailView, FormMixin):
|
||||
"""
|
||||
Base View for the User Profile. Handles getting and setting the User Profile
|
||||
"""
|
||||
|
||||
model = User
|
||||
context_object_name = "user"
|
||||
template_name = "profile.html"
|
||||
form_class = UserProfileForm
|
||||
base_view_name = "user-profile"
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
from .steps_helper import StepsHelper
|
||||
from .always_404 import always_404
|
||||
|
||||
from .permission_views import (
|
||||
DomainPermissionView,
|
||||
DomainRequestPermissionView,
|
||||
DomainRequestPermissionWithdrawView,
|
||||
DomainRequestWizardPermissionView,
|
||||
PortfolioMembersPermission,
|
||||
DomainRequestPortfolioViewonlyView,
|
||||
DomainInvitationPermissionCancelView,
|
||||
)
|
||||
from .api_views import get_senior_official_from_federal_agency_json
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import logging
|
||||
from django.http import JsonResponse
|
||||
from django.forms.models import model_to_dict
|
||||
from registrar.decorators import IS_STAFF, grant_access
|
||||
from registrar.models import FederalAgency, SeniorOfficial, DomainRequest
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from registrar.utility.admin_helpers import get_action_needed_reason_default_email, get_rejection_reason_default_email
|
||||
from registrar.models.portfolio import Portfolio
|
||||
from registrar.utility.constants import BranchChoices
|
||||
|
@ -11,8 +10,7 @@ from registrar.utility.constants import BranchChoices
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_senior_official_from_federal_agency_json(request):
|
||||
"""Returns federal_agency information as a JSON"""
|
||||
|
||||
|
@ -39,8 +37,7 @@ def get_senior_official_from_federal_agency_json(request):
|
|||
return JsonResponse({"error": "Senior Official not found"}, status=404)
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_portfolio_json(request):
|
||||
"""Returns portfolio information as a JSON"""
|
||||
|
||||
|
@ -96,8 +93,7 @@ def get_portfolio_json(request):
|
|||
return JsonResponse(portfolio_dict)
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_suborganization_list_json(request):
|
||||
"""Returns suborganization list information for a portfolio as a JSON"""
|
||||
|
||||
|
@ -119,8 +115,7 @@ def get_suborganization_list_json(request):
|
|||
return JsonResponse({"results": results, "pagination": {"more": False}})
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_federal_and_portfolio_types_from_federal_agency_json(request):
|
||||
"""Returns specific portfolio information as a JSON. Request must have
|
||||
both agency_name and organization_type."""
|
||||
|
@ -148,8 +143,7 @@ def get_federal_and_portfolio_types_from_federal_agency_json(request):
|
|||
return JsonResponse(response_data)
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_action_needed_email_for_user_json(request):
|
||||
"""Returns a default action needed email for a given user"""
|
||||
|
||||
|
@ -173,8 +167,7 @@ def get_action_needed_email_for_user_json(request):
|
|||
return JsonResponse({"email": email}, status=200)
|
||||
|
||||
|
||||
@login_required
|
||||
@staff_member_required
|
||||
@grant_access(IS_STAFF)
|
||||
def get_rejection_email_for_user_json(request):
|
||||
"""Returns a default rejection email for a given user"""
|
||||
|
||||
|
|
|
@ -35,3 +35,10 @@ def custom_403_error_view(request, exception=None, context=None):
|
|||
if context is None:
|
||||
context = {}
|
||||
return render(request, "403.html", context=context, status=403)
|
||||
|
||||
|
||||
def custom_404_error_view(request, exception=None, context=None):
|
||||
"""Used to redirect 404 errors to a custom view"""
|
||||
if context is None:
|
||||
context = {}
|
||||
return render(request, "404.html", context=context, status=404)
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
"""Permissions-related mixin classes."""
|
||||
"""Mixin classes."""
|
||||
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
DomainRequest,
|
||||
DomainInvitation,
|
||||
DomainInformation,
|
||||
UserDomainRole,
|
||||
)
|
||||
import logging
|
||||
|
||||
|
||||
|
@ -143,486 +134,3 @@ class OrderableFieldsMixin:
|
|||
# Infer the column name in a similar manner to how Django does
|
||||
method.short_description = field.replace("_", " ")
|
||||
return method
|
||||
|
||||
|
||||
class PermissionsLoginMixin(PermissionRequiredMixin):
|
||||
"""Mixin that redirects to login page if not logged in, otherwise 403."""
|
||||
|
||||
def handle_no_permission(self):
|
||||
self.raise_exception = self.request.user.is_authenticated
|
||||
return super().handle_no_permission()
|
||||
|
||||
|
||||
class DomainAndRequestsReportsPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin for domain and requests csv downloads"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class PortfolioReportsPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin for portfolio csv downloads"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_view_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return self.request.user.is_org_user(self.request)
|
||||
|
||||
|
||||
class DomainPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain if user has access,
|
||||
otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
pk = self.kwargs["pk"]
|
||||
# If pk is none then something went very wrong...
|
||||
if pk is None:
|
||||
raise ValueError("Primary key is None")
|
||||
|
||||
# test if domain in editable state
|
||||
if not self.in_editable_state(pk):
|
||||
return False
|
||||
|
||||
if self.can_access_other_user_domains(pk):
|
||||
return True
|
||||
|
||||
# user needs to have a role on the domain
|
||||
if not UserDomainRole.objects.filter(user=self.request.user, domain__id=pk).exists():
|
||||
return self.can_access_domain_via_portfolio(pk)
|
||||
|
||||
# if we need to check more about the nature of role, do it here.
|
||||
return True
|
||||
|
||||
def can_access_domain_via_portfolio(self, pk):
|
||||
"""Most views should not allow permission to portfolio users.
|
||||
If particular views allow access to the domain pages, they will need to override
|
||||
this function.
|
||||
"""
|
||||
return False
|
||||
|
||||
def in_editable_state(self, pk):
|
||||
"""Is the domain in an editable state"""
|
||||
|
||||
requested_domain = None
|
||||
if Domain.objects.filter(id=pk).exists():
|
||||
requested_domain = Domain.objects.get(id=pk)
|
||||
|
||||
# if domain is editable return true
|
||||
if requested_domain and requested_domain.is_editable():
|
||||
return True
|
||||
return False
|
||||
|
||||
def can_access_other_user_domains(self, pk):
|
||||
"""Checks to see if an authorized user (staff or superuser)
|
||||
can access a domain that they did not create or was invited to.
|
||||
"""
|
||||
|
||||
# Check if the user is permissioned...
|
||||
user_is_analyst_or_superuser = self.request.user.has_perm(
|
||||
"registrar.analyst_access_permission"
|
||||
) or self.request.user.has_perm("registrar.full_access_permission")
|
||||
|
||||
if not user_is_analyst_or_superuser:
|
||||
return False
|
||||
|
||||
# Check if the user is attempting a valid edit action.
|
||||
# In other words, if the analyst/admin did not click
|
||||
# the 'Manage Domain' button in /admin,
|
||||
# then they cannot access this page.
|
||||
session = self.request.session
|
||||
can_do_action = (
|
||||
"analyst_action" in session
|
||||
and "analyst_action_location" in session
|
||||
and session["analyst_action_location"] == pk
|
||||
)
|
||||
|
||||
if not can_do_action:
|
||||
return False
|
||||
|
||||
# Analysts may manage domains, when they are in these statuses:
|
||||
valid_domain_statuses = [
|
||||
DomainRequest.DomainRequestStatus.APPROVED,
|
||||
DomainRequest.DomainRequestStatus.IN_REVIEW,
|
||||
DomainRequest.DomainRequestStatus.REJECTED,
|
||||
DomainRequest.DomainRequestStatus.ACTION_NEEDED,
|
||||
# Edge case - some domains do not have
|
||||
# a status or DomainInformation... aka a status of 'None'.
|
||||
# It is necessary to access those to correct errors.
|
||||
None,
|
||||
]
|
||||
|
||||
requested_domain = None
|
||||
if DomainInformation.objects.filter(id=pk).exists():
|
||||
requested_domain = DomainInformation.objects.get(id=pk)
|
||||
|
||||
# if no domain information or domain request exist, the user
|
||||
# should be able to manage the domain; however, if domain information
|
||||
# and domain request exist, and domain request is not in valid status,
|
||||
# user should not be able to manage domain
|
||||
if (
|
||||
requested_domain
|
||||
and requested_domain.domain_request
|
||||
and requested_domain.domain_request.status not in valid_domain_statuses
|
||||
):
|
||||
return False
|
||||
|
||||
# Valid session keys exist,
|
||||
# the user is permissioned,
|
||||
# and it is in a valid status
|
||||
return True
|
||||
|
||||
|
||||
class DomainRequestPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain request if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain request.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# user needs to be the creator of the domain request
|
||||
# this query is empty if there isn't a domain request with this
|
||||
# id and this user as creator
|
||||
if not DomainRequest.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class DomainRequestPortfolioViewonlyPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain request if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain request.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if not self.request.user.is_org_user(self.request):
|
||||
return False
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_view_all_requests_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class UserDeleteDomainRolePermission(PermissionsLoginMixin):
|
||||
"""Permission mixin for UserDomainRole if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this domain request.
|
||||
|
||||
The user is in self.request.user and the domain needs to be looked
|
||||
up from the domain's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
domain_pk = self.kwargs["pk"]
|
||||
user_pk = self.kwargs["user_pk"]
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# Check if the UserDomainRole object exists, then check
|
||||
# if the user requesting the delete has permissions to do so
|
||||
has_delete_permission = UserDomainRole.objects.filter(
|
||||
user=user_pk,
|
||||
domain=domain_pk,
|
||||
domain__permissions__user=self.request.user,
|
||||
).exists()
|
||||
|
||||
user_is_analyst_or_superuser = self.request.user.has_perm(
|
||||
"registrar.analyst_access_permission"
|
||||
) or self.request.user.has_perm("registrar.full_access_permission")
|
||||
|
||||
if not (has_delete_permission or user_is_analyst_or_superuser):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class DomainRequestPermissionWithdraw(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to withdraw action on domain request
|
||||
if user has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to withdraw this domain request."""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# user needs to be the creator of the domain request
|
||||
# this query is empty if there isn't a domain request with this
|
||||
# id and this user as creator
|
||||
if not DomainRequest.objects.filter(creator=self.request.user, id=self.kwargs["pk"]).exists():
|
||||
return False
|
||||
|
||||
# Restricted users should not be able to withdraw domain requests
|
||||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class DomainRequestWizardPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to start or edit domain request if
|
||||
user has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has permission to start or edit a domain request.
|
||||
|
||||
The user is in self.request.user
|
||||
"""
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
# The user has an ineligible flag
|
||||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
# If the user is an org user and doesn't have add/edit perms, forbid this
|
||||
if self.request.user.is_org_user(self.request):
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_edit_request_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
# user needs to be the creator of the domain request to edit it.
|
||||
id = self.kwargs.get("id") if hasattr(self, "kwargs") else None
|
||||
if not id:
|
||||
domain_request_wizard = self.request.session.get("wizard_domain_request")
|
||||
if domain_request_wizard:
|
||||
id = domain_request_wizard.get("domain_request_id")
|
||||
|
||||
# If no id is provided, we can assume that the user is starting a new request.
|
||||
# If one IS provided, check that they are the original creator of it.
|
||||
if id:
|
||||
if not DomainRequest.objects.filter(creator=self.request.user, id=id).exists():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class DomainInvitationPermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to domain invitation if user has
|
||||
access, otherwise 403"
|
||||
|
||||
A user has access to a domain invitation if they have a role on the
|
||||
associated domain.
|
||||
"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has a role on the domain of this invitation."""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if not DomainInvitation.objects.filter(
|
||||
id=self.kwargs["pk"], domain__permissions__user=self.request.user
|
||||
).exists():
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class UserProfilePermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to user profile if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access.
|
||||
|
||||
If the user is authenticated, they have access
|
||||
"""
|
||||
|
||||
# Check if the user is authenticated
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class PortfolioBasePermission(PermissionsLoginMixin):
|
||||
"""Permission mixin that redirects to portfolio pages if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]
|
||||
"""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
return self.request.user.is_org_user(self.request)
|
||||
|
||||
|
||||
class PortfolioDomainsPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio domain pages if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to domains for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_any_domains_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioDomainRequestsPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio domain request pages if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to domain requests for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_any_requests_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioMembersPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio members pages if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to members for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_view_members_portfolio_permission(
|
||||
portfolio
|
||||
) and not self.request.user.has_edit_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioMemberPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio member or invited member pages if user
|
||||
has access, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to members or invited members for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_view_members_portfolio_permission(
|
||||
portfolio
|
||||
) and not self.request.user.has_edit_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioMemberEditPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio member or invited member pages if user
|
||||
has access to edit, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to members or invited members for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_edit_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioMemberDomainsPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio member or invited member domains pages if user
|
||||
has access to edit, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to member or invited member domains for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_view_members_portfolio_permission(
|
||||
portfolio
|
||||
) and not self.request.user.has_edit_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
||||
|
||||
class PortfolioMemberDomainsEditPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio member or invited member domains edit pages if user
|
||||
has access to edit, otherwise 403"""
|
||||
|
||||
def has_permission(self):
|
||||
"""Check if this user has access to member or invited member domains for this portfolio.
|
||||
|
||||
The user is in self.request.user and the portfolio can be looked
|
||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||
|
||||
portfolio = self.request.session.get("portfolio")
|
||||
if not self.request.user.has_edit_members_portfolio_permission(portfolio):
|
||||
return False
|
||||
|
||||
return super().has_permission()
|
||||
|
|
|
@ -1,291 +0,0 @@
|
|||
"""View classes that enforce authorization."""
|
||||
|
||||
import abc # abstract base class
|
||||
|
||||
from django.views.generic import DetailView, DeleteView, TemplateView, UpdateView
|
||||
from registrar.models import Domain, DomainRequest, DomainInvitation, Portfolio
|
||||
from registrar.models.user import User
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
|
||||
from .mixins import (
|
||||
DomainPermission,
|
||||
DomainRequestPermission,
|
||||
DomainRequestPermissionWithdraw,
|
||||
DomainInvitationPermission,
|
||||
DomainRequestWizardPermission,
|
||||
PortfolioDomainRequestsPermission,
|
||||
PortfolioDomainsPermission,
|
||||
PortfolioMemberDomainsPermission,
|
||||
PortfolioMemberDomainsEditPermission,
|
||||
PortfolioMemberEditPermission,
|
||||
UserDeleteDomainRolePermission,
|
||||
UserProfilePermission,
|
||||
PortfolioBasePermission,
|
||||
PortfolioMembersPermission,
|
||||
PortfolioMemberPermission,
|
||||
DomainRequestPortfolioViewonlyPermission,
|
||||
)
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DomainPermissionView(DomainPermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for domains that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = Domain
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "domain"
|
||||
|
||||
# Adds context information for user permissions
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
user = self.request.user
|
||||
context["is_analyst_or_superuser"] = user.has_perm("registrar.analyst_access_permission") or user.has_perm(
|
||||
"registrar.full_access_permission"
|
||||
)
|
||||
context["is_domain_manager"] = UserDomainRole.objects.filter(user=user, domain=self.object).exists()
|
||||
context["is_portfolio_user"] = self.can_access_domain_via_portfolio(self.object.pk)
|
||||
context["is_editable"] = self.is_editable()
|
||||
# Stored in a variable for the linter
|
||||
action = "analyst_action"
|
||||
action_location = "analyst_action_location"
|
||||
# Flag to see if an analyst is attempting to make edits
|
||||
if action in self.request.session:
|
||||
context[action] = self.request.session[action]
|
||||
if action_location in self.request.session:
|
||||
context[action_location] = self.request.session[action_location]
|
||||
|
||||
return context
|
||||
|
||||
def is_editable(self):
|
||||
"""Returns whether domain is editable in the context of the view"""
|
||||
domain_editable = self.object.is_editable()
|
||||
if not domain_editable:
|
||||
return False
|
||||
|
||||
# if user is domain manager or analyst or admin, return True
|
||||
if (
|
||||
self.can_access_other_user_domains(self.object.id)
|
||||
or UserDomainRole.objects.filter(user=self.request.user, domain=self.object).exists()
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainRequestPermissionView(DomainRequestPermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain requests that enforces permissions
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = DomainRequest
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainRequestPortfolioViewonlyView(DomainRequestPortfolioViewonlyPermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain requests that enforces permissions
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = DomainRequest
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainRequestPermissionWithdrawView(DomainRequestPermissionWithdraw, DetailView, abc.ABC):
|
||||
"""Abstract base view for domain request withdraw function
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = DomainRequest
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "DomainRequest"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainRequestWizardPermissionView(DomainRequestWizardPermission, TemplateView, abc.ABC):
|
||||
"""Abstract base view for the domain request form that enforces permissions
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class DomainInvitationPermissionCancelView(DomainInvitationPermission, UpdateView, abc.ABC):
|
||||
"""Abstract view for cancelling a DomainInvitation."""
|
||||
|
||||
model = DomainInvitation
|
||||
object: DomainInvitation
|
||||
|
||||
|
||||
class DomainRequestPermissionDeleteView(DomainRequestPermission, DeleteView, abc.ABC):
|
||||
"""Abstract view for deleting a DomainRequest."""
|
||||
|
||||
model = DomainRequest
|
||||
object: DomainRequest
|
||||
|
||||
|
||||
class UserDomainRolePermissionDeleteView(UserDeleteDomainRolePermission, DeleteView, abc.ABC):
|
||||
"""Abstract base view for deleting a UserDomainRole.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = UserDomainRole
|
||||
# workaround for type mismatch in DeleteView
|
||||
object: UserDomainRole
|
||||
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "userdomainrole"
|
||||
|
||||
|
||||
class UserProfilePermissionView(UserProfilePermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for user profile view that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = User
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "user"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PortfolioBasePermissionView(PortfolioBasePermission, DetailView, abc.ABC):
|
||||
"""Abstract base view for portfolio views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
# DetailView property for what model this is viewing
|
||||
model = Portfolio
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "portfolio"
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
def template_name(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PortfolioDomainsPermissionView(PortfolioDomainsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio domains views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class NoPortfolioDomainsPermissionView(PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for a user without access to the
|
||||
portfolio domains views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioDomainRequestsPermissionView(PortfolioDomainRequestsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio domain request views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioMembersPermissionView(PortfolioMembersPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio members views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioMemberPermissionView(PortfolioMemberPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio member views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioMemberEditPermissionView(PortfolioMemberEditPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio member edit views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioMemberDomainsPermissionView(PortfolioMemberDomainsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio member domains views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
||||
|
||||
|
||||
class PortfolioMemberDomainsEditPermissionView(
|
||||
PortfolioMemberDomainsEditPermission, PortfolioBasePermissionView, abc.ABC
|
||||
):
|
||||
"""Abstract base view for portfolio member domains edit views that enforces permissions.
|
||||
|
||||
This abstract view cannot be instantiated. Actual views must specify
|
||||
`template_name`.
|
||||
"""
|
Loading…
Add table
Add a link
Reference in a new issue