Update atst to atat

This commit is contained in:
leigh-mil
2020-02-28 16:01:45 -05:00
parent 6eb48239cf
commit c2814416fb
215 changed files with 735 additions and 746 deletions

View File

@@ -0,0 +1,6 @@
from .portfolios import (
Portfolios,
PortfolioError,
PortfolioDeletionApplicationsExistError,
PortfolioStateMachines,
)

View File

@@ -0,0 +1,172 @@
from sqlalchemy import or_
from typing import List
from uuid import UUID
from atat.database import db
from atat.domain.permission_sets import PermissionSets
from atat.domain.authz import Authorization
from atat.domain.portfolio_roles import PortfolioRoles
from atat.domain.invitations import PortfolioInvitations
from atat.models import (
Portfolio,
PortfolioStateMachine,
FSMStates,
Permissions,
PortfolioRole,
PortfolioRoleStatus,
TaskOrder,
CLIN,
)
from .query import PortfoliosQuery, PortfolioStateMachinesQuery
from .scopes import ScopedPortfolio
class PortfolioError(Exception):
pass
class PortfolioDeletionApplicationsExistError(Exception):
pass
class PortfolioStateMachines(object):
@classmethod
def create(cls, portfolio, **sm_attrs):
sm_attrs.update({"portfolio": portfolio})
sm = PortfolioStateMachinesQuery.create(**sm_attrs)
return sm
class Portfolios(object):
@classmethod
def get_or_create_state_machine(cls, portfolio):
"""
get or create Portfolio State Machine for a Portfolio
"""
return portfolio.state_machine or PortfolioStateMachines.create(portfolio)
@classmethod
def create(cls, user, portfolio_attrs):
portfolio = PortfoliosQuery.create(**portfolio_attrs)
perms_sets = PermissionSets.get_many(PortfolioRoles.PORTFOLIO_PERMISSION_SETS)
Portfolios._create_portfolio_role(
user,
portfolio,
status=PortfolioRoleStatus.ACTIVE,
permission_sets=perms_sets,
)
PortfoliosQuery.add_and_commit(portfolio)
return portfolio
@classmethod
def get(cls, user, portfolio_id):
portfolio = PortfoliosQuery.get(portfolio_id)
return ScopedPortfolio(user, portfolio)
@classmethod
def delete(cls, portfolio):
if len(portfolio.applications) != 0:
raise PortfolioDeletionApplicationsExistError()
for portfolio_role in portfolio.roles:
PortfolioRoles.disable(portfolio_role=portfolio_role, commit=False)
portfolio.deleted = True
db.session.add(portfolio)
db.session.commit()
return portfolio
@classmethod
def get_for_update(cls, portfolio_id):
portfolio = PortfoliosQuery.get(portfolio_id)
return portfolio
@classmethod
def for_user(cls, user):
if Authorization.has_atat_permission(user, Permissions.VIEW_PORTFOLIO):
portfolios = PortfoliosQuery.get_all()
else:
portfolios = PortfoliosQuery.get_for_user(user)
return portfolios
@classmethod
def add_member(cls, portfolio, member, permission_sets=None):
portfolio_role = PortfolioRoles.add(member, portfolio.id, permission_sets)
return portfolio_role
@classmethod
def invite(cls, portfolio, inviter, member_data):
permission_sets = PortfolioRoles._permission_sets_for_names(
member_data.get("permission_sets", [])
)
role = PortfolioRole(portfolio=portfolio, permission_sets=permission_sets)
invitation = PortfolioInvitations.create(
inviter=inviter, role=role, member_data=member_data["user_data"]
)
PortfoliosQuery.add_and_commit(role)
return invitation
@classmethod
def update_member(cls, member, permission_sets):
return PortfolioRoles.update(member, permission_sets)
@classmethod
def _create_portfolio_role(
cls, user, portfolio, status=PortfolioRoleStatus.PENDING, permission_sets=None
):
if permission_sets is None:
permission_sets = []
portfolio_role = PortfoliosQuery.create_portfolio_role(
user, portfolio, status=status, permission_sets=permission_sets
)
PortfoliosQuery.add_and_commit(portfolio_role)
return portfolio_role
@classmethod
def update(cls, portfolio, new_data):
if "name" in new_data:
portfolio.name = new_data["name"]
if "description" in new_data:
portfolio.description = new_data["description"]
PortfoliosQuery.add_and_commit(portfolio)
@classmethod
def base_provision_query(cls):
return db.session.query(Portfolio.id)
@classmethod
def get_portfolios_pending_provisioning(cls, now) -> List[UUID]:
"""
Any portfolio with a corresponding State Machine that is either:
not started yet,
failed in creating a tenant
failed
"""
results = (
db.session.query(Portfolio.id)
.join(PortfolioStateMachine)
.join(TaskOrder)
.join(CLIN)
.filter(Portfolio.deleted == False)
.filter(CLIN.start_date <= now)
.filter(CLIN.end_date > now)
.filter(
or_(
PortfolioStateMachine.state == FSMStates.UNSTARTED,
PortfolioStateMachine.state.like("%CREATED"),
)
)
)
return [id_ for id_, in results]

View File

@@ -0,0 +1,66 @@
from sqlalchemy import or_
from atat.database import db
from atat.domain.common import Query
from atat.models.portfolio import Portfolio
from atat.models.portfolio_role import PortfolioRole, Status as PortfolioRoleStatus
from atat.models.application_role import (
ApplicationRole,
Status as ApplicationRoleStatus,
)
from atat.models.application import Application
from atat.models.portfolio_state_machine import PortfolioStateMachine
# from atat.models.application import Application
class PortfolioStateMachinesQuery(Query):
model = PortfolioStateMachine
class PortfoliosQuery(Query):
model = Portfolio
@classmethod
def get_for_user(cls, user):
return (
db.session.query(Portfolio)
.filter(
or_(
Portfolio.id.in_(
db.session.query(Portfolio.id)
.join(Application)
.filter(Portfolio.id == Application.portfolio_id)
.filter(
Application.id.in_(
db.session.query(Application.id)
.join(ApplicationRole)
.filter(
ApplicationRole.application_id == Application.id
)
.filter(ApplicationRole.user_id == user.id)
.filter(
ApplicationRole.status
== ApplicationRoleStatus.ACTIVE
)
.filter(ApplicationRole.deleted == False)
.subquery()
)
)
),
Portfolio.id.in_(
db.session.query(Portfolio.id)
.join(PortfolioRole)
.filter(PortfolioRole.user == user)
.filter(PortfolioRole.status == PortfolioRoleStatus.ACTIVE)
.subquery()
),
)
)
.filter(Portfolio.deleted == False)
.order_by(Portfolio.name.asc())
.all()
)
@classmethod
def create_portfolio_role(cls, user, portfolio, **kwargs):
return PortfolioRole(user=user, portfolio=portfolio, **kwargs)

View File

@@ -0,0 +1,39 @@
from atat.domain.authz import Authorization
from atat.models.permissions import Permissions
from atat.domain.applications import Applications
class ScopedResource(object):
"""
An abstract class that represents a resource that is restricted
in some way by the priveleges of the user viewing that resource.
"""
def __init__(self, user, resource):
self.user = user
self.resource = resource
def __getattr__(self, name):
return getattr(self.resource, name)
def __eq__(self, other):
return self.resource == other
class ScopedPortfolio(ScopedResource):
"""
An object that obeys the same API as a Portfolio, but with the added
functionality that it only returns sub-resources (applications and environments)
that the given user is allowed to see.
"""
@property
def applications(self):
can_view_all_applications = Authorization.has_portfolio_permission(
self.user, self.resource, Permissions.VIEW_APPLICATION
)
if can_view_all_applications:
return self.resource.applications
else:
return Applications.for_user(self.user, self.resource)