Merge pull request #264 from dod-ccpo/view-pe-as-workspace-user
View projects and environments as a workspace user
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from atst.database import db
|
||||
from atst.models.environment import Environment
|
||||
from atst.models.environment_role import EnvironmentRole, CSPRole
|
||||
from atst.models.project import Project
|
||||
|
||||
|
||||
class Environments(object):
|
||||
@@ -19,11 +20,22 @@ class Environments(object):
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def add_member(cls, user, environment, member):
|
||||
def add_member(cls, user, environment, member, role=CSPRole.NONSENSE_ROLE):
|
||||
environment_user = EnvironmentRole(
|
||||
user=member, environment=environment, role=CSPRole.NONSENSE_ROLE.value
|
||||
user=member, environment=environment, role=role.value
|
||||
)
|
||||
db.session.add(environment_user)
|
||||
db.session.commit()
|
||||
|
||||
return environment
|
||||
|
||||
@classmethod
|
||||
def for_user(cls, user, project):
|
||||
return (
|
||||
db.session.query(Environment)
|
||||
.join(EnvironmentRole)
|
||||
.join(Project)
|
||||
.filter(EnvironmentRole.user_id == user.id)
|
||||
.filter(Project.id == Environment.project_id)
|
||||
.all()
|
||||
)
|
||||
|
@@ -4,14 +4,19 @@ from atst.domain.environments import Environments
|
||||
from atst.domain.exceptions import NotFoundError
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.models.project import Project
|
||||
from atst.models.environment import Environment
|
||||
from atst.models.environment_role import EnvironmentRole
|
||||
|
||||
|
||||
class Projects(object):
|
||||
@classmethod
|
||||
def create(cls, workspace, name, description, environment_names):
|
||||
def create(cls, user, workspace, name, description, environment_names):
|
||||
project = Project(workspace=workspace, name=name, description=description)
|
||||
Environments.create_many(project, environment_names)
|
||||
|
||||
for environment in project.environments:
|
||||
Environments.add_member(user, environment, user)
|
||||
|
||||
db.session.add(project)
|
||||
db.session.commit()
|
||||
|
||||
@@ -33,3 +38,14 @@ class Projects(object):
|
||||
raise NotFoundError("project")
|
||||
|
||||
return project
|
||||
|
||||
@classmethod
|
||||
def for_user(self, user, workspace):
|
||||
return (
|
||||
db.session.query(Project)
|
||||
.join(Environment)
|
||||
.join(EnvironmentRole)
|
||||
.filter(Project.workspace_id == workspace.id)
|
||||
.filter(EnvironmentRole.user_id == user.id)
|
||||
.all()
|
||||
)
|
||||
|
1
atst/domain/workspaces/__init__.py
Normal file
1
atst/domain/workspaces/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .workspaces import Workspaces
|
65
atst/domain/workspaces/scopes.py
Normal file
65
atst/domain/workspaces/scopes.py
Normal file
@@ -0,0 +1,65 @@
|
||||
from atst.domain.authz import Authorization
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.domain.projects import Projects
|
||||
from atst.domain.environments import Environments
|
||||
|
||||
|
||||
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 ScopedWorkspace(ScopedResource):
|
||||
"""
|
||||
An object that obeys the same API as a Workspace, but with the added
|
||||
functionality that it only returns sub-resources (projects and environments)
|
||||
that the given user is allowed to see.
|
||||
"""
|
||||
|
||||
@property
|
||||
def projects(self):
|
||||
can_view_all_projects = Authorization.has_workspace_permission(
|
||||
self.user, self.resource, Permissions.VIEW_APPLICATION_IN_WORKSPACE
|
||||
)
|
||||
|
||||
if can_view_all_projects:
|
||||
projects = self.resource.projects
|
||||
else:
|
||||
projects = Projects.for_user(self.user, self.resource)
|
||||
|
||||
return [ScopedProject(self.user, project) for project in projects]
|
||||
|
||||
|
||||
class ScopedProject(ScopedResource):
|
||||
"""
|
||||
An object that obeys the same API as a Workspace, but with the added
|
||||
functionality that it only returns sub-resources (environments)
|
||||
that the given user is allowed to see.
|
||||
"""
|
||||
|
||||
@property
|
||||
def environments(self):
|
||||
can_view_all_environments = Authorization.has_workspace_permission(
|
||||
self.user,
|
||||
self.resource.workspace,
|
||||
Permissions.VIEW_ENVIRONMENT_IN_APPLICATION,
|
||||
)
|
||||
|
||||
if can_view_all_environments:
|
||||
environments = self.resource.environments
|
||||
else:
|
||||
environments = Environments.for_user(self.user, self.resource)
|
||||
|
||||
return environments
|
@@ -9,6 +9,7 @@ from atst.domain.authz import Authorization
|
||||
from atst.models.permissions import Permissions
|
||||
from atst.domain.users import Users
|
||||
from atst.domain.workspace_users import WorkspaceUsers
|
||||
from .scopes import ScopedWorkspace
|
||||
|
||||
|
||||
class Workspaces(object):
|
||||
@@ -30,7 +31,7 @@ class Workspaces(object):
|
||||
user, workspace, Permissions.VIEW_WORKSPACE, "get workspace"
|
||||
)
|
||||
|
||||
return workspace
|
||||
return ScopedWorkspace(user, workspace)
|
||||
|
||||
@classmethod
|
||||
def get_for_update(cls, user, workspace_id):
|
||||
@@ -87,9 +88,11 @@ class Workspaces(object):
|
||||
last_name=data["last_name"],
|
||||
email=data["email"],
|
||||
)
|
||||
workspace_user = WorkspaceUsers.add(
|
||||
new_user, workspace.id, data["workspace_role"]
|
||||
)
|
||||
return Workspaces.add_member(workspace, new_user, data["workspace_role"])
|
||||
|
||||
@classmethod
|
||||
def add_member(cls, workspace, member, role_name):
|
||||
workspace_user = WorkspaceUsers.add(member, workspace.id, role_name)
|
||||
return workspace_user
|
||||
|
||||
@classmethod
|
@@ -22,7 +22,8 @@ class Workspace(Base, TimestampsMixin):
|
||||
def _is_workspace_owner(workspace_role):
|
||||
return workspace_role.role.name == "owner"
|
||||
|
||||
return first_or_none(_is_workspace_owner, self.roles)
|
||||
owner = first_or_none(_is_workspace_owner, self.roles)
|
||||
return owner.user if owner else None
|
||||
|
||||
@property
|
||||
def users(self):
|
||||
|
@@ -112,6 +112,7 @@ def create_project(workspace_id):
|
||||
if form.validate():
|
||||
project_data = form.data
|
||||
Projects.create(
|
||||
g.current_user,
|
||||
workspace,
|
||||
project_data["name"],
|
||||
project_data["description"],
|
||||
|
Reference in New Issue
Block a user