Merge pull request #738 from dod-ccpo/update-ppoc
Update Point of Contact
This commit is contained in:
commit
2ae9f0cab7
@ -121,6 +121,28 @@ class PortfolioRoles(object):
|
|||||||
)
|
)
|
||||||
return PermissionSets.get_many(perms_set_names)
|
return PermissionSets.get_many(perms_set_names)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def make_ppoc(cls, portfolio_role):
|
||||||
|
portfolio = portfolio_role.portfolio
|
||||||
|
original_owner_role = PortfolioRoles.get(
|
||||||
|
portfolio_id=portfolio.id, user_id=portfolio.owner.id
|
||||||
|
)
|
||||||
|
PortfolioRoles.revoke_ppoc_permissions(portfolio_role=original_owner_role)
|
||||||
|
PortfolioRoles.add(
|
||||||
|
user=portfolio_role.user,
|
||||||
|
portfolio_id=portfolio.id,
|
||||||
|
permission_sets=PortfolioRoles.PORTFOLIO_PERMISSION_SETS,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def revoke_ppoc_permissions(cls, portfolio_role):
|
||||||
|
permission_sets = [
|
||||||
|
permission_set.name
|
||||||
|
for permission_set in portfolio_role.permission_sets
|
||||||
|
if permission_set.name != PermissionSets.PORTFOLIO_POC
|
||||||
|
]
|
||||||
|
PortfolioRoles.update(portfolio_role=portfolio_role, set_names=permission_sets)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def disable(cls, portfolio_role):
|
def disable(cls, portfolio_role):
|
||||||
portfolio_role.status = PortfolioRoleStatus.DISABLED
|
portfolio_role.status = PortfolioRoleStatus.DISABLED
|
||||||
|
@ -80,3 +80,11 @@ class NewForm(PermissionsForm):
|
|||||||
translate("forms.new_member.dod_id_label"),
|
translate("forms.new_member.dod_id_label"),
|
||||||
validators=[Required(), Length(min=10), IsNumber()],
|
validators=[Required(), Length(min=10), IsNumber()],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AssignPPOCForm(PermissionsForm):
|
||||||
|
user_id = SelectField(
|
||||||
|
label=translate("forms.assign_ppoc.dod_id"),
|
||||||
|
validators=[Required()],
|
||||||
|
choices=[("", "- Select -")],
|
||||||
|
)
|
||||||
|
@ -6,12 +6,14 @@ from . import portfolios_bp
|
|||||||
from atst.domain.reports import Reports
|
from atst.domain.reports import Reports
|
||||||
from atst.domain.portfolios import Portfolios
|
from atst.domain.portfolios import Portfolios
|
||||||
from atst.domain.portfolio_roles import PortfolioRoles
|
from atst.domain.portfolio_roles import PortfolioRoles
|
||||||
|
from atst.domain.permission_sets import PermissionSets
|
||||||
|
from atst.domain.users import Users
|
||||||
from atst.domain.audit_log import AuditLog
|
from atst.domain.audit_log import AuditLog
|
||||||
from atst.domain.common import Paginator
|
from atst.domain.common import Paginator
|
||||||
|
from atst.domain.exceptions import NotFoundError
|
||||||
from atst.forms.portfolio import PortfolioForm
|
from atst.forms.portfolio import PortfolioForm
|
||||||
import atst.forms.portfolio_member as member_forms
|
import atst.forms.portfolio_member as member_forms
|
||||||
from atst.models.permissions import Permissions
|
from atst.models.permissions import Permissions
|
||||||
from atst.domain.permission_sets import PermissionSets
|
|
||||||
from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
from atst.domain.authz.decorator import user_can_access_decorator as user_can
|
||||||
from atst.utils.flash import formatted_flash as flash
|
from atst.utils.flash import formatted_flash as flash
|
||||||
from atst.domain.exceptions import UnauthorizedError
|
from atst.domain.exceptions import UnauthorizedError
|
||||||
@ -70,12 +72,19 @@ def render_admin_page(portfolio, form=None):
|
|||||||
member_perms_form = member_forms.MembersPermissionsForm(
|
member_perms_form = member_forms.MembersPermissionsForm(
|
||||||
data={"members_permissions": members_data}
|
data={"members_permissions": members_data}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assign_ppoc_form = member_forms.AssignPPOCForm()
|
||||||
|
assign_ppoc_form.user_id.choices += [
|
||||||
|
(user.id, user.full_name) for user in portfolio.users
|
||||||
|
]
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"portfolios/admin.html",
|
"portfolios/admin.html",
|
||||||
form=form,
|
form=form,
|
||||||
portfolio_form=portfolio_form,
|
portfolio_form=portfolio_form,
|
||||||
member_perms_form=member_perms_form,
|
member_perms_form=member_perms_form,
|
||||||
member_form=member_forms.NewForm(),
|
member_form=member_forms.NewForm(),
|
||||||
|
assign_ppoc_form=assign_ppoc_form,
|
||||||
portfolio=portfolio,
|
portfolio=portfolio,
|
||||||
audit_events=audit_events,
|
audit_events=audit_events,
|
||||||
user=g.current_user,
|
user=g.current_user,
|
||||||
@ -117,6 +126,32 @@ def edit_portfolio_members(portfolio_id):
|
|||||||
return render_admin_page(portfolio)
|
return render_admin_page(portfolio)
|
||||||
|
|
||||||
|
|
||||||
|
@portfolios_bp.route("/portfolios/<portfolio_id>/update_ppoc", methods=["POST"])
|
||||||
|
@user_can(Permissions.EDIT_PORTFOLIO_POC, message="update portfolio ppoc")
|
||||||
|
def update_ppoc(portfolio_id):
|
||||||
|
user_id = http_request.form.get("user_id")
|
||||||
|
|
||||||
|
portfolio = Portfolios.get(g.current_user, portfolio_id)
|
||||||
|
new_ppoc = Users.get(user_id)
|
||||||
|
|
||||||
|
if new_ppoc not in portfolio.users:
|
||||||
|
raise NotFoundError("user not in portfolio")
|
||||||
|
|
||||||
|
portfolio_role = PortfolioRoles.get(portfolio_id=portfolio_id, user_id=user_id)
|
||||||
|
PortfolioRoles.make_ppoc(portfolio_role=portfolio_role)
|
||||||
|
|
||||||
|
flash("primary_point_of_contact_changed", ppoc_name=new_ppoc.full_name)
|
||||||
|
|
||||||
|
return redirect(
|
||||||
|
url_for(
|
||||||
|
"portfolios.portfolio_admin",
|
||||||
|
portfolio_id=portfolio.id,
|
||||||
|
fragment="primary-point-of-contact",
|
||||||
|
_anchor="primary-point-of-contact",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@portfolios_bp.route("/portfolios/<portfolio_id>/edit", methods=["POST"])
|
@portfolios_bp.route("/portfolios/<portfolio_id>/edit", methods=["POST"])
|
||||||
@user_can(Permissions.EDIT_PORTFOLIO_NAME, message="edit portfolio")
|
@user_can(Permissions.EDIT_PORTFOLIO_NAME, message="edit portfolio")
|
||||||
def edit_portfolio(portfolio_id):
|
def edit_portfolio(portfolio_id):
|
||||||
|
@ -2,6 +2,11 @@ from flask import flash, render_template_string
|
|||||||
from atst.utils.localization import translate
|
from atst.utils.localization import translate
|
||||||
|
|
||||||
MESSAGES = {
|
MESSAGES = {
|
||||||
|
"primary_point_of_contact_changed": {
|
||||||
|
"title_template": "Primary Point of Contact Changed",
|
||||||
|
"message_template": "You have successfully added {{ ppoc_name }} as Point of Contact. You are no longer the PoC.",
|
||||||
|
"category": "success",
|
||||||
|
},
|
||||||
"invitation_resent": {
|
"invitation_resent": {
|
||||||
"title_template": "Invitation resent",
|
"title_template": "Invitation resent",
|
||||||
"message_template": "The {{ officer_type }} has been resent instructions to join this portfolio.",
|
"message_template": "The {{ officer_type }} has been resent instructions to join this portfolio.",
|
||||||
|
@ -25,13 +25,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro MultiStepModalForm(name, form, form_action, steps, button_text="", dismissable=False) -%}
|
{% macro MultiStepModalForm(name, form, form_action, steps, button_icon="", button_text="", link_classes="icon-link modal-link", dismissable=False) -%}
|
||||||
{% set step_count = steps|length %}
|
{% set step_count = steps|length %}
|
||||||
<multi-step-modal-form inline-template :steps={{ step_count }}>
|
<multi-step-modal-form inline-template :steps={{ step_count }}>
|
||||||
<div>
|
<div>
|
||||||
<a class='icon-link modal-link' v-on:click="openModal('{{ name }}')">
|
<a class='{{ link_classes }}' v-on:click="openModal('{{ name }}')">
|
||||||
{{ button_text }}
|
{{ button_text }}
|
||||||
{{ Icon('plus-circle-solid') }}
|
|
||||||
|
{% if button_icon != "" %}
|
||||||
|
{{ Icon(button_icon) }}
|
||||||
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% call Modal(name=name, dismissable=dismissable, classes="wide") %}
|
{% call Modal(name=name, dismissable=dismissable, classes="wide") %}
|
||||||
<form id="{{ name }}" action="{{ form_action }}" method="POST" v-on:submit="handleSubmit">
|
<form id="{{ name }}" action="{{ form_action }}" method="POST" v-on:submit="handleSubmit">
|
||||||
|
@ -80,5 +80,6 @@
|
|||||||
member_form,
|
member_form,
|
||||||
url_for("portfolios.create_member", portfolio_id=portfolio.id),
|
url_for("portfolios.create_member", portfolio_id=portfolio.id),
|
||||||
[step_one, step_two],
|
[step_one, step_two],
|
||||||
button_text="portfolios.admin.add_new_member" | translate)
|
button_text=("portfolios.admin.add_new_member" | translate),
|
||||||
}}
|
button_icon="plus-circle-solid",
|
||||||
|
) }}
|
||||||
|
82
templates/fragments/admin/change_ppoc.html
Normal file
82
templates/fragments/admin/change_ppoc.html
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
{% from "components/icon.html" import Icon %}
|
||||||
|
{% from "components/selector.html" import Selector %}
|
||||||
|
{% from "components/text_input.html" import TextInput %}
|
||||||
|
{% from "components/multi_step_modal_form.html" import MultiStepModalForm %}
|
||||||
|
{% from "components/alert.html" import Alert %}
|
||||||
|
{% from "components/options_input.html" import OptionsInput %}
|
||||||
|
|
||||||
|
{% set step_one %}
|
||||||
|
<div class="modal__form--header">
|
||||||
|
<h1>{{ "fragments.ppoc.update_ppoc_title" | translate }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{
|
||||||
|
Alert(
|
||||||
|
level="warning",
|
||||||
|
title=("fragments.ppoc.alert.title" | translate),
|
||||||
|
message=("fragments.ppoc.alert.message" | translate),
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
<div class='form-row'>
|
||||||
|
<div class='form-col form-col--half'>
|
||||||
|
{{
|
||||||
|
OptionsInput(
|
||||||
|
assign_ppoc_form.user_id
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class='form-col form-col--half'>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='action-group'>
|
||||||
|
<input
|
||||||
|
type='button'
|
||||||
|
v-on:click="next()"
|
||||||
|
v-bind:disabled="invalid"
|
||||||
|
class='action-group__action usa-button'
|
||||||
|
value='{{ "fragments.ppoc.assign_user_button_text" | translate }}'>
|
||||||
|
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('change-ppoc-form')">
|
||||||
|
{{ "common.cancel" | translate }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endset %}
|
||||||
|
|
||||||
|
{% set step_two %}
|
||||||
|
<div class="modal__form--padded">
|
||||||
|
<div class="modal__form--header">
|
||||||
|
<h1>{{ "fragments.ppoc.update_ppoc_confirmation_title" | translate }}</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{
|
||||||
|
Alert(
|
||||||
|
level="info",
|
||||||
|
title=("fragments.ppoc.confirm_alert.title" | translate),
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
|
||||||
|
<div class='action-group'>
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
class='action-group__action usa-button'
|
||||||
|
form="change-ppoc-form"
|
||||||
|
value='{{ "common.confirm" | translate }}'>
|
||||||
|
<a class='action-group__action icon-link icon-link--default' v-on:click="closeModal('change-ppoc-form')">
|
||||||
|
{{ "common.cancel" | translate }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endset %}
|
||||||
|
|
||||||
|
<div class="flex-reverse-row">
|
||||||
|
{{
|
||||||
|
MultiStepModalForm(
|
||||||
|
'change-ppoc-form',
|
||||||
|
assign_ppoc_form,
|
||||||
|
form_action=url_for("portfolios.update_ppoc", portfolio_id=portfolio.id),
|
||||||
|
steps=[step_one, step_two],
|
||||||
|
button_text=("fragments.ppoc.update_btn" | translate),
|
||||||
|
link_classes="usa-button-primary"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</div>
|
@ -1,5 +1,9 @@
|
|||||||
<div class="panel">
|
<section id="primary-point-of-contact" class="panel">
|
||||||
<div class="panel__content">
|
<div class="panel__content">
|
||||||
|
{% if g.matchesPath("primary-point-of-contact") %}
|
||||||
|
{% include "fragments/flash.html" %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<h2>{{ "fragments.ppoc.title" | translate }}</h2>
|
<h2>{{ "fragments.ppoc.title" | translate }}</h2>
|
||||||
<p>{{ "fragments.ppoc.subtitle" | translate }}</p>
|
<p>{{ "fragments.ppoc.subtitle" | translate }}</p>
|
||||||
|
|
||||||
@ -15,11 +19,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
{% if user_can(permissions.EDIT_PORTFOLIO_POC) %}
|
{% if user_can(permissions.EDIT_PORTFOLIO_POC) %}
|
||||||
<div class="flex-reverse-row">
|
{% include "fragments/admin/change_ppoc.html" %}
|
||||||
<a class="usa-button-primary">
|
|
||||||
{{ "fragments.ppoc.update_btn" | translate }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
from atst.domain.permission_sets import PermissionSets
|
||||||
from atst.domain.portfolio_roles import PortfolioRoles
|
from atst.domain.portfolio_roles import PortfolioRoles
|
||||||
from atst.domain.users import Users
|
from atst.domain.users import Users
|
||||||
|
from atst.models.permissions import Permissions
|
||||||
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
||||||
from atst.domain.permission_sets import PermissionSets
|
|
||||||
|
|
||||||
from tests.factories import (
|
from tests.factories import (
|
||||||
PortfolioFactory,
|
PortfolioFactory,
|
||||||
@ -37,3 +38,34 @@ def test_disable_portfolio_role():
|
|||||||
|
|
||||||
PortfolioRoles.disable(portfolio_role=portfolio_role)
|
PortfolioRoles.disable(portfolio_role=portfolio_role)
|
||||||
assert portfolio_role.status == PortfolioRoleStatus.DISABLED
|
assert portfolio_role.status == PortfolioRoleStatus.DISABLED
|
||||||
|
|
||||||
|
|
||||||
|
def test_revoke_ppoc_permissions():
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
portfolio_role = PortfolioRoles.get(
|
||||||
|
portfolio_id=portfolio.id, user_id=portfolio.owner.id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert Permissions.EDIT_PORTFOLIO_POC in portfolio_role.permissions
|
||||||
|
|
||||||
|
PortfolioRoles.revoke_ppoc_permissions(portfolio_role=portfolio_role)
|
||||||
|
assert Permissions.EDIT_PORTFOLIO_POC not in portfolio_role.permissions
|
||||||
|
|
||||||
|
|
||||||
|
def test_make_ppoc():
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
original_owner = portfolio.owner
|
||||||
|
new_owner = UserFactory.create()
|
||||||
|
|
||||||
|
new_owner_role = PortfolioRoles.add(user=new_owner, portfolio_id=portfolio.id)
|
||||||
|
|
||||||
|
PortfolioRoles.make_ppoc(portfolio_role=new_owner_role)
|
||||||
|
|
||||||
|
assert portfolio.owner is new_owner
|
||||||
|
assert Permissions.EDIT_PORTFOLIO_POC in new_owner_role.permissions
|
||||||
|
assert (
|
||||||
|
Permissions.EDIT_PORTFOLIO_POC
|
||||||
|
not in PortfolioRoles.get(
|
||||||
|
portfolio_id=portfolio.id, user_id=original_owner.id
|
||||||
|
).permissions
|
||||||
|
)
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
from flask import url_for
|
import pytest
|
||||||
|
|
||||||
|
from flask import url_for
|
||||||
from atst.domain.permission_sets import PermissionSets
|
from atst.domain.permission_sets import PermissionSets
|
||||||
|
from atst.domain.portfolios import Portfolios
|
||||||
from atst.models.permissions import Permissions
|
from atst.models.permissions import Permissions
|
||||||
from atst.domain.portfolio_roles import PortfolioRoles
|
from atst.domain.portfolio_roles import PortfolioRoles
|
||||||
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
||||||
|
from atst.domain.exceptions import UnauthorizedError
|
||||||
|
|
||||||
from tests.factories import (
|
from tests.factories import (
|
||||||
random_future_date,
|
random_future_date,
|
||||||
@ -28,6 +31,114 @@ def test_update_portfolio_name(client, user_session):
|
|||||||
assert portfolio.name == "a cool new name"
|
assert portfolio.name == "a cool new name"
|
||||||
|
|
||||||
|
|
||||||
|
def updating_ppoc_successfully(client, old_ppoc, new_ppoc, portfolio):
|
||||||
|
response = client.post(
|
||||||
|
url_for("portfolios.update_ppoc", portfolio_id=portfolio.id, _external=True),
|
||||||
|
data={"user_id": new_ppoc.id},
|
||||||
|
follow_redirects=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.headers["Location"] == url_for(
|
||||||
|
"portfolios.portfolio_admin",
|
||||||
|
portfolio_id=portfolio.id,
|
||||||
|
fragment="primary-point-of-contact",
|
||||||
|
_anchor="primary-point-of-contact",
|
||||||
|
_external=True,
|
||||||
|
)
|
||||||
|
assert portfolio.owner.id == new_ppoc.id
|
||||||
|
assert (
|
||||||
|
Permissions.EDIT_PORTFOLIO_POC
|
||||||
|
in PortfolioRoles.get(
|
||||||
|
portfolio_id=portfolio.id, user_id=new_ppoc.id
|
||||||
|
).permissions
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
Permissions.EDIT_PORTFOLIO_POC
|
||||||
|
not in PortfolioRoles.get(portfolio.id, old_ppoc.id).permissions
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_ppoc_no_user_id_specified(client, user_session):
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
|
||||||
|
user_session(portfolio.owner)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
url_for("portfolios.update_ppoc", portfolio_id=portfolio.id, _external=True),
|
||||||
|
follow_redirects=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_ppoc_to_member_not_on_portfolio(client, user_session):
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
original_ppoc = portfolio.owner
|
||||||
|
non_portfolio_member = UserFactory.create()
|
||||||
|
|
||||||
|
user_session(original_ppoc)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
url_for("portfolios.update_ppoc", portfolio_id=portfolio.id, _external=True),
|
||||||
|
data={"user_id": non_portfolio_member.id},
|
||||||
|
follow_redirects=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 404
|
||||||
|
assert portfolio.owner.id == original_ppoc.id
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_ppoc_when_ppoc(client, user_session):
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
original_ppoc = portfolio.owner
|
||||||
|
new_ppoc = UserFactory.create()
|
||||||
|
Portfolios.add_member(
|
||||||
|
member=new_ppoc,
|
||||||
|
portfolio=portfolio,
|
||||||
|
permission_sets=[PermissionSets.VIEW_PORTFOLIO],
|
||||||
|
)
|
||||||
|
|
||||||
|
user_session(original_ppoc)
|
||||||
|
|
||||||
|
updating_ppoc_successfully(
|
||||||
|
client=client, new_ppoc=new_ppoc, old_ppoc=original_ppoc, portfolio=portfolio
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_ppoc_when_cpo(client, user_session):
|
||||||
|
ccpo = UserFactory.create_ccpo()
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
original_ppoc = portfolio.owner
|
||||||
|
new_ppoc = UserFactory.create()
|
||||||
|
Portfolios.add_member(
|
||||||
|
member=new_ppoc,
|
||||||
|
portfolio=portfolio,
|
||||||
|
permission_sets=[PermissionSets.VIEW_PORTFOLIO],
|
||||||
|
)
|
||||||
|
|
||||||
|
user_session(ccpo)
|
||||||
|
|
||||||
|
updating_ppoc_successfully(
|
||||||
|
client=client, new_ppoc=new_ppoc, old_ppoc=original_ppoc, portfolio=portfolio
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_ppoc_when_not_ppoc(client, user_session):
|
||||||
|
portfolio = PortfolioFactory.create()
|
||||||
|
new_owner = UserFactory.create()
|
||||||
|
|
||||||
|
user_session(new_owner)
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
url_for("portfolios.update_ppoc", portfolio_id=portfolio.id, _external=True),
|
||||||
|
data={"dod_id": new_owner.dod_id},
|
||||||
|
follow_redirects=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 404
|
||||||
|
|
||||||
|
|
||||||
def test_portfolio_index_with_existing_portfolios(client, user_session):
|
def test_portfolio_index_with_existing_portfolios(client, user_session):
|
||||||
portfolio = PortfolioFactory.create()
|
portfolio = PortfolioFactory.create()
|
||||||
user_session(portfolio.owner)
|
user_session(portfolio.owner)
|
||||||
|
@ -28,6 +28,8 @@ flash:
|
|||||||
delete_member_success: You have successfully deleted {member_name} from the portfolio.
|
delete_member_success: You have successfully deleted {member_name} from the portfolio.
|
||||||
common:
|
common:
|
||||||
back: Back
|
back: Back
|
||||||
|
cancel: Cancel
|
||||||
|
confirm: Confirm
|
||||||
edit: Edit
|
edit: Edit
|
||||||
manage: manage
|
manage: manage
|
||||||
cancel: Cancel
|
cancel: Cancel
|
||||||
@ -61,6 +63,8 @@ footer:
|
|||||||
browser_support: JEDI Cloud supported on these web browsers
|
browser_support: JEDI Cloud supported on these web browsers
|
||||||
jedi_help_link_text: Questions? Contact your CCPO representative
|
jedi_help_link_text: Questions? Contact your CCPO representative
|
||||||
forms:
|
forms:
|
||||||
|
assign_ppoc:
|
||||||
|
dod_id: "Select new primary point of contact:"
|
||||||
ccpo_review:
|
ccpo_review:
|
||||||
comment_description: Provide instructions or notes for additional information that is necessary to approve the request here. The requestor may then re-submit the updated request or initiate contact outside of AT-AT if further discussion is required. <strong>This message will be shared with the person making the JEDI request.</strong>.
|
comment_description: Provide instructions or notes for additional information that is necessary to approve the request here. The requestor may then re-submit the updated request or initiate contact outside of AT-AT if further discussion is required. <strong>This message will be shared with the person making the JEDI request.</strong>.
|
||||||
comment_label: Instructions or comments
|
comment_label: Instructions or comments
|
||||||
@ -319,6 +323,14 @@ fragments:
|
|||||||
title: Primary point of contact (PPoC)
|
title: Primary point of contact (PPoC)
|
||||||
subtitle: The PPoC has the ability to edit all aspects of a portfolio and is the only one who can manage the PPoC role.
|
subtitle: The PPoC has the ability to edit all aspects of a portfolio and is the only one who can manage the PPoC role.
|
||||||
update_btn: Update
|
update_btn: Update
|
||||||
|
assign_user_button_text: Assign User
|
||||||
|
update_ppoc_confirmation_title: Confirmation
|
||||||
|
update_ppoc_title: Update Primary Point of Contact.
|
||||||
|
confirm_alert:
|
||||||
|
title: Once you assign a new point of contact, you will no longer be able to request portfolio deactivation or manage the point of contact role.
|
||||||
|
alert:
|
||||||
|
title: Warning!
|
||||||
|
message: Selecting a new primary contact gives that member full access to the portfolio and removes your PoC rights. Please be sure you want to proceed.
|
||||||
login:
|
login:
|
||||||
ccpo_logo_alt_text: Cloud Computing Program Office Logo
|
ccpo_logo_alt_text: Cloud Computing Program Office Logo
|
||||||
certificate_selection:
|
certificate_selection:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user