mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-07-25 20:18:38 +02:00
merge
This commit is contained in:
commit
604da37de3
15 changed files with 242 additions and 51 deletions
|
@ -1717,7 +1717,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
role="button"
|
role="button"
|
||||||
id="button-toggle-delete-domain-alert-${request.id}"
|
id="button-toggle-delete-domain-alert-${request.id}"
|
||||||
href="#toggle-delete-domain-alert-${request.id}"
|
href="#toggle-delete-domain-alert-${request.id}"
|
||||||
class="usa-button text-secondary usa-button--unstyled text-no-underline late-loading-modal-trigger margin-top-2 visible-mobile"
|
class="usa-button text-secondary usa-button--unstyled text-no-underline late-loading-modal-trigger margin-top-2 visible-mobile-flex"
|
||||||
aria-controls="toggle-delete-domain-alert-${request.id}"
|
aria-controls="toggle-delete-domain-alert-${request.id}"
|
||||||
data-open-modal
|
data-open-modal
|
||||||
>
|
>
|
||||||
|
@ -1726,7 +1726,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
</svg> Delete <span class="usa-sr-only">${domainName}</span>
|
</svg> Delete <span class="usa-sr-only">${domainName}</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="usa-accordion usa-accordion--more-actions margin-right-2 hidden-mobile">
|
<div class="usa-accordion usa-accordion--more-actions margin-right-2 hidden-mobile-flex">
|
||||||
<div class="usa-accordion__heading">
|
<div class="usa-accordion__heading">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
@ -159,18 +159,18 @@ abbr[title] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden-mobile {
|
.hidden-mobile-flex {
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
.visible-mobile {
|
.visible-mobile-flex {
|
||||||
display: block!important;
|
display: flex!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@include at-media(tablet) {
|
@include at-media(tablet) {
|
||||||
.hidden-mobile {
|
.hidden-mobile-flex {
|
||||||
display: block!important;
|
display: flex!important;
|
||||||
}
|
}
|
||||||
.visible-mobile {
|
.visible-mobile-flex {
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,6 +211,7 @@ a.usa-button--unstyled:visited {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dotgov-table a
|
||||||
a .usa-icon,
|
a .usa-icon,
|
||||||
.usa-button--with-icon .usa-icon {
|
.usa-button--with-icon .usa-icon {
|
||||||
height: 1.3em;
|
height: 1.3em;
|
||||||
|
@ -224,6 +225,7 @@ a .usa-icon,
|
||||||
}
|
}
|
||||||
|
|
||||||
button.text-secondary,
|
button.text-secondary,
|
||||||
|
button.text-secondary:hover,
|
||||||
.dotgov-table a.text-secondary {
|
.dotgov-table a.text-secondary {
|
||||||
color: $theme-color-error;
|
color: $theme-color-error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,22 +61,20 @@ def add_has_profile_feature_flag_to_context(request):
|
||||||
def portfolio_permissions(request):
|
def portfolio_permissions(request):
|
||||||
"""Make portfolio permissions for the request user available in global context"""
|
"""Make portfolio permissions for the request user available in global context"""
|
||||||
default_context = {
|
default_context = {
|
||||||
"has_base_portfolio_permission": False,
|
"has_base_portfolio_permission": False,
|
||||||
"has_domains_portfolio_permission": False,
|
"has_any_domains_portfolio_permission": False,
|
||||||
"has_requests_portfolio_permission": False,
|
"has_any_requests_portfolio_permission": False,
|
||||||
"has_edit_request_portfolio_permission": False,
|
"has_edit_request_portfolio_permission": False,
|
||||||
"has_view_suborganization_portfolio_permission": False,
|
"has_view_suborganization_portfolio_permission": False,
|
||||||
"has_edit_suborganization_portfolio_permission": False,
|
"has_edit_suborganization_portfolio_permission": False,
|
||||||
"portfolio": None,
|
"portfolio": None,
|
||||||
"has_organization_feature_flag": False,
|
"has_organization_feature_flag": False,
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
portfolio = request.session.get("portfolio")
|
portfolio = request.session.get("portfolio")
|
||||||
if portfolio:
|
if portfolio:
|
||||||
return {
|
return {
|
||||||
"has_base_portfolio_permission": request.user.has_base_portfolio_permission(portfolio),
|
"has_base_portfolio_permission": request.user.has_base_portfolio_permission(portfolio),
|
||||||
"has_domains_portfolio_permission": request.user.has_domains_portfolio_permission(portfolio),
|
|
||||||
"has_requests_portfolio_permission": request.user.has_requests_portfolio_permission(portfolio),
|
|
||||||
"has_edit_request_portfolio_permission": request.user.has_edit_request_portfolio_permission(portfolio),
|
"has_edit_request_portfolio_permission": request.user.has_edit_request_portfolio_permission(portfolio),
|
||||||
"has_view_suborganization_portfolio_permission": request.user.has_view_suborganization_portfolio_permission(
|
"has_view_suborganization_portfolio_permission": request.user.has_view_suborganization_portfolio_permission(
|
||||||
portfolio
|
portfolio
|
||||||
|
@ -84,6 +82,10 @@ def portfolio_permissions(request):
|
||||||
"has_edit_suborganization_portfolio_permission": request.user.has_edit_suborganization_portfolio_permission(
|
"has_edit_suborganization_portfolio_permission": request.user.has_edit_suborganization_portfolio_permission(
|
||||||
portfolio
|
portfolio
|
||||||
),
|
),
|
||||||
|
"has_any_domains_portfolio_permission": request.user.has_any_domains_portfolio_permission(portfolio),
|
||||||
|
"has_any_requests_portfolio_permission": request.user.has_any_requests_portfolio_permission(
|
||||||
|
portfolio
|
||||||
|
),
|
||||||
"portfolio": portfolio,
|
"portfolio": portfolio,
|
||||||
"has_organization_feature_flag": True,
|
"has_organization_feature_flag": True,
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ class User(AbstractUser):
|
||||||
def has_edit_org_portfolio_permission(self, portfolio):
|
def has_edit_org_portfolio_permission(self, portfolio):
|
||||||
return self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.EDIT_PORTFOLIO)
|
return self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.EDIT_PORTFOLIO)
|
||||||
|
|
||||||
def has_domains_portfolio_permission(self, portfolio):
|
def has_any_domains_portfolio_permission(self, portfolio):
|
||||||
return self._has_portfolio_permission(
|
return self._has_portfolio_permission(
|
||||||
portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS
|
portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS
|
||||||
) or self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)
|
) or self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)
|
||||||
|
@ -226,8 +226,8 @@ class User(AbstractUser):
|
||||||
def has_view_all_domains_portfolio_permission(self, portfolio):
|
def has_view_all_domains_portfolio_permission(self, portfolio):
|
||||||
"""Determines if the current user can view all available domains in a given portfolio"""
|
"""Determines if the current user can view all available domains in a given portfolio"""
|
||||||
return self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)
|
return self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)
|
||||||
|
|
||||||
def has_requests_portfolio_permission(self, portfolio):
|
def has_any_requests_portfolio_permission(self, portfolio):
|
||||||
return self._has_portfolio_permission(
|
return self._has_portfolio_permission(
|
||||||
portfolio, UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS
|
portfolio, UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS
|
||||||
) or self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.EDIT_REQUESTS)
|
) or self._has_portfolio_permission(portfolio, UserPortfolioPermissionChoices.EDIT_REQUESTS)
|
||||||
|
@ -261,19 +261,19 @@ class User(AbstractUser):
|
||||||
(self.has_edit_suborganization_portfolio_permission(portfolio), ["Admin"]),
|
(self.has_edit_suborganization_portfolio_permission(portfolio), ["Admin"]),
|
||||||
(
|
(
|
||||||
self.has_view_all_domains_portfolio_permission(portfolio)
|
self.has_view_all_domains_portfolio_permission(portfolio)
|
||||||
and self.has_requests_portfolio_permission(portfolio)
|
and self.has_any_requests_portfolio_permission(portfolio)
|
||||||
and self.has_edit_request_portfolio_permission(portfolio),
|
and self.has_edit_request_portfolio_permission(portfolio),
|
||||||
["View-only admin", "Domain requestor"],
|
["View-only admin", "Domain requestor"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
self.has_view_all_domains_portfolio_permission(portfolio)
|
self.has_view_all_domains_portfolio_permission(portfolio)
|
||||||
and self.has_requests_portfolio_permission(portfolio),
|
and self.has_any_requests_portfolio_permission(portfolio),
|
||||||
["View-only admin"],
|
["View-only admin"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
self.has_base_portfolio_permission(portfolio)
|
self.has_base_portfolio_permission(portfolio)
|
||||||
and self.has_edit_request_portfolio_permission(portfolio)
|
and self.has_edit_request_portfolio_permission(portfolio)
|
||||||
and self.has_domains_portfolio_permission(portfolio),
|
and self.has_any_domains_portfolio_permission(portfolio),
|
||||||
["Domain requestor", "Domain manager"],
|
["Domain requestor", "Domain manager"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -281,7 +281,7 @@ class User(AbstractUser):
|
||||||
["Domain requestor"],
|
["Domain requestor"],
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
self.has_base_portfolio_permission(portfolio) and self.has_domains_portfolio_permission(portfolio),
|
self.has_base_portfolio_permission(portfolio) and self.has_any_domains_portfolio_permission(portfolio),
|
||||||
["Domain manager"],
|
["Domain manager"],
|
||||||
),
|
),
|
||||||
(self.has_base_portfolio_permission(portfolio), ["Member"]),
|
(self.has_base_portfolio_permission(portfolio), ["Member"]),
|
||||||
|
|
|
@ -162,10 +162,14 @@ class CheckPortfolioMiddleware:
|
||||||
request.session["portfolio"] = request.user.get_first_portfolio()
|
request.session["portfolio"] = request.user.get_first_portfolio()
|
||||||
else:
|
else:
|
||||||
request.session["portfolio"] = None
|
request.session["portfolio"] = None
|
||||||
|
else:
|
||||||
|
# Edge case: waffle flag is changed while the user is logged in
|
||||||
|
if not request.user.is_org_user(request) and request.session.get("portfolio"):
|
||||||
|
request.session["portfolio"] = None
|
||||||
|
|
||||||
if request.session.get("portfolio"):
|
if request.session.get("portfolio"):
|
||||||
if current_path == self.home:
|
if current_path == self.home:
|
||||||
if request.user.has_domains_portfolio_permission(request.session["portfolio"]):
|
if request.user.has_any_domains_portfolio_permission(request.session["portfolio"]):
|
||||||
portfolio_redirect = reverse("domains")
|
portfolio_redirect = reverse("domains")
|
||||||
else:
|
else:
|
||||||
portfolio_redirect = reverse("no-portfolio-domains")
|
portfolio_redirect = reverse("no-portfolio-domains")
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
{% include "includes/summary_item.html" with title='DNSSEC' value='Not Enabled' edit_link=url editable=is_editable %}
|
{% include "includes/summary_item.html" with title='DNSSEC' value='Not Enabled' edit_link=url editable=is_editable %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if portfolio and has_domains_portfolio_permission and has_view_suborganization_portfolio_permission %}
|
{% if portfolio and has_any_domains_portfolio_permission and has_view_suborganization_portfolio_permission %}
|
||||||
{% url 'domain-suborganization' pk=domain.id as url %}
|
{% url 'domain-suborganization' pk=domain.id as url %}
|
||||||
{% include "includes/summary_item.html" with title='Suborganization' value=domain.domain_info.sub_organization edit_link=url editable=is_editable|and:has_edit_suborganization_portfolio_permission %}
|
{% include "includes/summary_item.html" with title='Suborganization' value=domain.domain_info.sub_organization edit_link=url editable=is_editable|and:has_edit_suborganization_portfolio_permission %}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
{% if portfolio %}
|
{% if portfolio %}
|
||||||
{% comment %} Only show this menu option if the user has the perms to do so {% endcomment %}
|
{% comment %} Only show this menu option if the user has the perms to do so {% endcomment %}
|
||||||
{% if has_domains_portfolio_permission and has_view_suborganization_portfolio_permission %}
|
{% if has_any_domains_portfolio_permission and has_view_suborganization_portfolio_permission %}
|
||||||
{% with url_name="domain-suborganization" %}
|
{% with url_name="domain-suborganization" %}
|
||||||
{% include "includes/domain_sidenav_item.html" with item_text="Suborganization" %}
|
{% include "includes/domain_sidenav_item.html" with item_text="Suborganization" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
If you believe there is an error please contact <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.
|
If you believe there is an error please contact <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if has_domains_portfolio_permission and has_edit_suborganization_portfolio_permission %}
|
{% if has_any_domains_portfolio_permission and has_edit_suborganization_portfolio_permission %}
|
||||||
<form class="usa-form usa-form--large" method="post" novalidate id="form-container">
|
<form class="usa-form usa-form--large" method="post" novalidate id="form-container">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% input_with_errors form.sub_organization %}
|
{% input_with_errors form.sub_organization %}
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
</div>
|
</div>
|
||||||
<ul class="usa-nav__primary usa-accordion">
|
<ul class="usa-nav__primary usa-accordion">
|
||||||
<li class="usa-nav__primary-item">
|
<li class="usa-nav__primary-item">
|
||||||
{% if has_domains_portfolio_permission %}
|
{% if has_any_domains_portfolio_permission %}
|
||||||
{% url 'domains' as url %}
|
{% url 'domains' as url %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% url 'no-portfolio-domains' as url %}
|
{% url 'no-portfolio-domains' as url %}
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- user has view but no edit permissions -->
|
<!-- user has view but no edit permissions -->
|
||||||
{% elif has_requests_portfolio_permission %}
|
{% elif has_any_requests_portfolio_permission %}
|
||||||
{% url 'domain-requests' as url %}
|
{% url 'domain-requests' as url %}
|
||||||
<a href="{{ url }}" class="usa-nav-link{% if 'request'|in_path:request.path %} usa-current{% endif %}">
|
<a href="{{ url }}" class="usa-nav-link{% if 'request'|in_path:request.path %} usa-current{% endif %}">
|
||||||
Domain requests
|
Domain requests
|
||||||
|
|
|
@ -1334,7 +1334,7 @@ class TestUser(TestCase):
|
||||||
@patch.multiple(
|
@patch.multiple(
|
||||||
User,
|
User,
|
||||||
has_view_all_domains_portfolio_permission=lambda self, portfolio: True,
|
has_view_all_domains_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_requests_portfolio_permission=lambda self, portfolio: True,
|
has_any_requests_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_edit_request_portfolio_permission=lambda self, portfolio: True,
|
has_edit_request_portfolio_permission=lambda self, portfolio: True,
|
||||||
)
|
)
|
||||||
def test_portfolio_role_summary_view_only_admin_and_domain_requestor(self):
|
def test_portfolio_role_summary_view_only_admin_and_domain_requestor(self):
|
||||||
|
@ -1344,7 +1344,7 @@ class TestUser(TestCase):
|
||||||
@patch.multiple(
|
@patch.multiple(
|
||||||
User,
|
User,
|
||||||
has_view_all_domains_portfolio_permission=lambda self, portfolio: True,
|
has_view_all_domains_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_requests_portfolio_permission=lambda self, portfolio: True,
|
has_any_requests_portfolio_permission=lambda self, portfolio: True,
|
||||||
)
|
)
|
||||||
def test_portfolio_role_summary_view_only_admin(self):
|
def test_portfolio_role_summary_view_only_admin(self):
|
||||||
# Test if the user is recognized as a View-only admin
|
# Test if the user is recognized as a View-only admin
|
||||||
|
@ -1354,7 +1354,7 @@ class TestUser(TestCase):
|
||||||
User,
|
User,
|
||||||
has_base_portfolio_permission=lambda self, portfolio: True,
|
has_base_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_edit_request_portfolio_permission=lambda self, portfolio: True,
|
has_edit_request_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_domains_portfolio_permission=lambda self, portfolio: True,
|
has_any_domains_portfolio_permission=lambda self, portfolio: True,
|
||||||
)
|
)
|
||||||
def test_portfolio_role_summary_member_domain_requestor_domain_manager(self):
|
def test_portfolio_role_summary_member_domain_requestor_domain_manager(self):
|
||||||
# Test if the user has 'Member', 'Domain requestor', and 'Domain manager' roles
|
# Test if the user has 'Member', 'Domain requestor', and 'Domain manager' roles
|
||||||
|
@ -1372,7 +1372,7 @@ class TestUser(TestCase):
|
||||||
@patch.multiple(
|
@patch.multiple(
|
||||||
User,
|
User,
|
||||||
has_base_portfolio_permission=lambda self, portfolio: True,
|
has_base_portfolio_permission=lambda self, portfolio: True,
|
||||||
has_domains_portfolio_permission=lambda self, portfolio: True,
|
has_any_domains_portfolio_permission=lambda self, portfolio: True,
|
||||||
)
|
)
|
||||||
def test_portfolio_role_summary_member_domain_manager(self):
|
def test_portfolio_role_summary_member_domain_manager(self):
|
||||||
# Test if the user has 'Member' and 'Domain manager' roles
|
# Test if the user has 'Member' and 'Domain manager' roles
|
||||||
|
@ -1387,6 +1387,73 @@ class TestUser(TestCase):
|
||||||
# Test if the user has no roles
|
# Test if the user has no roles
|
||||||
self.assertEqual(self.user.portfolio_role_summary(self.portfolio), [])
|
self.assertEqual(self.user.portfolio_role_summary(self.portfolio), [])
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_base_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_base_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.VIEW_PORTFOLIO)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_edit_org_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_edit_org_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.EDIT_PORTFOLIO)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_any_domains_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.side_effect = [False, True] # First permission false, second permission true
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_any_domains_portfolio_permission(self.portfolio))
|
||||||
|
self.assertEqual(mock_has_permission.call_count, 2)
|
||||||
|
mock_has_permission.assert_any_call(self.portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)
|
||||||
|
mock_has_permission.assert_any_call(self.portfolio, UserPortfolioPermissionChoices.VIEW_MANAGED_DOMAINS)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_view_all_domains_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_view_all_domains_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_any_requests_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.side_effect = [False, True] # First permission false, second permission true
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_any_requests_portfolio_permission(self.portfolio))
|
||||||
|
self.assertEqual(mock_has_permission.call_count, 2)
|
||||||
|
mock_has_permission.assert_any_call(self.portfolio, UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS)
|
||||||
|
mock_has_permission.assert_any_call(self.portfolio, UserPortfolioPermissionChoices.EDIT_REQUESTS)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_view_all_requests_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_view_all_requests_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_edit_request_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_edit_request_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.EDIT_REQUESTS)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_view_suborganization_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_view_suborganization_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.VIEW_SUBORGANIZATION)
|
||||||
|
|
||||||
|
@patch('registrar.models.User._has_portfolio_permission')
|
||||||
|
def test_has_edit_suborganization_portfolio_permission(self, mock_has_permission):
|
||||||
|
mock_has_permission.return_value = True
|
||||||
|
|
||||||
|
self.assertTrue(self.user.has_edit_suborganization_portfolio_permission(self.portfolio))
|
||||||
|
mock_has_permission.assert_called_once_with(self.portfolio, UserPortfolioPermissionChoices.EDIT_SUBORGANIZATION)
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_check_transition_domains_without_domains_on_login(self):
|
def test_check_transition_domains_without_domains_on_login(self):
|
||||||
"""A user's on_each_login callback does not check transition domains.
|
"""A user's on_each_login callback does not check transition domains.
|
||||||
|
@ -1548,8 +1615,8 @@ class TestUser(TestCase):
|
||||||
|
|
||||||
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")
|
||||||
|
|
||||||
user_can_view_all_domains = self.user.has_domains_portfolio_permission(portfolio)
|
user_can_view_all_domains = self.user.has_any_domains_portfolio_permission(portfolio)
|
||||||
user_can_view_all_requests = self.user.has_requests_portfolio_permission(portfolio)
|
user_can_view_all_requests = self.user.has_any_requests_portfolio_permission(portfolio)
|
||||||
|
|
||||||
self.assertFalse(user_can_view_all_domains)
|
self.assertFalse(user_can_view_all_domains)
|
||||||
self.assertFalse(user_can_view_all_requests)
|
self.assertFalse(user_can_view_all_requests)
|
||||||
|
@ -1560,8 +1627,8 @@ class TestUser(TestCase):
|
||||||
additional_permissions=[UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS],
|
additional_permissions=[UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS],
|
||||||
)
|
)
|
||||||
|
|
||||||
user_can_view_all_domains = self.user.has_domains_portfolio_permission(portfolio)
|
user_can_view_all_domains = self.user.has_any_domains_portfolio_permission(portfolio)
|
||||||
user_can_view_all_requests = self.user.has_requests_portfolio_permission(portfolio)
|
user_can_view_all_requests = self.user.has_any_requests_portfolio_permission(portfolio)
|
||||||
|
|
||||||
self.assertTrue(user_can_view_all_domains)
|
self.assertTrue(user_can_view_all_domains)
|
||||||
self.assertFalse(user_can_view_all_requests)
|
self.assertFalse(user_can_view_all_requests)
|
||||||
|
@ -1570,16 +1637,16 @@ class TestUser(TestCase):
|
||||||
portfolio_permission.save()
|
portfolio_permission.save()
|
||||||
portfolio_permission.refresh_from_db()
|
portfolio_permission.refresh_from_db()
|
||||||
|
|
||||||
user_can_view_all_domains = self.user.has_domains_portfolio_permission(portfolio)
|
user_can_view_all_domains = self.user.has_any_domains_portfolio_permission(portfolio)
|
||||||
user_can_view_all_requests = self.user.has_requests_portfolio_permission(portfolio)
|
user_can_view_all_requests = self.user.has_any_requests_portfolio_permission(portfolio)
|
||||||
|
|
||||||
self.assertTrue(user_can_view_all_domains)
|
self.assertTrue(user_can_view_all_domains)
|
||||||
self.assertTrue(user_can_view_all_requests)
|
self.assertTrue(user_can_view_all_requests)
|
||||||
|
|
||||||
UserDomainRole.objects.get_or_create(user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
UserDomainRole.objects.get_or_create(user=self.user, domain=self.domain, role=UserDomainRole.Roles.MANAGER)
|
||||||
|
|
||||||
user_can_view_all_domains = self.user.has_domains_portfolio_permission(portfolio)
|
user_can_view_all_domains = self.user.has_any_domains_portfolio_permission(portfolio)
|
||||||
user_can_view_all_requests = self.user.has_requests_portfolio_permission(portfolio)
|
user_can_view_all_requests = self.user.has_any_requests_portfolio_permission(portfolio)
|
||||||
|
|
||||||
self.assertTrue(user_can_view_all_domains)
|
self.assertTrue(user_can_view_all_domains)
|
||||||
self.assertTrue(user_can_view_all_requests)
|
self.assertTrue(user_can_view_all_requests)
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django.urls import reverse
|
||||||
from api.tests.common import less_console_noise_decorator
|
from api.tests.common import less_console_noise_decorator
|
||||||
from registrar.config import settings
|
from registrar.config import settings
|
||||||
from registrar.models import Portfolio, SeniorOfficial
|
from registrar.models import Portfolio, SeniorOfficial
|
||||||
|
from unittest import skip
|
||||||
from django_webtest import WebTest # type: ignore
|
from django_webtest import WebTest # type: ignore
|
||||||
from registrar.models import (
|
from registrar.models import (
|
||||||
DomainRequest,
|
DomainRequest,
|
||||||
|
@ -12,9 +13,10 @@ from registrar.models import (
|
||||||
)
|
)
|
||||||
from registrar.models.user_portfolio_permission import UserPortfolioPermission
|
from registrar.models.user_portfolio_permission import UserPortfolioPermission
|
||||||
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
|
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
|
||||||
from .common import create_test_user
|
from .common import MockSESClient, completed_domain_request, create_test_user
|
||||||
from waffle.testutils import override_flag
|
from waffle.testutils import override_flag
|
||||||
from django.contrib.sessions.middleware import SessionMiddleware
|
from django.contrib.sessions.middleware import SessionMiddleware
|
||||||
|
import boto3_mocking # type: ignore
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -502,7 +504,7 @@ class TestPortfolio(WebTest):
|
||||||
self.client.force_login(self.user)
|
self.client.force_login(self.user)
|
||||||
response = self.client.get(reverse("home"), follow=True)
|
response = self.client.get(reverse("home"), follow=True)
|
||||||
|
|
||||||
self.assertFalse(self.user.has_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
self.assertFalse(self.user.has_any_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "You aren")
|
self.assertContains(response, "You aren")
|
||||||
|
|
||||||
|
@ -517,7 +519,7 @@ class TestPortfolio(WebTest):
|
||||||
|
|
||||||
# Test the domains page - this user should have access
|
# Test the domains page - this user should have access
|
||||||
response = self.client.get(reverse("domains"))
|
response = self.client.get(reverse("domains"))
|
||||||
self.assertTrue(self.user.has_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
self.assertTrue(self.user.has_any_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "Domain name")
|
self.assertContains(response, "Domain name")
|
||||||
|
|
||||||
|
@ -528,7 +530,120 @@ class TestPortfolio(WebTest):
|
||||||
|
|
||||||
# Test the domains page - this user should have access
|
# Test the domains page - this user should have access
|
||||||
response = self.client.get(reverse("domains"))
|
response = self.client.get(reverse("domains"))
|
||||||
self.assertTrue(self.user.has_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
self.assertTrue(self.user.has_any_domains_portfolio_permission(response.wsgi_request.session.get("portfolio")))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "Domain name")
|
self.assertContains(response, "Domain name")
|
||||||
permission.delete()
|
permission.delete()
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
def test_portfolio_domain_requests_page_when_user_has_no_permissions(self):
|
||||||
|
"""Test the no requests page"""
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER]
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# create and submit a domain request
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
mock_client = MockSESClient()
|
||||||
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||||
|
domain_request.submit()
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
requests_page = self.client.get(reverse("no-portfolio-requests"), follow=True)
|
||||||
|
|
||||||
|
self.assertContains(requests_page, "You don’t have access to domain requests.")
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
def test_main_nav_when_user_has_no_permissions(self):
|
||||||
|
"""Test the nav contains a link to the no requests page"""
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_MEMBER]
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# create and submit a domain request
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
mock_client = MockSESClient()
|
||||||
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||||
|
domain_request.submit()
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
portfolio_landing_page = self.client.get(reverse("home"), follow=True)
|
||||||
|
|
||||||
|
# link to no requests
|
||||||
|
self.assertContains(portfolio_landing_page, "no-organization-requests/")
|
||||||
|
# dropdown
|
||||||
|
self.assertNotContains(portfolio_landing_page, "basic-nav-section-two")
|
||||||
|
# link to requests
|
||||||
|
self.assertNotContains(portfolio_landing_page, 'href="/requests/')
|
||||||
|
# link to create
|
||||||
|
self.assertNotContains(portfolio_landing_page, 'href="/request/')
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
def test_main_nav_when_user_has_all_permissions(self):
|
||||||
|
"""Test the nav contains a dropdown with a link to create and another link to view requests
|
||||||
|
Also test for the existence of the Create a new request btn on the requests page"""
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user, portfolio=self.portfolio, roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# create and submit a domain request
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
mock_client = MockSESClient()
|
||||||
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||||
|
domain_request.submit()
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
portfolio_landing_page = self.client.get(reverse("home"), follow=True)
|
||||||
|
|
||||||
|
# link to no requests
|
||||||
|
self.assertNotContains(portfolio_landing_page, "no-organization-requests/")
|
||||||
|
# dropdown
|
||||||
|
self.assertContains(portfolio_landing_page, "basic-nav-section-two")
|
||||||
|
# link to requests
|
||||||
|
self.assertContains(portfolio_landing_page, 'href="/requests/')
|
||||||
|
# link to create
|
||||||
|
self.assertContains(portfolio_landing_page, 'href="/request/')
|
||||||
|
|
||||||
|
requests_page = self.client.get(reverse("domain-requests"))
|
||||||
|
|
||||||
|
# create new request btn
|
||||||
|
self.assertContains(requests_page, 'Start a new domain request')
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
@override_flag("organization_feature", active=True)
|
||||||
|
def test_main_nav_when_user_has_view_but_not_edit_permissions(self):
|
||||||
|
"""Test the nav contains a simple link to view requests
|
||||||
|
Also test for the existence of the Create a new request btn on the requests page"""
|
||||||
|
UserPortfolioPermission.objects.get_or_create(
|
||||||
|
user=self.user, portfolio=self.portfolio, roles=[UserPortfolioPermissionChoices.VIEW_PORTFOLIO, UserPortfolioPermissionChoices.VIEW_ALL_REQUESTS]
|
||||||
|
)
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
# create and submit a domain request
|
||||||
|
domain_request = completed_domain_request(user=self.user)
|
||||||
|
mock_client = MockSESClient()
|
||||||
|
with boto3_mocking.clients.handler_for("sesv2", mock_client):
|
||||||
|
domain_request.submit()
|
||||||
|
domain_request.save()
|
||||||
|
|
||||||
|
portfolio_landing_page = self.client.get(reverse("home"), follow=True)
|
||||||
|
|
||||||
|
# link to no requests
|
||||||
|
self.assertNotContains(portfolio_landing_page, "no-organization-requests/")
|
||||||
|
# dropdown
|
||||||
|
self.assertNotContains(portfolio_landing_page, "basic-nav-section-two")
|
||||||
|
# link to requests
|
||||||
|
self.assertContains(portfolio_landing_page, 'href="/requests/')
|
||||||
|
# link to create
|
||||||
|
self.assertNotContains(portfolio_landing_page, 'href="/request/')
|
||||||
|
|
||||||
|
requests_page = self.client.get(reverse("domain-requests"))
|
||||||
|
|
||||||
|
# create new request btn
|
||||||
|
self.assertNotContains(requests_page, 'Start a new domain request')
|
||||||
|
|
||||||
|
@skip("TODO")
|
||||||
|
def test_portfolio_cache_updates_when_modified(self):
|
||||||
|
pass
|
||||||
|
|
|
@ -175,7 +175,7 @@ class DomainView(DomainBaseView):
|
||||||
If particular views allow permissions, they will need to override
|
If particular views allow permissions, they will need to override
|
||||||
this function."""
|
this function."""
|
||||||
portfolio = self.request.session.get("portfolio")
|
portfolio = self.request.session.get("portfolio")
|
||||||
if self.request.user.has_domains_portfolio_permission(portfolio):
|
if self.request.user.has_any_domains_portfolio_permission(portfolio):
|
||||||
if Domain.objects.filter(id=pk).exists():
|
if Domain.objects.filter(id=pk).exists():
|
||||||
domain = Domain.objects.get(id=pk)
|
domain = Domain.objects.get(id=pk)
|
||||||
if domain.domain_info.portfolio == portfolio:
|
if domain.domain_info.portfolio == portfolio:
|
||||||
|
|
|
@ -522,6 +522,7 @@ class DomainRequestWizard(DomainRequestWizardPermissionView, TemplateView):
|
||||||
return HttpResponseRedirect(reverse("domain-requests"))
|
return HttpResponseRedirect(reverse("domain-requests"))
|
||||||
else:
|
else:
|
||||||
return HttpResponseRedirect(reverse("home"))
|
return HttpResponseRedirect(reverse("home"))
|
||||||
|
|
||||||
# otherwise, proceed as normal
|
# otherwise, proceed as normal
|
||||||
return self.goto_next_step()
|
return self.goto_next_step()
|
||||||
|
|
||||||
|
|
|
@ -433,7 +433,7 @@ class PortfolioDomainsPermission(PortfolioBasePermission):
|
||||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||||
|
|
||||||
portfolio = self.request.session.get("portfolio")
|
portfolio = self.request.session.get("portfolio")
|
||||||
if not self.request.user.has_domains_portfolio_permission(portfolio):
|
if not self.request.user.has_any_domains_portfolio_permission(portfolio):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return super().has_permission()
|
return super().has_permission()
|
||||||
|
@ -450,7 +450,7 @@ class PortfolioDomainRequestsPermission(PortfolioBasePermission):
|
||||||
up from the portfolio's primary key in self.kwargs["pk"]"""
|
up from the portfolio's primary key in self.kwargs["pk"]"""
|
||||||
|
|
||||||
portfolio = self.request.session.get("portfolio")
|
portfolio = self.request.session.get("portfolio")
|
||||||
if not self.request.user.has_requests_portfolio_permission(portfolio):
|
if not self.request.user.has_any_requests_portfolio_permission(portfolio):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return super().has_permission()
|
return super().has_permission()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue