mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-22 04:19:26 +02:00
build our permissions a bit more
This commit is contained in:
parent
b1ae220602
commit
ebb95a7d67
10 changed files with 183 additions and 52 deletions
|
@ -683,6 +683,9 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
||||||
"fields": (
|
"fields": (
|
||||||
"is_active",
|
"is_active",
|
||||||
"groups",
|
"groups",
|
||||||
|
"portfolio",
|
||||||
|
"portfolio_roles",
|
||||||
|
"portfolio_permissions",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -712,6 +715,9 @@ class MyUserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
||||||
"Important dates",
|
"Important dates",
|
||||||
"last_login",
|
"last_login",
|
||||||
"date_joined",
|
"date_joined",
|
||||||
|
"portfolio",
|
||||||
|
"portfolio_roles",
|
||||||
|
"portfolio_permissions",
|
||||||
]
|
]
|
||||||
|
|
||||||
list_filter = (
|
list_filter = (
|
||||||
|
|
|
@ -25,7 +25,7 @@ from registrar.views.domain_request import Step
|
||||||
from registrar.views.domain_requests_json import get_domain_requests_json
|
from registrar.views.domain_requests_json import get_domain_requests_json
|
||||||
from registrar.views.domains_json import get_domains_json
|
from registrar.views.domains_json import get_domains_json
|
||||||
from registrar.views.utility import always_404
|
from registrar.views.utility import always_404
|
||||||
from registrar.views.portfolios import portfolio_domains, portfolio_domain_requests
|
from registrar.views.portfolios import PortfolioDomainsView, PortfolioDomainRequestsView, PortfolioOrganizationView
|
||||||
from api.views import available, get_current_federal, get_current_full
|
from api.views import available, get_current_federal, get_current_full
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,14 +61,19 @@ urlpatterns = [
|
||||||
path("", views.index, name="home"),
|
path("", views.index, name="home"),
|
||||||
path(
|
path(
|
||||||
"portfolio/<int:portfolio_id>/domains/",
|
"portfolio/<int:portfolio_id>/domains/",
|
||||||
portfolio_domains,
|
PortfolioDomainsView.as_view(),
|
||||||
name="portfolio-domains",
|
name="portfolio-domains",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"portfolio/<int:portfolio_id>/domain_requests/",
|
"portfolio/<int:portfolio_id>/domain_requests/",
|
||||||
portfolio_domain_requests,
|
PortfolioDomainRequestsView.as_view(),
|
||||||
name="portfolio-domain-requests",
|
name="portfolio-domain-requests",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"portfolio/<int:portfolio_id>/organization/",
|
||||||
|
PortfolioOrganizationView.as_view(),
|
||||||
|
name="portfolio-organization",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"admin/logout/",
|
"admin/logout/",
|
||||||
RedirectView.as_view(pattern_name="logout", permanent=False),
|
RedirectView.as_view(pattern_name="logout", permanent=False),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
|
from registrar.models.user import User
|
||||||
|
|
||||||
|
|
||||||
def language_code(request):
|
def language_code(request):
|
||||||
"""Add LANGUAGE_CODE to the template context.
|
"""Add LANGUAGE_CODE to the template context.
|
||||||
|
@ -36,3 +38,20 @@ def is_demo_site(request):
|
||||||
def is_production(request):
|
def is_production(request):
|
||||||
"""Add a boolean if this is our production site."""
|
"""Add a boolean if this is our production site."""
|
||||||
return {"IS_PRODUCTION": settings.IS_PRODUCTION}
|
return {"IS_PRODUCTION": settings.IS_PRODUCTION}
|
||||||
|
|
||||||
|
|
||||||
|
def has_base_portfolio_permission(request):
|
||||||
|
""""""
|
||||||
|
return {"has_base_portfolio_permission": request.user.has_portfolio_permissions(User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO)}
|
||||||
|
|
||||||
|
def has_domains_portfolio_permission(request):
|
||||||
|
""""""
|
||||||
|
return {"has_domains_portfolio_permission": request.user.has_portfolio_permissions(User.UserPortfolioPermissionChoices.VIEW_DOMAINS)}
|
||||||
|
|
||||||
|
def has_requests_portfolio_permission(request):
|
||||||
|
""""""
|
||||||
|
return {"has_requests_portfolio_permission": request.user.has_portfolio_permissions(User.UserPortfolioPermissionChoices.VIEW_REQUESTS)}
|
||||||
|
|
||||||
|
def has_organization_portfolio_permission(request):
|
||||||
|
""""""
|
||||||
|
return {"has_organization_portfolio_permission": request.user.has_portfolio_permissions(User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO)}
|
||||||
|
|
|
@ -255,8 +255,12 @@ class User(AbstractUser):
|
||||||
def has_portfolio_permissions(self, portfolio_permission):
|
def has_portfolio_permissions(self, portfolio_permission):
|
||||||
"""The views should only call this guy when testing for perms and not rely on roles"""
|
"""The views should only call this guy when testing for perms and not rely on roles"""
|
||||||
|
|
||||||
|
# TODO: this does not seem to be working
|
||||||
if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
||||||
return self.domains
|
print(f'portfolio_permission {portfolio_permission}')
|
||||||
|
return True
|
||||||
|
|
||||||
|
print(f'portfolio_permission {portfolio_permission}')
|
||||||
|
|
||||||
return portfolio_permission in self.portfolio_permissions if self.portfolio_permissions else False
|
return portfolio_permission in self.portfolio_permissions if self.portfolio_permissions else False
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import logging
|
||||||
from urllib.parse import parse_qs
|
from urllib.parse import parse_qs
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from registrar.models.portfolio import Portfolio
|
from registrar.context_processors import has_base_portfolio_permission, has_domains_portfolio_permission, has_requests_portfolio_permission
|
||||||
from registrar.models.user import User
|
from registrar.models.user import User
|
||||||
from waffle.decorators import flag_is_active
|
from waffle.decorators import flag_is_active
|
||||||
|
|
||||||
|
@ -148,13 +148,19 @@ class CheckPortfolioMiddleware:
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
# user_portfolios = Portfolio.objects.filter(creator=request.user)
|
# user_portfolios = Portfolio.objects.filter(creator=request.user)
|
||||||
|
|
||||||
required_permission = User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO
|
if has_base_portfolio_permission(request):
|
||||||
|
# print('user has portfolio')
|
||||||
if request.user.has_portfolio_permissions(required_permission):
|
|
||||||
print('user has portfolio')
|
|
||||||
portfolio = request.user.portfolio
|
portfolio = request.user.portfolio
|
||||||
home_with_portfolio = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id})
|
|
||||||
return HttpResponseRedirect(home_with_portfolio)
|
if has_domains_portfolio_permission(request):
|
||||||
|
portfolio_redirect = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id})
|
||||||
|
elif has_requests_portfolio_permission(request):
|
||||||
|
portfolio_redirect = reverse("portfolio-requests", kwargs={"portfolio_id": portfolio.id})
|
||||||
|
else:
|
||||||
|
# View organization is the lowest access
|
||||||
|
portfolio_redirect = reverse("portfolio-organization", kwargs={"portfolio_id": portfolio.id})
|
||||||
|
|
||||||
|
return HttpResponseRedirect(portfolio_redirect)
|
||||||
|
|
||||||
print('user does not have a portfolio')
|
# print('user does not have a portfolio')
|
||||||
return None
|
return None
|
||||||
|
|
8
src/registrar/templates/portfolio_organization.html
Normal file
8
src/registrar/templates/portfolio_organization.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends 'portfolio.html' %}
|
||||||
|
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block portfolio_content %}
|
||||||
|
<h1>Organization</h1>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -4,26 +4,31 @@
|
||||||
<nav aria-label="">
|
<nav aria-label="">
|
||||||
<h2 class="margin-top-0 text-semibold">{{ portfolio.organization_name }}</h2>
|
<h2 class="margin-top-0 text-semibold">{{ portfolio.organization_name }}</h2>
|
||||||
<ul class="usa-sidenav usa-sidenav--portfolio">
|
<ul class="usa-sidenav usa-sidenav--portfolio">
|
||||||
<li class="usa-sidenav__item">
|
{% if has_domains_portfolio_permission %}
|
||||||
{% url 'portfolio-domains' portfolio.id as url %}
|
<li class="usa-sidenav__item">
|
||||||
<a href="{{ url }}" {% if request.path == url %}class="usa-current"{% endif %}>
|
{% url 'portfolio-domains' portfolio.id as url %}
|
||||||
Domains
|
<a href="{{ url }}" {% if request.path == url %}class="usa-current"{% endif %}>
|
||||||
</a>
|
Domains
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if has_requests_portfolio_permission %}
|
||||||
<li class="usa-sidenav__item">
|
<li class="usa-sidenav__item">
|
||||||
{% url 'portfolio-domain-requests' portfolio.id as url %}
|
{% url 'portfolio-domain-requests' portfolio.id as url %}
|
||||||
<a href="{{ url }}" {% if request.path == url %}class="usa-current"{% endif %}>
|
<a href="{{ url }}" {% if request.path == url %}class="usa-current"{% endif %}>
|
||||||
Domain requests
|
Domain requests
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<li class="usa-sidenav__item">
|
<li class="usa-sidenav__item">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
Members
|
Members
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="usa-sidenav__item">
|
<li class="usa-sidenav__item">
|
||||||
<a href="#">
|
{% url 'portfolio-organization' portfolio.id as url %}
|
||||||
|
<a href="{{ url }}" {% if request.path == url %}class="usa-current"{% endif %}>
|
||||||
Organization
|
Organization
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,39 +1,51 @@
|
||||||
from django.shortcuts import get_object_or_404, render
|
from django.shortcuts import get_object_or_404, render
|
||||||
from registrar.models.portfolio import Portfolio
|
from registrar.models.portfolio import Portfolio
|
||||||
|
from registrar.views.utility.permission_views import PortfolioDomainRequestsPermissionView, PortfolioDomainsPermissionView, PortfolioOrganizationssPermissionView
|
||||||
from waffle.decorators import flag_is_active
|
from waffle.decorators import flag_is_active
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.views.generic import View
|
||||||
|
|
||||||
|
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
||||||
|
|
||||||
@login_required
|
template_name = "portfolio_domains.html"
|
||||||
def portfolio_domains(request, portfolio_id):
|
|
||||||
context = {}
|
|
||||||
|
|
||||||
if request.user.is_authenticated:
|
def get(self, request, portfolio_id):
|
||||||
# This is a django waffle flag which toggles features based off of the "flag" table
|
context = {}
|
||||||
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
|
||||||
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
|
||||||
|
|
||||||
# Retrieve the portfolio object based on the provided portfolio_id
|
if self.request.user.is_authenticated:
|
||||||
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
||||||
context["portfolio"] = portfolio
|
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
||||||
|
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
||||||
|
context["portfolio"] = portfolio
|
||||||
|
|
||||||
return render(request, "portfolio_domains.html", context)
|
return render(request, "portfolio_domains.html", context)
|
||||||
|
|
||||||
|
class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
||||||
|
|
||||||
@login_required
|
template_name = "portfolio_requests.html"
|
||||||
def portfolio_domain_requests(request, portfolio_id):
|
|
||||||
context = {}
|
|
||||||
|
|
||||||
if request.user.is_authenticated:
|
def get(self, request, portfolio_id):
|
||||||
# This is a django waffle flag which toggles features based off of the "flag" table
|
context = {}
|
||||||
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
|
||||||
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
|
||||||
|
|
||||||
# Retrieve the portfolio object based on the provided portfolio_id
|
if self.request.user.is_authenticated:
|
||||||
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
||||||
context["portfolio"] = portfolio
|
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
||||||
|
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
||||||
|
context["portfolio"] = portfolio
|
||||||
|
request.session["new_request"] = True
|
||||||
|
|
||||||
# This controls the creation of a new domain request in the wizard
|
return render(request, "portfolio_requests.html", context)
|
||||||
request.session["new_request"] = True
|
|
||||||
|
|
||||||
return render(request, "portfolio_requests.html", context)
|
class PortfolioOrganizationView(PortfolioOrganizationssPermissionView, View):
|
||||||
|
|
||||||
|
template_name = "portfolio_organization.html"
|
||||||
|
|
||||||
|
def get(self, request, portfolio_id):
|
||||||
|
context = {}
|
||||||
|
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
|
||||||
|
context["has_organization_feature_flag"] = flag_is_active(request, "organization_feature")
|
||||||
|
portfolio = get_object_or_404(Portfolio, id=portfolio_id)
|
||||||
|
context["portfolio"] = portfolio
|
||||||
|
|
||||||
|
return render(request, "portfolio_organization.html", context)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||||
|
|
||||||
|
from registrar.context_processors import has_base_portfolio_permission, has_domains_portfolio_permission, has_organization_portfolio_permission, has_requests_portfolio_permission
|
||||||
from registrar.models import (
|
from registrar.models import (
|
||||||
Domain,
|
Domain,
|
||||||
DomainRequest,
|
DomainRequest,
|
||||||
|
@ -401,7 +402,7 @@ class UserProfilePermission(PermissionsLoginMixin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PortfolioBasePermission(PermissionsLoginMixin):
|
class PortfolioPermission(PermissionsLoginMixin):
|
||||||
"""Permission mixin that redirects to portfolio pages if user
|
"""Permission mixin that redirects to portfolio pages if user
|
||||||
has access, otherwise 403"""
|
has access, otherwise 403"""
|
||||||
|
|
||||||
|
@ -417,10 +418,58 @@ class PortfolioBasePermission(PermissionsLoginMixin):
|
||||||
# portfolio_id = self.kwargs["pk"]
|
# portfolio_id = self.kwargs["pk"]
|
||||||
# portfolio = Portfolio.objects.get(pk=portfolio_id)
|
# portfolio = Portfolio.objects.get(pk=portfolio_id)
|
||||||
|
|
||||||
# The 'Base' portfolio permission is VIEW_PORTFOLIO
|
if not has_base_portfolio_permission(self.request):
|
||||||
required_permission = User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO
|
return False
|
||||||
|
|
||||||
if not self.request.user.has_portfolio_permissions(required_permission):
|
return True
|
||||||
|
|
||||||
|
class PortfolioDomainsPermission(PortfolioPermission):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_permission(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
permission_dict = has_domains_portfolio_permission(self.request)
|
||||||
|
has_permission = permission_dict['has_domains_portfolio_permission']
|
||||||
|
|
||||||
|
if not has_permission:
|
||||||
|
return False
|
||||||
|
|
||||||
|
print('return true')
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class PortfolioDomainRequestsPermission(PortfolioPermission):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_permission(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
permission_dict = has_requests_portfolio_permission(self.request)
|
||||||
|
has_permission = permission_dict['has_requests_portfolio_permission']
|
||||||
|
|
||||||
|
if not has_permission:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
class PortfolioOrganizationssPermission(PortfolioPermission):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_permission(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
permission_dict = has_organization_portfolio_permission(self.request)
|
||||||
|
has_permission = permission_dict['has_organization_portfolio_permission']
|
||||||
|
|
||||||
|
if not has_permission:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -13,9 +13,12 @@ from .mixins import (
|
||||||
DomainRequestPermissionWithdraw,
|
DomainRequestPermissionWithdraw,
|
||||||
DomainInvitationPermission,
|
DomainInvitationPermission,
|
||||||
DomainRequestWizardPermission,
|
DomainRequestWizardPermission,
|
||||||
|
PortfolioDomainRequestsPermission,
|
||||||
|
PortfolioDomainsPermission,
|
||||||
|
PortfolioOrganizationssPermission,
|
||||||
UserDeleteDomainRolePermission,
|
UserDeleteDomainRolePermission,
|
||||||
UserProfilePermission,
|
UserProfilePermission,
|
||||||
PortfolioBasePermission,
|
PortfolioPermission,
|
||||||
)
|
)
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -166,7 +169,7 @@ class UserProfilePermissionView(UserProfilePermission, DetailView, abc.ABC):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
class PortfolioPermissionView(PortfolioBasePermission, DetailView, abc.ABC):
|
class PortfolioBasePermissionView(PortfolioPermission, DetailView, abc.ABC):
|
||||||
"""Abstract base view for portfolio views that enforces permissions.
|
"""Abstract base view for portfolio views that enforces permissions.
|
||||||
|
|
||||||
This abstract view cannot be instantiated. Actual views must specify
|
This abstract view cannot be instantiated. Actual views must specify
|
||||||
|
@ -184,3 +187,17 @@ class PortfolioPermissionView(PortfolioBasePermission, DetailView, abc.ABC):
|
||||||
def template_name(self):
|
def template_name(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class PortfolioDomainsPermissionView(PortfolioDomainsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class PortfolioDomainRequestsPermissionView(PortfolioDomainRequestsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
class PortfolioOrganizationssPermissionView(PortfolioOrganizationssPermission, PortfolioBasePermissionView, abc.ABC):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue