From 70940b09c22a9d6139b2b5e18e89697621846258 Mon Sep 17 00:00:00 2001 From: Montana Date: Tue, 27 Nov 2018 10:44:49 -0500 Subject: [PATCH] Refactor workspace routes --- atst/app.py | 2 +- atst/routes/workspaces.py | 391 -------------------------- atst/routes/workspaces/__init__.py | 40 +++ atst/routes/workspaces/index.py | 80 ++++++ atst/routes/workspaces/invitations.py | 49 ++++ atst/routes/workspaces/members.py | 172 +++++++++++ atst/routes/workspaces/projects.py | 78 +++++ 7 files changed, 420 insertions(+), 392 deletions(-) delete mode 100644 atst/routes/workspaces.py create mode 100644 atst/routes/workspaces/__init__.py create mode 100644 atst/routes/workspaces/index.py create mode 100644 atst/routes/workspaces/invitations.py create mode 100644 atst/routes/workspaces/members.py create mode 100644 atst/routes/workspaces/projects.py diff --git a/atst/app.py b/atst/app.py index b309806a..88002c4f 100644 --- a/atst/app.py +++ b/atst/app.py @@ -12,7 +12,7 @@ from atst.database import db from atst.assets import environment as assets_environment from atst.filters import register_filters from atst.routes import bp -from atst.routes.workspaces import bp as workspace_routes +from atst.routes.workspaces import workspaces_bp as workspace_routes from atst.routes.requests import requests_bp from atst.routes.dev import bp as dev_routes from atst.routes.users import bp as user_routes diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py deleted file mode 100644 index c216d5ee..00000000 --- a/atst/routes/workspaces.py +++ /dev/null @@ -1,391 +0,0 @@ -import re -from datetime import date, timedelta - -from flask import ( - Blueprint, - render_template, - request as http_request, - g, - redirect, - url_for, -) - -from atst.domain.exceptions import UnauthorizedError, AlreadyExistsError -from atst.domain.projects import Projects -from atst.domain.reports import Reports -from atst.domain.workspaces import Workspaces -from atst.domain.workspace_roles import WorkspaceRoles, MEMBER_STATUSES -from atst.domain.environments import Environments -from atst.domain.environment_roles import EnvironmentRoles -from atst.forms.project import NewProjectForm, ProjectForm -from atst.forms.new_member import NewMemberForm -from atst.forms.edit_member import EditMemberForm -from atst.forms.workspace import WorkspaceForm -from atst.forms.data import ( - ENVIRONMENT_ROLES, - ENV_ROLE_MODAL_DESCRIPTION, - WORKSPACE_ROLE_DEFINITIONS, -) -from atst.domain.authz import Authorization -from atst.models.permissions import Permissions -from atst.domain.invitations import Invitations -from atst.queue import queue - -bp = Blueprint("workspaces", __name__) - - -@bp.context_processor -def workspace(): - workspaces = Workspaces.for_user(g.current_user) - workspace = None - if "workspace_id" in http_request.view_args: - try: - workspace = Workspaces.get( - g.current_user, http_request.view_args["workspace_id"] - ) - workspaces = [ws for ws in workspaces if not ws.id == workspace.id] - except UnauthorizedError: - pass - - def user_can(permission): - if workspace: - return Authorization.has_workspace_permission( - g.current_user, workspace, permission - ) - return False - - return { - "workspace": workspace, - "workspaces": workspaces, - "permissions": Permissions, - "user_can": user_can, - } - - -@bp.route("/workspaces") -def workspaces(): - workspaces = Workspaces.for_user(g.current_user) - return render_template("workspaces/index.html", page=5, workspaces=workspaces) - - -@bp.route("/workspaces//edit") -def workspace(workspace_id): - workspace = Workspaces.get_for_update_information(g.current_user, workspace_id) - form = WorkspaceForm(data={"name": workspace.name}) - return render_template("workspaces/edit.html", form=form, workspace=workspace) - - -@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) - - -@bp.route("/workspaces//edit", methods=["POST"]) -def edit_workspace(workspace_id): - workspace = Workspaces.get_for_update_information(g.current_user, workspace_id) - form = WorkspaceForm(http_request.form) - if form.validate(): - Workspaces.update(workspace, form.data) - return redirect( - url_for("workspaces.workspace_projects", workspace_id=workspace.id) - ) - else: - return render_template("workspaces/edit.html", form=form, workspace=workspace) - - -@bp.route("/workspaces/") -def show_workspace(workspace_id): - return redirect(url_for("workspaces.workspace_projects", workspace_id=workspace_id)) - - -@bp.route("/workspaces//members") -def workspace_members(workspace_id): - workspace = Workspaces.get_with_members(g.current_user, workspace_id) - new_member_name = http_request.args.get("newMemberName") - resent_invitation_to = http_request.args.get("resentInvitationTo") - new_member = next( - filter(lambda m: m.user_name == new_member_name, workspace.members), None - ) - members_list = [ - { - "name": k.user_name, - "status": k.display_status, - "id": k.user_id, - "role": k.role_displayname, - "num_env": k.num_environment_roles, - "edit_link": url_for( - "workspaces.view_member", workspace_id=workspace.id, member_id=k.user_id - ), - } - for k in workspace.members - ] - - return render_template( - "workspaces/members/index.html", - workspace=workspace, - role_choices=WORKSPACE_ROLE_DEFINITIONS, - status_choices=MEMBER_STATUSES, - members=members_list, - new_member=new_member, - resent_invitation_to=resent_invitation_to, - ) - - -@bp.route("/workspaces//reports") -def workspace_reports(workspace_id): - workspace = Workspaces.get(g.current_user, workspace_id) - Authorization.check_workspace_permission( - g.current_user, - workspace, - Permissions.VIEW_USAGE_DOLLARS, - "view workspace reports", - ) - - today = date.today() - month = http_request.args.get("month", today.month) - year = http_request.args.get("year", today.year) - current_month = date(int(year), int(month), 15) - prev_month = current_month - timedelta(days=28) - two_months_ago = prev_month - timedelta(days=28) - - expiration_date = workspace.request.task_order.expiration_date - if expiration_date: - remaining_difference = expiration_date - today - remaining_days = remaining_difference.days - else: - remaining_days = None - - return render_template( - "workspaces/reports/index.html", - cumulative_budget=Reports.cumulative_budget(workspace), - workspace_totals=Reports.workspace_totals(workspace), - monthly_totals=Reports.monthly_totals(workspace), - jedi_request=workspace.request, - task_order=workspace.request.task_order, - current_month=current_month, - prev_month=prev_month, - two_months_ago=two_months_ago, - expiration_date=expiration_date, - remaining_days=remaining_days, - ) - - -@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 - ) - - -@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 - ) - - -@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 - ) - - -@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, - ) - - -@bp.route("/workspaces//members/new") -def new_member(workspace_id): - workspace = Workspaces.get(g.current_user, workspace_id) - form = NewMemberForm() - return render_template( - "workspaces/members/new.html", workspace=workspace, form=form - ) - - -def send_invite_email(owner_name, token, new_member_email): - body = render_template("emails/invitation.txt", owner=owner_name, token=token) - queue.send_mail( - [new_member_email], - "{} has invited you to a JEDI Cloud Workspace".format(owner_name), - body, - ) - - -@bp.route("/workspaces//members/new", methods=["POST"]) -def create_member(workspace_id): - workspace = Workspaces.get(g.current_user, workspace_id) - form = NewMemberForm(http_request.form) - user = g.current_user - - if form.validate(): - try: - new_member = Workspaces.create_member(user, workspace, form.data) - invite = Invitations.create(user, new_member) - send_invite_email( - g.current_user.full_name, invite.token, new_member.user.email - ) - - return redirect( - url_for( - "workspaces.workspace_members", - workspace_id=workspace.id, - newMemberName=new_member.user_name, - ) - ) - except AlreadyExistsError: - return render_template( - "error.html", message="There was an error processing your request." - ) - else: - return render_template( - "workspaces/members/new.html", workspace=workspace, form=form - ) - - -@bp.route("/workspaces//members//member_edit") -def view_member(workspace_id, member_id): - workspace = Workspaces.get(g.current_user, workspace_id) - Authorization.check_workspace_permission( - g.current_user, - workspace, - Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, - "edit this workspace user", - ) - member = WorkspaceRoles.get(workspace_id, member_id) - projects = Projects.get_all(g.current_user, member, workspace) - form = EditMemberForm(workspace_role=member.role_name) - editable = g.current_user == member.user - return render_template( - "workspaces/members/edit.html", - workspace=workspace, - member=member, - projects=projects, - form=form, - choices=ENVIRONMENT_ROLES, - env_role_modal_description=ENV_ROLE_MODAL_DESCRIPTION, - EnvironmentRoles=EnvironmentRoles, - editable=editable, - ) - - -@bp.route( - "/workspaces//members//member_edit", methods=["POST"] -) -def update_member(workspace_id, member_id): - workspace = Workspaces.get(g.current_user, workspace_id) - Authorization.check_workspace_permission( - g.current_user, - workspace, - Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, - "edit this workspace user", - ) - member = WorkspaceRoles.get(workspace_id, member_id) - - ids_and_roles = [] - form_dict = http_request.form.to_dict() - for entry in form_dict: - if re.match("env_", entry): - env_id = entry[4:] - env_role = form_dict[entry] or None - ids_and_roles.append({"id": env_id, "role": env_role}) - - form = EditMemberForm(http_request.form) - if form.validate(): - new_role_name = None - if form.data["workspace_role"] != member.role: - member = Workspaces.update_member( - g.current_user, workspace, member, form.data["workspace_role"] - ) - new_role_name = member.role_displayname - - Environments.update_environment_roles( - g.current_user, workspace, member, ids_and_roles - ) - - return redirect( - url_for( - "workspaces.workspace_members", - workspace_id=workspace.id, - memberName=member.user_name, - updatedRole=new_role_name, - ) - ) - else: - return render_template( - "workspaces/members/edit.html", - form=form, - workspace=workspace, - member=member, - ) - - -@bp.route("/workspaces/invitations/", methods=["GET"]) -def accept_invitation(token): - invite = Invitations.accept(g.current_user, token) - - return redirect( - url_for("workspaces.show_workspace", workspace_id=invite.workspace.id) - ) - - -@bp.route("/workspaces//invitations//revoke", methods=["POST"]) -def revoke_invitation(workspace_id, token): - workspace = Workspaces.get_for_update_member(g.current_user, workspace_id) - Invitations.revoke(token) - - return redirect(url_for("workspaces.workspace_members", workspace_id=workspace.id)) - - -@bp.route("/workspaces//invitations//resend", methods=["POST"]) -def resend_invitation(workspace_id, token): - invite = Invitations.resend(g.current_user, workspace_id, token) - send_invite_email(g.current_user.full_name, invite.token, invite.user_email) - return redirect( - url_for( - "workspaces.workspace_members", - workspace_id=workspace_id, - resentInvitationTo=invite.user_name, - ) - ) diff --git a/atst/routes/workspaces/__init__.py b/atst/routes/workspaces/__init__.py new file mode 100644 index 00000000..16e1f746 --- /dev/null +++ b/atst/routes/workspaces/__init__.py @@ -0,0 +1,40 @@ +from flask import Blueprint, request as http_request, g + +workspaces_bp = Blueprint("workspaces", __name__) + +from . import index +from . import projects +from . import members +from . import invitations +from atst.domain.exceptions import UnauthorizedError +from atst.domain.workspaces import Workspaces +from atst.domain.authz import Authorization +from atst.models.permissions import Permissions + + +@workspaces_bp.context_processor +def workspace(): + workspaces = Workspaces.for_user(g.current_user) + workspace = None + if "workspace_id" in http_request.view_args: + try: + workspace = Workspaces.get( + g.current_user, http_request.view_args["workspace_id"] + ) + workspaces = [ws for ws in workspaces if not ws.id == workspace.id] + except UnauthorizedError: + pass + + def user_can(permission): + if workspace: + return Authorization.has_workspace_permission( + g.current_user, workspace, permission + ) + return False + + return { + "workspace": workspace, + "workspaces": workspaces, + "permissions": Permissions, + "user_can": user_can, + } diff --git a/atst/routes/workspaces/index.py b/atst/routes/workspaces/index.py new file mode 100644 index 00000000..a92ead98 --- /dev/null +++ b/atst/routes/workspaces/index.py @@ -0,0 +1,80 @@ +from datetime import date, timedelta + +from flask import render_template, request as http_request, g, redirect, url_for + +from . import workspaces_bp +from atst.domain.reports import Reports +from atst.domain.workspaces import Workspaces +from atst.forms.workspace import WorkspaceForm +from atst.domain.authz import Authorization +from atst.models.permissions import Permissions + + +@workspaces_bp.route("/workspaces") +def workspaces(): + workspaces = Workspaces.for_user(g.current_user) + return render_template("workspaces/index.html", page=5, workspaces=workspaces) + + +@workspaces_bp.route("/workspaces//edit") +def workspace(workspace_id): + workspace = Workspaces.get_for_update_information(g.current_user, workspace_id) + form = WorkspaceForm(data={"name": workspace.name}) + return render_template("workspaces/edit.html", form=form, workspace=workspace) + + +@workspaces_bp.route("/workspaces//edit", methods=["POST"]) +def edit_workspace(workspace_id): + workspace = Workspaces.get_for_update_information(g.current_user, workspace_id) + form = WorkspaceForm(http_request.form) + if form.validate(): + Workspaces.update(workspace, form.data) + return redirect( + url_for("workspaces.workspace_projects", workspace_id=workspace.id) + ) + else: + return render_template("workspaces/edit.html", form=form, workspace=workspace) + + +@workspaces_bp.route("/workspaces/") +def show_workspace(workspace_id): + return redirect(url_for("workspaces.workspace_projects", workspace_id=workspace_id)) + + +@workspaces_bp.route("/workspaces//reports") +def workspace_reports(workspace_id): + workspace = Workspaces.get(g.current_user, workspace_id) + Authorization.check_workspace_permission( + g.current_user, + workspace, + Permissions.VIEW_USAGE_DOLLARS, + "view workspace reports", + ) + + today = date.today() + month = http_request.args.get("month", today.month) + year = http_request.args.get("year", today.year) + current_month = date(int(year), int(month), 15) + prev_month = current_month - timedelta(days=28) + two_months_ago = prev_month - timedelta(days=28) + + expiration_date = workspace.request.task_order.expiration_date + if expiration_date: + remaining_difference = expiration_date - today + remaining_days = remaining_difference.days + else: + remaining_days = None + + return render_template( + "workspaces/reports/index.html", + cumulative_budget=Reports.cumulative_budget(workspace), + workspace_totals=Reports.workspace_totals(workspace), + monthly_totals=Reports.monthly_totals(workspace), + jedi_request=workspace.request, + task_order=workspace.request.task_order, + current_month=current_month, + prev_month=prev_month, + two_months_ago=two_months_ago, + expiration_date=expiration_date, + remaining_days=remaining_days, + ) diff --git a/atst/routes/workspaces/invitations.py b/atst/routes/workspaces/invitations.py new file mode 100644 index 00000000..e1396c1e --- /dev/null +++ b/atst/routes/workspaces/invitations.py @@ -0,0 +1,49 @@ +from flask import g, redirect, url_for, render_template + +from . import workspaces_bp +from atst.domain.workspaces import Workspaces +from atst.domain.invitations import Invitations +from atst.queue import queue + + +def send_invite_email(owner_name, token, new_member_email): + body = render_template("emails/invitation.txt", owner=owner_name, token=token) + queue.send_mail( + [new_member_email], + "{} has invited you to a JEDI Cloud Workspace".format(owner_name), + body, + ) + + +@workspaces_bp.route("/workspaces/invitations/", methods=["GET"]) +def accept_invitation(token): + invite = Invitations.accept(g.current_user, token) + + return redirect( + url_for("workspaces.show_workspace", workspace_id=invite.workspace.id) + ) + + +@workspaces_bp.route( + "/workspaces//invitations//revoke", methods=["POST"] +) +def revoke_invitation(workspace_id, token): + workspace = Workspaces.get_for_update_member(g.current_user, workspace_id) + Invitations.revoke(token) + + return redirect(url_for("workspaces.workspace_members", workspace_id=workspace.id)) + + +@workspaces_bp.route( + "/workspaces//invitations//resend", methods=["POST"] +) +def resend_invitation(workspace_id, token): + invite = Invitations.resend(g.current_user, workspace_id, token) + send_invite_email(g.current_user.full_name, invite.token, invite.user_email) + return redirect( + url_for( + "workspaces.workspace_members", + workspace_id=workspace_id, + resentInvitationTo=invite.user_name, + ) + ) diff --git a/atst/routes/workspaces/members.py b/atst/routes/workspaces/members.py new file mode 100644 index 00000000..92c3c380 --- /dev/null +++ b/atst/routes/workspaces/members.py @@ -0,0 +1,172 @@ +import re + +from flask import render_template, request as http_request, g, redirect, url_for + +from . import workspaces_bp +from atst.routes.workspaces.invitations import send_invite_email +from atst.domain.exceptions import AlreadyExistsError +from atst.domain.projects import Projects +from atst.domain.workspaces import Workspaces +from atst.domain.workspace_roles import WorkspaceRoles, MEMBER_STATUSES +from atst.domain.environments import Environments +from atst.domain.environment_roles import EnvironmentRoles +from atst.forms.new_member import NewMemberForm +from atst.forms.edit_member import EditMemberForm +from atst.forms.data import ( + ENVIRONMENT_ROLES, + ENV_ROLE_MODAL_DESCRIPTION, + WORKSPACE_ROLE_DEFINITIONS, +) +from atst.domain.authz import Authorization +from atst.models.permissions import Permissions +from atst.domain.invitations import Invitations + + +@workspaces_bp.route("/workspaces//members") +def workspace_members(workspace_id): + workspace = Workspaces.get_with_members(g.current_user, workspace_id) + new_member_name = http_request.args.get("newMemberName") + resent_invitation_to = http_request.args.get("resentInvitationTo") + new_member = next( + filter(lambda m: m.user_name == new_member_name, workspace.members), None + ) + members_list = [ + { + "name": k.user_name, + "status": k.display_status, + "id": k.user_id, + "role": k.role_displayname, + "num_env": k.num_environment_roles, + "edit_link": url_for( + "workspaces.view_member", workspace_id=workspace.id, member_id=k.user_id + ), + } + for k in workspace.members + ] + + return render_template( + "workspaces/members/index.html", + workspace=workspace, + role_choices=WORKSPACE_ROLE_DEFINITIONS, + status_choices=MEMBER_STATUSES, + members=members_list, + new_member=new_member, + resent_invitation_to=resent_invitation_to, + ) + + +@workspaces_bp.route("/workspaces//members/new") +def new_member(workspace_id): + workspace = Workspaces.get(g.current_user, workspace_id) + form = NewMemberForm() + return render_template( + "workspaces/members/new.html", workspace=workspace, form=form + ) + + +@workspaces_bp.route("/workspaces//members/new", methods=["POST"]) +def create_member(workspace_id): + workspace = Workspaces.get(g.current_user, workspace_id) + form = NewMemberForm(http_request.form) + user = g.current_user + + if form.validate(): + try: + new_member = Workspaces.create_member(user, workspace, form.data) + invite = Invitations.create(user, new_member) + send_invite_email( + g.current_user.full_name, invite.token, new_member.user.email + ) + + return redirect( + url_for( + "workspaces.workspace_members", + workspace_id=workspace.id, + newMemberName=new_member.user_name, + ) + ) + except AlreadyExistsError: + return render_template( + "error.html", message="There was an error processing your request." + ) + else: + return render_template( + "workspaces/members/new.html", workspace=workspace, form=form + ) + + +@workspaces_bp.route("/workspaces//members//member_edit") +def view_member(workspace_id, member_id): + workspace = Workspaces.get(g.current_user, workspace_id) + Authorization.check_workspace_permission( + g.current_user, + workspace, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + "edit this workspace user", + ) + member = WorkspaceRoles.get(workspace_id, member_id) + projects = Projects.get_all(g.current_user, member, workspace) + form = EditMemberForm(workspace_role=member.role_name) + editable = g.current_user == member.user + return render_template( + "workspaces/members/edit.html", + workspace=workspace, + member=member, + projects=projects, + form=form, + choices=ENVIRONMENT_ROLES, + env_role_modal_description=ENV_ROLE_MODAL_DESCRIPTION, + EnvironmentRoles=EnvironmentRoles, + editable=editable, + ) + + +@workspaces_bp.route( + "/workspaces//members//member_edit", methods=["POST"] +) +def update_member(workspace_id, member_id): + workspace = Workspaces.get(g.current_user, workspace_id) + Authorization.check_workspace_permission( + g.current_user, + workspace, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + "edit this workspace user", + ) + member = WorkspaceRoles.get(workspace_id, member_id) + + ids_and_roles = [] + form_dict = http_request.form.to_dict() + for entry in form_dict: + if re.match("env_", entry): + env_id = entry[4:] + env_role = form_dict[entry] or None + ids_and_roles.append({"id": env_id, "role": env_role}) + + form = EditMemberForm(http_request.form) + if form.validate(): + new_role_name = None + if form.data["workspace_role"] != member.role: + member = Workspaces.update_member( + g.current_user, workspace, member, form.data["workspace_role"] + ) + new_role_name = member.role_displayname + + Environments.update_environment_roles( + g.current_user, workspace, member, ids_and_roles + ) + + return redirect( + url_for( + "workspaces.workspace_members", + workspace_id=workspace.id, + memberName=member.user_name, + updatedRole=new_role_name, + ) + ) + else: + return render_template( + "workspaces/members/edit.html", + form=form, + workspace=workspace, + member=member, + ) diff --git a/atst/routes/workspaces/projects.py b/atst/routes/workspaces/projects.py new file mode 100644 index 00000000..cc6f10f8 --- /dev/null +++ b/atst/routes/workspaces/projects.py @@ -0,0 +1,78 @@ +from flask import render_template, request as http_request, g, redirect, url_for + +from . import workspaces_bp +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, + )