mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-16 06:24:12 +02:00
wip
This commit is contained in:
parent
6269cc56e3
commit
40737cbcf7
8 changed files with 49 additions and 56 deletions
|
@ -10,8 +10,10 @@ 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"
|
||||
|
@ -97,11 +99,21 @@ def _user_has_permission(user, request, rules, **kwargs):
|
|||
has_permission = _can_access_other_user_domains(request, domain_id)
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
if not any(conditions_met) and IS_PORTFOLIO_MEMBER in rules:
|
||||
has_permission = user.is_org_user(request)
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
if not any(conditions_met) and HAS_PORTFOLIO_DOMAINS_VIEW_ALL in rules:
|
||||
domain_id = kwargs.get("domain_pk")
|
||||
has_permission = _can_access_domain_via_portfolio_view_all_domains(request, domain_id)
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
if not any(conditions_met) and HAS_PORTFOLIO_DOMAINS_ANY_PERM in rules:
|
||||
has_permission = user.is_org_user(request) and user.has_any_domains_portfolio_permission(
|
||||
request.session.get("portfolio")
|
||||
)
|
||||
conditions_met.append(has_permission)
|
||||
|
||||
if not any(conditions_met) and IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER in rules:
|
||||
domain_id = kwargs.get("domain_pk")
|
||||
has_permission = _is_domain_manager(user, domain_id) and _is_portfolio_member(request)
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -13,6 +13,7 @@ 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
|
||||
from django.views.generic.edit import FormMixin
|
||||
from django.conf import settings
|
||||
from registrar.decorators import (
|
||||
|
@ -1332,10 +1333,12 @@ class DomainInvitationCancelView(SuccessMessageMixin, DomainInvitationPermission
|
|||
|
||||
|
||||
@grant_access(IS_DOMAIN_MANAGER, IS_STAFF_MANAGING_DOMAIN)
|
||||
class DomainDeleteUserView(UserDomainRolePermissionDeleteView):
|
||||
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"""
|
||||
|
|
|
@ -15,20 +15,20 @@ def get_domain_requests_json(request):
|
|||
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(
|
||||
|
@ -44,7 +44,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.
|
||||
|
@ -63,7 +63,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")
|
||||
|
||||
|
@ -91,7 +91,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(",")
|
||||
|
@ -106,7 +106,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'
|
||||
|
||||
|
@ -119,7 +119,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,
|
||||
|
|
|
@ -6,7 +6,12 @@ from django.shortcuts import get_object_or_404, redirect, render
|
|||
from django.urls import reverse
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.contrib import messages
|
||||
from registrar.decorators import HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM, grant_access
|
||||
from registrar.decorators import (
|
||||
HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM,
|
||||
HAS_PORTFOLIO_DOMAINS_ANY_PERM,
|
||||
IS_PORTFOLIO_MEMBER,
|
||||
grant_access,
|
||||
)
|
||||
from registrar.forms import portfolio as portfolioForms
|
||||
from registrar.models import Portfolio, User
|
||||
from registrar.models.domain import Domain
|
||||
|
@ -26,9 +31,7 @@ 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 (
|
||||
PortfolioDomainsPermissionView,
|
||||
PortfolioBasePermissionView,
|
||||
NoPortfolioDomainsPermissionView,
|
||||
PortfolioMemberDomainsPermissionView,
|
||||
PortfolioMemberDomainsEditPermissionView,
|
||||
PortfolioMemberEditPermissionView,
|
||||
|
@ -45,7 +48,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"
|
||||
|
||||
|
@ -685,7 +689,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.
|
||||
"""
|
||||
|
@ -714,7 +719,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.
|
||||
"""
|
||||
|
|
|
@ -373,23 +373,6 @@ class PortfolioBasePermission(PermissionsLoginMixin):
|
|||
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 PortfolioMembersPermission(PortfolioBasePermission):
|
||||
"""Permission mixin that allows access to portfolio members pages if user
|
||||
has access, otherwise 403"""
|
||||
|
|
|
@ -10,7 +10,6 @@ from registrar.models.user_domain_role import UserDomainRole
|
|||
from .mixins import (
|
||||
DomainPermission,
|
||||
DomainInvitationPermission,
|
||||
PortfolioDomainsPermission,
|
||||
PortfolioMemberDomainsPermission,
|
||||
PortfolioMemberDomainsEditPermission,
|
||||
PortfolioMemberEditPermission,
|
||||
|
@ -74,6 +73,13 @@ class DomainPermissionView(DomainPermission, DetailView, abc.ABC):
|
|||
|
||||
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
|
||||
|
||||
# Abstract property enforces NotImplementedError on an attribute.
|
||||
@property
|
||||
@abc.abstractmethod
|
||||
|
@ -142,23 +148,6 @@ class PortfolioBasePermissionView(PortfolioBasePermission, DetailView, abc.ABC):
|
|||
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 PortfolioMembersPermissionView(PortfolioMembersPermission, PortfolioBasePermissionView, abc.ABC):
|
||||
"""Abstract base view for portfolio members views that enforces permissions.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue