Merge pull request #721 from dod-ccpo/app-perms-bug
User can only update apps or revoke invites related to their portfolios
This commit is contained in:
commit
cd999f52ac
@ -5,21 +5,31 @@ from flask import g, current_app as app, request
|
||||
from . import user_can_access
|
||||
from atst.domain.portfolios import Portfolios
|
||||
from atst.domain.task_orders import TaskOrders
|
||||
from atst.domain.applications import Applications
|
||||
from atst.domain.invitations import Invitations
|
||||
from atst.domain.exceptions import UnauthorizedError
|
||||
|
||||
|
||||
def check_access(permission, message, exception, *args, **kwargs):
|
||||
access_args = {"message": message}
|
||||
|
||||
if "portfolio_id" in kwargs:
|
||||
if "application_id" in kwargs:
|
||||
application = Applications.get(kwargs["application_id"])
|
||||
access_args["portfolio"] = application.portfolio
|
||||
|
||||
elif "task_order_id" in kwargs:
|
||||
task_order = TaskOrders.get(kwargs["task_order_id"])
|
||||
access_args["portfolio"] = task_order.portfolio
|
||||
|
||||
elif "token" in kwargs:
|
||||
invite = Invitations._get(kwargs["token"])
|
||||
access_args["portfolio"] = invite.portfolio_role.portfolio
|
||||
|
||||
elif "portfolio_id" in kwargs:
|
||||
access_args["portfolio"] = Portfolios.get(
|
||||
g.current_user, kwargs["portfolio_id"]
|
||||
)
|
||||
|
||||
if "task_order_id" in kwargs:
|
||||
task_order = TaskOrders.get(kwargs["task_order_id"])
|
||||
access_args["portfolio"] = task_order.portfolio
|
||||
|
||||
if exception is not None and exception(g.current_user, **access_args, **kwargs):
|
||||
return True
|
||||
|
||||
|
@ -157,6 +157,54 @@ def test_user_without_permission_cannot_update_application(client, user_session)
|
||||
assert application.description == "Cool stuff happening here!"
|
||||
|
||||
|
||||
def test_user_can_only_access_apps_in_their_portfolio(client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
other_portfolio = PortfolioFactory.create(
|
||||
applications=[
|
||||
{
|
||||
"name": "Awesome Application",
|
||||
"description": "More cool stuff happening here!",
|
||||
"environments": [{"name": "dev"}],
|
||||
}
|
||||
]
|
||||
)
|
||||
other_application = other_portfolio.applications[0]
|
||||
user_session(portfolio.owner)
|
||||
|
||||
# user can't view application edit form
|
||||
response = client.get(
|
||||
url_for(
|
||||
"portfolios.edit_application",
|
||||
portfolio_id=portfolio.id,
|
||||
application_id=other_application.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
# user can't post update application form
|
||||
time_updated = other_application.time_updated
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.update_application",
|
||||
portfolio_id=portfolio.id,
|
||||
application_id=other_application.id,
|
||||
),
|
||||
data={"name": "New Name", "description": "A new description."},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert time_updated == other_application.time_updated
|
||||
|
||||
# user can't view application members
|
||||
response = client.get(
|
||||
url_for(
|
||||
"portfolios.application_members",
|
||||
portfolio_id=portfolio.id,
|
||||
application_id=other_application.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
def create_environment(user):
|
||||
portfolio = PortfolioFactory.create()
|
||||
portfolio_role = PortfolioRoleFactory.create(portfolio=portfolio, user=user)
|
||||
|
@ -169,6 +169,58 @@ def test_revoke_invitation(client, user_session):
|
||||
assert invite.is_revoked
|
||||
|
||||
|
||||
def test_user_can_only_revoke_invites_in_their_portfolio(client, user_session):
|
||||
portfolio = PortfolioFactory.create()
|
||||
other_portfolio = PortfolioFactory.create()
|
||||
user = UserFactory.create()
|
||||
portfolio_role = PortfolioRoleFactory.create(
|
||||
user=user, portfolio=other_portfolio, status=PortfolioRoleStatus.PENDING
|
||||
)
|
||||
invite = InvitationFactory.create(
|
||||
user_id=user.id,
|
||||
portfolio_role=portfolio_role,
|
||||
status=InvitationStatus.REJECTED_EXPIRED,
|
||||
expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1),
|
||||
)
|
||||
user_session(portfolio.owner)
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.revoke_invitation",
|
||||
portfolio_id=portfolio.id,
|
||||
token=invite.token,
|
||||
)
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
assert not invite.is_revoked
|
||||
|
||||
|
||||
def test_user_can_only_resend_invites_in_their_portfolio(client, user_session, queue):
|
||||
portfolio = PortfolioFactory.create()
|
||||
other_portfolio = PortfolioFactory.create()
|
||||
user = UserFactory.create()
|
||||
portfolio_role = PortfolioRoleFactory.create(
|
||||
user=user, portfolio=other_portfolio, status=PortfolioRoleStatus.PENDING
|
||||
)
|
||||
invite = InvitationFactory.create(
|
||||
user_id=user.id,
|
||||
portfolio_role=portfolio_role,
|
||||
status=InvitationStatus.REJECTED_EXPIRED,
|
||||
expiration_time=datetime.datetime.now() - datetime.timedelta(seconds=1),
|
||||
)
|
||||
user_session(portfolio.owner)
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.resend_invitation",
|
||||
portfolio_id=portfolio.id,
|
||||
token=invite.token,
|
||||
)
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
assert len(queue.get_queue()) == 0
|
||||
|
||||
|
||||
def test_resend_invitation_sends_email(client, user_session, queue):
|
||||
user = UserFactory.create()
|
||||
portfolio = PortfolioFactory.create()
|
||||
|
@ -128,6 +128,20 @@ class TestPortfolioFunding:
|
||||
assert context["funding_end_date"] is expiring_to.end_date
|
||||
assert context["funded"] == False
|
||||
|
||||
def test_user_can_only_access_to_in_their_portfolio(
|
||||
self, app, user_session, portfolio
|
||||
):
|
||||
other_task_order = TaskOrderFactory.create()
|
||||
user_session(portfolio.owner)
|
||||
response = app.test_client().get(
|
||||
url_for(
|
||||
"portfolios.view_task_order",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
class TestTaskOrderInvitations:
|
||||
def setup(self):
|
||||
@ -227,6 +241,54 @@ class TestTaskOrderInvitations:
|
||||
assert len(queue.get_queue()) == queue_length
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_user_can_only_invite_to_task_order_in_their_portfolio(
|
||||
self, user_session, client, portfolio
|
||||
):
|
||||
other_task_order = TaskOrderFactory.create()
|
||||
user_session(portfolio.owner)
|
||||
|
||||
# user can't see invites
|
||||
response = client.get(
|
||||
url_for(
|
||||
"portfolios.task_order_invitations",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
# user can't send invites
|
||||
time_updated = other_task_order.time_updated
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.edit_task_order_invitations",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
),
|
||||
data={
|
||||
"contracting_officer-first_name": "Luke",
|
||||
"contracting_officer-last_name": "Skywalker",
|
||||
"contracting_officer-dod_id": "0123456789",
|
||||
"contracting_officer-email": "luke@skywalker.mil",
|
||||
"contracting_officer-phone_number": "0123456789",
|
||||
"contracting_officer-invite": "y",
|
||||
},
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert time_updated == other_task_order.time_updated
|
||||
|
||||
# user can't resend invites
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.resend_invite",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
invite_type="ko_invite",
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert time_updated == other_task_order.time_updated
|
||||
|
||||
|
||||
def test_ko_can_view_task_order(client, user_session, portfolio, user):
|
||||
PortfolioRoleFactory.create(
|
||||
@ -464,6 +526,57 @@ def test_submit_completed_ko_review_page_as_ko(
|
||||
assert task_order.loas == loa_list
|
||||
|
||||
|
||||
def test_ko_can_only_access_their_to(app, user_session, client, portfolio, pdf_upload):
|
||||
ko = UserFactory.create()
|
||||
|
||||
PortfolioRoleFactory.create(
|
||||
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)
|
||||
dd_254 = DD254Factory.create()
|
||||
TaskOrders.add_dd_254(task_order, dd_254.to_dictionary())
|
||||
other_task_order = TaskOrderFactory.create()
|
||||
user_session(ko)
|
||||
|
||||
# KO can't see TO
|
||||
response = client.get(
|
||||
url_for(
|
||||
"portfolios.ko_review",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
# KO can't submit review for TO
|
||||
form_data = {
|
||||
"start_date": "02/10/2019",
|
||||
"end_date": "03/10/2019",
|
||||
"number": "1938745981",
|
||||
"loas-0": "1231231231",
|
||||
"custom_clauses": "hi im a custom clause",
|
||||
"pdf": pdf_upload,
|
||||
}
|
||||
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.submit_ko_review",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
),
|
||||
data=form_data,
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert not TaskOrders.is_signed_by_ko(other_task_order)
|
||||
|
||||
|
||||
def test_so_review_page(app, client, user_session, portfolio):
|
||||
so = UserFactory.create()
|
||||
PortfolioRoleFactory.create(
|
||||
@ -541,6 +654,45 @@ def test_submit_so_review(app, client, user_session, portfolio):
|
||||
assert task_order.dd_254.certifying_official == dd_254_data["certifying_official"]
|
||||
|
||||
|
||||
def test_so_can_only_access_their_to(app, client, user_session, portfolio):
|
||||
so = UserFactory.create()
|
||||
PortfolioRoleFactory.create(
|
||||
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()
|
||||
other_task_order = TaskOrderFactory.create()
|
||||
user_session(so)
|
||||
|
||||
# SO can't view dd254
|
||||
response = client.get(
|
||||
url_for(
|
||||
"portfolios.so_review",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
# SO can't submit dd254
|
||||
response = client.post(
|
||||
url_for(
|
||||
"portfolios.submit_so_review",
|
||||
portfolio_id=portfolio.id,
|
||||
task_order_id=other_task_order.id,
|
||||
),
|
||||
data=dd_254_data,
|
||||
)
|
||||
assert response.status_code == 404
|
||||
assert not other_task_order.dd_254
|
||||
|
||||
|
||||
def test_resend_invite_when_invalid_invite_officer(
|
||||
app, client, user_session, portfolio, user
|
||||
):
|
||||
|
Loading…
x
Reference in New Issue
Block a user