diff --git a/src/registrar/decorators.py b/src/registrar/decorators.py index f44a274d7..edaa0bf95 100644 --- a/src/registrar/decorators.py +++ b/src/registrar/decorators.py @@ -24,7 +24,6 @@ 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_VIEW_AND_EDIT = "has_portfolio_members_view_and_edit" HAS_PORTFOLIO_MEMBERS_EDIT = "has_portfolio_members_edit" HAS_PORTFOLIO_MEMBERS_VIEW = "has_portfolio_members_view" @@ -120,7 +119,8 @@ def _user_has_permission(user, request, rules, **kwargs): ), ( HAS_PORTFOLIO_DOMAINS_ANY_PERM, - lambda: user.is_org_user(request) and user.has_any_domains_portfolio_permission(portfolio), + lambda: user.is_org_user(request) and user.has_any_domains_portfolio_permission(portfolio) + and _domain_exists_under_portfolio(portfolio, kwargs.get("domain_pk")), ), ( IS_PORTFOLIO_MEMBER_AND_DOMAIN_MANAGER, @@ -139,7 +139,8 @@ def _user_has_permission(user, request, rules, **kwargs): ), ( HAS_PORTFOLIO_DOMAIN_REQUESTS_ANY_PERM, - lambda: user.is_org_user(request) and user.has_any_requests_portfolio_permission(portfolio), + lambda: user.is_org_user(request) and user.has_any_requests_portfolio_permission(portfolio) + and _domain_request_exists_under_portfolio(portfolio, kwargs.get("domain_request_pk")), ), ( HAS_PORTFOLIO_DOMAIN_REQUESTS_VIEW_ALL, @@ -158,17 +159,6 @@ def _user_has_permission(user, request, rules, **kwargs): and ( user.has_view_members_portfolio_permission(portfolio) or user.has_edit_members_portfolio_permission(portfolio) - ), - ), - ( - # More restrictive check as compared to HAS_PORTFOLIO_MEMBERS_ANY_PERM. - # This is needed because grant_access does not apply perms in a layered fashion - # and grants access when any valid perm is found - so chaining view and edit works differently. - HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT, - lambda: user.is_org_user(request) - and ( - user.has_view_members_portfolio_permission(portfolio) - and user.has_edit_members_portfolio_permission(portfolio) ) and ( # AND rather than OR because these functions return true if the PK is not found. diff --git a/src/registrar/views/portfolios.py b/src/registrar/views/portfolios.py index 1a31f9a7f..53538a19e 100644 --- a/src/registrar/views/portfolios.py +++ b/src/registrar/views/portfolios.py @@ -13,7 +13,6 @@ from registrar.decorators import ( HAS_PORTFOLIO_MEMBERS_ANY_PERM, HAS_PORTFOLIO_MEMBERS_EDIT, HAS_PORTFOLIO_MEMBERS_VIEW, - HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT, IS_PORTFOLIO_MEMBER, grant_access, ) @@ -73,7 +72,7 @@ class PortfolioDomainRequestsView(View): return render(request, "portfolio_requests.html") -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW) +@grant_access(HAS_PORTFOLIO_MEMBERS_ANY_PERM) class PortfolioMemberView(DetailView, View): model = Portfolio context_object_name = "portfolio" @@ -118,9 +117,7 @@ class PortfolioMemberView(DetailView, View): ) -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioMemberDeleteView(View): pk_url_kwarg = "member_pk" @@ -223,9 +220,7 @@ class PortfolioMemberDeleteView(View): messages.warning(self.request, "Could not send email notification to existing organization admins.") -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioMemberEditView(DetailView, View): model = Portfolio context_object_name = "portfolio" @@ -329,9 +324,7 @@ class PortfolioMemberDomainsView(View): ) -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioMemberDomainsEditView(DetailView, View): model = Portfolio context_object_name = "portfolio" @@ -489,11 +482,10 @@ class PortfolioInvitedMemberView(DetailView, View): ) -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioInvitedMemberDeleteView(View): pk_url_kwarg = "invitedmember_pk" + def post(self, request, invitedmember_pk): """ Find and delete the portfolio invited member using the provided primary key (pk). @@ -537,9 +529,7 @@ class PortfolioInvitedMemberDeleteView(View): messages.warning(self.request, "Could not send email notification to existing organization admins.") -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioInvitedMemberEditView(DetailView, View): model = Portfolio context_object_name = "portfolio" @@ -629,9 +619,7 @@ class PortfolioInvitedMemberDomainsView(View): ) -# The parent page requires VIEW access, the child requires EDIT. -# This prevents url skimming without having to inherit the base class. -@grant_access(HAS_PORTFOLIO_MEMBERS_VIEW_AND_EDIT) +@grant_access(HAS_PORTFOLIO_MEMBERS_EDIT) class PortfolioInvitedMemberDomainsEditView(DetailView, View): model = Portfolio