From 56c213285fe5ca78b8bfac4892b8d5f6a7e43381 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 7 Jan 2020 16:41:07 -0500 Subject: [PATCH] Add route to update portfolio manager perms, add modal form to update in the UI --- atst/routes/portfolios/admin.py | 36 +++++++++++-- atst/utils/flash.py | 12 +++++ .../fragments/portfolio_members.html | 30 +++++++++-- tests/routes/portfolios/test_admin.py | 51 +++++++++++++++++++ tests/routes/portfolios/test_invitations.py | 8 +-- tests/test_access.py | 18 +++++++ 6 files changed, 144 insertions(+), 11 deletions(-) diff --git a/atst/routes/portfolios/admin.py b/atst/routes/portfolios/admin.py index 699bdfab..921cd54a 100644 --- a/atst/routes/portfolios/admin.py +++ b/atst/routes/portfolios/admin.py @@ -19,9 +19,6 @@ from atst.domain.exceptions import UnauthorizedError def filter_perm_sets_data(member): perm_sets_data = { - "perms_portfolio_mgmt": bool( - member.has_permission_set(PermissionSets.EDIT_PORTFOLIO_ADMIN) - ), "perms_app_mgmt": bool( member.has_permission_set( PermissionSets.EDIT_PORTFOLIO_APPLICATION_MANAGEMENT @@ -33,6 +30,9 @@ def filter_perm_sets_data(member): "perms_reporting": bool( member.has_permission_set(PermissionSets.EDIT_PORTFOLIO_REPORTS) ), + "perms_portfolio_mgmt": bool( + member.has_permission_set(PermissionSets.EDIT_PORTFOLIO_ADMIN) + ), } return perm_sets_data @@ -41,6 +41,7 @@ def filter_perm_sets_data(member): def filter_members_data(members_list, portfolio): members_data = [] for member in members_list: + permission_sets = filter_perm_sets_data(member) members_data.append( { "role_id": member.id, @@ -48,7 +49,7 @@ def filter_members_data(members_list, portfolio): "permission_sets": filter_perm_sets_data(member), "status": member.display_status, "ppoc": PermissionSets.PORTFOLIO_POC in member.permission_sets, - # add in stuff here for forms + "form": member_forms.PermissionsForm(permission_sets), } ) @@ -166,3 +167,30 @@ def remove_member(portfolio_id, portfolio_role_id): fragment="portfolio-members", ) ) + + +@portfolios_bp.route( + "/portfolios//members/", methods=["POST"] +) +@user_can(Permissions.EDIT_PORTFOLIO_USERS, message="update portfolio members") +def update_member(portfolio_id, portfolio_role_id): + form_data = http_request.form + form = member_forms.PermissionsForm(formdata=form_data) + portfolio_role = PortfolioRoles.get_by_id(portfolio_role_id) + portfolio = Portfolios.get(user=g.current_user, portfolio_id=portfolio_id) + + if form.validate() and portfolio.owner_role != portfolio_role: + PortfolioRoles.update(portfolio_role, form.data["permission_sets"]) + flash("update_portfolio_member", member_name=portfolio_role.full_name) + + return redirect( + url_for( + "portfolios.admin", + portfolio_id=portfolio_id, + _anchor="portfolio-members", + fragment="portfolio-members", + ) + ) + else: + flash("update_portfolio_member_error", member_name=portfolio_role.full_name) + return (render_admin_page(portfolio), 400) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index da2c9253..3c9eacc1 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -153,6 +153,18 @@ MESSAGES = { "message": "flash.task_order.submitted.message", "category": "success", }, + "update_portfolio_member": { + "title_template": "Success!", + "message_template": """ + You have successfully updated access permissions for {{ member_name }}. + """, + "category": "success", + }, + "update_portfolio_member_error": { + "title_template": "Permissions for {{ member_name }} could not be updated", + "message_template": "An unexpected problem occurred with your request, please try again. If the problem persists, contact an administrator.", + "category": "error", + }, "updated_application_team_settings": { "title": "flash.success", "message": "flash.updated_application_team_settings", diff --git a/templates/portfolios/fragments/portfolio_members.html b/templates/portfolios/fragments/portfolio_members.html index 67a365cd..59bd5d8a 100644 --- a/templates/portfolios/fragments/portfolio_members.html +++ b/templates/portfolios/fragments/portfolio_members.html @@ -7,6 +7,29 @@ {% import "portfolios/fragments/member_form_fields.html" as member_form_fields %} {% from "components/toggle_menu.html" import ToggleMenu %} +{% if user_can(permissions.EDIT_PORTFOLIO_USERS) -%} + {% for member in members -%} + {% set modal_name = "edit_member-{}".format(loop.index) %} + {% call Modal(modal_name, classes="form-content--app-mem") %} + + + + + {% endcall %} + {%- endfor %} +{%- endif %} +

Portfolio Managers

@@ -20,6 +43,7 @@ {% for member in members -%} + {% set perms_modal = "edit_member-{}".format(loop.index) %} {{ member.user_name }}{% if member.role_id == current_member_id %} (You){% endif %} @@ -39,7 +63,7 @@ {%-endfor %} {% if user_can(permissions.EDIT_PORTFOLIO_USERS) -%} {% call ToggleMenu() %} - Edit Permissions + Edit Permissions Resend Invite Revoke Invite {% endcall %} @@ -68,13 +92,13 @@ form=member_form_fields.InfoFields(new_manager_form.user_data), next_button_text="Next: Permissions", previous=False, - modal=new_manager_modal_name, + modal=new_manager_modal, ), member_form.SubmitStep( name=new_manager_modal, form=member_form_fields.PermsFields(new_manager_form), submit_text="Add Mananger", - modal=new_manager_modal_name, + modal=new_manager_modal, ) ], ) }} diff --git a/tests/routes/portfolios/test_admin.py b/tests/routes/portfolios/test_admin.py index d20843a3..6adee9fc 100644 --- a/tests/routes/portfolios/test_admin.py +++ b/tests/routes/portfolios/test_admin.py @@ -222,3 +222,54 @@ def test_remove_portfolio_member_ppoc(client, user_session): PortfolioRoles.get(portfolio_id=portfolio.id, user_id=portfolio.owner.id).status == PortfolioRoleStatus.ACTIVE ) + + +def test_portfolios_update_member(client, user_session): + portfolio = PortfolioFactory.create() + portfolio_role = PortfolioRoleFactory.create( + portfolio=portfolio, + permission_sets=[PermissionSets.get(PermissionSets.EDIT_PORTFOLIO_ADMIN)], + ) + + form_data = { + "perms_app_mgmt": "y", + } + + user_session(portfolio.owner) + response = client.post( + url_for( + "portfolios.update_member", + portfolio_id=portfolio.id, + portfolio_role_id=portfolio_role.id, + ), + data=form_data, + follow_redirects=False, + ) + + assert response.status_code == 302 + assert portfolio_role.has_permission_set( + PermissionSets.EDIT_PORTFOLIO_APPLICATION_MANAGEMENT + ) + assert not portfolio_role.has_permission_set(PermissionSets.EDIT_PORTFOLIO_ADMIN) + + +def test_can_not_update_ppoc_permissions(client, user_session): + portfolio = PortfolioFactory.create() + owner = portfolio.owner + + form_data = { + "perms_app_mgmt": "y", + } + + user_session(owner) + response = client.post( + url_for( + "portfolios.update_member", + portfolio_id=portfolio.id, + portfolio_role_id=portfolio.owner_role.id, + ), + data=form_data, + follow_redirects=False, + ) + + assert response.status_code == 400 diff --git a/tests/routes/portfolios/test_invitations.py b/tests/routes/portfolios/test_invitations.py index 44c72460..a5ebbf6a 100644 --- a/tests/routes/portfolios/test_invitations.py +++ b/tests/routes/portfolios/test_invitations.py @@ -269,10 +269,10 @@ def test_existing_member_invite_resent_to_email_submitted_in_form( _DEFAULT_PERMS_FORM_DATA = { - "permission_sets-perms_app_mgmt": False, - "permission_sets-perms_funding": False, - "permission_sets-perms_reporting": False, - "permission_sets-perms_portfolio_mgmt": False, + "permission_sets-perms_app_mgmt": "n", + "permission_sets-perms_funding": "n", + "permission_sets-perms_reporting": "n", + "permission_sets-perms_portfolio_mgmt": "n", } diff --git a/tests/test_access.py b/tests/test_access.py index 8b26010c..375c5e7e 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -373,6 +373,24 @@ def test_portfolios_edit_access(post_url_assert_status): post_url_assert_status(rando, url, 404) +# portfolios.update_member +def test_portfolios_update_member_access(post_url_assert_status): + ccpo = user_with(PermissionSets.EDIT_PORTFOLIO_ADMIN) + owner = user_with() + rando = user_with() + portfolio = PortfolioFactory.create(owner=owner) + portfolio_role = PortfolioRoleFactory.create(portfolio=portfolio) + + url = url_for( + "portfolios.update_member", + portfolio_id=portfolio.id, + portfolio_role_id=portfolio_role.id, + ) + post_url_assert_status(ccpo, url, 302) + post_url_assert_status(owner, url, 302) + post_url_assert_status(rando, url, 404) + + # applications.new def test_applications_new_access(get_url_assert_status): ccpo = user_with(PermissionSets.EDIT_PORTFOLIO_APPLICATION_MANAGEMENT)