mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-25 20:18:38 +02:00
wip
This commit is contained in:
parent
d84aa421d9
commit
a334f7dc3e
19 changed files with 216 additions and 131 deletions
|
@ -296,56 +296,56 @@ 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: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:pk>/dns",
|
||||
"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",
|
||||
),
|
||||
|
@ -370,7 +370,7 @@ urlpatterns = [
|
|||
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 +392,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
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
from functools import wraps
|
||||
from django.http import JsonResponse
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from registrar.models.domain import Domain
|
||||
from registrar.models.user_domain_role import UserDomainRole
|
||||
import functools
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.utils.decorators import method_decorator
|
||||
from registrar.models import DomainInformation, DomainRequest, UserDomainRole
|
||||
|
||||
# Constants for clarity
|
||||
ALL = "all"
|
||||
IS_SUPERUSER = "is_superuser"
|
||||
IS_STAFF = "is_staff"
|
||||
IS_DOMAIN_MANAGER = "is_domain_manager"
|
||||
IS_STAFF_MANAGING_DOMAIN = "is_staff_managing_domain"
|
||||
|
||||
def grant_access(*rules):
|
||||
"""
|
||||
|
@ -20,53 +19,128 @@ def grant_access(*rules):
|
|||
@grant_access(IS_DOMAIN_MANAGER)
|
||||
"""
|
||||
|
||||
def decorator(view_func):
|
||||
view_func.has_explicit_access = True # Mark as explicitly access-controlled
|
||||
existing_rules = getattr(view_func, "_access_rules", set())
|
||||
existing_rules.update(rules) # Support multiple rules in one call
|
||||
view_func._access_rules = existing_rules # Store rules on the function
|
||||
def decorator(view):
|
||||
if isinstance(view, type): # If decorating a class-based view (CBV)
|
||||
original_dispatch = view.dispatch # save original dispatch method
|
||||
|
||||
@wraps(view_func)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
user = request.user
|
||||
|
||||
# Skip authentication if @login_not_required is applied
|
||||
if getattr(view_func, "login_not_required", False):
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
# Allow everyone if `ALL` is in rules
|
||||
if ALL in view_func._access_rules:
|
||||
return view_func(request, *args, **kwargs)
|
||||
@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
|
||||
return original_dispatch(self, request, *args, **kwargs)
|
||||
|
||||
# Ensure user is authenticated
|
||||
if not user.is_authenticated:
|
||||
return JsonResponse({"error": "Authentication required"}, status=403)
|
||||
view.dispatch = wrapped_dispatch # replace dispatch with wrapped version
|
||||
return view
|
||||
|
||||
conditions_met = []
|
||||
else: # If decorating a function-based view (FBV)
|
||||
view.has_explicit_access = True
|
||||
existing_rules = getattr(view, "_access_rules", set())
|
||||
existing_rules.update(rules)
|
||||
view._access_rules = existing_rules
|
||||
|
||||
if IS_STAFF in view_func._access_rules:
|
||||
conditions_met.append(user.is_staff)
|
||||
|
||||
if not any(conditions_met) and IS_SUPERUSER in view_func._access_rules:
|
||||
conditions_met.append(user.is_superuser)
|
||||
|
||||
if not any(conditions_met) and IS_DOMAIN_MANAGER in view_func._access_rules:
|
||||
domain_id = kwargs.get('pk') or kwargs.get('domain_id')
|
||||
if not domain_id:
|
||||
return JsonResponse({"error": "Domain ID missing"}, status=400)
|
||||
try:
|
||||
domain = Domain.objects.get(pk=domain_id)
|
||||
has_permission = UserDomainRole.objects.filter(
|
||||
user=user, domain=domain
|
||||
).exists()
|
||||
conditions_met.append(has_permission)
|
||||
except ObjectDoesNotExist:
|
||||
return JsonResponse({"error": "Invalid Domain"}, status=404)
|
||||
|
||||
if not any(conditions_met):
|
||||
return JsonResponse({"error": "Access Denied"}, status=403)
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
@functools.wraps(view)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
if not _user_has_permission(request.user, request, rules, **kwargs):
|
||||
raise PermissionDenied
|
||||
return view(request, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def _user_has_permission(user, request, rules, **kwargs):
|
||||
"""
|
||||
Checks if the user meets the permission requirements.
|
||||
"""
|
||||
|
||||
# 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
|
||||
if not user.is_authenticated:
|
||||
return False
|
||||
|
||||
conditions_met = []
|
||||
|
||||
if IS_STAFF in rules:
|
||||
conditions_met.append(user.is_staff)
|
||||
|
||||
if not any(conditions_met) and IS_SUPERUSER in rules:
|
||||
conditions_met.append(user.is_superuser)
|
||||
|
||||
if not any(conditions_met) and IS_DOMAIN_MANAGER in rules:
|
||||
domain_id = kwargs.get('domain_pk')
|
||||
# Check UserDomainRole directly instead of fetching Domain
|
||||
has_permission = UserDomainRole.objects.filter(user=user, domain_id=domain_id).exists()
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
if not any(conditions_met) and IS_STAFF_MANAGING_DOMAIN in rules:
|
||||
domain_id = kwargs.get('domain_pk')
|
||||
has_permission = _can_access_other_user_domains(request, domain_id)
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
return any(conditions_met)
|
||||
|
||||
|
||||
def _can_access_other_user_domains(request, domain_pk):
|
||||
"""Checks to see if an authorized user (staff or superuser)
|
||||
can access a domain that they did not create or were invited to.
|
||||
"""
|
||||
|
||||
# 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_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 = DomainInformation.objects.filter(domain_id=domain_pk).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
|
||||
|
|
|
@ -6,9 +6,9 @@ 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.http import JsonResponse
|
||||
from django.urls import resolve
|
||||
from registrar.models import User
|
||||
from waffle.decorators import flag_is_active
|
||||
|
@ -182,7 +182,7 @@ class RestrictAccessMiddleware:
|
|||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
self.ignored_paths = [re.compile(pattern) for pattern in getattr(settings, "LOGIN_REQUIRED_IGNORE_PATHS", [])]
|
||||
|
||||
|
||||
def __call__(self, request):
|
||||
# Allow requests that match LOGIN_REQUIRED_IGNORE_PATHS
|
||||
if any(pattern.match(request.path) for pattern in self.ignored_paths):
|
||||
|
@ -194,7 +194,7 @@ class RestrictAccessMiddleware:
|
|||
view_func = resolver_match.func
|
||||
app_name = resolver_match.app_name # Get app name of resolved view
|
||||
except Exception:
|
||||
return JsonResponse({"error": "Not Found"}, status=404)
|
||||
return self.get_response(request)
|
||||
|
||||
# Auto-allow Django's built-in admin views (but NOT custom /admin/* views)
|
||||
if app_name == "admin":
|
||||
|
@ -206,6 +206,6 @@ class RestrictAccessMiddleware:
|
|||
|
||||
# Enforce explicit access fules for other views
|
||||
if not getattr(view_func, "has_explicit_access", False):
|
||||
return JsonResponse({"error": "Access Denied"}, status=403)
|
||||
raise PermissionDenied
|
||||
|
||||
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 has_domain_renewal_flag and 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 has_domain_renewal_flag and 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 has_domain_renewal_flag and 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">
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -15,6 +15,7 @@ from django.shortcuts import redirect, render, get_object_or_404
|
|||
from django.urls import reverse
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django.conf import settings
|
||||
from registrar.decorators import IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN, grant_access
|
||||
from registrar.forms.domain import DomainSuborganizationForm, DomainRenewalForm
|
||||
from registrar.models import (
|
||||
Domain,
|
||||
|
@ -95,7 +96,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,7 +109,7 @@ 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
|
||||
|
||||
|
||||
|
@ -256,7 +257,7 @@ class DomainFormBaseView(DomainBaseView, FormMixin):
|
|||
exc_info=True,
|
||||
)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainView(DomainBaseView):
|
||||
"""Domain detail overview page."""
|
||||
|
||||
|
@ -310,7 +311,7 @@ class DomainView(DomainBaseView):
|
|||
self.object = self.get_object()
|
||||
self._update_session_with_domain()
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainRenewalView(DomainBaseView):
|
||||
"""Domain detail overview page."""
|
||||
|
||||
|
@ -344,9 +345,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 +364,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, has_domain_renewal_flag, and is_editable for re-render
|
||||
|
@ -379,7 +380,7 @@ class DomainRenewalView(DomainBaseView):
|
|||
},
|
||||
)
|
||||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainOrgNameAddressView(DomainFormBaseView):
|
||||
"""Organization view"""
|
||||
|
||||
|
@ -396,7 +397,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."""
|
||||
|
@ -455,7 +456,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."""
|
||||
|
@ -494,7 +495,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."""
|
||||
|
@ -587,7 +588,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."""
|
||||
|
@ -764,7 +765,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."""
|
||||
|
@ -885,7 +886,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."""
|
||||
|
@ -936,7 +937,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."""
|
||||
|
@ -1042,7 +1043,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."""
|
||||
|
@ -1199,7 +1200,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."""
|
||||
|
@ -1304,7 +1305,7 @@ 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}."
|
||||
|
@ -1317,13 +1318,13 @@ class DomainDeleteUserView(UserDomainRolePermissionDeleteView):
|
|||
|
||||
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"""
|
||||
|
|
|
@ -143,7 +143,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,
|
||||
|
|
|
@ -35,3 +35,11 @@ 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"""
|
||||
print("this is called")
|
||||
if context is None:
|
||||
context = {}
|
||||
return render(request, "404.html", context=context, status=404)
|
|
@ -203,7 +203,7 @@ class DomainPermission(PermissionsLoginMixin):
|
|||
"""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"]
|
||||
up from the domain's primary key in self.kwargs["domain_pk"]
|
||||
"""
|
||||
|
||||
if not self.request.user.is_authenticated:
|
||||
|
@ -212,7 +212,7 @@ class DomainPermission(PermissionsLoginMixin):
|
|||
if self.request.user.is_restricted():
|
||||
return False
|
||||
|
||||
pk = self.kwargs["pk"]
|
||||
pk = self.kwargs["domain_pk"]
|
||||
# If pk is none then something went very wrong...
|
||||
if pk is None:
|
||||
raise ValueError("Primary key is None")
|
||||
|
|
|
@ -39,6 +39,7 @@ class DomainPermissionView(DomainPermission, DetailView, abc.ABC):
|
|||
|
||||
# DetailView property for what model this is viewing
|
||||
model = Domain
|
||||
pk_url_kwarg = "domain_pk"
|
||||
# variable name in template context for the model object
|
||||
context_object_name = "domain"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue