This updates the `Portfolios.for_user` method to screen out deleted ApplicationRole entities. For extra assurance, we also mark application roles as disabled when they are deleted.
243 lines
7.5 KiB
Python
243 lines
7.5 KiB
Python
import pytest
|
|
from uuid import uuid4
|
|
|
|
from atst.domain.exceptions import NotFoundError, UnauthorizedError
|
|
from atst.domain.portfolios import (
|
|
Portfolios,
|
|
PortfolioError,
|
|
PortfolioDeletionApplicationsExistError,
|
|
)
|
|
from atst.domain.portfolio_roles import PortfolioRoles
|
|
from atst.domain.applications import Applications
|
|
from atst.domain.environments import Environments
|
|
from atst.domain.permission_sets import PermissionSets, PORTFOLIO_PERMISSION_SETS
|
|
from atst.models.application_role import Status as ApplicationRoleStatus
|
|
from atst.models.portfolio_role import Status as PortfolioRoleStatus
|
|
|
|
from tests.factories import (
|
|
ApplicationFactory,
|
|
ApplicationRoleFactory,
|
|
UserFactory,
|
|
PortfolioRoleFactory,
|
|
PortfolioFactory,
|
|
get_all_portfolio_permission_sets,
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def portfolio_owner():
|
|
return UserFactory.create()
|
|
|
|
|
|
@pytest.fixture(scope="function")
|
|
def portfolio(portfolio_owner):
|
|
portfolio = PortfolioFactory.create(owner=portfolio_owner)
|
|
return portfolio
|
|
|
|
|
|
def test_can_create_portfolio():
|
|
portfolio = PortfolioFactory.create(name="frugal-whale")
|
|
assert portfolio.name == "frugal-whale"
|
|
|
|
|
|
def test_get_nonexistent_portfolio_raises():
|
|
with pytest.raises(NotFoundError):
|
|
Portfolios.get(UserFactory.build(), uuid4())
|
|
|
|
|
|
def test_creating_portfolio_adds_owner(portfolio, portfolio_owner):
|
|
assert portfolio.roles[0].user == portfolio_owner
|
|
|
|
|
|
def test_portfolio_has_timestamps(portfolio):
|
|
assert portfolio.time_created == portfolio.time_updated
|
|
|
|
|
|
def test_update_portfolio_role_role(portfolio, portfolio_owner):
|
|
user_data = {
|
|
"first_name": "New",
|
|
"last_name": "User",
|
|
"email": "new.user@mail.com",
|
|
"portfolio_role": "developer",
|
|
"dod_id": "1234567890",
|
|
}
|
|
PortfolioRoleFactory._meta.sqlalchemy_session_persistence = "flush"
|
|
member = PortfolioRoleFactory.create(portfolio=portfolio)
|
|
permission_sets = [PermissionSets.EDIT_PORTFOLIO_FUNDING]
|
|
|
|
updated_member = Portfolios.update_member(member, permission_sets=permission_sets)
|
|
assert updated_member.portfolio == portfolio
|
|
|
|
|
|
def test_scoped_portfolio_for_admin_missing_view_apps_perms(portfolio_owner, portfolio):
|
|
Applications.create(
|
|
portfolio, "My Application 2", "My application 2", ["dev", "staging", "prod"]
|
|
)
|
|
restricted_admin = UserFactory.create()
|
|
PortfolioRoleFactory.create(
|
|
portfolio=portfolio,
|
|
user=restricted_admin,
|
|
permission_sets=[PermissionSets.get(PermissionSets.VIEW_PORTFOLIO)],
|
|
)
|
|
scoped_portfolio = Portfolios.get(restricted_admin, portfolio.id)
|
|
assert scoped_portfolio.id == portfolio.id
|
|
assert len(portfolio.applications) == 1
|
|
assert len(scoped_portfolio.applications) == 0
|
|
|
|
|
|
def test_scoped_portfolio_returns_all_applications_for_portfolio_admin(
|
|
portfolio, portfolio_owner
|
|
):
|
|
for _ in range(5):
|
|
Applications.create(
|
|
portfolio, "My Application", "My application", ["dev", "staging", "prod"]
|
|
)
|
|
|
|
admin = UserFactory.create()
|
|
perm_sets = get_all_portfolio_permission_sets()
|
|
PortfolioRoleFactory.create(
|
|
user=admin, portfolio=portfolio, permission_sets=perm_sets
|
|
)
|
|
scoped_portfolio = Portfolios.get(admin, portfolio.id)
|
|
|
|
assert len(scoped_portfolio.applications) == 5
|
|
assert len(scoped_portfolio.applications[0].environments) == 3
|
|
|
|
|
|
def test_scoped_portfolio_returns_all_applications_for_portfolio_owner(
|
|
portfolio, portfolio_owner
|
|
):
|
|
for _ in range(5):
|
|
Applications.create(
|
|
portfolio, "My Application", "My application", ["dev", "staging", "prod"]
|
|
)
|
|
|
|
scoped_portfolio = Portfolios.get(portfolio_owner, portfolio.id)
|
|
|
|
assert len(scoped_portfolio.applications) == 5
|
|
assert len(scoped_portfolio.applications[0].environments) == 3
|
|
|
|
|
|
def test_for_user_returns_portfolios_for_applications_user_invited_to():
|
|
bob = UserFactory.create()
|
|
portfolio = PortfolioFactory.create()
|
|
application = ApplicationFactory.create(portfolio=portfolio)
|
|
ApplicationRoleFactory.create(
|
|
application=application, user=bob, status=ApplicationRoleStatus.ACTIVE
|
|
)
|
|
|
|
assert portfolio in Portfolios.for_user(user=bob)
|
|
|
|
|
|
def test_for_user_returns_active_portfolios_for_user(portfolio, portfolio_owner):
|
|
bob = UserFactory.create()
|
|
PortfolioRoleFactory.create(
|
|
user=bob, portfolio=portfolio, status=PortfolioRoleStatus.ACTIVE
|
|
)
|
|
PortfolioFactory.create()
|
|
|
|
bobs_portfolios = Portfolios.for_user(bob)
|
|
|
|
assert len(bobs_portfolios) == 1
|
|
|
|
|
|
def test_for_user_does_not_return_inactive_portfolios(portfolio, portfolio_owner):
|
|
bob = UserFactory.create()
|
|
Portfolios.add_member(portfolio, bob)
|
|
PortfolioFactory.create()
|
|
bobs_portfolios = Portfolios.for_user(bob)
|
|
|
|
assert len(bobs_portfolios) == 0
|
|
|
|
|
|
def test_for_user_returns_all_portfolios_for_ccpo(portfolio, portfolio_owner):
|
|
sam = UserFactory.create_ccpo()
|
|
PortfolioFactory.create()
|
|
|
|
sams_portfolios = Portfolios.for_user(sam)
|
|
assert len(sams_portfolios) == 2
|
|
|
|
|
|
def test_can_create_portfolios_with_matching_names():
|
|
portfolio_name = "Great Portfolio"
|
|
PortfolioFactory.create(name=portfolio_name)
|
|
PortfolioFactory.create(name=portfolio_name)
|
|
|
|
|
|
def test_disabled_members_dont_show_up(session):
|
|
portfolio = PortfolioFactory.create()
|
|
PortfolioRoleFactory.create(portfolio=portfolio, status=PortfolioRoleStatus.ACTIVE)
|
|
PortfolioRoleFactory.create(
|
|
portfolio=portfolio, status=PortfolioRoleStatus.DISABLED
|
|
)
|
|
|
|
# should only return portfolio owner and ACTIVE member
|
|
assert len(portfolio.members) == 2
|
|
|
|
|
|
def test_does_not_count_disabled_members(session):
|
|
portfolio = PortfolioFactory.create()
|
|
PortfolioRoleFactory.create(portfolio=portfolio, status=PortfolioRoleStatus.ACTIVE)
|
|
PortfolioRoleFactory.create(portfolio=portfolio)
|
|
PortfolioRoleFactory.create(
|
|
portfolio=portfolio, status=PortfolioRoleStatus.DISABLED
|
|
)
|
|
|
|
assert portfolio.user_count == 3
|
|
|
|
|
|
def test_invite():
|
|
portfolio = PortfolioFactory.create()
|
|
inviter = UserFactory.create()
|
|
member_data = UserFactory.dictionary()
|
|
|
|
invitation = Portfolios.invite(portfolio, inviter, member_data)
|
|
|
|
assert invitation.role
|
|
assert invitation.role.portfolio == portfolio
|
|
assert invitation.role.user is None
|
|
assert invitation.dod_id == member_data["dod_id"]
|
|
|
|
|
|
def test_delete_success():
|
|
portfolio = PortfolioFactory.create()
|
|
|
|
assert not portfolio.deleted
|
|
|
|
Portfolios.delete(portfolio=portfolio)
|
|
|
|
assert portfolio.deleted
|
|
|
|
|
|
def test_delete_failure_with_applications():
|
|
portfolio = PortfolioFactory.create()
|
|
application = ApplicationFactory.create(portfolio=portfolio)
|
|
|
|
assert not portfolio.deleted
|
|
|
|
with pytest.raises(PortfolioDeletionApplicationsExistError):
|
|
Portfolios.delete(portfolio=portfolio)
|
|
|
|
assert not portfolio.deleted
|
|
|
|
|
|
def test_for_user_does_not_include_deleted_portfolios():
|
|
user = UserFactory.create()
|
|
PortfolioFactory.create(owner=user, deleted=True)
|
|
assert len(Portfolios.for_user(user)) == 0
|
|
|
|
|
|
def test_for_user_does_not_include_deleted_application_roles():
|
|
user1 = UserFactory.create()
|
|
user2 = UserFactory.create()
|
|
portfolio = PortfolioFactory.create()
|
|
app = ApplicationFactory.create(portfolio=portfolio)
|
|
ApplicationRoleFactory.create(
|
|
status=ApplicationRoleStatus.ACTIVE, user=user1, application=app
|
|
)
|
|
assert len(Portfolios.for_user(user1)) == 1
|
|
ApplicationRoleFactory.create(
|
|
status=ApplicationRoleStatus.ACTIVE, user=user2, application=app, deleted=True
|
|
)
|
|
assert len(Portfolios.for_user(user2)) == 0
|