diff --git a/atst/domain/projects.py b/atst/domain/applications.py
similarity index 53%
rename from atst/domain/projects.py
rename to atst/domain/applications.py
index 9b75976e..c96b4206 100644
--- a/atst/domain/projects.py
+++ b/atst/domain/applications.py
@@ -3,46 +3,50 @@ from atst.domain.authz import Authorization
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.application import Application
from atst.models.environment import Environment
from atst.models.environment_role import EnvironmentRole
-class Projects(object):
+class Applications(object):
@classmethod
def create(cls, user, workspace, name, description, environment_names):
- project = Project(workspace=workspace, name=name, description=description)
- db.session.add(project)
+ application = Application(
+ workspace=workspace, name=name, description=description
+ )
+ db.session.add(application)
- Environments.create_many(project, environment_names)
+ Environments.create_many(application, environment_names)
db.session.commit()
- return project
+ return application
@classmethod
- def get(cls, user, workspace, project_id):
- # TODO: this should check permission for this particular project
+ def get(cls, user, workspace, application_id):
+ # TODO: this should check permission for this particular application
Authorization.check_workspace_permission(
user,
workspace,
Permissions.VIEW_APPLICATION_IN_WORKSPACE,
- "view project in workspace",
+ "view application in workspace",
)
try:
- project = db.session.query(Project).filter_by(id=project_id).one()
+ application = (
+ db.session.query(Application).filter_by(id=application_id).one()
+ )
except NoResultFound:
- raise NotFoundError("project")
+ raise NotFoundError("application")
- return project
+ return application
@classmethod
def for_user(self, user, workspace):
return (
- db.session.query(Project)
+ db.session.query(Application)
.join(Environment)
.join(EnvironmentRole)
- .filter(Project.workspace_id == workspace.id)
+ .filter(Application.workspace_id == workspace.id)
.filter(EnvironmentRole.user_id == user.id)
.all()
)
@@ -53,26 +57,26 @@ class Projects(object):
user,
workspace,
Permissions.VIEW_APPLICATION_IN_WORKSPACE,
- "view project in workspace",
+ "view application in workspace",
)
try:
- projects = (
- db.session.query(Project).filter_by(workspace_id=workspace.id).all()
+ applications = (
+ db.session.query(Application).filter_by(workspace_id=workspace.id).all()
)
except NoResultFound:
- raise NotFoundError("projects")
+ raise NotFoundError("applications")
- return projects
+ return applications
@classmethod
- def update(cls, user, workspace, project, new_data):
+ def update(cls, user, workspace, application, new_data):
if "name" in new_data:
- project.name = new_data["name"]
+ application.name = new_data["name"]
if "description" in new_data:
- project.description = new_data["description"]
+ application.description = new_data["description"]
- db.session.add(project)
+ db.session.add(application)
db.session.commit()
- return project
+ return application
diff --git a/atst/domain/csp/reports.py b/atst/domain/csp/reports.py
index c052377b..e7a012e5 100644
--- a/atst/domain/csp/reports.py
+++ b/atst/domain/csp/reports.py
@@ -22,12 +22,12 @@ class MockEnvironment:
self.name = env_name
-class MockProject:
- def __init__(self, project_name, envs):
+class MockApplication:
+ def __init__(self, application_name, envs):
def make_env(name):
- return MockEnvironment("{}_{}".format(project_name, name), name)
+ return MockEnvironment("{}_{}".format(application_name, name), name)
- self.name = project_name
+ self.name = application_name
self.environments = [make_env(env_name) for env_name in envs]
@@ -161,13 +161,13 @@ class MockReportingProvider(ReportingInterface):
REPORT_FIXTURE_MAP = {
"Aardvark": {
"cumulative": CUMULATIVE_BUDGET_AARDVARK,
- "projects": [
- MockProject("LC04", ["Integ", "PreProd", "Prod"]),
- MockProject("SF18", ["Integ", "PreProd", "Prod"]),
- MockProject("Canton", ["Prod"]),
- MockProject("BD04", ["Integ", "PreProd"]),
- MockProject("SCV18", ["Dev"]),
- MockProject(
+ "applications": [
+ MockApplication("LC04", ["Integ", "PreProd", "Prod"]),
+ MockApplication("SF18", ["Integ", "PreProd", "Prod"]),
+ MockApplication("Canton", ["Prod"]),
+ MockApplication("BD04", ["Integ", "PreProd"]),
+ MockApplication("SCV18", ["Dev"]),
+ MockApplication(
"Crown",
[
"CR Portal Dev",
@@ -182,9 +182,9 @@ class MockReportingProvider(ReportingInterface):
},
"Beluga": {
"cumulative": CUMULATIVE_BUDGET_BELUGA,
- "projects": [
- MockProject("NP02", ["Integ", "PreProd", "NP02_Prod"]),
- MockProject("FM", ["Integ", "Prod"]),
+ "applications": [
+ MockApplication("NP02", ["Integ", "PreProd", "NP02_Prod"]),
+ MockApplication("FM", ["Integ", "Prod"]),
],
"budget": 70000,
},
@@ -194,8 +194,8 @@ class MockReportingProvider(ReportingInterface):
return sum(
[
spend
- for project in data
- for env in project.environments
+ for application in data
+ for env in application.environments
for spend in self.MONTHLY_SPEND_BY_ENVIRONMENT[env.id].values()
]
)
@@ -210,31 +210,31 @@ class MockReportingProvider(ReportingInterface):
def get_total_spending(self, workspace):
if workspace.name in self.REPORT_FIXTURE_MAP:
return self._sum_monthly_spend(
- self.REPORT_FIXTURE_MAP[workspace.name]["projects"]
+ self.REPORT_FIXTURE_MAP[workspace.name]["applications"]
)
return 0
- def _rollup_project_totals(self, data):
- project_totals = {}
- for project, environments in data.items():
- project_spend = [
+ def _rollup_application_totals(self, data):
+ application_totals = {}
+ for application, environments in data.items():
+ application_spend = [
(month, spend)
for env in environments.values()
if env
for month, spend in env.items()
]
- project_totals[project] = {
+ application_totals[application] = {
month: sum([spend[1] for spend in spends])
- for month, spends in groupby(sorted(project_spend), lambda x: x[0])
+ for month, spends in groupby(sorted(application_spend), lambda x: x[0])
}
- return project_totals
+ return application_totals
- def _rollup_workspace_totals(self, project_totals):
+ def _rollup_workspace_totals(self, application_totals):
monthly_spend = [
(month, spend)
- for project in project_totals.values()
- for month, spend in project.items()
+ for application in application_totals.values()
+ for month, spend in application.items()
]
workspace_totals = {}
for month, spends in groupby(sorted(monthly_spend), lambda m: m[0]):
@@ -254,39 +254,39 @@ class MockReportingProvider(ReportingInterface):
return self.MONTHLY_SPEND_BY_ENVIRONMENT.get(environment_id, {})
def monthly_totals(self, workspace):
- """Return month totals rolled up by environment, project, and workspace.
+ """Return month totals rolled up by environment, application, and workspace.
- Data should returned with three top level keys, "workspace", "projects",
+ Data should returned with three top level keys, "workspace", "applications",
and "environments".
- The "projects" key will have budget data per month for each project,
+ The "applications" key will have budget data per month for each application,
The "environments" key will have budget data for each environment.
The "workspace" key will be total monthly spending for the workspace.
For example:
{
"environments": { "X-Wing": { "Prod": { "01/2018": 75.42 } } },
- "projects": { "X-Wing": { "01/2018": 75.42 } },
+ "applications": { "X-Wing": { "01/2018": 75.42 } },
"workspace": { "01/2018": 75.42 },
}
"""
- projects = workspace.projects
+ applications = workspace.applications
if workspace.name in self.REPORT_FIXTURE_MAP:
- projects = self.REPORT_FIXTURE_MAP[workspace.name]["projects"]
+ applications = self.REPORT_FIXTURE_MAP[workspace.name]["applications"]
environments = {
- project.name: {
+ application.name: {
env.name: self.monthly_totals_for_environment(env.id)
- for env in project.environments
+ for env in application.environments
}
- for project in projects
+ for application in applications
}
- project_totals = self._rollup_project_totals(environments)
- workspace_totals = self._rollup_workspace_totals(project_totals)
+ application_totals = self._rollup_application_totals(environments)
+ workspace_totals = self._rollup_workspace_totals(application_totals)
return {
"environments": environments,
- "projects": project_totals,
+ "applications": application_totals,
"workspace": workspace_totals,
}
diff --git a/atst/domain/environments.py b/atst/domain/environments.py
index 680248cd..7502266b 100644
--- a/atst/domain/environments.py
+++ b/atst/domain/environments.py
@@ -4,7 +4,7 @@ from sqlalchemy.orm.exc import NoResultFound
from atst.database import db
from atst.models.environment import Environment
from atst.models.environment_role import EnvironmentRole
-from atst.models.project import Project
+from atst.models.application import Application
from atst.models.permissions import Permissions
from atst.domain.authz import Authorization
from atst.domain.environment_roles import EnvironmentRoles
@@ -14,18 +14,18 @@ from .exceptions import NotFoundError
class Environments(object):
@classmethod
- def create(cls, project, name):
- environment = Environment(project=project, name=name)
+ def create(cls, application, name):
+ environment = Environment(application=application, name=name)
environment.cloud_id = app.csp.cloud.create_application(environment.name)
db.session.add(environment)
db.session.commit()
return environment
@classmethod
- def create_many(cls, project, names):
+ def create_many(cls, application, names):
environments = []
for name in names:
- environment = Environments.create(project, name)
+ environment = Environments.create(application, name)
environments.append(environment)
db.session.add_all(environments)
@@ -40,13 +40,13 @@ class Environments(object):
return environment
@classmethod
- def for_user(cls, user, project):
+ def for_user(cls, user, application):
return (
db.session.query(Environment)
.join(EnvironmentRole)
- .join(Project)
+ .join(Application)
.filter(EnvironmentRole.user_id == user.id)
- .filter(Environment.project_id == project.id)
+ .filter(Environment.project_id == application.id)
.all()
)
diff --git a/atst/domain/roles.py b/atst/domain/roles.py
index 469126a8..d0b41aa3 100644
--- a/atst/domain/roles.py
+++ b/atst/domain/roles.py
@@ -58,7 +58,7 @@ WORKSPACE_ROLES = [
{
"name": "owner",
"display_name": "Workspace Owner",
- "description": "Adds, edits, deactivates access to all projects, environments, and members. Views budget reports. Initiates and edits JEDI Cloud requests.",
+ "description": "Adds, edits, deactivates access to all applications, environments, and members. Views budget reports. Initiates and edits JEDI Cloud requests.",
"permissions": [
Permissions.REQUEST_JEDI_WORKSPACE,
Permissions.VIEW_ORIGINAL_JEDI_REQEUST,
@@ -94,7 +94,7 @@ WORKSPACE_ROLES = [
{
"name": "admin",
"display_name": "Administrator",
- "description": "Adds and edits projects, environments, members, but cannot deactivate. Cannot view budget reports or JEDI Cloud requests.",
+ "description": "Adds and edits applications, environments, members, but cannot deactivate. Cannot view budget reports or JEDI Cloud requests.",
"permissions": [
Permissions.VIEW_USAGE_REPORT,
Permissions.ADD_AND_ASSIGN_CSP_ROLES,
@@ -125,13 +125,13 @@ WORKSPACE_ROLES = [
{
"name": "developer",
"display_name": "Developer",
- "description": "Views only the projects and environments they are granted access to. Can also view members associated with each environment.",
+ "description": "Views only the applications and environments they are granted access to. Can also view members associated with each environment.",
"permissions": [Permissions.VIEW_USAGE_REPORT, Permissions.VIEW_WORKSPACE],
},
{
"name": "billing_auditor",
"display_name": "Billing Auditor",
- "description": "Views only the projects and environments they are granted access to. Can also view budgets and reports associated with the workspace.",
+ "description": "Views only the applications and environments they are granted access to. Can also view budgets and reports associated with the workspace.",
"permissions": [
Permissions.VIEW_USAGE_REPORT,
Permissions.VIEW_USAGE_DOLLARS,
@@ -140,7 +140,7 @@ WORKSPACE_ROLES = [
},
{
"name": "security_auditor",
- "description": "Views only the projects and environments they are granted access to. Can also view activity logs.",
+ "description": "Views only the applications and environments they are granted access to. Can also view activity logs.",
"display_name": "Security Auditor",
"permissions": [
Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS,
diff --git a/atst/domain/workspaces/scopes.py b/atst/domain/workspaces/scopes.py
index e03d1098..69c64642 100644
--- a/atst/domain/workspaces/scopes.py
+++ b/atst/domain/workspaces/scopes.py
@@ -1,6 +1,6 @@
from atst.domain.authz import Authorization
from atst.models.permissions import Permissions
-from atst.domain.projects import Projects
+from atst.domain.applications import Applications
from atst.domain.environments import Environments
@@ -24,25 +24,27 @@ class ScopedResource(object):
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)
+ functionality that it only returns sub-resources (applications and environments)
that the given user is allowed to see.
"""
@property
- def projects(self):
- can_view_all_projects = Authorization.has_workspace_permission(
+ def applications(self):
+ can_view_all_applications = Authorization.has_workspace_permission(
self.user, self.resource, Permissions.VIEW_APPLICATION_IN_WORKSPACE
)
- if can_view_all_projects:
- projects = self.resource.projects
+ if can_view_all_applications:
+ applications = self.resource.applications
else:
- projects = Projects.for_user(self.user, self.resource)
+ applications = Applications.for_user(self.user, self.resource)
- return [ScopedProject(self.user, project) for project in projects]
+ return [
+ ScopedApplication(self.user, application) for application in applications
+ ]
-class ScopedProject(ScopedResource):
+class ScopedApplication(ScopedResource):
"""
An object that obeys the same API as a Workspace, but with the added
functionality that it only returns sub-resources (environments)
diff --git a/atst/domain/workspaces/workspaces.py b/atst/domain/workspaces/workspaces.py
index 7fe580ae..e8be09de 100644
--- a/atst/domain/workspaces/workspaces.py
+++ b/atst/domain/workspaces/workspaces.py
@@ -44,10 +44,10 @@ class Workspaces(object):
return ScopedWorkspace(user, workspace)
@classmethod
- def get_for_update_projects(cls, user, workspace_id):
+ def get_for_update_applications(cls, user, workspace_id):
workspace = WorkspacesQuery.get(workspace_id)
Authorization.check_workspace_permission(
- user, workspace, Permissions.ADD_APPLICATION_IN_WORKSPACE, "add project"
+ user, workspace, Permissions.ADD_APPLICATION_IN_WORKSPACE, "add application"
)
return workspace
diff --git a/atst/forms/project.py b/atst/forms/application.py
similarity index 64%
rename from atst/forms/project.py
rename to atst/forms/application.py
index 7ed30a00..d917f72d 100644
--- a/atst/forms/project.py
+++ b/atst/forms/application.py
@@ -5,29 +5,29 @@ from atst.forms.validators import ListItemRequired, ListItemsUnique
from atst.utils.localization import translate
-class ProjectForm(FlaskForm):
+class ApplicationForm(FlaskForm):
name = StringField(
- label=translate("forms.project.name_label"), validators=[Required()]
+ label=translate("forms.application.name_label"), validators=[Required()]
)
description = TextAreaField(
- label=translate("forms.project.description_label"), validators=[Required()]
+ label=translate("forms.application.description_label"), validators=[Required()]
)
-class NewProjectForm(ProjectForm):
+class NewApplicationForm(ApplicationForm):
EMPTY_ENVIRONMENT_NAMES = ["", None]
environment_names = FieldList(
- StringField(label=translate("forms.project.environment_names_label")),
+ StringField(label=translate("forms.application.environment_names_label")),
validators=[
ListItemRequired(
message=translate(
- "forms.project.environment_names_required_validation_message"
+ "forms.application.environment_names_required_validation_message"
)
),
ListItemsUnique(
message=translate(
- "forms.project.environment_names_unique_validation_message"
+ "forms.application.environment_names_unique_validation_message"
)
),
],
diff --git a/atst/forms/data.py b/atst/forms/data.py
index 202664fd..cce774c6 100644
--- a/atst/forms/data.py
+++ b/atst/forms/data.py
@@ -6,8 +6,8 @@ SERVICE_BRANCHES = [
("Army and Air Force Exchange Service", "Army and Air Force Exchange Service"),
("Army, Department of the", "Army, Department of the"),
(
- "Defense Advanced Research Projects Agency",
- "Defense Advanced Research Projects Agency",
+ "Defense Advanced Research Applications Agency",
+ "Defense Advanced Research Applications Agency",
),
("Defense Commissary Agency", "Defense Commissary Agency"),
("Defense Contract Audit Agency", "Defense Contract Audit Agency"),
@@ -137,7 +137,7 @@ ENVIRONMENT_ROLES = [
"billing_administrator",
{
"name": "Billing Administrator",
- "description": "Views cloud resource usage, budget reports, and invoices; Tracks budgets, including spend reports, cost planning and projections, and sets limits based on cloud service usage.",
+ "description": "Views cloud resource usage, budget reports, and invoices; Tracks budgets, including spend reports, cost planning and applicationions, and sets limits based on cloud service usage.",
},
),
(
@@ -162,7 +162,7 @@ ENVIRONMENT_ROLES = [
ENV_ROLE_MODAL_DESCRIPTION = {
"header": "Assign Environment Role",
- "body": "An environment role determines the permissions a member of the workspace assumes when using the JEDI Cloud.
A member may have different environment roles across different projects. A member can only have one assigned environment role in a given environment.",
+ "body": "An environment role determines the permissions a member of the workspace assumes when using the JEDI Cloud.
A member may have different environment roles across different applications. A member can only have one assigned environment role in a given environment.",
}
FUNDING_TYPES = [
@@ -210,7 +210,7 @@ TEAM_EXPERIENCE = [
("built_3", "Built or Migrated 3-5 applications"),
(
"built_many",
- "Built or migrated many applications, or consulted on several such projects",
+ "Built or migrated many applications, or consulted on several such applications",
),
]
diff --git a/atst/forms/edit_member.py b/atst/forms/edit_member.py
index 974621c1..e2683d95 100644
--- a/atst/forms/edit_member.py
+++ b/atst/forms/edit_member.py
@@ -8,7 +8,7 @@ from .data import WORKSPACE_ROLES
class EditMemberForm(FlaskForm):
- # This form also accepts a field for each environment in each project
+ # This form also accepts a field for each environment in each application
# that the user is a member of
workspace_role = SelectField(
diff --git a/atst/models/__init__.py b/atst/models/__init__.py
index 0116c5ff..6705589c 100644
--- a/atst/models/__init__.py
+++ b/atst/models/__init__.py
@@ -11,7 +11,7 @@ from .workspace_role import WorkspaceRole
from .pe_number import PENumber
from .legacy_task_order import LegacyTaskOrder
from .workspace import Workspace
-from .project import Project
+from .application import Application
from .environment import Environment
from .attachment import Attachment
from .request_revision import RequestRevision
diff --git a/atst/models/project.py b/atst/models/application.py
similarity index 72%
rename from atst/models/project.py
rename to atst/models/application.py
index cd9b5593..c3e0a05c 100644
--- a/atst/models/project.py
+++ b/atst/models/application.py
@@ -6,7 +6,7 @@ from atst.models.types import Id
from atst.models import mixins
-class Project(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
+class Application(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
__tablename__ = "projects"
id = Id()
@@ -15,13 +15,13 @@ class Project(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
workspace_id = Column(ForeignKey("workspaces.id"), nullable=False)
workspace = relationship("Workspace")
- environments = relationship("Environment", back_populates="project")
+ environments = relationship("Environment", back_populates="application")
@property
def displayname(self):
return self.name
def __repr__(self): # pragma: no cover
- return "".format(
+ return "".format(
self.name, self.description, self.workspace.name, self.id
)
diff --git a/atst/models/environment.py b/atst/models/environment.py
index 01348d39..2c4cb43c 100644
--- a/atst/models/environment.py
+++ b/atst/models/environment.py
@@ -13,7 +13,7 @@ class Environment(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
name = Column(String, nullable=False)
project_id = Column(ForeignKey("projects.id"), nullable=False)
- project = relationship("Project")
+ application = relationship("Application")
cloud_id = Column(String)
@@ -31,16 +31,16 @@ class Environment(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
@property
def workspace(self):
- return self.project.workspace
+ return self.application.workspace
def auditable_workspace_id(self):
- return self.project.workspace_id
+ return self.application.workspace_id
def __repr__(self):
- return "".format(
+ return "".format(
self.name,
self.num_users,
- self.project.name,
- self.project.workspace.name,
+ self.application.name,
+ self.application.workspace.name,
self.id,
)
diff --git a/atst/models/environment_role.py b/atst/models/environment_role.py
index e3e3f008..158b5cfe 100644
--- a/atst/models/environment_role.py
+++ b/atst/models/environment_role.py
@@ -45,10 +45,10 @@ class EnvironmentRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
"role": self.role,
"environment": self.environment.displayname,
"environment_id": str(self.environment_id),
- "project": self.environment.project.name,
- "project_id": str(self.environment.project_id),
- "workspace": self.environment.project.workspace.name,
- "workspace_id": str(self.environment.project.workspace.id),
+ "application": self.environment.application.name,
+ "application_id": str(self.environment.project_id),
+ "workspace": self.environment.application.workspace.name,
+ "workspace_id": str(self.environment.application.workspace.id),
}
diff --git a/atst/models/task_order.py b/atst/models/task_order.py
index b4c3e50d..19d8a0ab 100644
--- a/atst/models/task_order.py
+++ b/atst/models/task_order.py
@@ -47,7 +47,7 @@ class TaskOrder(Base, mixins.TimestampsMixin):
defense_component = Column(String) # Department of Defense Component
app_migration = Column(String) # App Migration
native_apps = Column(String) # Native Apps
- complexity = Column(ARRAY(String)) # Project Complexity
+ complexity = Column(ARRAY(String)) # Application Complexity
complexity_other = Column(String)
dev_team = Column(ARRAY(String)) # Development Team
dev_team_other = Column(String)
diff --git a/atst/models/workspace.py b/atst/models/workspace.py
index d02acd19..fccc6ee4 100644
--- a/atst/models/workspace.py
+++ b/atst/models/workspace.py
@@ -14,7 +14,7 @@ class Workspace(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
id = types.Id()
name = Column(String)
request_id = Column(ForeignKey("requests.id"), nullable=True)
- projects = relationship("Project", back_populates="workspace")
+ applications = relationship("Application", back_populates="workspace")
roles = relationship("WorkspaceRole")
task_orders = relationship("TaskOrder")
@@ -54,7 +54,7 @@ class Workspace(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
@property
def all_environments(self):
- return list(chain.from_iterable(p.environments for p in self.projects))
+ return list(chain.from_iterable(p.environments for p in self.applications))
def auditable_workspace_id(self):
return self.id
diff --git a/atst/models/workspace_role.py b/atst/models/workspace_role.py
index 580dc07f..84c64a8f 100644
--- a/atst/models/workspace_role.py
+++ b/atst/models/workspace_role.py
@@ -8,7 +8,7 @@ from .types import Id
from atst.database import db
from atst.models.environment_role import EnvironmentRole
-from atst.models.project import Project
+from atst.models.application import Application
from atst.models.environment import Environment
from atst.models.role import Role
@@ -126,9 +126,9 @@ class WorkspaceRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
return (
db.session.query(EnvironmentRole)
.join(EnvironmentRole.environment)
- .join(Environment.project)
- .join(Project.workspace)
- .filter(Project.workspace_id == self.workspace_id)
+ .join(Environment.application)
+ .join(Application.workspace)
+ .filter(Application.workspace_id == self.workspace_id)
.filter(EnvironmentRole.user_id == self.user_id)
.count()
)
@@ -138,9 +138,9 @@ class WorkspaceRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
return (
db.session.query(EnvironmentRole)
.join(EnvironmentRole.environment)
- .join(Environment.project)
- .join(Project.workspace)
- .filter(Project.workspace_id == self.workspace_id)
+ .join(Environment.application)
+ .join(Application.workspace)
+ .filter(Application.workspace_id == self.workspace_id)
.filter(EnvironmentRole.user_id == self.user_id)
.all()
)
diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py
index 07550af7..af63d5dd 100644
--- a/atst/routes/__init__.py
+++ b/atst/routes/__init__.py
@@ -67,7 +67,7 @@ def home():
)
else:
return redirect(
- url_for("workspaces.workspace_projects", workspace_id=workspace_id)
+ url_for("workspaces.workspace_applications", workspace_id=workspace_id)
)
else:
return redirect(url_for("workspaces.workspaces"))
diff --git a/atst/routes/requests/financial_verification.py b/atst/routes/requests/financial_verification.py
index 4ccec8fd..52d8311e 100644
--- a/atst/routes/requests/financial_verification.py
+++ b/atst/routes/requests/financial_verification.py
@@ -250,7 +250,9 @@ def update_financial_verification(request_id):
if updated_request.legacy_task_order.verified:
workspace = Requests.auto_approve_and_create_workspace(updated_request)
flash("new_workspace")
- return redirect(url_for("workspaces.new_project", workspace_id=workspace.id))
+ return redirect(
+ url_for("workspaces.new_application", workspace_id=workspace.id)
+ )
else:
return redirect(url_for("requests.requests_index", modal="pendingCCPOApproval"))
diff --git a/atst/routes/requests/index.py b/atst/routes/requests/index.py
index 55967ecf..69f433ba 100644
--- a/atst/routes/requests/index.py
+++ b/atst/routes/requests/index.py
@@ -66,7 +66,7 @@ class RequestsIndex(object):
def _workspace_link_for_request(self, request):
if request.is_approved:
return url_for(
- "workspaces.workspace_projects", workspace_id=request.workspace.id
+ "workspaces.workspace_applications", workspace_id=request.workspace.id
)
else:
return None
diff --git a/atst/routes/workspaces/__init__.py b/atst/routes/workspaces/__init__.py
index 96aa24b5..9d822771 100644
--- a/atst/routes/workspaces/__init__.py
+++ b/atst/routes/workspaces/__init__.py
@@ -3,7 +3,7 @@ from flask import Blueprint, request as http_request, g, render_template
workspaces_bp = Blueprint("workspaces", __name__)
from . import index
-from . import projects
+from . import applications
from . import members
from . import invitations
from . import task_orders
diff --git a/atst/routes/workspaces/applications.py b/atst/routes/workspaces/applications.py
new file mode 100644
index 00000000..c80374c0
--- /dev/null
+++ b/atst/routes/workspaces/applications.py
@@ -0,0 +1,102 @@
+from flask import (
+ current_app as app,
+ g,
+ redirect,
+ render_template,
+ request as http_request,
+ url_for,
+)
+
+from . import workspaces_bp
+from atst.domain.environment_roles import EnvironmentRoles
+from atst.domain.exceptions import UnauthorizedError
+from atst.domain.applications import Applications
+from atst.domain.workspaces import Workspaces
+from atst.forms.application import NewApplicationForm, ApplicationForm
+
+
+@workspaces_bp.route("/workspaces//applications")
+def workspace_applications(workspace_id):
+ workspace = Workspaces.get(g.current_user, workspace_id)
+ return render_template("workspaces/applications/index.html", workspace=workspace)
+
+
+@workspaces_bp.route("/workspaces//applications/new")
+def new_application(workspace_id):
+ workspace = Workspaces.get_for_update_applications(g.current_user, workspace_id)
+ form = NewApplicationForm()
+ return render_template(
+ "workspaces/applications/new.html", workspace=workspace, form=form
+ )
+
+
+@workspaces_bp.route("/workspaces//applications/new", methods=["POST"])
+def create_application(workspace_id):
+ workspace = Workspaces.get_for_update_applications(g.current_user, workspace_id)
+ form = NewApplicationForm(http_request.form)
+
+ if form.validate():
+ application_data = form.data
+ Applications.create(
+ g.current_user,
+ workspace,
+ application_data["name"],
+ application_data["description"],
+ application_data["environment_names"],
+ )
+ return redirect(
+ url_for("workspaces.workspace_applications", workspace_id=workspace.id)
+ )
+ else:
+ return render_template(
+ "workspaces/applications/new.html", workspace=workspace, form=form
+ )
+
+
+@workspaces_bp.route("/workspaces//applications//edit")
+def edit_application(workspace_id, application_id):
+ workspace = Workspaces.get_for_update_applications(g.current_user, workspace_id)
+ application = Applications.get(g.current_user, workspace, application_id)
+ form = ApplicationForm(name=application.name, description=application.description)
+
+ return render_template(
+ "workspaces/applications/edit.html",
+ workspace=workspace,
+ application=application,
+ form=form,
+ )
+
+
+@workspaces_bp.route(
+ "/workspaces//applications//edit", methods=["POST"]
+)
+def update_application(workspace_id, application_id):
+ workspace = Workspaces.get_for_update_applications(g.current_user, workspace_id)
+ application = Applications.get(g.current_user, workspace, application_id)
+ form = ApplicationForm(http_request.form)
+ if form.validate():
+ application_data = form.data
+ Applications.update(g.current_user, workspace, application, application_data)
+
+ return redirect(
+ url_for("workspaces.workspace_applications", workspace_id=workspace.id)
+ )
+ else:
+ return render_template(
+ "workspaces/applications/edit.html",
+ workspace=workspace,
+ application=application,
+ form=form,
+ )
+
+
+@workspaces_bp.route("/workspaces//environments//access")
+def access_environment(workspace_id, environment_id):
+ env_role = EnvironmentRoles.get(g.current_user.id, environment_id)
+ if not env_role:
+ raise UnauthorizedError(
+ g.current_user, "access environment {}".format(environment_id)
+ )
+ else:
+ token = app.csp.cloud.get_access_token(env_role)
+ return redirect(url_for("atst.csp_environment_access", token=token))
diff --git a/atst/routes/workspaces/index.py b/atst/routes/workspaces/index.py
index 063f66f5..c9462bbf 100644
--- a/atst/routes/workspaces/index.py
+++ b/atst/routes/workspaces/index.py
@@ -32,7 +32,7 @@ def edit_workspace(workspace_id):
if form.validate():
Workspaces.update(workspace, form.data)
return redirect(
- url_for("workspaces.workspace_projects", workspace_id=workspace.id)
+ url_for("workspaces.workspace_applications", workspace_id=workspace.id)
)
else:
return render_template("workspaces/edit.html", form=form, workspace=workspace)
@@ -40,7 +40,9 @@ def edit_workspace(workspace_id):
@workspaces_bp.route("/workspaces/")
def show_workspace(workspace_id):
- return redirect(url_for("workspaces.workspace_projects", workspace_id=workspace_id))
+ return redirect(
+ url_for("workspaces.workspace_applications", workspace_id=workspace_id)
+ )
@workspaces_bp.route("/workspaces//reports")
diff --git a/atst/routes/workspaces/members.py b/atst/routes/workspaces/members.py
index 7c590153..b9a53452 100644
--- a/atst/routes/workspaces/members.py
+++ b/atst/routes/workspaces/members.py
@@ -4,7 +4,7 @@ from flask import render_template, request as http_request, g, redirect, url_for
from . import workspaces_bp
from atst.domain.exceptions import AlreadyExistsError
-from atst.domain.projects import Projects
+from atst.domain.applications import Applications
from atst.domain.workspaces import Workspaces
from atst.domain.workspace_roles import WorkspaceRoles, MEMBER_STATUS_CHOICES
from atst.domain.environments import Environments
@@ -101,7 +101,7 @@ def view_member(workspace_id, member_id):
"edit this workspace user",
)
member = WorkspaceRoles.get(workspace_id, member_id)
- projects = Projects.get_all(g.current_user, member, workspace)
+ applications = Applications.get_all(g.current_user, member, workspace)
form = EditMemberForm(workspace_role=member.role_name)
editable = g.current_user == member.user
can_revoke_access = Workspaces.can_revoke_access_for(workspace, member)
@@ -113,7 +113,7 @@ def view_member(workspace_id, member_id):
"workspaces/members/edit.html",
workspace=workspace,
member=member,
- projects=projects,
+ applications=applications,
form=form,
choices=ENVIRONMENT_ROLES,
env_role_modal_description=ENV_ROLE_MODAL_DESCRIPTION,
diff --git a/atst/routes/workspaces/projects.py b/atst/routes/workspaces/projects.py
deleted file mode 100644
index 67cc2931..00000000
--- a/atst/routes/workspaces/projects.py
+++ /dev/null
@@ -1,99 +0,0 @@
-from flask import (
- current_app as app,
- g,
- redirect,
- render_template,
- request as http_request,
- url_for,
-)
-
-from . import workspaces_bp
-from atst.domain.environment_roles import EnvironmentRoles
-from atst.domain.exceptions import UnauthorizedError
-from atst.domain.projects import Projects
-from atst.domain.workspaces import Workspaces
-from atst.forms.project import NewProjectForm, ProjectForm
-
-
-@workspaces_bp.route("/workspaces//projects")
-def workspace_projects(workspace_id):
- workspace = Workspaces.get(g.current_user, workspace_id)
- return render_template("workspaces/projects/index.html", workspace=workspace)
-
-
-@workspaces_bp.route("/workspaces//projects/new")
-def new_project(workspace_id):
- workspace = Workspaces.get_for_update_projects(g.current_user, workspace_id)
- form = NewProjectForm()
- return render_template(
- "workspaces/projects/new.html", workspace=workspace, form=form
- )
-
-
-@workspaces_bp.route("/workspaces//projects/new", methods=["POST"])
-def create_project(workspace_id):
- workspace = Workspaces.get_for_update_projects(g.current_user, workspace_id)
- form = NewProjectForm(http_request.form)
-
- if form.validate():
- project_data = form.data
- Projects.create(
- g.current_user,
- workspace,
- project_data["name"],
- project_data["description"],
- project_data["environment_names"],
- )
- return redirect(
- url_for("workspaces.workspace_projects", workspace_id=workspace.id)
- )
- else:
- return render_template(
- "workspaces/projects/new.html", workspace=workspace, form=form
- )
-
-
-@workspaces_bp.route("/workspaces//projects//edit")
-def edit_project(workspace_id, project_id):
- workspace = Workspaces.get_for_update_projects(g.current_user, workspace_id)
- project = Projects.get(g.current_user, workspace, project_id)
- form = ProjectForm(name=project.name, description=project.description)
-
- return render_template(
- "workspaces/projects/edit.html", workspace=workspace, project=project, form=form
- )
-
-
-@workspaces_bp.route(
- "/workspaces//projects//edit", methods=["POST"]
-)
-def update_project(workspace_id, project_id):
- workspace = Workspaces.get_for_update_projects(g.current_user, workspace_id)
- project = Projects.get(g.current_user, workspace, project_id)
- form = ProjectForm(http_request.form)
- if form.validate():
- project_data = form.data
- Projects.update(g.current_user, workspace, project, project_data)
-
- return redirect(
- url_for("workspaces.workspace_projects", workspace_id=workspace.id)
- )
- else:
- return render_template(
- "workspaces/projects/edit.html",
- workspace=workspace,
- project=project,
- form=form,
- )
-
-
-@workspaces_bp.route("/workspaces//environments//access")
-def access_environment(workspace_id, environment_id):
- env_role = EnvironmentRoles.get(g.current_user.id, environment_id)
- if not env_role:
- raise UnauthorizedError(
- g.current_user, "access environment {}".format(environment_id)
- )
- else:
- token = app.csp.cloud.get_access_token(env_role)
- return redirect(url_for("atst.csp_environment_access", token=token))
diff --git a/js/components/forms/edit_project_roles.js b/js/components/forms/edit_application_roles.js
similarity index 92%
rename from js/components/forms/edit_project_roles.js
rename to js/components/forms/edit_application_roles.js
index d1c5107c..ef7438d5 100644
--- a/js/components/forms/edit_project_roles.js
+++ b/js/components/forms/edit_application_roles.js
@@ -4,7 +4,7 @@ import toggler from '../toggler'
import EditEnvironmentRole from './edit_environment_role'
export default {
- name: 'edit-project-roles',
+ name: 'edit-application-roles',
mixins: [FormMixin, Modal],
diff --git a/js/components/forms/edit_environment_role.js b/js/components/forms/edit_environment_role.js
index 45a3506a..4bb8fb55 100644
--- a/js/components/forms/edit_environment_role.js
+++ b/js/components/forms/edit_environment_role.js
@@ -20,7 +20,7 @@ export default {
props: {
choices: Array,
initialData: String,
- projectId: String
+ applicationId: String
},
data: function () {
@@ -30,7 +30,7 @@ export default {
},
mounted: function() {
- this.$root.$on('revoke-' + this.projectId, this.revoke)
+ this.$root.$on('revoke-' + this.applicationId, this.revoke)
},
methods: {
diff --git a/js/components/forms/new_project.js b/js/components/forms/new_application.js
similarity index 99%
rename from js/components/forms/new_project.js
rename to js/components/forms/new_application.js
index ebcea13f..d607b101 100644
--- a/js/components/forms/new_project.js
+++ b/js/components/forms/new_application.js
@@ -4,7 +4,7 @@ import textinput from '../text_input'
const createEnvironment = (name) => ({ name })
export default {
- name: 'new-project',
+ name: 'new-application',
mixins: [FormMixin],
diff --git a/js/components/requests_list.js b/js/components/requests_list.js
index 735dcdd3..6f3adcb9 100644
--- a/js/components/requests_list.js
+++ b/js/components/requests_list.js
@@ -60,7 +60,7 @@ export default {
sortFunc: defaultSort,
},
{
- displayName: 'Projected Annual Usage ($)',
+ displayName: 'Applicationed Annual Usage ($)',
attr: 'annual_usage',
sortFunc: defaultSort,
},
diff --git a/js/components/tables/spend_table.js b/js/components/tables/spend_table.js
index fd694ce7..c87028ab 100644
--- a/js/components/tables/spend_table.js
+++ b/js/components/tables/spend_table.js
@@ -5,7 +5,7 @@ export default {
name: 'spend-table',
props: {
- projects: Object,
+ applications: Object,
workspace: Object,
environments: Object,
currentMonthIndex: String,
@@ -15,21 +15,21 @@ export default {
data: function () {
return {
- projectsState: this.projects
+ applicationsState: this.applications
}
},
created: function () {
- Object.keys(this.projects).forEach(project => {
- set(this.projectsState[project], 'isVisible', false)
+ Object.keys(this.applications).forEach(application => {
+ set(this.applicationsState[application], 'isVisible', false)
})
},
methods: {
- toggle: function (e, projectName) {
- this.projectsState = Object.assign(this.projectsState, {
- [projectName]: Object.assign(this.projectsState[projectName],{
- isVisible: !this.projectsState[projectName].isVisible
+ toggle: function (e, applicationName) {
+ this.applicationsState = Object.assign(this.applicationsState, {
+ [applicationName]: Object.assign(this.applicationsState[applicationName],{
+ isVisible: !this.applicationsState[applicationName].isVisible
})
})
},
diff --git a/js/index.js b/js/index.js
index 5bbee5d1..97fe3acc 100644
--- a/js/index.js
+++ b/js/index.js
@@ -13,9 +13,9 @@ import DetailsOfUse from './components/forms/details_of_use'
import poc from './components/forms/poc'
import financial from './components/forms/financial'
import toggler from './components/toggler'
-import NewProject from './components/forms/new_project'
+import NewApplication from './components/forms/new_application'
import EditEnvironmentRole from './components/forms/edit_environment_role'
-import EditProjectRoles from './components/forms/edit_project_roles'
+import EditApplicationRoles from './components/forms/edit_application_roles'
import funding from './components/forms/funding'
import Modal from './mixins/modal'
import selector from './components/selector'
@@ -44,7 +44,7 @@ const app = new Vue({
DetailsOfUse,
poc,
financial,
- NewProject,
+ NewApplication,
selector,
BudgetChart,
SpendTable,
@@ -52,7 +52,7 @@ const app = new Vue({
MembersList,
LocalDatetime,
EditEnvironmentRole,
- EditProjectRoles,
+ EditApplicationRoles,
RequestsList,
ConfirmationPopover,
funding,
diff --git a/script/seed_sample.py b/script/seed_sample.py
index 8d62759a..84ef41f4 100644
--- a/script/seed_sample.py
+++ b/script/seed_sample.py
@@ -10,7 +10,7 @@ from atst.app import make_config, make_app
from atst.domain.users import Users
from atst.domain.requests import Requests
from atst.domain.workspaces import Workspaces
-from atst.domain.projects import Projects
+from atst.domain.applications import Applications
from atst.domain.workspace_roles import WorkspaceRoles
from atst.models.invitation import Status as InvitationStatus
from atst.domain.exceptions import AlreadyExistsError
@@ -122,7 +122,7 @@ def seed_db():
db.session.commit()
- Projects.create(
+ Applications.create(
user,
workspace=workspace,
name="First Project",
diff --git a/styles/atat.scss b/styles/atat.scss
index 37389c5e..ce01d0e9 100644
--- a/styles/atat.scss
+++ b/styles/atat.scss
@@ -42,8 +42,8 @@
@import 'sections/login';
@import 'sections/home';
@import 'sections/request_approval';
-@import 'sections/projects_list';
-@import 'sections/project_edit';
+@import 'sections/application_list';
+@import 'sections/application_edit';
@import 'sections/member_edit';
@import 'sections/reports';
@import 'sections/task_order';
diff --git a/styles/components/_site_action.scss b/styles/components/_site_action.scss
index 98af0b18..7b42a4ec 100644
--- a/styles/components/_site_action.scss
+++ b/styles/components/_site_action.scss
@@ -12,4 +12,4 @@
color: $color-primary !important;
}
-}
\ No newline at end of file
+}
diff --git a/styles/elements/_kpi.scss b/styles/elements/_kpi.scss
index f68fe30c..05c2ff78 100644
--- a/styles/elements/_kpi.scss
+++ b/styles/elements/_kpi.scss
@@ -22,4 +22,4 @@
padding-bottom: $gap / 2;
}
-}
\ No newline at end of file
+}
diff --git a/styles/sections/_project_edit.scss b/styles/sections/_application_edit.scss
similarity index 79%
rename from styles/sections/_project_edit.scss
rename to styles/sections/_application_edit.scss
index ef1bc39a..ce05522f 100644
--- a/styles/sections/_project_edit.scss
+++ b/styles/sections/_application_edit.scss
@@ -1,4 +1,4 @@
-.project-edit__env-list-item {
+.application-edit__env-list-item {
display: flex;
flex-direction: row;
align-items: flex-end;
@@ -8,7 +8,7 @@
flex-grow: 1;
}
- .project-edit__env-list-item__remover {
+ .application-edit__env-list-item__remover {
@include icon-link;
@include icon-link-vertical;
@include icon-link-color($color-red, $color-red-lightest);
diff --git a/styles/sections/_projects_list.scss b/styles/sections/_application_list.scss
similarity index 65%
rename from styles/sections/_projects_list.scss
rename to styles/sections/_application_list.scss
index e48bb7af..0294d646 100644
--- a/styles/sections/_projects_list.scss
+++ b/styles/sections/_application_list.scss
@@ -1,5 +1,5 @@
-.project-list-item {
- .project-list-item__environment {
+.application-list-item {
+ .application-list-item__environment {
display: flex;
flex-direction: row;
justify-content: space-between;
@@ -8,12 +8,12 @@
margin: 0;
}
- .project-list-item__environment__link {
+ .application-list-item__environment__link {
@include icon-link;
@include icon-link-large;
}
- .project-list-item__environment__members {
+ .application-list-item__environment__members {
display: flex;
flex-direction: row;
align-items: center;
diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss
index 176c197a..9098b268 100644
--- a/styles/sections/_home.scss
+++ b/styles/sections/_home.scss
@@ -67,4 +67,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/styles/sections/_reports.scss b/styles/sections/_reports.scss
index 39abad06..ccd5a5f8 100644
--- a/styles/sections/_reports.scss
+++ b/styles/sections/_reports.scss
@@ -289,8 +289,8 @@
}
}
- .spend-table__project {
- .spend-table__project__toggler {
+ .spend-table__application {
+ .spend-table__application__toggler {
@include icon-link-color($color-black-light, $color-gray-lightest);
margin-left: -$gap;
@@ -300,7 +300,7 @@
}
}
- .spend-table__project__env {
+ .spend-table__application__env {
margin-left: $gap;
&:last-child {
diff --git a/templates/audit_log/events/project.html b/templates/audit_log/events/application.html
similarity index 100%
rename from templates/audit_log/events/project.html
rename to templates/audit_log/events/application.html
diff --git a/templates/audit_log/events/environment_role.html b/templates/audit_log/events/environment_role.html
index ea25fd6f..f59b8fe0 100644
--- a/templates/audit_log/events/environment_role.html
+++ b/templates/audit_log/events/environment_role.html
@@ -12,7 +12,7 @@
in Environment {{ event.event_details["environment_id"] }} ({{ event.event_details["environment"] }})
- in Application {{ event.event_details["project_id"] }} ({{ event.event_details["project"] }})
+ in Application {{ event.event_details["application_id"] }} ({{ event.event_details["application"] }})
in Portfolio {{ event.event_details["workspace_id"] }} ({{ event.event_details["workspace"] }})
{% endif %}
diff --git a/templates/fragments/edit_project_form.html b/templates/fragments/edit_application_form.html
similarity index 53%
rename from templates/fragments/edit_project_form.html
rename to templates/fragments/edit_application_form.html
index f490a7e8..9b9e1bbc 100644
--- a/templates/fragments/edit_project_form.html
+++ b/templates/fragments/edit_application_form.html
@@ -1,6 +1,6 @@
{% from "components/text_input.html" import TextInput %}
-{% set title_text = ('fragments.edit_project_form.existing_project_title' | translate({ "project_name": project.name })) if project else ('fragments.edit_project_form.new_project_title' | translate) %}
+{% set title_text = ('fragments.edit_application_form.existing_application_title' | translate({ "application_name": application.name })) if application else ('fragments.edit_application_form.new_application_title' | translate) %}
{{ form.csrf_token }}
Separate your portfolio into applications and environments; this allows your team to manage user access to systems more securely and track expenditures for each project.
+
Separate your portfolio into applications and environments; this allows your team to manage user access to systems more securely and track expenditures for each application.
Here’s an example:
Application A has a development environment, production environment, and sandbox environment. The cloud resources in the development environment are grouped and accessed separately from the production environment and sandbox environment.