mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-06 11:13:21 +02:00
lint
This commit is contained in:
parent
ea6ccae948
commit
cb3b1fd7fa
12 changed files with 123 additions and 121 deletions
|
@ -35,7 +35,6 @@ from django_admin_multiple_choice_list_filter.list_filters import MultipleChoice
|
||||||
from import_export import resources
|
from import_export import resources
|
||||||
from import_export.admin import ImportExportModelAdmin
|
from import_export.admin import ImportExportModelAdmin
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.contrib.postgres.forms import SimpleArrayField
|
|
||||||
from django.contrib.admin.widgets import FilteredSelectMultiple
|
from django.contrib.admin.widgets import FilteredSelectMultiple
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
@ -91,6 +90,7 @@ class UserResource(resources.ModelResource):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.User
|
model = models.User
|
||||||
|
|
||||||
|
|
||||||
class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple):
|
class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple):
|
||||||
def __init__(self, verbose_name, is_stacked=False, choices=(), **kwargs):
|
def __init__(self, verbose_name, is_stacked=False, choices=(), **kwargs):
|
||||||
super().__init__(verbose_name, is_stacked, **kwargs)
|
super().__init__(verbose_name, is_stacked, **kwargs)
|
||||||
|
@ -98,26 +98,25 @@ class FilteredSelectMultipleArrayWidget(FilteredSelectMultiple):
|
||||||
|
|
||||||
def value_from_datadict(self, data, files, name):
|
def value_from_datadict(self, data, files, name):
|
||||||
values = super().value_from_datadict(data, files, name)
|
values = super().value_from_datadict(data, files, name)
|
||||||
# print(f'value_from_datadict - values: {values}')
|
|
||||||
return values or []
|
return values or []
|
||||||
|
|
||||||
def get_context(self, name, value, attrs):
|
def get_context(self, name, value, attrs):
|
||||||
# print(f'get_context - initial value: {value}')
|
|
||||||
if value is None:
|
if value is None:
|
||||||
value = []
|
value = []
|
||||||
elif isinstance(value, str):
|
elif isinstance(value, str):
|
||||||
value = value.split(',')
|
value = value.split(",")
|
||||||
# print(f'get_context - processed value: {value}')
|
self.choices = [(choice, label) for choice, label in self.choices if choice in value] + [
|
||||||
self.choices = [(choice, label) for choice, label in self.choices if choice in value] + [(choice, label) for choice, label in self.choices if choice not in value]
|
(choice, label) for choice, label in self.choices if choice not in value
|
||||||
# print(f'get_context - choices: {self.choices}')
|
]
|
||||||
context = super().get_context(name, value, attrs)
|
context = super().get_context(name, value, attrs)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
class MyUserAdminForm(UserChangeForm):
|
class MyUserAdminForm(UserChangeForm):
|
||||||
"""This form utilizes the custom widget for its class's ManyToMany UIs.
|
"""This form utilizes the custom widget for its class's ManyToMany UIs.
|
||||||
|
|
||||||
It inherits from UserChangeForm which has special handling for the password and username fields."""
|
It inherits from UserChangeForm which has special handling for the password and username fields."""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.User
|
model = models.User
|
||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
@ -125,8 +124,14 @@ class MyUserAdminForm(UserChangeForm):
|
||||||
widgets = {
|
widgets = {
|
||||||
"groups": NoAutocompleteFilteredSelectMultiple("groups", False),
|
"groups": NoAutocompleteFilteredSelectMultiple("groups", False),
|
||||||
"user_permissions": NoAutocompleteFilteredSelectMultiple("user_permissions", False),
|
"user_permissions": NoAutocompleteFilteredSelectMultiple("user_permissions", False),
|
||||||
"portfolio_roles": FilteredSelectMultipleArrayWidget("portfolio_roles", is_stacked=False, choices=User.UserPortfolioRoleChoices.choices),
|
"portfolio_roles": FilteredSelectMultipleArrayWidget(
|
||||||
"portfolio_additional_permissions": FilteredSelectMultipleArrayWidget("portfolio_additional_permissions", is_stacked=False, choices=User.UserPortfolioPermissionChoices.choices),
|
"portfolio_roles", is_stacked=False, choices=User.UserPortfolioRoleChoices.choices
|
||||||
|
),
|
||||||
|
"portfolio_additional_permissions": FilteredSelectMultipleArrayWidget(
|
||||||
|
"portfolio_additional_permissions",
|
||||||
|
is_stacked=False,
|
||||||
|
choices=User.UserPortfolioPermissionChoices.choices,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
|
@ -43,7 +43,13 @@ def is_production(request):
|
||||||
def portfolio_permissions(request):
|
def portfolio_permissions(request):
|
||||||
""""""
|
""""""
|
||||||
return {
|
return {
|
||||||
"has_base_portfolio_permission": request.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO),
|
"has_base_portfolio_permission": request.user.has_portfolio_permission(
|
||||||
"has_domains_portfolio_permission": request.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_DOMAINS),
|
User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO
|
||||||
"has_domain_requests_portfolio_permission": request.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.VIEW_REQUESTS)
|
),
|
||||||
|
"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
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,9 @@ class Portfolio(TimeStampedModel):
|
||||||
|
|
||||||
# Stores who created this model. If no creator is specified in DJA,
|
# Stores who created this model. If no creator is specified in DJA,
|
||||||
# then the creator will default to the current request user"""
|
# then the creator will default to the current request user"""
|
||||||
creator = models.ForeignKey("registrar.User", on_delete=models.PROTECT, help_text="Associated user", related_name="creator", unique=False)
|
creator = models.ForeignKey(
|
||||||
|
"registrar.User", on_delete=models.PROTECT, help_text="Associated user", related_name="creator", unique=False
|
||||||
|
)
|
||||||
|
|
||||||
notes = models.TextField(
|
notes = models.TextField(
|
||||||
null=True,
|
null=True,
|
||||||
|
|
|
@ -63,7 +63,7 @@ class User(AbstractUser):
|
||||||
|
|
||||||
class UserPortfolioRoleChoices(models.TextChoices):
|
class UserPortfolioRoleChoices(models.TextChoices):
|
||||||
"""
|
"""
|
||||||
Roles make it easier for admins to look at
|
Roles make it easier for admins to look at
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ORGANIZATION_ADMIN = "organization_admin", "Admin"
|
ORGANIZATION_ADMIN = "organization_admin", "Admin"
|
||||||
|
@ -71,8 +71,7 @@ class User(AbstractUser):
|
||||||
ORGANIZATION_MEMBER = "organization_member", "Member"
|
ORGANIZATION_MEMBER = "organization_member", "Member"
|
||||||
|
|
||||||
class UserPortfolioPermissionChoices(models.TextChoices):
|
class UserPortfolioPermissionChoices(models.TextChoices):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
VIEW_DOMAINS = "view_domains", "View all domains and domain reports"
|
VIEW_DOMAINS = "view_domains", "View all domains and domain reports"
|
||||||
# EDIT_DOMAINS is really self.domains. We add is hear and leverage it in has_permission
|
# EDIT_DOMAINS is really self.domains. We add is hear and leverage it in has_permission
|
||||||
|
@ -83,14 +82,13 @@ class User(AbstractUser):
|
||||||
|
|
||||||
VIEW_MEMBER = "view_member", "View members"
|
VIEW_MEMBER = "view_member", "View members"
|
||||||
EDIT_MEMBER = "edit_member", "Create and edit members"
|
EDIT_MEMBER = "edit_member", "Create and edit members"
|
||||||
|
|
||||||
VIEW_REQUESTS = "view_requests", "View requests"
|
VIEW_REQUESTS = "view_requests", "View requests"
|
||||||
EDIT_REQUESTS = "edit_requests", "Create and edit requests"
|
EDIT_REQUESTS = "edit_requests", "Create and edit requests"
|
||||||
|
|
||||||
VIEW_PORTFOLIO = "view_portfolio", "View organization"
|
VIEW_PORTFOLIO = "view_portfolio", "View organization"
|
||||||
EDIT_PORTFOLIO = "edit_portfolio", "Edit organization"
|
EDIT_PORTFOLIO = "edit_portfolio", "Edit organization"
|
||||||
|
|
||||||
|
|
||||||
PORTFOLIO_ROLE_PERMISSIONS = {
|
PORTFOLIO_ROLE_PERMISSIONS = {
|
||||||
UserPortfolioRoleChoices.ORGANIZATION_ADMIN: [
|
UserPortfolioRoleChoices.ORGANIZATION_ADMIN: [
|
||||||
UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
||||||
|
@ -105,14 +103,13 @@ class User(AbstractUser):
|
||||||
UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
||||||
UserPortfolioPermissionChoices.VIEW_MEMBER,
|
UserPortfolioPermissionChoices.VIEW_MEMBER,
|
||||||
UserPortfolioPermissionChoices.VIEW_REQUESTS,
|
UserPortfolioPermissionChoices.VIEW_REQUESTS,
|
||||||
UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
||||||
],
|
],
|
||||||
UserPortfolioRoleChoices.ORGANIZATION_MEMBER: [
|
UserPortfolioRoleChoices.ORGANIZATION_MEMBER: [
|
||||||
UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# #### Constants for choice fields ####
|
# #### Constants for choice fields ####
|
||||||
RESTRICTED = "restricted"
|
RESTRICTED = "restricted"
|
||||||
STATUS_CHOICES = ((RESTRICTED, RESTRICTED),)
|
STATUS_CHOICES = ((RESTRICTED, RESTRICTED),)
|
||||||
|
@ -249,24 +246,22 @@ class User(AbstractUser):
|
||||||
|
|
||||||
def has_contact_info(self):
|
def has_contact_info(self):
|
||||||
return bool(self.title or self.email or self.phone)
|
return bool(self.title or self.email or self.phone)
|
||||||
|
|
||||||
def has_portfolio_permission(self, portfolio_permission):
|
def has_portfolio_permission(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"""
|
||||||
|
|
||||||
print(f"IN has_portfolio_permission")
|
|
||||||
|
|
||||||
# EDIT_DOMAINS === user is a manager on a domain (has UserDomainRole)
|
# EDIT_DOMAINS === user is a manager on a domain (has UserDomainRole)
|
||||||
# NOTE: Should we check whether the domain is in the portfolio?
|
# NOTE: Should we check whether the domain is in the portfolio?
|
||||||
if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
if portfolio_permission == self.UserPortfolioPermissionChoices.EDIT_DOMAINS and self.domains.exists():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if not self.portfolio:
|
if not self.portfolio:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
portfolio_permissions = self._get_portfolio_permissions()
|
portfolio_permissions = self._get_portfolio_permissions()
|
||||||
|
|
||||||
return portfolio_permission in portfolio_permissions
|
return portfolio_permission in portfolio_permissions
|
||||||
|
|
||||||
def _get_portfolio_permissions(self):
|
def _get_portfolio_permissions(self):
|
||||||
"""
|
"""
|
||||||
Retrieve the permissions for the user's portfolio roles.
|
Retrieve the permissions for the user's portfolio roles.
|
||||||
|
|
|
@ -149,20 +149,22 @@ class CheckPortfolioMiddleware:
|
||||||
# user_portfolios = Portfolio.objects.filter(creator=request.user)
|
# user_portfolios = Portfolio.objects.filter(creator=request.user)
|
||||||
|
|
||||||
permission_dict = portfolio_permissions(request)
|
permission_dict = portfolio_permissions(request)
|
||||||
has_portfolio_base_permission = permission_dict['has_base_portfolio_permission']
|
has_portfolio_base_permission = permission_dict["has_base_portfolio_permission"]
|
||||||
|
|
||||||
if has_portfolio_base_permission:
|
if has_portfolio_base_permission:
|
||||||
portfolio = request.user.portfolio
|
portfolio = request.user.portfolio
|
||||||
|
|
||||||
permission_dict = portfolio_permissions(request)
|
permission_dict = portfolio_permissions(request)
|
||||||
has_portfolio_domains_permission = permission_dict['has_domains_portfolio_permission']
|
has_portfolio_domains_permission = permission_dict["has_domains_portfolio_permission"]
|
||||||
|
|
||||||
if has_portfolio_domains_permission:
|
if has_portfolio_domains_permission:
|
||||||
portfolio_redirect = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id})
|
portfolio_redirect = reverse("portfolio-domains", kwargs={"portfolio_id": portfolio.id})
|
||||||
else:
|
else:
|
||||||
# View organization is the lowest access
|
# View organization is the lowest access
|
||||||
portfolio_redirect = reverse("portfolio-organization", kwargs={"portfolio_id": portfolio.id})
|
portfolio_redirect = reverse(
|
||||||
|
"portfolio-organization", kwargs={"portfolio_id": portfolio.id}
|
||||||
|
)
|
||||||
|
|
||||||
return HttpResponseRedirect(portfolio_redirect)
|
return HttpResponseRedirect(portfolio_redirect)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -3723,8 +3723,8 @@ class TestMyUserAdmin(MockDb):
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
self.assertContains(response,"Portfolio roles:")
|
self.assertContains(response, "Portfolio roles:")
|
||||||
self.assertContains(response,"Portfolio additional permissions:")
|
self.assertContains(response, "Portfolio additional permissions:")
|
||||||
|
|
||||||
|
|
||||||
class AuditedAdminTest(TestCase):
|
class AuditedAdminTest(TestCase):
|
||||||
|
|
|
@ -1217,13 +1217,13 @@ class TestUser(TestCase):
|
||||||
|
|
||||||
def test_has_portfolio_permission(self):
|
def test_has_portfolio_permission(self):
|
||||||
"""
|
"""
|
||||||
0. Returns False when user does not have a permission
|
0. Returns False when user does not have a permission
|
||||||
1. Returns False when a user does not have a portfolio
|
1. Returns False when a user does not have a portfolio
|
||||||
2. Returns True when user has direct permission
|
2. Returns True when user has direct permission
|
||||||
3. Returns True when user has permission through a role
|
3. Returns True when user has permission through a role
|
||||||
4. Returns True EDIT_DOMAINS when user does not have the perm but has UserDomainRole
|
4. Returns True EDIT_DOMAINS when user does not have the perm but has UserDomainRole
|
||||||
|
|
||||||
Note: This tests _get_portfolio_permissions as a side effect
|
Note: This tests _get_portfolio_permissions as a side effect
|
||||||
"""
|
"""
|
||||||
portfolio, _ = Portfolio.objects.get_or_create(creator=self.user, organization_name="Hotel California")
|
portfolio, _ = Portfolio.objects.get_or_create(creator=self.user, organization_name="Hotel California")
|
||||||
|
|
||||||
|
@ -1239,7 +1239,7 @@ class TestUser(TestCase):
|
||||||
self.assertFalse(user_can_view_requests)
|
self.assertFalse(user_can_view_requests)
|
||||||
self.assertFalse(user_can_edit_domains)
|
self.assertFalse(user_can_edit_domains)
|
||||||
|
|
||||||
self.user.portfolio=portfolio
|
self.user.portfolio = portfolio
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
|
|
||||||
|
@ -1263,16 +1263,18 @@ class TestUser(TestCase):
|
||||||
self.assertTrue(user_can_view_requests)
|
self.assertTrue(user_can_view_requests)
|
||||||
self.assertFalse(user_can_edit_domains)
|
self.assertFalse(user_can_edit_domains)
|
||||||
|
|
||||||
UserDomainRole.objects.all().get_or_create(user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
UserDomainRole.objects.all().get_or_create(
|
||||||
|
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_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_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_edit_domains = self.user.has_portfolio_permission(User.UserPortfolioPermissionChoices.EDIT_DOMAINS)
|
||||||
|
|
||||||
self.assertTrue(user_can_view_domains)
|
self.assertTrue(user_can_view_domains)
|
||||||
self.assertTrue(user_can_view_requests)
|
self.assertTrue(user_can_view_requests)
|
||||||
self.assertTrue(user_can_edit_domains)
|
self.assertTrue(user_can_edit_domains)
|
||||||
|
|
||||||
Portfolio.objects.all().delete()
|
Portfolio.objects.all().delete()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -554,7 +554,6 @@ class ExportDataTest(MockDb, MockEppLib):
|
||||||
csv_file.seek(0)
|
csv_file.seek(0)
|
||||||
# Read the content into a variable
|
# Read the content into a variable
|
||||||
csv_content = csv_file.read()
|
csv_content = csv_file.read()
|
||||||
print(csv_content)
|
|
||||||
expected_content = (
|
expected_content = (
|
||||||
# Header
|
# Header
|
||||||
"Domain request,Status,Domain type,Federal type,"
|
"Domain request,Status,Domain type,Federal type,"
|
||||||
|
|
|
@ -1,45 +1,14 @@
|
||||||
from unittest import skip
|
|
||||||
from unittest.mock import MagicMock, ANY, patch
|
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
|
||||||
from api.tests.common import less_console_noise_decorator
|
from api.tests.common import less_console_noise_decorator
|
||||||
from registrar.models.portfolio import Portfolio
|
from registrar.models.portfolio import Portfolio
|
||||||
|
|
||||||
from .common import MockEppLib, MockSESClient, create_user # type: ignore
|
|
||||||
from django_webtest import WebTest # type: ignore
|
from django_webtest import WebTest # type: ignore
|
||||||
import boto3_mocking # type: ignore
|
|
||||||
|
|
||||||
from registrar.utility.errors import (
|
|
||||||
NameserverError,
|
|
||||||
NameserverErrorCodes,
|
|
||||||
SecurityEmailError,
|
|
||||||
SecurityEmailErrorCodes,
|
|
||||||
GenericError,
|
|
||||||
GenericErrorCodes,
|
|
||||||
DsDataError,
|
|
||||||
DsDataErrorCodes,
|
|
||||||
)
|
|
||||||
|
|
||||||
from registrar.models import (
|
from registrar.models import (
|
||||||
DomainRequest,
|
DomainRequest,
|
||||||
Domain,
|
Domain,
|
||||||
DomainInformation,
|
DomainInformation,
|
||||||
DomainInvitation,
|
|
||||||
Contact,
|
|
||||||
PublicContact,
|
|
||||||
Host,
|
|
||||||
HostIP,
|
|
||||||
UserDomainRole,
|
UserDomainRole,
|
||||||
User,
|
User,
|
||||||
FederalAgency,
|
|
||||||
)
|
)
|
||||||
from datetime import date, datetime, timedelta
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
from .common import less_console_noise
|
|
||||||
from .test_views import TestWithUser
|
from .test_views import TestWithUser
|
||||||
from waffle.testutils import override_flag
|
from waffle.testutils import override_flag
|
||||||
|
|
||||||
|
@ -61,7 +30,7 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
def test_middleware_does_not_redirect_if_no_permission(self):
|
def test_middleware_does_not_redirect_if_no_permission(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
|
@ -89,7 +58,7 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
def test_middleware_redirects_to_portfolio_organization_page(self):
|
def test_middleware_redirects_to_portfolio_organization_page(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
|
@ -99,14 +68,17 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
portfolio_page = self.app.get(reverse("home")).follow()
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
# Assert that we're on the right page
|
# Assert that we're on the right page
|
||||||
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
self.assertContains(portfolio_page, '<h1>Organization</h1>')
|
self.assertContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_middleware_redirects_to_portfolio_domains_page(self):
|
def test_middleware_redirects_to_portfolio_domains_page(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO, User.UserPortfolioPermissionChoices.VIEW_DOMAINS]
|
self.user.portfolio_additional_permissions = [
|
||||||
|
User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
||||||
|
User.UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
||||||
|
]
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
|
@ -115,20 +87,22 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
portfolio_page = self.app.get(reverse("home")).follow()
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
# Assert that we're on the right page
|
# Assert that we're on the right page
|
||||||
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
self.assertNotContains(portfolio_page, '<h1>Organization</h1>')
|
self.assertNotContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
self.assertContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
self.assertContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_portfolio_domains_page_403_when_user_not_have_permission(self):
|
def test_portfolio_domains_page_403_when_user_not_have_permission(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
# This will redirect the user to the portfolio page.
|
# This will redirect the user to the portfolio page.
|
||||||
# Follow implicity checks if our redirect is working.
|
# Follow implicity checks if our redirect is working.
|
||||||
response = self.app.get(reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk}), status=403)
|
response = self.app.get(
|
||||||
|
reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk}), status=403
|
||||||
|
)
|
||||||
# Assert the response is a 403
|
# Assert the response is a 403
|
||||||
# Assert the response is a 403 Forbidden
|
# Assert the response is a 403 Forbidden
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
@ -137,28 +111,32 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
def test_portfolio_domain_requests_page_403_when_user_not_have_permission(self):
|
def test_portfolio_domain_requests_page_403_when_user_not_have_permission(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
# This will redirect the user to the portfolio page.
|
# This will redirect the user to the portfolio page.
|
||||||
# Follow implicity checks if our redirect is working.
|
# Follow implicity checks if our redirect is working.
|
||||||
response = self.app.get(reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk}), status=403)
|
response = self.app.get(
|
||||||
|
reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk}), status=403
|
||||||
|
)
|
||||||
# Assert the response is a 403
|
# Assert the response is a 403
|
||||||
# Assert the response is a 403 Forbidden
|
# Assert the response is a 403 Forbidden
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_portfolio_organization_page_403_when_user_not_have_permission(self):
|
def test_portfolio_organization_page_403_when_user_not_have_permission(self):
|
||||||
""""""
|
""""""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
# This will redirect the user to the portfolio page.
|
# This will redirect the user to the portfolio page.
|
||||||
# Follow implicity checks if our redirect is working.
|
# Follow implicity checks if our redirect is working.
|
||||||
response = self.app.get(reverse("portfolio-organization", kwargs={"portfolio_id": self.portfolio.pk}), status=403)
|
response = self.app.get(
|
||||||
|
reverse("portfolio-organization", kwargs={"portfolio_id": self.portfolio.pk}), status=403
|
||||||
|
)
|
||||||
# Assert the response is a 403
|
# Assert the response is a 403
|
||||||
# Assert the response is a 403 Forbidden
|
# Assert the response is a 403 Forbidden
|
||||||
self.assertEqual(response.status_code, 403)
|
self.assertEqual(response.status_code, 403)
|
||||||
|
@ -167,8 +145,12 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
def test_navigation_links_hidden_when_user_not_have_permission(self):
|
def test_navigation_links_hidden_when_user_not_have_permission(self):
|
||||||
"""This test is AMAZING"""
|
"""This test is AMAZING"""
|
||||||
self.app.set_user(self.user.username)
|
self.app.set_user(self.user.username)
|
||||||
self.user.portfolio=self.portfolio
|
self.user.portfolio = self.portfolio
|
||||||
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO, User.UserPortfolioPermissionChoices.VIEW_DOMAINS, User.UserPortfolioPermissionChoices.VIEW_REQUESTS]
|
self.user.portfolio_additional_permissions = [
|
||||||
|
User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
||||||
|
User.UserPortfolioPermissionChoices.VIEW_DOMAINS,
|
||||||
|
User.UserPortfolioPermissionChoices.VIEW_REQUESTS,
|
||||||
|
]
|
||||||
self.user.save()
|
self.user.save()
|
||||||
self.user.refresh_from_db()
|
self.user.refresh_from_db()
|
||||||
with override_flag("organization_feature", active=True):
|
with override_flag("organization_feature", active=True):
|
||||||
|
@ -177,10 +159,14 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
portfolio_page = self.app.get(reverse("home")).follow()
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
# Assert that we're on the right page
|
# Assert that we're on the right page
|
||||||
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
self.assertNotContains(portfolio_page, '<h1>Organization</h1>')
|
self.assertNotContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
self.assertContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
self.assertContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
||||||
self.assertContains(portfolio_page, reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk}))
|
self.assertContains(
|
||||||
self.assertContains(portfolio_page, reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk}))
|
portfolio_page, reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk})
|
||||||
|
)
|
||||||
|
self.assertContains(
|
||||||
|
portfolio_page, reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk})
|
||||||
|
)
|
||||||
|
|
||||||
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
self.user.portfolio_additional_permissions = [User.UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
||||||
self.user.save()
|
self.user.save()
|
||||||
|
@ -189,10 +175,14 @@ class TestPortfolioViews(TestWithUser, WebTest):
|
||||||
portfolio_page = self.app.get(reverse("home")).follow()
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
|
|
||||||
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
self.assertContains(portfolio_page, '<h1>Organization</h1>')
|
self.assertContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
self.assertNotContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
self.assertNotContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
||||||
self.assertNotContains(portfolio_page, reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk}))
|
self.assertNotContains(
|
||||||
self.assertNotContains(portfolio_page, reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk}))
|
portfolio_page, reverse("portfolio-domains", kwargs={"portfolio_id": self.portfolio.pk})
|
||||||
|
)
|
||||||
|
self.assertNotContains(
|
||||||
|
portfolio_page, reverse("portfolio-domain-requests", kwargs={"portfolio_id": self.portfolio.pk})
|
||||||
|
)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
Portfolio.objects.all().delete()
|
Portfolio.objects.all().delete()
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
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, PortfolioBasePermissionView
|
from registrar.views.utility.permission_views import (
|
||||||
|
PortfolioDomainRequestsPermissionView,
|
||||||
|
PortfolioDomainsPermissionView,
|
||||||
|
PortfolioBasePermissionView,
|
||||||
|
)
|
||||||
from waffle.decorators import flag_is_active
|
from waffle.decorators import flag_is_active
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
||||||
|
|
||||||
template_name = "portfolio_domains.html"
|
template_name = "portfolio_domains.html"
|
||||||
|
@ -19,6 +24,7 @@ class PortfolioDomainsView(PortfolioDomainsPermissionView, View):
|
||||||
|
|
||||||
return render(request, "portfolio_domains.html", context)
|
return render(request, "portfolio_domains.html", context)
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
||||||
|
|
||||||
template_name = "portfolio_requests.html"
|
template_name = "portfolio_requests.html"
|
||||||
|
@ -35,6 +41,7 @@ class PortfolioDomainRequestsView(PortfolioDomainRequestsPermissionView, View):
|
||||||
|
|
||||||
return render(request, "portfolio_requests.html", context)
|
return render(request, "portfolio_requests.html", context)
|
||||||
|
|
||||||
|
|
||||||
class PortfolioOrganizationView(PortfolioBasePermissionView, View):
|
class PortfolioOrganizationView(PortfolioBasePermissionView, View):
|
||||||
|
|
||||||
template_name = "portfolio_organization.html"
|
template_name = "portfolio_organization.html"
|
||||||
|
|
|
@ -10,7 +10,6 @@ from registrar.models import (
|
||||||
DomainInformation,
|
DomainInformation,
|
||||||
UserDomainRole,
|
UserDomainRole,
|
||||||
)
|
)
|
||||||
from registrar.models.user import User
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
@ -400,7 +399,7 @@ class UserProfilePermission(PermissionsLoginMixin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PortfolioBasePermission(PermissionsLoginMixin):
|
class PortfolioBasePermission(PermissionsLoginMixin):
|
||||||
"""Permission mixin that redirects to portfolio pages if user
|
"""Permission mixin that redirects to portfolio pages if user
|
||||||
|
@ -416,40 +415,37 @@ class PortfolioBasePermission(PermissionsLoginMixin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
permission_dict = portfolio_permissions(self.request)
|
permission_dict = portfolio_permissions(self.request)
|
||||||
has_permission = permission_dict['has_base_portfolio_permission']
|
has_permission = permission_dict["has_base_portfolio_permission"]
|
||||||
|
|
||||||
if not has_permission:
|
if not has_permission:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainsPermission(PortfolioBasePermission):
|
class PortfolioDomainsPermission(PortfolioBasePermission):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
def has_permission(self):
|
def has_permission(self):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
permission_dict = portfolio_permissions(self.request)
|
permission_dict = portfolio_permissions(self.request)
|
||||||
has_permission = permission_dict['has_domains_portfolio_permission']
|
has_permission = permission_dict["has_domains_portfolio_permission"]
|
||||||
|
|
||||||
if not has_permission:
|
if not has_permission:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainRequestsPermission(PortfolioBasePermission):
|
class PortfolioDomainRequestsPermission(PortfolioBasePermission):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
def has_permission(self):
|
def has_permission(self):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
permission_dict = portfolio_permissions(self.request)
|
permission_dict = portfolio_permissions(self.request)
|
||||||
has_permission = permission_dict['has_domain_requests_portfolio_permission']
|
has_permission = permission_dict["has_domain_requests_portfolio_permission"]
|
||||||
|
|
||||||
if not has_permission:
|
if not has_permission:
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -188,10 +188,8 @@ class PortfolioBasePermissionView(PortfolioBasePermission, DetailView, abc.ABC):
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainsPermissionView(PortfolioDomainsPermission, PortfolioBasePermissionView, abc.ABC):
|
class PortfolioDomainsPermissionView(PortfolioDomainsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class PortfolioDomainRequestsPermissionView(PortfolioDomainRequestsPermission, PortfolioBasePermissionView, abc.ABC):
|
class PortfolioDomainRequestsPermissionView(PortfolioDomainRequestsPermission, PortfolioBasePermissionView, abc.ABC):
|
||||||
"""
|
""" """
|
||||||
"""
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue