diff --git a/atst/routes/applications/team.py b/atst/routes/applications/team.py index 97783f89..d4fa0a22 100644 --- a/atst/routes/applications/team.py +++ b/atst/routes/applications/team.py @@ -6,6 +6,7 @@ from atst.domain.applications import Applications from atst.domain.application_roles import ApplicationRoles from atst.domain.authz.decorator import user_can_access_decorator as user_can from atst.domain.environment_roles import EnvironmentRoles +from atst.domain.environments import Environments from atst.domain.exceptions import AlreadyExistsError from atst.domain.permission_sets import PermissionSets from atst.domain.users import Users @@ -97,15 +98,25 @@ def update_team(application_id): form = TeamForm(http_request.form) if form.validate(): - for member in form.members: - app_role = ApplicationRoles.get(member.data["user_id"], application.id) + for member_form in form.members: + app_role = ApplicationRoles.get(member_form.user_id.data, application.id) new_perms = [ perm - for perm in member.data["permission_sets"] + for perm in member_form.data["permission_sets"] if perm != PermissionSets.VIEW_APPLICATION ] ApplicationRoles.update_permission_sets(app_role, new_perms) - flash("updated_application_members_permissions") + + for environment_role_form in member_form.environment_roles: + user = Users.get(member_form.user_id.data) + environment = Environments.get( + environment_role_form.environment_id.data + ) + Environments.update_env_role( + environment, user, environment_role_form.role.data + ) + + flash("updated_application_team_settings", application_name=application.name) return redirect( url_for( diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 1557a90e..0a96366a 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -186,10 +186,10 @@ MESSAGES = { """, "category": "success", }, - "updated_application_members_permissions": { + "updated_application_team_settings": { "title_template": translate("flash.success"), "message_template": """ -

{{ "flash.updated_application_members_permissions" | translate }}

+

{{ "flash.updated_application_team_settings" | translate({"application_name": application_name}) }}

""", "category": "success", }, diff --git a/templates/fragments/applications/edit_team.html b/templates/fragments/applications/edit_team.html index dedee4a7..74dba163 100644 --- a/templates/fragments/applications/edit_team.html +++ b/templates/fragments/applications/edit_team.html @@ -36,57 +36,59 @@ ) }} - {% call ToggleSection(section_name="environments") %} - +
+ + {{ "portfolios.applications.team_settings.add_to_environment" | translate }} + {{ Icon("plus") }} + + +
+ {% endcall %} + {{ member_form.user_id() }} + {% endfor %} diff --git a/tests/routes/applications/test_team.py b/tests/routes/applications/test_team.py index 39aaf533..b2d5a0e1 100644 --- a/tests/routes/applications/test_team.py +++ b/tests/routes/applications/test_team.py @@ -3,6 +3,7 @@ import uuid from flask import url_for from atst.domain.permission_sets import PermissionSets +from atst.models import CSPRole from tests.factories import * @@ -17,7 +18,7 @@ def test_application_team(client, user_session): assert response.status_code == 200 -def test_update_team(client, user_session): +def test_update_team_permissions(client, user_session): application = ApplicationFactory.create() owner = application.portfolio.owner app_role = ApplicationRoleFactory.create( @@ -91,6 +92,63 @@ def test_update_team_with_non_app_user(client, user_session): assert response.status_code == 404 +def test_update_team_environment_roles(client, user_session): + application = ApplicationFactory.create() + owner = application.portfolio.owner + app_role = ApplicationRoleFactory.create( + application=application, permission_sets=[] + ) + app_user = app_role.user + environment = EnvironmentFactory.create(application=application) + env_role = EnvironmentRoleFactory.create( + user=app_user, environment=environment, role=CSPRole.NETWORK_ADMIN.value + ) + user_session(owner) + response = client.post( + url_for("applications.update_team", application_id=application.id), + data={ + "members-0-user_id": app_user.id, + "members-0-permission_sets-perms_team_mgmt": PermissionSets.EDIT_APPLICATION_TEAM, + "members-0-permission_sets-perms_env_mgmt": PermissionSets.EDIT_APPLICATION_ENVIRONMENTS, + "members-0-permission_sets-perms_del_env": PermissionSets.DELETE_APPLICATION_ENVIRONMENTS, + "members-0-environment_roles-0-environment_id": environment.id, + "members-0-environment_roles-0-role": CSPRole.TECHNICAL_READ.value, + }, + ) + + assert response.status_code == 302 + assert env_role.role == CSPRole.TECHNICAL_READ.value + + +@pytest.mark.skip(reason="Need to rebase against master") +def test_update_team_revoke_environment_access(client, user_session): + application = ApplicationFactory.create() + owner = application.portfolio.owner + app_role = ApplicationRoleFactory.create( + application=application, permission_sets=[] + ) + app_user = app_role.user + environment = EnvironmentFactory.create(application=application) + env_role = EnvironmentRoleFactory.create( + user=app_user, environment=environment, role=CSPRole.BASIC_ACCESS.value + ) + user_session(owner) + response = client.post( + url_for("applications.update_team", application_id=application.id), + data={ + "members-0-user_id": app_user.id, + "members-0-permission_sets-perms_team_mgmt": PermissionSets.EDIT_APPLICATION_TEAM, + "members-0-permission_sets-perms_env_mgmt": PermissionSets.EDIT_APPLICATION_ENVIRONMENTS, + "members-0-permission_sets-perms_del_env": PermissionSets.DELETE_APPLICATION_ENVIRONMENTS, + "members-0-environment_roles-0-environment_id": environment.id, + "members-0-environment_roles-0-role": "", + }, + ) + + assert response.status_code == 302 + assert env_role.role == CSPRole.TECHNICAL_READ.value + + def test_create_member(client, user_session): user = UserFactory.create() application = ApplicationFactory.create( diff --git a/translations.yaml b/translations.yaml index 53e25cdf..1bbd8dac 100644 --- a/translations.yaml +++ b/translations.yaml @@ -80,7 +80,7 @@ flash: portfolio_home: Go to my portfolio home page success: Success! new_application_member: 'You have successfully invited {user_name} to the team.' - updated_application_members_permissions: 'You have successfully updated member permissions.' + updated_application_team_settings: 'You have updated the {application_name} team settings.' footer: about_link_text: Joint Enterprise Defense Infrastructure browser_support: JEDI Cloud supported on these web browsers