Merge pull request #701 from dod-ccpo/portfolio-perms

Portfolio perms
This commit is contained in:
dandds
2019-03-18 08:40:35 -04:00
committed by GitHub
60 changed files with 940 additions and 738 deletions

View File

@@ -12,7 +12,7 @@ from tests.factories import (
from atst.domain.applications import Applications
from atst.domain.portfolios import Portfolios
from atst.domain.roles import Roles
from atst.domain.permission_sets import PermissionSets
from atst.models.portfolio_role import Status as PortfolioRoleStatus
@@ -29,7 +29,7 @@ def test_user_without_permission_has_no_budget_report_link(client, user_session)
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(
user, portfolio, "developer", status=PortfolioRoleStatus.ACTIVE
user, portfolio, status=PortfolioRoleStatus.ACTIVE
)
user_session(user)
response = client.get("/portfolios/{}/applications".format(portfolio.id))
@@ -45,10 +45,7 @@ def test_user_with_permission_has_activity_log_link(client, user_session):
ccpo = UserFactory.from_atat_role("ccpo")
admin = UserFactory.create()
PortfolioRoleFactory.create(
portfolio=portfolio,
user=admin,
role=Roles.get("admin"),
status=PortfolioRoleStatus.ACTIVE,
portfolio=portfolio, user=admin, status=PortfolioRoleStatus.ACTIVE
)
user_session(portfolio.owner)
@@ -103,7 +100,7 @@ def test_user_with_permission_has_add_application_link(client, user_session):
def test_user_without_permission_has_no_add_application_link(client, user_session):
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(user, portfolio, "developer")
Portfolios._create_portfolio_role(user, portfolio)
user_session(user)
response = client.get("/portfolios/{}/applications".format(portfolio.id))
assert (

View File

@@ -12,6 +12,7 @@ from atst.domain.portfolios import Portfolios
from atst.models.portfolio_role import Status as PortfolioRoleStatus
from atst.models.invitation import Status as InvitationStatus
from atst.domain.users import Users
from atst.domain.permission_sets import PermissionSets
def test_existing_member_accepts_valid_invite(client, user_session):
@@ -45,11 +46,18 @@ def test_new_member_accepts_valid_invite(monkeypatch, client, user_session):
user_info = UserFactory.dictionary()
user_session(portfolio.owner)
client.post(
response = client.post(
url_for("portfolios.create_member", portfolio_id=portfolio.id),
data={"portfolio_role": "developer", **user_info},
data={
"perms_app_mgmt": PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT,
"perms_funding": PermissionSets.VIEW_PORTFOLIO_FUNDING,
"perms_reporting": PermissionSets.VIEW_PORTFOLIO_REPORTS,
"perms_portfolio_mgmt": PermissionSets.VIEW_PORTFOLIO_ADMIN,
**user_info,
},
)
assert response.status_code == 302
user = Users.get_by_dod_id(user_info["dod_id"])
token = user.invitations[0].token
@@ -94,7 +102,7 @@ def test_user_who_has_not_accepted_portfolio_invite_cannot_view(client, user_ses
user_session(portfolio.owner)
response = client.post(
url_for("portfolios.create_member", portfolio_id=portfolio.id),
data={"portfolio_role": "developer", **user.to_dictionary()},
data=user.to_dictionary(),
)
# user tries to view portfolio before accepting invitation

View File

@@ -12,35 +12,48 @@ from atst.domain.portfolio_roles import PortfolioRoles
from atst.domain.applications import Applications
from atst.domain.environments import Environments
from atst.domain.environment_roles import EnvironmentRoles
from atst.domain.permission_sets import PermissionSets
from atst.queue import queue
from atst.models.portfolio_role import Status as PortfolioRoleStatus
from atst.models.invitation import Status as InvitationStatus
_DEFAULT_PERMS_FORM_DATA = {
"perms_app_mgmt": PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT,
"perms_funding": PermissionSets.VIEW_PORTFOLIO_FUNDING,
"perms_reporting": PermissionSets.VIEW_PORTFOLIO_REPORTS,
"perms_portfolio_mgmt": PermissionSets.VIEW_PORTFOLIO_ADMIN,
}
def create_portfolio_and_invite_user(
ws_role="developer",
ws_status=PortfolioRoleStatus.PENDING,
invite_status=InvitationStatus.PENDING,
):
portfolio = PortfolioFactory.create()
owner = UserFactory.create()
portfolio = PortfolioFactory.create(owner=owner)
if ws_role != "owner":
user = UserFactory.create()
member = PortfolioRoleFactory.create(
user=user, portfolio=portfolio, status=ws_status
)
InvitationFactory.create(
user=portfolio.owner,
inviter=portfolio.owner,
user=user,
portfolio_role=member,
email=member.user.email,
status=invite_status,
)
return portfolio
return (portfolio, member)
else:
return (portfolio, portfolio.members[0])
def test_user_with_permission_has_add_member_link(client, user_session):
portfolio = PortfolioFactory.create()
user_session(portfolio.owner)
response = client.get("/portfolios/{}/members".format(portfolio.id))
assert response.status_code == 200
assert (
'href="/portfolios/{}/members/new"'.format(portfolio.id).encode()
in response.data
@@ -50,7 +63,7 @@ def test_user_with_permission_has_add_member_link(client, user_session):
def test_user_without_permission_has_no_add_member_link(client, user_session):
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(user, portfolio, "developer")
Portfolios._create_portfolio_role(user, portfolio)
user_session(user)
response = client.get("/portfolios/{}/members".format(portfolio.id))
assert (
@@ -62,8 +75,8 @@ def test_user_without_permission_has_no_add_member_link(client, user_session):
def test_permissions_for_view_member(client, user_session):
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(user, portfolio, "developer")
member = PortfolioRoles.add(user, portfolio.id, "developer")
Portfolios._create_portfolio_role(user, portfolio)
member = PortfolioRoles.add(user, portfolio.id)
user_session(user)
response = client.get(
url_for("portfolios.view_member", portfolio_id=portfolio.id, member_id=user.id)
@@ -85,6 +98,7 @@ def test_create_member(client, user_session):
"last_name": "Zuckerman",
"email": "some_pig@zuckermans.com",
"portfolio_role": "developer",
**_DEFAULT_PERMS_FORM_DATA,
},
follow_redirects=True,
)
@@ -94,13 +108,16 @@ 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) == 5
@pytest.mark.skip(reason="permission set display not implemented")
def test_view_member_shows_role(client, user_session):
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(user, portfolio, "developer")
member = PortfolioRoles.add(user, portfolio.id, "developer")
Portfolios._create_portfolio_role(user, portfolio)
member = PortfolioRoles.add(user, portfolio.id)
user_session(portfolio.owner)
response = client.get(
url_for("portfolios.view_member", portfolio_id=portfolio.id, member_id=user.id)
@@ -112,25 +129,29 @@ def test_view_member_shows_role(client, user_session):
def test_update_member_portfolio_role(client, user_session):
portfolio = PortfolioFactory.create()
user = UserFactory.create()
member = PortfolioRoles.add(user, portfolio.id, "developer")
member = PortfolioRoles.add(user, portfolio.id)
user_session(portfolio.owner)
response = client.post(
url_for(
"portfolios.update_member", portfolio_id=portfolio.id, member_id=user.id
),
data={"portfolio_role": "security_auditor"},
data={
**_DEFAULT_PERMS_FORM_DATA,
"perms_funding": PermissionSets.EDIT_PORTFOLIO_FUNDING,
},
follow_redirects=True,
)
assert response.status_code == 200
assert b"role updated successfully" in response.data
assert member.role_name == "security_auditor"
edit_funding = PermissionSets.get(PermissionSets.EDIT_PORTFOLIO_FUNDING)
assert edit_funding in member.permission_sets
def test_update_member_portfolio_role_with_no_data(client, user_session):
portfolio = PortfolioFactory.create()
user = UserFactory.create()
member = PortfolioRoles.add(user, portfolio.id, "developer")
member = PortfolioRoles.add(user, portfolio.id)
user_session(portfolio.owner)
original_perms_len = len(member.permission_sets)
response = client.post(
url_for(
"portfolios.update_member", portfolio_id=portfolio.id, member_id=user.id
@@ -139,13 +160,13 @@ def test_update_member_portfolio_role_with_no_data(client, user_session):
follow_redirects=True,
)
assert response.status_code == 200
assert member.role_name == "developer"
assert len(member.permission_sets) == original_perms_len
def test_update_member_environment_role(client, user_session):
portfolio = PortfolioFactory.create()
user = UserFactory.create()
member = PortfolioRoles.add(user, portfolio.id, "developer")
member = PortfolioRoles.add(user, portfolio.id)
application = Applications.create(
portfolio.owner,
portfolio,
@@ -163,9 +184,9 @@ def test_update_member_environment_role(client, user_session):
"portfolios.update_member", portfolio_id=portfolio.id, member_id=user.id
),
data={
"portfolio_role": "developer",
"env_" + str(env1_id): "security_auditor",
"env_" + str(env2_id): "devops",
**_DEFAULT_PERMS_FORM_DATA,
},
follow_redirects=True,
)
@@ -179,7 +200,7 @@ def test_update_member_environment_role(client, user_session):
def test_update_member_environment_role_with_no_data(client, user_session):
portfolio = PortfolioFactory.create()
user = UserFactory.create()
member = PortfolioRoles.add(user, portfolio.id, "developer")
member = PortfolioRoles.add(user, portfolio.id)
application = Applications.create(
portfolio.owner,
portfolio,
@@ -242,11 +263,10 @@ def test_does_not_show_any_buttons_if_owner(client, user_session):
def test_only_shows_revoke_access_button_if_active(client, user_session):
portfolio = create_portfolio_and_invite_user(
portfolio, member = create_portfolio_and_invite_user(
ws_status=PortfolioRoleStatus.ACTIVE, invite_status=InvitationStatus.ACCEPTED
)
user_session(portfolio.owner)
member = portfolio.members[1]
response = client.get(
url_for(
"portfolios.view_member",
@@ -254,17 +274,18 @@ def test_only_shows_revoke_access_button_if_active(client, user_session):
member_id=member.user.id,
)
)
assert response.status_code == 200
assert "Remove Portfolio Access" in response.data.decode()
assert "Revoke Invitation" not in response.data.decode()
assert "Resend Invitation" not in response.data.decode()
def test_only_shows_revoke_invite_button_if_pending(client, user_session):
portfolio = create_portfolio_and_invite_user(
portfolio, member = create_portfolio_and_invite_user(
ws_status=PortfolioRoleStatus.PENDING, invite_status=InvitationStatus.PENDING
)
user_session(portfolio.owner)
member = portfolio.members[1]
# member = next((memb for memb in portfolio.members if memb != portfolio.owner), None)
response = client.get(
url_for(
"portfolios.view_member",
@@ -278,12 +299,11 @@ def test_only_shows_revoke_invite_button_if_pending(client, user_session):
def test_only_shows_resend_button_if_expired(client, user_session):
portfolio = create_portfolio_and_invite_user(
portfolio, member = create_portfolio_and_invite_user(
ws_status=PortfolioRoleStatus.PENDING,
invite_status=InvitationStatus.REJECTED_EXPIRED,
)
user_session(portfolio.owner)
member = portfolio.members[1]
response = client.get(
url_for(
"portfolios.view_member",
@@ -297,11 +317,10 @@ def test_only_shows_resend_button_if_expired(client, user_session):
def test_only_shows_resend_button_if_revoked(client, user_session):
portfolio = create_portfolio_and_invite_user(
portfolio, member = create_portfolio_and_invite_user(
ws_status=PortfolioRoleStatus.PENDING, invite_status=InvitationStatus.REVOKED
)
user_session(portfolio.owner)
member = portfolio.members[1]
response = client.get(
url_for(
"portfolios.view_member",

View File

@@ -2,7 +2,7 @@ from flask import url_for
import pytest
from datetime import timedelta, date
from atst.domain.roles import Roles
from atst.domain.permission_sets import PermissionSets
from atst.domain.task_orders import TaskOrders
from atst.models.portfolio_role import Status as PortfolioStatus
from atst.models.invitation import Status as InvitationStatus
@@ -230,10 +230,13 @@ class TestTaskOrderInvitations:
def test_ko_can_view_task_order(client, user_session, portfolio, user):
PortfolioRoleFactory.create(
role=Roles.get("owner"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(portfolio=portfolio, contracting_officer=user)
user_session(user)
@@ -294,16 +297,22 @@ def test_ko_can_view_ko_review_page(client, user_session):
cor = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=ko,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=cor,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(
portfolio=portfolio,
@@ -365,10 +374,13 @@ def test_mo_redirected_to_build_page(client, user_session, portfolio):
def test_cor_redirected_to_build_page(client, user_session, portfolio):
cor = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=cor,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(
portfolio=portfolio, contracting_officer_representative=cor
@@ -384,10 +396,13 @@ def test_submit_completed_ko_review_page_as_cor(
client, user_session, pdf_upload, portfolio, user
):
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(
@@ -429,10 +444,13 @@ def test_submit_completed_ko_review_page_as_ko(
ko = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=ko,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(portfolio=portfolio, contracting_officer=ko)
@@ -470,10 +488,13 @@ def test_submit_completed_ko_review_page_as_ko(
def test_so_review_page(app, client, user_session, portfolio):
so = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=so,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(portfolio=portfolio, security_officer=so)
@@ -508,10 +529,13 @@ def test_so_review_page(app, client, user_session, portfolio):
def test_submit_so_review(app, client, user_session, portfolio):
so = UserFactory.create()
PortfolioRoleFactory.create(
role=Roles.get("officer"),
portfolio=portfolio,
user=so,
status=PortfolioStatus.ACTIVE,
permission_sets=[
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO),
PermissionSets.get(PermissionSets.VIEW_PORTFOLIO_FUNDING),
],
)
task_order = TaskOrderFactory.create(portfolio=portfolio, security_officer=so)
dd_254_data = DD254Factory.dictionary()
@@ -548,10 +572,7 @@ def test_resend_invite_when_invalid_invite_officer(
)
PortfolioRoleFactory.create(
role=Roles.get("owner"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
portfolio=portfolio, user=user, status=PortfolioStatus.ACTIVE
)
user_session(user)
@@ -580,10 +601,7 @@ def test_resend_invite_when_officer_type_missing(
)
PortfolioRoleFactory.create(
role=Roles.get("owner"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
portfolio=portfolio, user=user, status=PortfolioStatus.ACTIVE
)
user_session(user)
@@ -610,10 +628,7 @@ def test_resend_invite_when_ko(app, client, user_session, portfolio, user):
)
portfolio_role = PortfolioRoleFactory.create(
role=Roles.get("owner"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
portfolio=portfolio, user=user, status=PortfolioStatus.ACTIVE
)
original_invitation = Invitations.create(
@@ -654,10 +669,7 @@ def test_resend_invite_when_not_pending(app, client, user_session, portfolio, us
)
portfolio_role = PortfolioRoleFactory.create(
role=Roles.get("owner"),
portfolio=portfolio,
user=user,
status=PortfolioStatus.ACTIVE,
portfolio=portfolio, user=user, status=PortfolioStatus.ACTIVE
)
original_invitation = InvitationFactory.create(

View File

@@ -28,9 +28,6 @@ def test_invite_officers_to_task_order(client, user_session, queue):
# owner and three officers are portfolio members
assert len(portfolio.members) == 4
roles = [member.role.name for member in portfolio.members]
# officers exist in roles
assert roles.count("officer") == 3
# email invitations are enqueued
assert len(queue.get_queue()) == 3
# task order has relationship to user for each officer role

View File

@@ -340,3 +340,15 @@ def test_review_task_order_form(client, user_session, task_order):
)
assert response.status_code == 200
def test_update_task_order_clears_unnecessary_other_responses():
user = UserFactory.create()
to_data = TaskOrderFactory.dictionary()
to_data["complexity"] = ["storage"]
to_data["complexity_other"] = "something else"
to_data["dev_team"] = ["civilians"]
to_data["dev_team_other"] = "something else"
workflow = UpdateTaskOrderWorkflow(user, to_data)
assert workflow.task_order_form_data["complexity_other"] is None
assert workflow.task_order_form_data["dev_team_other"] is None

View File

@@ -33,7 +33,7 @@ def test_non_owner_user_with_one_portfolio_redirected_to_portfolio_applications(
user = UserFactory.create()
portfolio = PortfolioFactory.create()
Portfolios._create_portfolio_role(
user, portfolio, "developer", status=PortfolioRoleStatus.ACTIVE
user, portfolio, status=PortfolioRoleStatus.ACTIVE
)
user_session(user)
@@ -51,7 +51,7 @@ def test_non_owner_user_with_mulitple_portfolios_redirected_to_portfolios(
portfolio = PortfolioFactory.create()
portfolios.append(portfolio)
role = Portfolios._create_portfolio_role(
user, portfolio, "developer", status=PortfolioRoleStatus.ACTIVE
user, portfolio, status=PortfolioRoleStatus.ACTIVE
)
user_session(user)