diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index 46919ac4..2e117e88 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -2,6 +2,7 @@ from flask import redirect, render_template, request as http_request, url_for from . import applications_bp from atst.domain.environment_roles import EnvironmentRoles +from atst.domain.environments import Environments from atst.domain.applications import Applications from atst.forms.application import ApplicationForm from atst.forms.app_settings import EnvironmentRolesForm @@ -76,11 +77,43 @@ def update(application_id): ) ) else: + env_data = serialize_env_member_form_data(application) + env_forms = {} + for data in env_data: + env_forms[data["env_id"]] = EnvironmentRolesForm(data=data) + return render_template( "portfolios/applications/edit.html", application=application, form=form, environments_obj=get_environments_obj_for_app(application=application), + env_forms=env_forms, + ) + + +@applications_bp.route( + "/applications//update_env_roles", methods=["POST"] +) +@user_can(Permissions.ASSIGN_ENVIRONMENT_MEMBER, message="update application") +def update_env_roles(application_id): + application = Applications.get(application_id) + env_roles_form = EnvironmentRolesForm(http_request.form) + + if env_roles_form.validate(): + env_data = env_roles_form.data + Environments.update_env_roles_by_environment( + environment_id=env_data["env_id"], team_roles=env_data["team_roles"] + ) + return redirect(url_for("applications.settings", application_id=application.id)) + else: + return render_template( + "portfolios/applications/edit.html", + application=application, + form=ApplicationForm( + name=application.name, description=application.description + ), + environments_obj=get_environments_obj_for_app(application=application), + env_forms=env_roles_form, ) diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index b0f4d427..ff8025b0 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -7,12 +7,15 @@ from tests.factories import ( EnvironmentRoleFactory, EnvironmentFactory, ApplicationFactory, + ApplicationRoleFactory, ) from atst.domain.applications import Applications from atst.domain.environment_roles import EnvironmentRoles from atst.domain.environments import Environments +from atst.domain.permission_sets import PermissionSets from atst.domain.portfolios import Portfolios +from atst.models.environment_role import CSPRole from atst.models.portfolio_role import Status as PortfolioRoleStatus from tests.utils import captured_templates @@ -163,6 +166,89 @@ def test_user_without_permission_cannot_update_application(client, user_session) assert application.description == "Cool stuff happening here!" +def test_user_with_permission_can_update_team_env_roles(client, user_session): + environment = EnvironmentFactory.create() + application = environment.application + env_role_1 = EnvironmentRoleFactory.create( + environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + env_role_2 = EnvironmentRoleFactory.create( + environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + env_role_3 = EnvironmentRoleFactory.create( + environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + app_role = ApplicationRoleFactory.create(application=application) + form_data = { + "env_id": environment.id, + "team_roles-0-user_id": env_role_1.user.id, + "team_roles-0-name": env_role_1.user.full_name, + "team_roles-0-role": CSPRole.NETWORK_ADMIN.value, + "team_roles-1-user_id": env_role_2.user.id, + "team_roles-1-name": env_role_2.user.full_name, + "team_roles-1-role": CSPRole.BASIC_ACCESS.value, + "team_roles-2-user_id": env_role_3.user.id, + "team_roles-2-name": env_role_3.user.full_name, + "team_roles-2-role": "No access", + "team_roles-3-user_id": app_role.user.id, + "team_roles-3-name": app_role.user.full_name, + "team_roles-3-role": CSPRole.TECHNICAL_READ.value, + } + + user_session(application.portfolio.owner) + response = client.post( + url_for("applications.update_env_roles", application_id=application.id), + data=form_data, + follow_redirects=True, + ) + + assert response.status_code == 200 + assert env_role_1.role == CSPRole.NETWORK_ADMIN.value + assert env_role_2.role == CSPRole.BASIC_ACCESS.value + assert not EnvironmentRoles.get(env_role_3.user.id, environment.id) + assert EnvironmentRoles.get(app_role.user.id, environment.id) + + +def test_user_without_permission_cannot_update_team_env_roles(client, user_session): + environment = EnvironmentFactory.create() + application = environment.application + app_role_without_perms = ApplicationRoleFactory.create(application=application) + env_role_1 = EnvironmentRoleFactory.create( + environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + env_role_2 = EnvironmentRoleFactory.create( + environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + app_role = ApplicationRoleFactory.create(application=application) + form_data = { + "env_id": environment.id, + "team_roles-0-user_id": env_role_1.user.id, + "team_roles-0-name": env_role_1.user.full_name, + "team_roles-0-role": CSPRole.NETWORK_ADMIN.value, + "team_roles-1-user_id": env_role_2.user.id, + "team_roles-1-name": env_role_2.user.full_name, + "team_roles-1-role": "No access", + "team_roles-2-user_id": app_role.user.id, + "team_roles-2-name": app_role.user.full_name, + "team_roles-2-role": CSPRole.TECHNICAL_READ.value, + } + + user_session(app_role_without_perms.user) + response = client.post( + url_for("applications.update_env_roles", application_id=application.id), + data=form_data, + follow_redirects=True, + ) + + assert response.status_code == 404 + assert env_role_1.role == CSPRole.BASIC_ACCESS.value + assert ( + EnvironmentRoles.get(env_role_2.user.id, environment.id).role + == CSPRole.BASIC_ACCESS.value + ) + assert not EnvironmentRoles.get(app_role.user.id, environment.id) + + def test_user_can_only_access_apps_in_their_portfolio(client, user_session): portfolio = PortfolioFactory.create() other_portfolio = PortfolioFactory.create(