mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-15 17:17:02 +02:00
Merge pull request #2515 from cisagov/rjm/2505-org-view-only
Issue #2505: Read-only view for portfolio org page - [RJM]
This commit is contained in:
commit
f12c71ab16
14 changed files with 171 additions and 58 deletions
|
@ -82,3 +82,13 @@ legend.float-left-tablet + button.float-right-tablet {
|
||||||
color: var(--close-button-hover-bg);
|
color: var(--close-button-hover-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.read-only-label {
|
||||||
|
font-size: size('body', 'sm');
|
||||||
|
color: color('primary');
|
||||||
|
margin-bottom: units(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-only-value {
|
||||||
|
margin-top: units(0);
|
||||||
|
}
|
||||||
|
|
|
@ -247,11 +247,14 @@ class User(AbstractUser):
|
||||||
|
|
||||||
return portfolio_permission in portfolio_permissions
|
return portfolio_permission in portfolio_permissions
|
||||||
|
|
||||||
# the methods below are checks for individual portfolio permissions. they are defined here
|
# the methods below are checks for individual portfolio permissions. They are defined here
|
||||||
# to make them easier to call elsewhere throughout the application
|
# to make them easier to call elsewhere throughout the application
|
||||||
def has_base_portfolio_permission(self):
|
def has_base_portfolio_permission(self):
|
||||||
return self._has_portfolio_permission(UserPortfolioPermissionChoices.VIEW_PORTFOLIO)
|
return self._has_portfolio_permission(UserPortfolioPermissionChoices.VIEW_PORTFOLIO)
|
||||||
|
|
||||||
|
def has_edit_org_portfolio_permission(self):
|
||||||
|
return self._has_portfolio_permission(UserPortfolioPermissionChoices.EDIT_PORTFOLIO)
|
||||||
|
|
||||||
def has_domains_portfolio_permission(self):
|
def has_domains_portfolio_permission(self):
|
||||||
return self._has_portfolio_permission(
|
return self._has_portfolio_permission(
|
||||||
UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS
|
UserPortfolioPermissionChoices.VIEW_ALL_DOMAINS
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<section class="section--outlined domain-requests" id="domain-requests">
|
<section class="section--outlined domain-requests" id="domain-requests">
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
{% if portfolio is None %}
|
{% if not has_domain_requests_portfolio_permission %}
|
||||||
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
<div class="mobile:grid-col-12 desktop:grid-col-6">
|
||||||
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
|
<h2 id="domain-requests-header" class="flex-6">Domain requests</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
<section class="section--outlined domains{% if portfolio is not None %} margin-top-0{% endif %}" id="domains">
|
<section class="section--outlined domains{% if not has_domains_portfolio_permission %} margin-top-0{% endif %}" id="domains">
|
||||||
<div class="section--outlined__header margin-bottom-3 {% if portfolio is None %} section--outlined__header--no-portfolio justify-content-space-between{% else %} grid-row{% endif %}">
|
<div class="section--outlined__header margin-bottom-3 {% if not has_domains_portfolio_permission %} section--outlined__header--no-portfolio justify-content-space-between{% else %} grid-row{% endif %}">
|
||||||
{% if portfolio is None %}
|
{% if not has_domains_portfolio_permission %}
|
||||||
<h2 id="domains-header" class="display-inline-block">Domains</h2>
|
<h2 id="domains-header" class="display-inline-block">Domains</h2>
|
||||||
<span class="display-none" id="no-portfolio-js-flag"></span>
|
<span class="display-none" id="no-portfolio-js-flag"></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- Embedding the portfolio value in a data attribute -->
|
<!-- Embedding the portfolio value in a data attribute -->
|
||||||
<span id="portfolio-js-value" data-portfolio="{{ portfolio.id }}"></span>
|
<span id="portfolio-js-value" data-portfolio="{{ portfolio.id }}"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="section--outlined__search {% if portfolio %} mobile:grid-col-12 desktop:grid-col-6{% endif %}">
|
<div class="section--outlined__search {% if has_domains_portfolio_permission %} mobile:grid-col-12 desktop:grid-col-6{% endif %}">
|
||||||
<section aria-label="Domains search component" class="margin-top-2">
|
<section aria-label="Domains search component" class="margin-top-2">
|
||||||
<form class="usa-search usa-search--small" method="POST" role="search">
|
<form class="usa-search usa-search--small" method="POST" role="search">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div class="section--outlined__utility-button mobile-lg:padding-right-105 {% if portfolio %} mobile:grid-col-12 desktop:grid-col-6 desktop:padding-left-3{% endif %}">
|
<div class="section--outlined__utility-button mobile-lg:padding-right-105 {% if has_domains_portfolio_permission %} mobile:grid-col-12 desktop:grid-col-6 desktop:padding-left-3{% endif %}">
|
||||||
<section aria-label="Domains report component" class="mobile-lg:margin-top-205">
|
<section aria-label="Domains report component" class="mobile-lg:margin-top-205">
|
||||||
<a href="{% url 'export_data_type_user' %}" class="usa-button usa-button--unstyled" role="button">
|
<a href="{% url 'export_data_type_user' %}" class="usa-button usa-button--unstyled" role="button">
|
||||||
<svg class="usa-icon usa-icon--big margin-right-neg-4px" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
<svg class="usa-icon usa-icon--big margin-right-neg-4px" aria-hidden="true" focusable="false" role="img" width="24" height="24">
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if portfolio %}
|
{% if has_domains_portfolio_permission %}
|
||||||
<div class="display-flex flex-align-center">
|
<div class="display-flex flex-align-center">
|
||||||
<span class="margin-right-2 margin-top-neg-1 usa-prose text-base-darker">Filter by</span>
|
<span class="margin-right-2 margin-top-neg-1 usa-prose text-base-darker">Filter by</span>
|
||||||
<div class="usa-accordion usa-accordion--select margin-right-2">
|
<div class="usa-accordion usa-accordion--select margin-right-2">
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
<th data-sortable="name" scope="col" role="columnheader">Domain name</th>
|
<th data-sortable="name" scope="col" role="columnheader">Domain name</th>
|
||||||
<th data-sortable="expiration_date" scope="col" role="columnheader">Expires</th>
|
<th data-sortable="expiration_date" scope="col" role="columnheader">Expires</th>
|
||||||
<th data-sortable="state_display" scope="col" role="columnheader">Status</th>
|
<th data-sortable="state_display" scope="col" role="columnheader">Status</th>
|
||||||
{% if portfolio %}
|
{% if has_domains_portfolio_permission %}
|
||||||
<th data-sortable="suborganization" scope="col" role="columnheader">Suborganization</th>
|
<th data-sortable="suborganization" scope="col" role="columnheader">Suborganization</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<th
|
<th
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
<input type="hidden" name="redirect" value="{{ form.initial.redirect }}">
|
<input type="hidden" name="redirect" value="{{ form.initial.redirect }}">
|
||||||
|
|
||||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-editable usa-form-editable--no-border padding-top-2" %}
|
{% with toggleable_input=True toggleable_label=True group_classes="usa-form-editable usa-form-editable--no-border padding-top-2" %}
|
||||||
{% input_with_errors form.full_name %}
|
{% input_with_errors form.full_name %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
|
@ -53,12 +53,12 @@
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-editable padding-top-2" %}
|
{% with toggleable_input=True toggleable_label=True group_classes="usa-form-editable padding-top-2" %}
|
||||||
{% input_with_errors form.title %}
|
{% input_with_errors form.title %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
{% public_site_url "help/account-management/#get-help-with-login.gov" as login_help_url %}
|
{% public_site_url "help/account-management/#get-help-with-login.gov" as login_help_url %}
|
||||||
{% with show_readonly=True add_class="display-none" group_classes="usa-form-editable usa-form-editable padding-top-2 bold-usa-label" %}
|
{% with toggleable_input=True add_class="display-none" group_classes="usa-form-editable usa-form-editable padding-top-2 bold-usa-label" %}
|
||||||
{% with link_href=login_help_url %}
|
{% with link_href=login_help_url %}
|
||||||
{% with sublabel_text="We recommend using your work email for your .gov account. If the wrong email is displayed below, you’ll need to update your Login.gov account and log back in. Get help with your Login.gov account." %}
|
{% with sublabel_text="We recommend using your work email for your .gov account. If the wrong email is displayed below, you’ll need to update your Login.gov account and log back in. Get help with your Login.gov account." %}
|
||||||
{% with link_text="Get help with your Login.gov account" target_blank=True do_not_show_max_chars=True %}
|
{% with link_text="Get help with your Login.gov account" target_blank=True do_not_show_max_chars=True %}
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
||||||
{% with show_edit_button=True show_readonly=True group_classes="usa-form-editable padding-top-2" %}
|
{% with toggleable_input=True toggleable_label=True group_classes="usa-form-editable padding-top-2" %}
|
||||||
{% with add_class="usa-input--medium" %}
|
{% with add_class="usa-input--medium" %}
|
||||||
{% input_with_errors form.phone %}
|
{% input_with_errors form.phone %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
|
7
src/registrar/templates/includes/input_read_only.html
Normal file
7
src/registrar/templates/includes/input_read_only.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{% comment %}
|
||||||
|
Template include for read-only form fields
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="read-only-label">{{ field.label }}</h4>
|
||||||
|
<p class="read-only-value">{{ field.value }}</p>
|
|
@ -27,8 +27,8 @@ error messages, if necessary.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not field.widget_type == "checkbox" %}
|
{% if not field.widget_type == "checkbox" %}
|
||||||
{% if show_edit_button %}
|
{% if toggleable_label %}
|
||||||
{% include "includes/label_with_edit_button.html" with bold_label=True %}
|
{% include "includes/toggleable_label.html" with bold_label=True %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% include "django/forms/label.html" %}
|
{% include "django/forms/label.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -63,8 +63,8 @@ error messages, if necessary.
|
||||||
<div class="display-flex flex-align-center">
|
<div class="display-flex flex-align-center">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if show_readonly %}
|
{% if toggleable_input %}
|
||||||
{% include "includes/readonly_input.html" %}
|
{% include "includes/toggleable_input.html" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# this is the input field, itself #}
|
{# this is the input field, itself #}
|
||||||
|
|
|
@ -23,42 +23,53 @@
|
||||||
|
|
||||||
<p>The name of your federal agency will be publicly listed as the domain registrant.</p>
|
<p>The name of your federal agency will be publicly listed as the domain registrant.</p>
|
||||||
|
|
||||||
|
{% if has_edit_org_portfolio_permission %}
|
||||||
<p>
|
<p>
|
||||||
The federal agency for your organization can’t be updated here.
|
The federal agency for your organization can’t be updated here.
|
||||||
To suggest an update, email <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.
|
To suggest an update, email <a href="mailto:help@get.gov" class="usa-link">help@get.gov</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% include "includes/form_errors.html" with form=form %}
|
{% include "includes/form_errors.html" with form=form %}
|
||||||
|
|
||||||
{% include "includes/required_fields.html" %}
|
{% include "includes/required_fields.html" %}
|
||||||
|
<form class="usa-form usa-form--large" method="post" novalidate>
|
||||||
<form class="usa-form usa-form--large" method="post" novalidate id="form-container">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
<h4 class="read-only-label">Federal agency</h4>
|
||||||
<p>
|
<p class="read-only-value">
|
||||||
<strong class="text-primary display-block margin-bottom-1">Federal agency</strong>
|
{{ portfolio.federal_agency }}
|
||||||
{{ portfolio }}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% input_with_errors form.address_line1 %}
|
{% input_with_errors form.address_line1 %}
|
||||||
|
|
||||||
{% input_with_errors form.address_line2 %}
|
{% input_with_errors form.address_line2 %}
|
||||||
|
|
||||||
{% input_with_errors form.city %}
|
{% input_with_errors form.city %}
|
||||||
|
|
||||||
{% input_with_errors form.state_territory %}
|
{% input_with_errors form.state_territory %}
|
||||||
|
|
||||||
{% with add_class="usa-input--small" %}
|
{% with add_class="usa-input--small" %}
|
||||||
{% input_with_errors form.zipcode %}
|
{% input_with_errors form.zipcode %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
|
<button type="submit" class="usa-button">
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
class="usa-button"
|
|
||||||
>
|
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<h4 class="read-only-label">Federal agency</h4>
|
||||||
|
<p class="read-only-value">
|
||||||
|
{{ portfolio.federal_agency }}
|
||||||
|
</p>
|
||||||
|
{% if form.address_line1.value is not None %}
|
||||||
|
{% include "includes/input_read_only.html" with field=form.address_line1 %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form.address_line2.value is not None %}
|
||||||
|
{% include "includes/input_read_only.html" with field=form.address_line2 %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form.city.value is not None %}
|
||||||
|
{% include "includes/input_read_only.html" with field=form.city %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form.state_territory.value is not None %}
|
||||||
|
{% include "includes/input_read_only.html" with field=form.state_territory %}
|
||||||
|
{% endif %}
|
||||||
|
{% if form.zipcode.value is not None %}
|
||||||
|
{% include "includes/input_read_only.html" with field=form.zipcode %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -26,7 +26,7 @@ def input_with_errors(context, field=None): # noqa: C901
|
||||||
add_group_class: append to input element's surrounding tag's `class` attribute
|
add_group_class: append to input element's surrounding tag's `class` attribute
|
||||||
attr_* - adds or replaces any single html attribute for the input
|
attr_* - adds or replaces any single html attribute for the input
|
||||||
add_error_attr_* - like `attr_*` but only if field.errors is not empty
|
add_error_attr_* - like `attr_*` but only if field.errors is not empty
|
||||||
show_edit_button: shows a simple edit button, and adds display-none to the input field.
|
toggleable_input: shows a simple edit button, and adds display-none to the input field.
|
||||||
|
|
||||||
Example usage:
|
Example usage:
|
||||||
```
|
```
|
||||||
|
@ -92,7 +92,7 @@ def input_with_errors(context, field=None): # noqa: C901
|
||||||
elif key == "add_group_class":
|
elif key == "add_group_class":
|
||||||
group_classes.append(value)
|
group_classes.append(value)
|
||||||
|
|
||||||
elif key == "show_edit_button":
|
elif key == "toggleable_input":
|
||||||
# Hide the primary input field.
|
# Hide the primary input field.
|
||||||
# Used such that we can toggle it with JS
|
# Used such that we can toggle it with JS
|
||||||
if "display-none" not in classes:
|
if "display-none" not in classes:
|
||||||
|
|
|
@ -7,6 +7,7 @@ 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 registrar.models.utility.portfolio_helper import UserPortfolioRoleChoices
|
||||||
from .common import MockEppLib, MockSESClient, create_user # type: ignore
|
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
|
import boto3_mocking # type: ignore
|
||||||
|
@ -326,7 +327,7 @@ class TestDomainDetail(TestDomainOverview):
|
||||||
phone="8003111234",
|
phone="8003111234",
|
||||||
title="test title",
|
title="test title",
|
||||||
portfolio=portfolio,
|
portfolio=portfolio,
|
||||||
portfolio_roles=[User.UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
|
portfolio_roles=[UserPortfolioRoleChoices.ORGANIZATION_ADMIN],
|
||||||
)
|
)
|
||||||
domain, _ = Domain.objects.get_or_create(name="bogusdomain.gov")
|
domain, _ = Domain.objects.get_or_create(name="bogusdomain.gov")
|
||||||
DomainInformation.objects.get_or_create(creator=user, domain=domain, portfolio=portfolio)
|
DomainInformation.objects.get_or_create(creator=user, domain=domain, portfolio=portfolio)
|
||||||
|
|
|
@ -10,7 +10,7 @@ from registrar.models import (
|
||||||
UserDomainRole,
|
UserDomainRole,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices
|
from registrar.models.utility.portfolio_helper import UserPortfolioPermissionChoices, UserPortfolioRoleChoices
|
||||||
from .common import create_test_user
|
from .common import create_test_user
|
||||||
from waffle.testutils import override_flag
|
from waffle.testutils import override_flag
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class TestPortfolio(WebTest):
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_middleware_redirects_to_portfolio_organization_page(self):
|
def test_middleware_redirects_to_portfolio_organization_page(self):
|
||||||
"""Test that user with VIEW_PORTFOLIO is redirected to portfolio organization page"""
|
"""Test that user with a portfolio and VIEW_PORTFOLIO is redirected to portfolio organization page"""
|
||||||
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 = [UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
self.user.portfolio_additional_permissions = [UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
||||||
|
@ -84,7 +84,8 @@ class TestPortfolio(WebTest):
|
||||||
|
|
||||||
@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):
|
||||||
"""Test that user with VIEW_PORTFOLIO and VIEW_ALL_DOMAINS is redirected to portfolio domains page"""
|
"""Test that user with a portfolio, VIEW_PORTFOLIO, VIEW_ALL_DOMAINS
|
||||||
|
is redirected to portfolio domains page"""
|
||||||
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 = [
|
self.user.portfolio_additional_permissions = [
|
||||||
|
@ -144,6 +145,51 @@ class TestPortfolio(WebTest):
|
||||||
# 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
|
||||||
|
def test_portfolio_organization_page_read_only(self):
|
||||||
|
"""Test that user with a portfolio can access the portfolio organization page, read only"""
|
||||||
|
self.app.set_user(self.user.username)
|
||||||
|
self.user.portfolio = self.portfolio
|
||||||
|
self.portfolio.city = "Los Angeles"
|
||||||
|
self.user.portfolio_additional_permissions = [UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
||||||
|
self.portfolio.save()
|
||||||
|
self.user.save()
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
with override_flag("organization_feature", active=True):
|
||||||
|
response = self.app.get(reverse("organization"))
|
||||||
|
# Assert the response is a 200
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# The label for Federal agency will always be a h4
|
||||||
|
self.assertContains(response, '<h4 class="read-only-label">Federal agency</h4>')
|
||||||
|
# The read only label for city will be a h4
|
||||||
|
self.assertContains(response, '<h4 class="read-only-label">City</h4>')
|
||||||
|
self.assertNotContains(response, 'for="id_city"')
|
||||||
|
self.assertContains(response, '<p class="read-only-value">Los Angeles</p>')
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_portfolio_organization_page_edit_access(self):
|
||||||
|
"""Test that user with a portfolio can access the portfolio organization page, read only"""
|
||||||
|
self.app.set_user(self.user.username)
|
||||||
|
self.user.portfolio = self.portfolio
|
||||||
|
self.user.portfolio_additional_permissions = [
|
||||||
|
UserPortfolioPermissionChoices.VIEW_PORTFOLIO,
|
||||||
|
UserPortfolioPermissionChoices.EDIT_PORTFOLIO,
|
||||||
|
]
|
||||||
|
self.portfolio.city = "Los Angeles"
|
||||||
|
self.portfolio.save()
|
||||||
|
self.user.save()
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
with override_flag("organization_feature", active=True):
|
||||||
|
response = self.app.get(reverse("organization"))
|
||||||
|
# Assert the response is a 200
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# The label for Federal agency will always be a h4
|
||||||
|
self.assertContains(response, '<h4 class="read-only-label">Federal agency</h4>')
|
||||||
|
# The read only label for city will be a h4
|
||||||
|
self.assertNotContains(response, '<h4 class="read-only-label">City</h4>')
|
||||||
|
self.assertNotContains(response, '<p class="read-only-value">Los Angeles</p>>')
|
||||||
|
self.assertContains(response, 'for="id_city"')
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_navigation_links_hidden_when_user_not_have_permission(self):
|
def test_navigation_links_hidden_when_user_not_have_permission(self):
|
||||||
"""Test that navigation links are hidden when user does not have portfolio permissions"""
|
"""Test that navigation links are hidden when user does not have portfolio permissions"""
|
||||||
|
@ -167,7 +213,7 @@ class TestPortfolio(WebTest):
|
||||||
self.assertContains(portfolio_page, reverse("domains"))
|
self.assertContains(portfolio_page, reverse("domains"))
|
||||||
self.assertContains(portfolio_page, reverse("domain-requests"))
|
self.assertContains(portfolio_page, reverse("domain-requests"))
|
||||||
|
|
||||||
# reducing portfolio permissions to just VIEW_PORTFOLIO, which should remove domains
|
# removing non-basic portfolio perms, which should remove domains
|
||||||
# and domain requests from nav
|
# and domain requests from nav
|
||||||
self.user.portfolio_additional_permissions = [UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
self.user.portfolio_additional_permissions = [UserPortfolioPermissionChoices.VIEW_PORTFOLIO]
|
||||||
self.user.save()
|
self.user.save()
|
||||||
|
@ -181,6 +227,39 @@ class TestPortfolio(WebTest):
|
||||||
self.assertNotContains(portfolio_page, reverse("domains"))
|
self.assertNotContains(portfolio_page, reverse("domains"))
|
||||||
self.assertNotContains(portfolio_page, reverse("domain-requests"))
|
self.assertNotContains(portfolio_page, reverse("domain-requests"))
|
||||||
|
|
||||||
|
@less_console_noise_decorator
|
||||||
|
def test_navigation_links_hidden_when_user_not_have_role(self):
|
||||||
|
"""Test that admin / memmber roles are associated with the right access"""
|
||||||
|
self.app.set_user(self.user.username)
|
||||||
|
self.user.portfolio = self.portfolio
|
||||||
|
self.user.portfolio_roles = [UserPortfolioRoleChoices.ORGANIZATION_ADMIN]
|
||||||
|
self.user.save()
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
with override_flag("organization_feature", active=True):
|
||||||
|
# This will redirect the user to the portfolio page.
|
||||||
|
# Follow implicity checks if our redirect is working.
|
||||||
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
|
# Assert that we're on the right page
|
||||||
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
|
self.assertNotContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
|
self.assertContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
||||||
|
self.assertContains(portfolio_page, reverse("domains"))
|
||||||
|
self.assertContains(portfolio_page, reverse("domain-requests"))
|
||||||
|
|
||||||
|
# removing non-basic portfolio role, which should remove domains
|
||||||
|
# and domain requests from nav
|
||||||
|
self.user.portfolio_roles = [UserPortfolioRoleChoices.ORGANIZATION_MEMBER]
|
||||||
|
self.user.save()
|
||||||
|
self.user.refresh_from_db()
|
||||||
|
|
||||||
|
portfolio_page = self.app.get(reverse("home")).follow()
|
||||||
|
|
||||||
|
self.assertContains(portfolio_page, self.portfolio.organization_name)
|
||||||
|
self.assertContains(portfolio_page, "<h1>Organization</h1>")
|
||||||
|
self.assertNotContains(portfolio_page, '<h1 id="domains-header">Domains</h1>')
|
||||||
|
self.assertNotContains(portfolio_page, reverse("domains"))
|
||||||
|
self.assertNotContains(portfolio_page, reverse("domain-requests"))
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_portfolio_org_name(self):
|
def test_portfolio_org_name(self):
|
||||||
"""Can load portfolio's org name page."""
|
"""Can load portfolio's org name page."""
|
||||||
|
@ -215,8 +294,9 @@ class TestPortfolio(WebTest):
|
||||||
self.portfolio.organization_name = "Hotel California"
|
self.portfolio.organization_name = "Hotel California"
|
||||||
self.portfolio.save()
|
self.portfolio.save()
|
||||||
page = self.app.get(reverse("organization"))
|
page = self.app.get(reverse("organization"))
|
||||||
# Once in the sidenav, once in the main nav, once in the form
|
# Once in the sidenav, once in the main nav
|
||||||
self.assertContains(page, "Hotel California", count=3)
|
self.assertContains(page, "Hotel California", count=2)
|
||||||
|
self.assertContains(page, "Non-Federal Agency")
|
||||||
|
|
||||||
@less_console_noise_decorator
|
@less_console_noise_decorator
|
||||||
def test_domain_org_name_address_form(self):
|
def test_domain_org_name_address_form(self):
|
||||||
|
|
|
@ -48,6 +48,7 @@ class PortfolioOrganizationView(PortfolioBasePermissionView, FormMixin):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add additional context data to the template."""
|
"""Add additional context data to the template."""
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["has_edit_org_portfolio_permission"] = self.request.user.has_edit_org_portfolio_permission()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue