diff --git a/atst/domain/portfolio_roles.py b/atst/domain/portfolio_roles.py index e9e88574..8d885455 100644 --- a/atst/domain/portfolio_roles.py +++ b/atst/domain/portfolio_roles.py @@ -80,7 +80,7 @@ class PortfolioRoles(object): raise NotFoundError("portfolio role") @classmethod - def add(cls, user, portfolio_id, role_name): + def add(cls, user, portfolio_id, role_name, permission_sets=None): role = Roles.get(role_name) new_portfolio_role = None @@ -103,12 +103,31 @@ class PortfolioRoles(object): status=PortfolioRoleStatus.PENDING, ) + if permission_sets: + new_portfolio_role.permission_sets = PortfolioRoles._permission_sets_for_names( + permission_sets + ) + user.portfolio_roles.append(new_portfolio_role) db.session.add(user) db.session.commit() return new_portfolio_role + _DEFAULT_PORTFOLIO_PERMS_SETS = { + "view_portfolio_application_management", + "view_portfolio_funding", + "view_portfolio_reports", + "view_portfolio_admin", + } + + @classmethod + def _permission_sets_for_names(cls, set_names): + perms_set_names = PortfolioRoles._DEFAULT_PORTFOLIO_PERMS_SETS.union( + set(set_names) + ) + return [Roles.get(perms_set_name) for perms_set_name in perms_set_names] + @classmethod def update_role(cls, portfolio_role, role_name): new_role = Roles.get(role_name) diff --git a/atst/domain/portfolios/portfolios.py b/atst/domain/portfolios/portfolios.py index 2e5282e2..342e3b74 100644 --- a/atst/domain/portfolios/portfolios.py +++ b/atst/domain/portfolios/portfolios.py @@ -105,11 +105,16 @@ class Portfolios(object): atat_role_name="default", provisional=True, ) - return Portfolios.add_member(portfolio, new_user, data["portfolio_role"]) + permission_sets = data.get("permission_sets", []) + return Portfolios.add_member( + portfolio, new_user, data["portfolio_role"], permission_sets=permission_sets + ) @classmethod - def add_member(cls, portfolio, member, role_name): - portfolio_role = PortfolioRoles.add(member, portfolio.id, role_name) + def add_member(cls, portfolio, member, role_name, permission_sets=None): + portfolio_role = PortfolioRoles.add( + member, portfolio.id, role_name, permission_sets + ) return portfolio_role @classmethod diff --git a/atst/forms/new_member.py b/atst/forms/new_member.py index cdea0c56..88d6ec21 100644 --- a/atst/forms/new_member.py +++ b/atst/forms/new_member.py @@ -32,3 +32,42 @@ class NewMemberForm(BaseForm): default="", description=translate("forms.new_member.portfolio_role_description"), ) + + perms_app_mgmt = SelectField( + None, + choices=[ + ("view_portfolio_application_management", "View Only"), + ("edit_portfolio_application_management", "Edit Access"), + ], + ) + perms_funding = SelectField( + None, + choices=[ + ("view_portfolio_funding", "View Only"), + ("edit_portfolio_funding", "Edit Access"), + ], + ) + perms_reporting = SelectField( + None, + choices=[ + ("view_portfolio_reports", "View Only"), + ("edit_portfolio_reports", "Edit Access"), + ], + ) + perms_portfolio_mgmt = SelectField( + None, + choices=[ + ("view_portfolio_admin", "View Only"), + ("edit_portfolio_admin", "Edit Access"), + ], + ) + + @property + def data(self): + _data = super().data + _data["permission_sets"] = [] + for field in _data: + if "perms" in field: + _data["permission_sets"].append(_data[field]) + + return _data diff --git a/templates/portfolios/members/new.html b/templates/portfolios/members/new.html index 3603bd62..58f8cf67 100644 --- a/templates/portfolios/members/new.html +++ b/templates/portfolios/members/new.html @@ -23,10 +23,33 @@ {{ TextInput(form.email,placeholder='jane@mail.mil', validation='email') }} {{ TextInput(form.dod_id,placeholder='10-digit number on the back of the CAC', validation='dodId') }} {{ Selector(form.portfolio_role) }} + + + + + + + + + + + + + + + +
{{ "portfolios.members.permissions.app_mgmt" | translate }}{{ "portfolios.members.permissions.funding" | translate }}{{ "portfolios.members.permissions.reporting" | translate }}{{ "portfolios.members.permissions.portfolio_mgmt" | translate }}
+ {{ form.perms_app_mgmt() }} + + {{ form.perms_funding() }} + + {{ form.perms_reporting() }} + + {{ form.perms_portfolio_mgmt() }} +
-
diff --git a/tests/domain/test_portfolio_roles.py b/tests/domain/test_portfolio_roles.py index 6d28b82c..3f2d9af6 100644 --- a/tests/domain/test_portfolio_roles.py +++ b/tests/domain/test_portfolio_roles.py @@ -63,3 +63,22 @@ def test_portfolio_role_permissions(): PortfolioRoles.portfolio_role_permissions(portfolio_two, new_user) == default_perms ) + + +def test_add_portfolio_role_with_permission_sets(): + portfolio = PortfolioFactory.create() + new_user = UserFactory.create() + permission_sets = ["edit_portfolio_application_management"] + port_role = PortfolioRoles.add( + new_user, portfolio.id, "developer", permission_sets=permission_sets + ) + assert len(port_role.permission_sets) == 5 + expected_names = [ + "edit_portfolio_application_management", + "view_portfolio_application_management", + "view_portfolio_funding", + "view_portfolio_reports", + "view_portfolio_admin", + ] + actual_names = [prms.name for prms in port_role.permission_sets] + assert expected_names == expected_names diff --git a/tests/routes/portfolios/test_invitations.py b/tests/routes/portfolios/test_invitations.py index 4e382127..a4d89144 100644 --- a/tests/routes/portfolios/test_invitations.py +++ b/tests/routes/portfolios/test_invitations.py @@ -47,7 +47,14 @@ def test_new_member_accepts_valid_invite(monkeypatch, client, user_session): user_session(portfolio.owner) client.post( url_for("portfolios.create_member", portfolio_id=portfolio.id), - data={"portfolio_role": "developer", **user_info}, + data={ + "portfolio_role": "developer", + "perms_app_mgmt": "view_portfolio_application_management", + "perms_funding": "view_portfolio_funding", + "perms_reporting": "view_portfolio_reports", + "perms_portfolio_mgmt": "view_portfolio_admin", + **user_info, + }, ) user = Users.get_by_dod_id(user_info["dod_id"]) diff --git a/tests/routes/portfolios/test_members.py b/tests/routes/portfolios/test_members.py index 0deb6a06..6932c174 100644 --- a/tests/routes/portfolios/test_members.py +++ b/tests/routes/portfolios/test_members.py @@ -85,6 +85,10 @@ def test_create_member(client, user_session): "last_name": "Zuckerman", "email": "some_pig@zuckermans.com", "portfolio_role": "developer", + "perms_app_mgmt": "view_portfolio_application_management", + "perms_funding": "view_portfolio_funding", + "perms_reporting": "view_portfolio_reports", + "perms_portfolio_mgmt": "view_portfolio_admin", }, follow_redirects=True, ) @@ -94,6 +98,8 @@ def test_create_member(client, user_session): assert user.has_portfolios assert user.invitations assert len(queue.get_queue()) == queue_length + 1 + portfolio_role = user.portfolio_roles[0] + assert len(portfolio_role.permission_sets) == 4 def test_view_member_shows_role(client, user_session): diff --git a/translations.yaml b/translations.yaml index 535e8f82..28c6c951 100644 --- a/translations.yaml +++ b/translations.yaml @@ -558,6 +558,12 @@ portfolios: subheading: Team Management admin: activity_log_title: Activity Log + members: + permissions: + app_mgmt: App Mgmt + funding: Funding + reporting: Reporting + portfolio_mgmt: Portfolio Mgmt testing: example_string: Hello World example_with_variables: 'Hello, {name}!'