diff --git a/src/registrar/admin.py b/src/registrar/admin.py index 86be4f9bf..d7bc662e3 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -92,6 +92,8 @@ class UserResource(resources.ModelResource): class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple): + """Custom widget to allow for editing an ArrayField in a widget similar to filter_horizontal widget""" + def __init__(self, verbose_name, is_stacked=False, choices=(), **kwargs): super().__init__(verbose_name, is_stacked, **kwargs) self.choices = choices @@ -655,10 +657,6 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin): "status", ) - # For each filter_horizontal, init in admin js extendFilterHorizontalWidgets - # to activate the edit/delete/view buttons - # filter_horizontal = ("portfolio_roles",) - # Renames inherited AbstractUser label 'email_address to 'email' def formfield_for_dbfield(self, dbfield, **kwargs): field = super().formfield_for_dbfield(dbfield, **kwargs) diff --git a/src/registrar/context_processors.py b/src/registrar/context_processors.py index f97cd093a..1ed39c903 100644 --- a/src/registrar/context_processors.py +++ b/src/registrar/context_processors.py @@ -1,7 +1,5 @@ from django.conf import settings -from registrar.models.user import User - def language_code(request): """Add LANGUAGE_CODE to the template context. @@ -50,15 +48,9 @@ def portfolio_permissions(request): "has_domain_requests_portfolio_permission": False, } return { - "has_base_portfolio_permission": request.user.has_portfolio_permission( - User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO - ), - "has_domains_portfolio_permission": request.user.has_portfolio_permission( - User.UserPortfolioPermissionChoices.VIEW_DOMAINS - ), - "has_domain_requests_portfolio_permission": request.user.has_portfolio_permission( - User.UserPortfolioPermissionChoices.VIEW_REQUESTS - ), + "has_base_portfolio_permission": request.user.has_base_portfolio_permission(), + "has_domains_portfolio_permission": request.user.has_domains_portfolio_permission(), + "has_domain_requests_portfolio_permission": request.user.has_domain_requests_portfolio_permission(), } except AttributeError: # Handles cases where request.user might not exist diff --git a/src/registrar/models/user.py b/src/registrar/models/user.py index ef96bee38..3b5a382f7 100644 --- a/src/registrar/models/user.py +++ b/src/registrar/models/user.py @@ -247,7 +247,21 @@ class User(AbstractUser): def has_contact_info(self): return bool(self.title or self.email or self.phone) - def has_portfolio_permission(self, portfolio_permission): + def _get_portfolio_permissions(self): + """ + Retrieve the permissions for the user's portfolio roles. + """ + portfolio_permissions = set() # Use a set to avoid duplicate permissions + + if self.portfolio_roles: + for role in self.portfolio_roles: + if role in self.PORTFOLIO_ROLE_PERMISSIONS: + portfolio_permissions.update(self.PORTFOLIO_ROLE_PERMISSIONS[role]) + if self.portfolio_additional_permissions: + portfolio_permissions.update(self.portfolio_additional_permissions) + return list(portfolio_permissions) # Convert back to list if necessary + + def _has_portfolio_permission(self, portfolio_permission): """The views should only call this guy when testing for perms and not rely on roles""" # EDIT_DOMAINS === user is a manager on a domain (has UserDomainRole) @@ -262,19 +276,19 @@ class User(AbstractUser): return portfolio_permission in portfolio_permissions - def _get_portfolio_permissions(self): - """ - Retrieve the permissions for the user's portfolio roles. - """ - portfolio_permissions = set() # Use a set to avoid duplicate permissions + # the methods below are checks for individual portfolio permissions. they are defined here + # to make them easier to call elsewhere throughout the application + def has_base_portfolio_permission(self): + return self._has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO) - if self.portfolio_roles: - for role in self.portfolio_roles: - if role in self.PORTFOLIO_ROLE_PERMISSIONS: - portfolio_permissions.update(self.PORTFOLIO_ROLE_PERMISSIONS[role]) - if self.portfolio_additional_permissions: - portfolio_permissions.update(self.portfolio_additional_permissions) - return list(portfolio_permissions) # Convert back to list if necessary + def has_domains_portfolio_permission(self): + return self._has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS) + + def has_edit_domains_portfolio_permission(self): + return self._has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS) + + def has_domain_requests_portfolio_permission(self): + return self._has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS) @classmethod def needs_identity_verification(cls, email, uuid): diff --git a/src/registrar/registrar_middleware.py b/src/registrar/registrar_middleware.py index d6518d316..d45af9ec3 100644 --- a/src/registrar/registrar_middleware.py +++ b/src/registrar/registrar_middleware.py @@ -6,7 +6,6 @@ import logging from urllib.parse import parse_qs from django.urls import reverse from django.http import HttpResponseRedirect -from registrar.context_processors import portfolio_permissions from registrar.models.user import User from waffle.decorators import flag_is_active @@ -146,18 +145,11 @@ class CheckPortfolioMiddleware: if current_path == self.home: if has_organization_feature_flag: if request.user.is_authenticated: - # user_portfolios = Portfolio.objects.filter(creator=request.user) - permission_dict = portfolio_permissions(request) - has_portfolio_base_permission = permission_dict["has_base_portfolio_permission"] - - if has_portfolio_base_permission: + if request.user.has_base_portfolio_permission(): portfolio = request.user.portfolio - permission_dict = portfolio_permissions(request) - has_portfolio_domains_permission = permission_dict["has_domains_portfolio_permission"] - - if has_portfolio_domains_permission: + if request.user.has_domains_portfolio_permission(): portfolio_redirect = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id}) else: # View organization is the lowest access diff --git a/src/registrar/tests/test_models.py b/src/registrar/tests/test_models.py index 5e11779ed..78cb3258b 100644 --- a/src/registrar/tests/test_models.py +++ b/src/registrar/tests/test_models.py @@ -1231,9 +1231,9 @@ class TestUser(TestCase): self.user.save() self.user.refresh_from_db() - user_can_view_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS) - user_can_view_requests = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS) - user_can_edit_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS) + user_can_view_domains = self.user.has_domains_portfolio_permission() + user_can_view_requests = self.user.has_domain_requests_portfolio_permission() + user_can_edit_domains = self.user.has_edit_domains_portfolio_permission() self.assertFalse(user_can_view_domains) self.assertFalse(user_can_view_requests) @@ -1243,9 +1243,9 @@ class TestUser(TestCase): self.user.save() self.user.refresh_from_db() - user_can_view_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS) - user_can_view_requests = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS) - user_can_edit_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS) + user_can_view_domains = self.user.has_domains_portfolio_permission() + user_can_view_requests = self.user.has_domain_requests_portfolio_permission() + user_can_edit_domains = self.user.has_edit_domains_portfolio_permission() self.assertTrue(user_can_view_domains) self.assertFalse(user_can_view_requests) @@ -1255,9 +1255,9 @@ class TestUser(TestCase): self.user.save() self.user.refresh_from_db() - user_can_view_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS) - user_can_view_requests = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS) - user_can_edit_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS) + user_can_view_domains = self.user.has_domains_portfolio_permission() + user_can_view_requests = self.user.has_domain_requests_portfolio_permission() + user_can_edit_domains = self.user.has_edit_domains_portfolio_permission() self.assertTrue(user_can_view_domains) self.assertTrue(user_can_view_requests) @@ -1267,9 +1267,9 @@ class TestUser(TestCase): user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER ) - user_can_view_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS) - user_can_view_requests = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS) - user_can_edit_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS) + user_can_view_domains = self.user.has_domains_portfolio_permission() + user_can_view_requests = self.user.has_domain_requests_portfolio_permission() + user_can_edit_domains = self.user.has_edit_domains_portfolio_permission() self.assertTrue(user_can_view_domains) self.assertTrue(user_can_view_requests) diff --git a/src/registrar/views/utility/mixins.py b/src/registrar/views/utility/mixins.py index fafcfaf7a..5f8485ec5 100644 --- a/src/registrar/views/utility/mixins.py +++ b/src/registrar/views/utility/mixins.py @@ -2,7 +2,6 @@ from django.contrib.auth.mixins import PermissionRequiredMixin -from registrar.context_processors import portfolio_permissions from registrar.models import ( Domain, DomainRequest, @@ -414,40 +413,34 @@ class PortfolioBasePermission(PermissionsLoginMixin): if not self.request.user.is_authenticated: return False - permission_dict = portfolio_permissions(self.request) - has_permission = permission_dict["has_base_portfolio_permission"] - - if not has_permission: - return False - - return True + return self.request.user.has_base_portfolio_permission() 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. - permission_dict = portfolio_permissions(self.request) - has_permission = permission_dict["has_domains_portfolio_permission"] + 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 has_permission: + if not self.request.user.is_authenticated: return False - - return True + return self.request.user.has_domains_portfolio_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. - permission_dict = portfolio_permissions(self.request) - has_permission = permission_dict["has_domain_requests_portfolio_permission"] + 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 has_permission: + if not self.request.user.is_authenticated: return False - - return True + return self.request.user.has_domain_requests_portfolio_permission()