From b270d0e4b0bcc25545d37fd50fa2678fc39911dd Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 17 Dec 2019 16:10:21 -0500 Subject: [PATCH 01/26] Update new portfolio layout - Move CTA buttons to floating footer - separated -> bordered --- styles/components/_forms.scss | 3 +- templates/portfolios/new/step_1.html | 54 ++++++++++++++-------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/styles/components/_forms.scss b/styles/components/_forms.scss index a6e0709a..43c31c43 100644 --- a/styles/components/_forms.scss +++ b/styles/components/_forms.scss @@ -1,7 +1,8 @@ // Form Grid .form-row { margin: ($gap * 4) 0; - &--separated { + + &--bordered { border-bottom: $color-gray-lighter 1px solid; } diff --git a/templates/portfolios/new/step_1.html b/templates/portfolios/new/step_1.html index 4613b063..3383128b 100644 --- a/templates/portfolios/new/step_1.html +++ b/templates/portfolios/new/step_1.html @@ -16,36 +16,36 @@ {{ StickyCTA(text="Create New Portfolio") }} -
- {{ form.csrf_token }} -
-
- {{ TextInput(form.name, optional=False) }} - {{"forms.portfolio.name.help_text" | translate | safe }} +
+ + {{ form.csrf_token }} +
+
+ {{ TextInput(form.name, optional=False, classes="form-col") }} + {{"forms.portfolio.name.help_text" | translate | safe }} +
-
-
-
- {{ TextInput(form.description, paragraph=True) }} - {{"forms.portfolio.description.help_text" | translate | safe }} +
+
+ {{ TextInput(form.description, paragraph=True) }} + {{"forms.portfolio.description.help_text" | translate | safe }} +
-
-
-
- {{ MultiCheckboxInput(form.defense_component, optional=False) }} - {{ "forms.portfolio.defense_component.help_text" | translate | safe }} +
+
+ {{ MultiCheckboxInput(form.defense_component, optional=False) }} + {{ "forms.portfolio.defense_component.help_text" | translate | safe }} +
-
-
- {{ - SaveButton( - text=('common.save' | translate), - form="portfolio-create", - element="input", - ) - }} -
- + {% endblock %} From 812caf5d7d4fdc537b3e244cd5fea146feccb861 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 11:02:18 -0500 Subject: [PATCH 02/26] Update schema and create/update Environments domain methods to enforce environment name uniqueness within an application context. --- ...dd_uniqueness_contraint_to_environment_.py | 28 +++++++++++++++++++ atst/domain/environments.py | 6 ++-- atst/models/environment.py | 8 +++++- tests/domain/test_environments.py | 23 ++++++++++++++- 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py diff --git a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py new file mode 100644 index 00000000..56985f73 --- /dev/null +++ b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py @@ -0,0 +1,28 @@ +"""add uniqueness contraint to environment within an application + +Revision ID: 08f2a640e9c2 +Revises: c487d91f1a26 +Create Date: 2019-12-16 10:43:12.331095 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '08f2a640e9c2' # pragma: allowlist secret +down_revision = 'c487d91f1a26' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_unique_constraint('environments_name_application_id_key', 'environments', ['name', 'application_id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('environments_name_application_id_key', 'environments', type_='unique') + # ### end Alembic commands ### diff --git a/atst/domain/environments.py b/atst/domain/environments.py index a1056623..fd5f3eb0 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -12,6 +12,7 @@ from atst.models import ( CLIN, ) from atst.domain.environment_roles import EnvironmentRoles +from atst.utils import update_or_raise_already_exists_error from .exceptions import NotFoundError, DisabledError @@ -21,7 +22,7 @@ class Environments(object): def create(cls, user, application, name): environment = Environment(application=application, name=name, creator=user) db.session.add(environment) - db.session.commit() + update_or_raise_already_exists_error(message="environment") return environment @classmethod @@ -39,7 +40,8 @@ class Environments(object): if name is not None: environment.name = name db.session.add(environment) - db.session.commit() + update_or_raise_already_exists_error(message="environment") + return environment @classmethod def get(cls, environment_id): diff --git a/atst/models/environment.py b/atst/models/environment.py index 5fc642e5..115f3ed7 100644 --- a/atst/models/environment.py +++ b/atst/models/environment.py @@ -1,4 +1,4 @@ -from sqlalchemy import Column, ForeignKey, String, TIMESTAMP +from sqlalchemy import Column, ForeignKey, String, TIMESTAMP, UniqueConstraint from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import JSONB from enum import Enum @@ -38,6 +38,12 @@ class Environment( primaryjoin="and_(EnvironmentRole.environment_id == Environment.id, EnvironmentRole.deleted == False)", ) + __table_args__ = ( + UniqueConstraint( + "name", "application_id", name="environments_name_application_id_key" + ), + ) + class ProvisioningStatus(Enum): PENDING = "pending" COMPLETED = "completed" diff --git a/tests/domain/test_environments.py b/tests/domain/test_environments.py index 3aa5f547..298f2675 100644 --- a/tests/domain/test_environments.py +++ b/tests/domain/test_environments.py @@ -4,7 +4,7 @@ from uuid import uuid4 from atst.domain.environments import Environments from atst.domain.environment_roles import EnvironmentRoles -from atst.domain.exceptions import NotFoundError, DisabledError +from atst.domain.exceptions import AlreadyExistsError, DisabledError, NotFoundError from atst.models.environment_role import CSPRole, EnvironmentRole from tests.factories import ( @@ -100,6 +100,27 @@ def test_update_environment(): assert environment.name == "name 2" +def test_create_does_not_duplicate_names_within_application(): + application = ApplicationFactory.create() + name = "Your Environment" + user = application.portfolio.owner + + assert Environments.create(user, application, name) + with pytest.raises(AlreadyExistsError): + Environments.create(user, application, name) + + +def test_update_does_not_duplicate_names_within_application(): + application = ApplicationFactory.create() + name = "Your Environment" + environment = EnvironmentFactory.create(application=application, name=name) + dupe_env = EnvironmentFactory.create(application=application) + user = application.portfolio.owner + + with pytest.raises(AlreadyExistsError): + Environments.update(dupe_env, name) + + class EnvQueryTest: @property def NOW(self): From 63a5d9274b86a24ffd3e44b15ab7296385ae6207 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Mon, 16 Dec 2019 14:38:46 -0500 Subject: [PATCH 03/26] Update route to handle error when env names are duplicated --- atst/routes/applications/settings.py | 69 +++++++++++++--------- atst/utils/flash.py | 5 ++ templates/applications/settings.html | 3 + tests/routes/applications/test_settings.py | 20 ++++++- translations.yaml | 6 +- 5 files changed, 70 insertions(+), 33 deletions(-) diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index f2d252a9..66131c15 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -1,4 +1,10 @@ -from flask import redirect, render_template, request as http_request, url_for, g +from flask import ( + redirect, + render_template, + request as http_request, + url_for, + g, +) from .blueprint import applications_bp from atst.domain.exceptions import AlreadyExistsError @@ -245,16 +251,36 @@ def handle_update_member(application_id, application_role_id, form_data): # TODO: flash error message +def handle_update_environment(form, application=None, environment=None): + if form.validate(): + try: + if environment: + environment = Environments.update( + environment=environment, name=form.name.data + ) + flash("application_environments_updated") + else: + environment = Environments.create( + g.current_user, application=application, name=form.name.data + ) + flash("environment_added", environment_name=form.name.data) + + return environment + + except AlreadyExistsError: + flash("application_environments_name_error", name=form.name.data) + return False + + else: + return False + + @applications_bp.route("/applications//settings") @user_can(Permissions.VIEW_APPLICATION, message="view application edit form") def settings(application_id): application = Applications.get(application_id) - return render_settings_page( - application=application, - active_toggler=http_request.args.get("active_toggler"), - active_toggler_section=http_request.args.get("active_toggler_section"), - ) + return render_settings_page(application=application,) @applications_bp.route("/environments//edit", methods=["POST"]) @@ -264,31 +290,21 @@ def update_environment(environment_id): application = environment.application env_form = EditEnvironmentForm(obj=environment, formdata=http_request.form) + updated_environment = handle_update_environment( + form=env_form, application=application, environment=environment + ) - if env_form.validate(): - Environments.update(environment=environment, name=env_form.name.data) - - flash("application_environments_updated") - + if updated_environment: return redirect( url_for( "applications.settings", application_id=application.id, fragment="application-environments", _anchor="application-environments", - active_toggler=environment.id, - active_toggler_section="edit", ) ) else: - return ( - render_settings_page( - application=application, - active_toggler=environment.id, - active_toggler_section="edit", - ), - 400, - ) + return (render_settings_page(application=application, show_flash=True), 400) @applications_bp.route( @@ -298,14 +314,9 @@ def update_environment(environment_id): def new_environment(application_id): application = Applications.get(application_id) env_form = EditEnvironmentForm(formdata=http_request.form) + environment = handle_update_environment(form=env_form, application=application) - if env_form.validate(): - Environments.create( - g.current_user, application=application, name=env_form.name.data - ) - - flash("environment_added", environment_name=env_form.data["name"]) - + if environment: return redirect( url_for( "applications.settings", @@ -315,7 +326,7 @@ def new_environment(application_id): ) ) else: - return (render_settings_page(application=application), 400) + return (render_settings_page(application=application, show_flash=True), 400) @applications_bp.route("/applications//edit", methods=["POST"]) diff --git a/atst/utils/flash.py b/atst/utils/flash.py index 0de143bb..f876330f 100644 --- a/atst/utils/flash.py +++ b/atst/utils/flash.py @@ -29,6 +29,11 @@ MESSAGES = { """, "category": "success", }, + "application_environments_name_error": { + "title_template": "", + "message_template": """{{ 'flash.application.env_name_error.message' | translate({ 'name': name }) }}""", + "category": "error", + }, "application_environments_updated": { "title_template": "Application environments updated", "message_template": "Application environments have been updated", diff --git a/templates/applications/settings.html b/templates/applications/settings.html index c8e41fcd..875f0232 100644 --- a/templates/applications/settings.html +++ b/templates/applications/settings.html @@ -13,6 +13,9 @@ {% block application_content %} + {% if show_flash -%} + {% include "fragments/flash.html" %} + {%- endif %}

{{ 'portfolios.applications.settings.name_description' | translate }}

{% if user_can(permissions.EDIT_APPLICATION) %} diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 08c979ad..597664d1 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -52,8 +52,6 @@ def test_updating_application_environments_success(client, user_session): _external=True, fragment="application-environments", _anchor="application-environments", - active_toggler=environment.id, - active_toggler_section="edit", ) assert environment.name == "new name a" @@ -78,6 +76,24 @@ def test_update_environment_failure(client, user_session): assert environment.name == "original name" +def test_enforces_unique_env_name(client, user_session, session): + application = ApplicationFactory.create() + user = application.portfolio.owner + name = "New Environment" + environment = EnvironmentFactory.create(application=application, name=name) + form_data = {"name": name} + user_session(user) + + session.begin_nested() + response = client.post( + url_for("applications.new_environment", application_id=application.id), + data=form_data, + ) + session.rollback() + + assert response.status_code == 400 + + def test_application_settings(client, user_session): portfolio = PortfolioFactory.create() application = Applications.create( diff --git a/translations.yaml b/translations.yaml index 6a678f48..e0277fff 100644 --- a/translations.yaml +++ b/translations.yaml @@ -116,6 +116,8 @@ flash: deleted: 'You have successfully deleted the {application_name} application. To view the retained activity log, visit the portfolio administration page.' name_error: message: 'The application name {name} has already been used in this portfolio. Please enter a unique name.' + env_name_error: + message: 'The environment name {name} has already been used in this application. Please enter a unique name.' delete_member_success: 'You have successfully deleted {member_name} from the portfolio.' deleted_member: Portfolio member deleted environment_added: 'The environment "{env_name}" has been added to the application.' @@ -199,7 +201,7 @@ forms:

- defense_component: + defense_component: label: "Select DoD component(s) funding your Portfolio:" choices: air_force: Air Force @@ -211,7 +213,7 @@ forms: help_text: |

Select the DOD component(s) that will fund all Applications within this Portfolio. - In JEDI, multiple DoD organizations can fund the same Portfolio.
+ In JEDI, multiple DoD organizations can fund the same Portfolio.
Select all that apply.

attachment: From e82e0b482a5cd4c02924dacb127cce716d54d021 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Tue, 17 Dec 2019 15:49:48 -0500 Subject: [PATCH 04/26] remove unused imports --- .../08f2a640e9c2_add_uniqueness_contraint_to_environment_.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py index 56985f73..bfc5b894 100644 --- a/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py +++ b/alembic/versions/08f2a640e9c2_add_uniqueness_contraint_to_environment_.py @@ -6,8 +6,6 @@ Create Date: 2019-12-16 10:43:12.331095 """ from alembic import op -import sqlalchemy as sa -from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = '08f2a640e9c2' # pragma: allowlist secret From d300ccf31b74e8fd9cf8b304edaf4eb650957d47 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 10:37:19 -0500 Subject: [PATCH 05/26] Catch error on update applications route when app name is duplicated within a portfolio --- .secrets.baseline | 4 +-- atst/routes/applications/new.py | 32 ++------------------ atst/routes/applications/settings.py | 34 +++++++++++++++++++--- tests/routes/applications/test_settings.py | 17 +++++++++++ tests/test_access.py | 12 ++++++-- 5 files changed, 61 insertions(+), 38 deletions(-) diff --git a/.secrets.baseline b/.secrets.baseline index 24361804..ffa18c6e 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -3,7 +3,7 @@ "files": "^.secrets.baseline$|^.*pgsslrootcert.yml$", "lines": null }, - "generated_at": "2019-12-13T20:38:57Z", + "generated_at": "2019-12-18T15:29:41Z", "plugins_used": [ { "base64_limit": 4.5, @@ -170,7 +170,7 @@ "hashed_secret": "e4f14805dfd1e6af030359090c535e149e6b4207", "is_secret": false, "is_verified": false, - "line_number": 659, + "line_number": 665, "type": "Hex High Entropy String" } ] diff --git a/atst/routes/applications/new.py b/atst/routes/applications/new.py index e9238775..9d673b04 100644 --- a/atst/routes/applications/new.py +++ b/atst/routes/applications/new.py @@ -1,9 +1,7 @@ -from flask import redirect, render_template, request as http_request, url_for, g +from flask import redirect, render_template, request as http_request, url_for from .blueprint import applications_bp from atst.domain.applications import Applications -from atst.domain.exceptions import AlreadyExistsError -from atst.domain.portfolios import Portfolios from atst.forms.application import NameAndDescriptionForm, EnvironmentsForm from atst.domain.authz.decorator import user_can_access_decorator as user_can from atst.models.permissions import Permissions @@ -13,6 +11,7 @@ from atst.routes.applications.settings import ( get_new_member_form, handle_create_member, handle_update_member, + handle_update_application, ) @@ -38,31 +37,6 @@ def render_new_application_form( return render_template(template, **render_args) -def update_application(form, application_id=None, portfolio_id=None): - if form.validate(): - application = None - try: - if application_id: - application = Applications.get(application_id) - application = Applications.update(application, form.data) - flash("application_updated", application_name=application.name) - else: - portfolio = Portfolios.get_for_update(portfolio_id) - application = Applications.create( - g.current_user, portfolio, **form.data - ) - flash("application_created", application_name=application.name) - - return application - - except AlreadyExistsError: - flash("application_name_error", name=form.data["name"]) - return False - - else: - return False - - @applications_bp.route("/portfolios//applications/new") @applications_bp.route("/applications//new/step_1") @user_can(Permissions.CREATE_APPLICATION, message="view create new application form") @@ -90,7 +64,7 @@ def create_or_update_new_application_step_1(portfolio_id=None, application_id=No form = get_new_application_form( {**http_request.form}, NameAndDescriptionForm, application_id ) - application = update_application(form, application_id, portfolio_id) + application = handle_update_application(form, application_id, portfolio_id) if application: return redirect( diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index 66131c15..fc95c615 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -16,6 +16,7 @@ from atst.domain.csp.cloud import GeneralCSPException from atst.domain.common import Paginator from atst.domain.environment_roles import EnvironmentRoles from atst.domain.invitations import ApplicationInvitations +from atst.domain.portfolios import Portfolios from atst.forms.application_member import NewForm as NewMemberForm, UpdateMemberForm from atst.forms.application import NameAndDescriptionForm, EditEnvironmentForm from atst.forms.data import ENV_ROLE_NO_ACCESS as NO_ACCESS @@ -275,6 +276,29 @@ def handle_update_environment(form, application=None, environment=None): return False +def handle_update_application(form, application_id=None, portfolio_id=None): + if form.validate(): + application = None + + try: + if application_id: + application = Applications.get(application_id) + application = Applications.update(application, form.data) + flash("application_updated", application_name=application.name) + else: + portfolio = Portfolios.get_for_update(portfolio_id) + application = Applications.create( + g.current_user, portfolio, **form.data + ) + flash("application_created", application_name=application.name) + + return application + + except AlreadyExistsError: + flash("application_name_error", name=form.data["name"]) + return False + + @applications_bp.route("/applications//settings") @user_can(Permissions.VIEW_APPLICATION, message="view application edit form") def settings(application_id): @@ -334,10 +358,9 @@ def new_environment(application_id): def update(application_id): application = Applications.get(application_id) form = NameAndDescriptionForm(http_request.form) - if form.validate(): - application_data = form.data - Applications.update(application, application_data) + updated_application = handle_update_application(form, application_id) + if updated_application: return redirect( url_for( "applications.portfolio_applications", @@ -345,7 +368,10 @@ def update(application_id): ) ) else: - return render_settings_page(application=application, application_form=form) + return ( + render_settings_page(application=application, show_flash=True), + 400, + ) @applications_bp.route("/applications//delete", methods=["POST"]) diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 597664d1..e9117166 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -274,6 +274,23 @@ def test_user_without_permission_cannot_update_application(client, user_session) assert application.description == "Cool stuff happening here!" +def test_update_application_enforces_unique_name(client, user_session, session): + portfolio = PortfolioFactory.create() + name = "Test Application" + application = ApplicationFactory.create(portfolio=portfolio, name=name) + dupe_application = ApplicationFactory.create(portfolio=portfolio) + user_session(portfolio.owner) + + session.begin_nested() + response = client.post( + url_for("applications.update", application_id=dupe_application.id), + data={"name": name, "description": dupe_application.description}, + ) + session.rollback() + + assert response.status_code == 400 + + def test_user_can_only_access_apps_in_their_portfolio(client, user_session): portfolio = PortfolioFactory.create() other_portfolio = PortfolioFactory.create( diff --git a/tests/test_access.py b/tests/test_access.py index ad4bd5be..ccae69ba 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -538,10 +538,16 @@ def test_applications_update_access(post_url_assert_status): ) app = portfolio.applications[0] + def _form_data(): + return { + "name": "Test Application %s" % (random.randrange(1, 1000)), + "description": "This is only a test", + } + url = url_for("applications.update", application_id=app.id) - post_url_assert_status(dev, url, 200) - post_url_assert_status(ccpo, url, 200) - post_url_assert_status(rando, url, 404) + post_url_assert_status(dev, url, 302, data=_form_data()) + post_url_assert_status(ccpo, url, 302, data=_form_data()) + post_url_assert_status(rando, url, 404, data=_form_data()) # applications.update_environments From f543602076b6468eb7eddc8a2c833a5976bac0d6 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 10:54:00 -0500 Subject: [PATCH 06/26] Update function name to better reflect what it does --- atst/domain/applications.py | 6 +++--- atst/domain/environments.py | 6 +++--- atst/domain/task_orders.py | 6 +++--- atst/utils/__init__.py | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/atst/domain/applications.py b/atst/domain/applications.py index c2321194..3dbb9953 100644 --- a/atst/domain/applications.py +++ b/atst/domain/applications.py @@ -11,7 +11,7 @@ from atst.models import ( ApplicationRoleStatus, EnvironmentRole, ) -from atst.utils import first_or_none, update_or_raise_already_exists_error +from atst.utils import first_or_none, commit_or_raise_already_exists_error class Applications(BaseDomainClass): @@ -28,7 +28,7 @@ class Applications(BaseDomainClass): if environment_names: Environments.create_many(user, application, environment_names) - update_or_raise_already_exists_error(message="application") + commit_or_raise_already_exists_error(message="application") return application @classmethod @@ -55,7 +55,7 @@ class Applications(BaseDomainClass): ) db.session.add(application) - update_or_raise_already_exists_error(message="application") + commit_or_raise_already_exists_error(message="application") return application @classmethod diff --git a/atst/domain/environments.py b/atst/domain/environments.py index fd5f3eb0..b8a59485 100644 --- a/atst/domain/environments.py +++ b/atst/domain/environments.py @@ -12,7 +12,7 @@ from atst.models import ( CLIN, ) from atst.domain.environment_roles import EnvironmentRoles -from atst.utils import update_or_raise_already_exists_error +from atst.utils import commit_or_raise_already_exists_error from .exceptions import NotFoundError, DisabledError @@ -22,7 +22,7 @@ class Environments(object): def create(cls, user, application, name): environment = Environment(application=application, name=name, creator=user) db.session.add(environment) - update_or_raise_already_exists_error(message="environment") + commit_or_raise_already_exists_error(message="environment") return environment @classmethod @@ -40,7 +40,7 @@ class Environments(object): if name is not None: environment.name = name db.session.add(environment) - update_or_raise_already_exists_error(message="environment") + commit_or_raise_already_exists_error(message="environment") return environment @classmethod diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py index 8ad8b0f4..9ecf41e9 100644 --- a/atst/domain/task_orders.py +++ b/atst/domain/task_orders.py @@ -4,7 +4,7 @@ from atst.database import db from atst.models.clin import CLIN from atst.models.task_order import TaskOrder, SORT_ORDERING from . import BaseDomainClass -from atst.utils import update_or_raise_already_exists_error +from atst.utils import commit_or_raise_already_exists_error class TaskOrders(BaseDomainClass): @@ -15,7 +15,7 @@ class TaskOrders(BaseDomainClass): def create(cls, portfolio_id, number, clins, pdf): task_order = TaskOrder(portfolio_id=portfolio_id, number=number, pdf=pdf) db.session.add(task_order) - update_or_raise_already_exists_error(message="task_order") + commit_or_raise_already_exists_error(message="task_order") TaskOrders.create_clins(task_order.id, clins) return task_order @@ -34,7 +34,7 @@ class TaskOrders(BaseDomainClass): task_order.number = number db.session.add(task_order) - update_or_raise_already_exists_error(message="task_order") + commit_or_raise_already_exists_error(message="task_order") return task_order @classmethod diff --git a/atst/utils/__init__.py b/atst/utils/__init__.py index 9772af67..d3f284cc 100644 --- a/atst/utils/__init__.py +++ b/atst/utils/__init__.py @@ -30,7 +30,7 @@ def pick(keys, dct): return {k: v for (k, v) in dct.items() if k in _keys} -def update_or_raise_already_exists_error(message): +def commit_or_raise_already_exists_error(message): try: db.session.commit() except IntegrityError: From d621781c3bfbddf3f821876288b19f93eb202a25 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 11:12:14 -0500 Subject: [PATCH 07/26] 170339063 - Adds network diagrams Network diagrams are created with plantuml Ex. java -jar ~/plantuml.jar ./useast.txt java -jar ~/plantuml.jar ./uswest.txt Running this will create .png diagrams. PNG is the default but can be changed to SVG, PDF, etc --- .../diagram/USEAST Development Network.png | Bin 0 -> 86931 bytes .../diagram/USWEST Development Network.png | Bin 0 -> 72551 bytes terraform/providers/dev/diagram/useast.txt | 50 ++++++++++++++++++ terraform/providers/dev/diagram/uswest.txt | 40 ++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 terraform/providers/dev/diagram/USEAST Development Network.png create mode 100644 terraform/providers/dev/diagram/USWEST Development Network.png create mode 100644 terraform/providers/dev/diagram/useast.txt create mode 100644 terraform/providers/dev/diagram/uswest.txt diff --git a/terraform/providers/dev/diagram/USEAST Development Network.png b/terraform/providers/dev/diagram/USEAST Development Network.png new file mode 100644 index 0000000000000000000000000000000000000000..a32c05db125f6db4f815ff3b907929cd4bda3530 GIT binary patch literal 86931 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 literal 0 HcmV?d00001 diff --git a/terraform/providers/dev/diagram/USWEST Development Network.png b/terraform/providers/dev/diagram/USWEST Development Network.png new file mode 100644 index 0000000000000000000000000000000000000000..ba04343de458324b2311872dfbd6cf078e7dad40 GIT binary patch literal 72551 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%0D}U|OIEGoFMP3Yk%MlNl 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 F{0Fn6iQfPK literal 0 HcmV?d00001 diff --git a/terraform/providers/dev/diagram/useast.txt b/terraform/providers/dev/diagram/useast.txt new file mode 100644 index 00000000..48ee5c45 --- /dev/null +++ b/terraform/providers/dev/diagram/useast.txt @@ -0,0 +1,50 @@ +@startuml USEAST Development Network + +title USEAST Development Network + +cloud Internet + +cloud Azure { + [Azure Storage] as storage + [Azure CDN] as cdn + cdn --> storage : "HTTPS/443" + note as cdn_note + CDN and Azure storage are + managed by Azure and configured + for geographic failover + end note +} +frame "USEAST Virtual Network" as vnet { + frame "Public Route Table" as public_rt{ + frame "Public Subnet" as public_subnet { + [ALB] + [Internet] --> ALB + note as public_useast + 10.1.1.0/24 + end note + } + } + frame "Private Route Table" as private_rt{ + frame "Private Subnet" as private_subnet { + [AKS] + [Redis] + [Postgres] + [AzurePrivateStorage] + AKS --> Redis : "TLS:6379" + AKS --> Postgres : "TLS:5432" + AKS --> AzurePrivateStorage : "HTTPS/443" + [ALB] --> AKS : "HTTPS:443" + note as private_useast + 10.1.2.0/24 + end note + } + } +} + +frame "US West Backup Region" as backupregion { + component "Backup Postgres" as pgbackup + [Postgres] --> pgbackup : "Private Peering / TLS:5432" +} + +note right of [ALB] : Azure Load Balancer restricted to AKS only +@enduml diff --git a/terraform/providers/dev/diagram/uswest.txt b/terraform/providers/dev/diagram/uswest.txt new file mode 100644 index 00000000..1b2338f8 --- /dev/null +++ b/terraform/providers/dev/diagram/uswest.txt @@ -0,0 +1,40 @@ +@startuml USWEST Development Network + +title USWEST Development Network + +cloud Internet + +frame "USEAST Virtual Network" as vnet { + frame "Public Route Table" as public_rt{ + frame "Public Subnet" as public_subnet { + [ALB] + [Internet] --> ALB + note as public_useast + 10.2.1.0/24 + end note + } + } + frame "Private Route Table" as private_rt{ + frame "Private Subnet" as private_subnet { + [AKS] + [Redis] + [Postgres] + [AzurePrivateStorage] + AKS --> Redis : "TLS:6379" + AKS --> Postgres : "TLS:5432" + AKS --> AzurePrivateStorage : "HTTPS/443" + [ALB] --> AKS : "HTTPS:443" + note as private_useast + 10.2.2.0/24 + end note + } + } +} + +frame "USEAST Primary Region " as primary_region{ + component "Postgres" as pgbackup + [Postgres] --> pgbackup : "Private Peering / TLS:5432" +} + +note right of [ALB] : Azure Load Balancer restricted to AKS only +@enduml From 13e8cb8ee108c213423cb702e399e0c24687f9c5 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Tue, 17 Dec 2019 16:43:35 -0500 Subject: [PATCH 08/26] Move form buttons to floating bottom action bar Form action buttons were previously in the sicky CTA bar. This commit moves them to a bottom action bar. --- styles/elements/_action_group.scss | 2 +- templates/home.html | 11 ++----- templates/task_orders/builder_base.html | 39 +++++++++++++------------ templates/task_orders/step_1.html | 1 - translations.yaml | 3 +- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/styles/elements/_action_group.scss b/styles/elements/_action_group.scss index 1f79f7d2..73cad181 100644 --- a/styles/elements/_action_group.scss +++ b/styles/elements/_action_group.scss @@ -46,7 +46,7 @@ background: white; right: 0; padding-right: $gap * 4; - border-top: 1px solid $color-gray-light; + border-top: 1px solid $color-gray-lighter; width: 100%; z-index: 1; } diff --git a/templates/home.html b/templates/home.html index 4e459639..aadcd2a8 100644 --- a/templates/home.html +++ b/templates/home.html @@ -13,12 +13,6 @@ {% set sticky_header = "home.get_started" | translate %} {% endif %} - {% call StickyCTA(sticky_header) %} - - {{ "home.add_portfolio_button_text" | translate }} - - {% endcall %} -

{% include "fragments/flash.html" %} @@ -92,9 +86,10 @@
-
- JEDI heirarchy diagram + + {{ "home.add_portfolio_button_text" | translate }} +
diff --git a/templates/task_orders/builder_base.html b/templates/task_orders/builder_base.html index 362a1038..70bc20c9 100644 --- a/templates/task_orders/builder_base.html +++ b/templates/task_orders/builder_base.html @@ -8,8 +8,26 @@
{{ form.csrf_token }} - {% call StickyCTA(text=('task_orders.form.sticky_header_text' | translate({"step": step}) )) %} - + {{ StickyCTA( + text='task_orders.form.sticky_header_text' | translate, + context=('task_orders.form.sticky_header_context' | translate({"step": step}) )) }} + + {% call Modal(name='cancel', dismissable=True) %} +
+

Do you want to save this draft?

+
+ + +
+
+ {% endcall %} + + {% include "fragments/flash.html" %} + +
+ {% block to_builder_form_field %}{% endblock %} +
+ {% block next_button %} - {% endcall %} - - {% call Modal(name='cancel', dismissable=True) %} -
-

Do you want to save this draft?

-
- - -
-
- {% endcall %} - - {% include "fragments/flash.html" %} - -
- {% block to_builder_form_field %}{% endblock %} -
diff --git a/templates/task_orders/step_1.html b/templates/task_orders/step_1.html index 758099fa..6be3218c 100644 --- a/templates/task_orders/step_1.html +++ b/templates/task_orders/step_1.html @@ -1,7 +1,6 @@ {% extends "task_orders/builder_base.html" %} {% from 'components/icon.html' import Icon %} -{% from "components/sticky_cta.html" import StickyCTA %} {% from "task_orders/form_header.html" import TOFormStepHeader %} {% from 'components/upload_input.html' import UploadInput %} diff --git a/translations.yaml b/translations.yaml index 6a678f48..8fe26475 100644 --- a/translations.yaml +++ b/translations.yaml @@ -526,7 +526,8 @@ task_orders: description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review. alert_message: All task orders require a Contracting Officer signature. next_button: 'Confirm & Submit' - sticky_header_text: 'Add Task Order (step {step} of 5)' + sticky_header_text: 'Add Task Order' + sticky_header_context: 'Step {step} of 5' empty_state: header: Add approved task orders message: Upload your approved Task Order here. You are required to confirm you have the appropriate signature. You will have the ability to add additional approved Task Orders with more funding to this Portfolio in the future. From 66cfaaa6c3e5a30e82931a884df5083986276f82 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 11:29:34 -0500 Subject: [PATCH 09/26] Update copy on TO signature page --- atst/forms/task_order.py | 3 +++ templates/task_orders/form_header.html | 10 ++++++---- templates/task_orders/step_5.html | 17 ++++++++++------- translations.yaml | 12 ++++++++---- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/atst/forms/task_order.py b/atst/forms/task_order.py index a5e02e8b..1c324736 100644 --- a/atst/forms/task_order.py +++ b/atst/forms/task_order.py @@ -151,3 +151,6 @@ class SignatureForm(BaseForm): translate("task_orders.sign.digital_signature_description"), validators=[Required()], ) + confirm = BooleanField( + translate("task_orders.sign.confirmation_description"), validators=[Required()], + ) diff --git a/templates/task_orders/form_header.html b/templates/task_orders/form_header.html index 79821bf7..05f9116a 100644 --- a/templates/task_orders/form_header.html +++ b/templates/task_orders/form_header.html @@ -1,8 +1,10 @@ -{% macro TOFormStepHeader(title, description, to_number=None) %} +{% macro TOFormStepHeader(description, title=None, to_number=None) %}
-
- {{ title }} -
+ {% if title -%} +
+ {{ title }} +
+ {%- endif %} {% if to_number %}

Task Order Number: {{ to_number }} diff --git a/templates/task_orders/step_5.html b/templates/task_orders/step_5.html index 2d19c35b..365174d9 100644 --- a/templates/task_orders/step_5.html +++ b/templates/task_orders/step_5.html @@ -10,11 +10,14 @@ {% set step = "5" %} {% block to_builder_form_field %} - {{ TOFormStepHeader('task_orders.form.step_5.title' | translate, 'task_orders.form.step_5.description' | translate, task_order.number) }} - - {% call Alert('', - message="task_orders.form.step_5.alert_message" | translate - ) %} - {{ CheckboxInput(form.signature) }} - {% endcall %} + {{ TOFormStepHeader('task_orders.form.step_5.description' | translate, to_number=task_order.number) }} + {{ CheckboxInput(form.signature) }} + {{ CheckboxInput(form.confirm) }} +


+
+ {{ "task_orders.sign.acknowledge.title" | translate }} +
+

+ {{ "task_orders.sign.acknowledge.text" | translate }} +

{% endblock %} diff --git a/translations.yaml b/translations.yaml index 6a678f48..1efb8a29 100644 --- a/translations.yaml +++ b/translations.yaml @@ -199,7 +199,7 @@ forms:

- defense_component: + defense_component: label: "Select DoD component(s) funding your Portfolio:" choices: air_force: Air Force @@ -211,7 +211,7 @@ forms: help_text: |

Select the DOD component(s) that will fund all Applications within this Portfolio. - In JEDI, multiple DoD organizations can fund the same Portfolio.
+ In JEDI, multiple DoD organizations can fund the same Portfolio.
Select all that apply.

attachment: @@ -523,7 +523,7 @@ task_orders: next_button: 'Next: Review Task Order' step_5: title: Confirm Signature - description: Finally, plase confirm that your uploaded document representing the information you've entered contains the required signature from your Contracting Officer. You will be informed as soon as CCPO completes their review. + description: Prior to submitting the Task Order, you must acknowledge, by marking the appropriate box below, that the uploaded Task Order is signed by an appropriate, duly warranted Contracting Officer who has the authority to execute the uploaded Task Order on your Agency’s behalf and has authorized you to upload the Task Order in accordance with Agency policy and procedures. You must further acknowledge, by marking the appropriate box below, that all information entered herein matches that of the submitted Task Order. alert_message: All task orders require a Contracting Officer signature. next_button: 'Confirm & Submit' sticky_header_text: 'Add Task Order (step {step} of 5)' @@ -539,7 +539,11 @@ task_orders: subtitle: Who will be involved in the work funded by this task order? team_title: Your team sign: - digital_signature_description: I acknowledge that the uploaded task order contains the required KO signature. + digital_signature_description: I confirm the uploaded Task Order is signed by the appropriate, duly warranted Agency Contracting Officer who authorized me to upload the Task Order. + confirmation_description: I confirm that the information entered here in matches that of the submitted Task Order. + acknowledge: + title: Acknowledge Statement + text: I acknowledge, by executing the confirmation above and submitting this verification, that I am subject to potential penalties that may include fines, imprisonment, or both, under the U.S. law and regulations for any false statement or misrepresentation in association with this Task Order submission or on any accompanying documentation. status_empty_state: 'This Portfolio has no {status} Task Orders.' status_list_title: '{status} Task Orders' JEDICLINType: From 72bb3009131f2f4b79169b92a541a04b4a2f8434 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:00:09 -0500 Subject: [PATCH 10/26] Styling for TO signature page --- styles/elements/_inputs.scss | 9 +++++++++ styles/sections/_task_order.scss | 9 +++++---- templates/task_orders/step_5.html | 6 ++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/styles/elements/_inputs.scss b/styles/elements/_inputs.scss index 47cc4f3c..a5040e41 100644 --- a/styles/elements/_inputs.scss +++ b/styles/elements/_inputs.scss @@ -165,6 +165,15 @@ margin-top: 0; margin-bottom: 0; } + + label { + margin-left: 3rem; + + &:before { + position: absolute; + left: -3rem; + } + } } select { diff --git a/styles/sections/_task_order.scss b/styles/sections/_task_order.scss index 228bf126..c09f49a7 100644 --- a/styles/sections/_task_order.scss +++ b/styles/sections/_task_order.scss @@ -20,10 +20,7 @@ } &__header { - .h2, - p { - margin-bottom: $gap * 0.5; - } + margin-bottom: $gap * 6; } .col { @@ -155,6 +152,10 @@ } } } + + &__confirmation { + margin-left: $gap * 8; + } } .task-order__modal-cancel { diff --git a/templates/task_orders/step_5.html b/templates/task_orders/step_5.html index 365174d9..e5ce9189 100644 --- a/templates/task_orders/step_5.html +++ b/templates/task_orders/step_5.html @@ -11,8 +11,10 @@ {% block to_builder_form_field %} {{ TOFormStepHeader('task_orders.form.step_5.description' | translate, to_number=task_order.number) }} - {{ CheckboxInput(form.signature) }} - {{ CheckboxInput(form.confirm) }} +
+ {{ CheckboxInput(form.signature) }} + {{ CheckboxInput(form.confirm) }} +

{{ "task_orders.sign.acknowledge.title" | translate }} From 5b55b5800e26ba8c8f5c422e562444dd0c900419 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:18:43 -0500 Subject: [PATCH 11/26] Remove route, tests, and template code for deleting an application --- atst/routes/applications/settings.py | 15 ------ templates/applications/settings.html | 53 +--------------------- tests/routes/applications/test_settings.py | 35 -------------- tests/test_access.py | 34 -------------- 4 files changed, 1 insertion(+), 136 deletions(-) diff --git a/atst/routes/applications/settings.py b/atst/routes/applications/settings.py index f2d252a9..7d5c20d4 100644 --- a/atst/routes/applications/settings.py +++ b/atst/routes/applications/settings.py @@ -337,21 +337,6 @@ def update(application_id): return render_settings_page(application=application, application_form=form) -@applications_bp.route("/applications//delete", methods=["POST"]) -@user_can(Permissions.DELETE_APPLICATION, message="delete application") -def delete(application_id): - application = Applications.get(application_id) - Applications.delete(application) - - flash("application_deleted", application_name=application.name) - - return redirect( - url_for( - "applications.portfolio_applications", portfolio_id=application.portfolio_id - ) - ) - - @applications_bp.route("/environments//delete", methods=["POST"]) @user_can(Permissions.DELETE_ENVIRONMENT, message="delete environment") def delete_environment(environment_id): diff --git a/templates/applications/settings.html b/templates/applications/settings.html index c8e41fcd..9d2fb146 100644 --- a/templates/applications/settings.html +++ b/templates/applications/settings.html @@ -59,59 +59,8 @@ environments_obj, new_env_form) }} - {% if user_can(permissions.DELETE_APPLICATION) %} - {% set env_count = application.environments | length %} - {% if env_count == 1 %} - {% set pluralized_env = "environment" %} - {% else %} - {% set pluralized_env = "environments" %} - {% endif %} - -

- {{ "portfolios.applications.delete.subheading" | translate }} -

-
-
- {{ "portfolios.applications.delete.text" | translate({"application_name": application.name}) | safe }} -
-
-
- -
-
-
- - {% call Modal(name="delete-application") %} -

{{ "portfolios.applications.delete.header" | translate }}

-
- {{ - Alert( - title=("components.modal.destructive_title" | translate), - message=("portfolios.applications.delete.alert.message" | translate), - level="warning" - ) - }} - - {{ - DeleteConfirmation( - modal_id="delete_application", - delete_text=('portfolios.applications.delete.button' | translate), - delete_action= url_for('applications.delete', application_id=application.id), - form=application_form - ) - }} - {% endcall %} - {% endif %} - -
- {% if user_can(permissions.VIEW_APPLICATION_ACTIVITY_LOG) and config.get("USE_AUDIT_LOG", False) %} +
{% include "fragments/audit_events_log.html" %} {{ Pagination(audit_events, url=url_for('applications.settings', application_id=application.id)) }} {% endif %} diff --git a/tests/routes/applications/test_settings.py b/tests/routes/applications/test_settings.py index 08c979ad..cd075c80 100644 --- a/tests/routes/applications/test_settings.py +++ b/tests/routes/applications/test_settings.py @@ -288,41 +288,6 @@ def test_user_can_only_access_apps_in_their_portfolio(client, user_session): assert time_updated == other_application.time_updated -def test_delete_application(client, user_session): - user = UserFactory.create() - port = PortfolioFactory.create( - owner=user, - applications=[ - { - "name": "mos eisley", - "environments": [ - {"name": "bar"}, - {"name": "booth"}, - {"name": "band stage"}, - ], - } - ], - ) - application = port.applications[0] - user_session(user) - - response = client.post( - url_for("applications.delete", application_id=application.id) - ) - # appropriate response and redirect - assert response.status_code == 302 - assert response.location == url_for( - "applications.portfolio_applications", portfolio_id=port.id, _external=True - ) - # appropriate flash message - message = get_flashed_messages()[0] - assert "deleted" in message["message"] - assert application.name in message["message"] - # app and envs are soft deleted - assert len(port.applications) == 0 - assert len(application.environments) == 0 - - def test_new_environment(client, user_session): user = UserFactory.create() portfolio = PortfolioFactory(owner=user) diff --git a/tests/test_access.py b/tests/test_access.py index ad4bd5be..5c8d5ae1 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -343,40 +343,6 @@ def test_portfolios_invite_member_access(post_url_assert_status): post_url_assert_status(rando, url, 404) -# applications.delete -def test_applications_delete_access(post_url_assert_status, monkeypatch): - ccpo = UserFactory.create_ccpo() - owner = user_with() - app_admin = user_with() - rando = user_with() - - portfolio = PortfolioFactory.create( - owner=owner, applications=[{"name": "mos eisley"}] - ) - application = portfolio.applications[0] - - ApplicationRoleFactory.create( - user=app_admin, - application=application, - permission_sets=PermissionSets.get_many( - [ - PermissionSets.VIEW_APPLICATION, - PermissionSets.EDIT_APPLICATION_ENVIRONMENTS, - PermissionSets.EDIT_APPLICATION_TEAM, - PermissionSets.DELETE_APPLICATION_ENVIRONMENTS, - ] - ), - ) - - monkeypatch.setattr("atst.domain.applications.Applications.delete", lambda *a: True) - - url = url_for("applications.delete", application_id=application.id) - post_url_assert_status(app_admin, url, 404) - post_url_assert_status(rando, url, 404) - post_url_assert_status(owner, url, 302) - post_url_assert_status(ccpo, url, 302) - - # applications.settings def test_application_settings_access(get_url_assert_status): ccpo = user_with(PermissionSets.VIEW_PORTFOLIO_APPLICATION_MANAGEMENT) From 2b884f2c855c40e6dba5a23e7b932b053806be44 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 12:22:14 -0500 Subject: [PATCH 12/26] Remove route, tests, and template code for deleting a portfolio --- atst/routes/portfolios/index.py | 10 ----- templates/portfolios/admin.html | 6 +-- .../fragments/delete_portfolio.html | 42 ------------------- tests/routes/portfolios/test_index.py | 32 -------------- tests/test_access.py | 31 -------------- 5 files changed, 1 insertion(+), 120 deletions(-) delete mode 100644 templates/portfolios/fragments/delete_portfolio.html diff --git a/atst/routes/portfolios/index.py b/atst/routes/portfolios/index.py index 0447be57..f9e7d5cf 100644 --- a/atst/routes/portfolios/index.py +++ b/atst/routes/portfolios/index.py @@ -56,13 +56,3 @@ def reports(portfolio_id): monthly_spending=Reports.monthly_spending(portfolio), retrieved=datetime.now(), # mocked datetime of reporting data retrival ) - - -@portfolios_bp.route("/portfolios//destroy", methods=["POST"]) -@user_can(Permissions.ARCHIVE_PORTFOLIO, message="archive portfolio") -def delete_portfolio(portfolio_id): - Portfolios.delete(portfolio=g.portfolio) - - flash("portfolio_deleted", portfolio_name=g.portfolio.name) - - return redirect(url_for("atst.home")) diff --git a/templates/portfolios/admin.html b/templates/portfolios/admin.html index 5bfb7d7c..d1e6e353 100644 --- a/templates/portfolios/admin.html +++ b/templates/portfolios/admin.html @@ -56,14 +56,10 @@ {% include "portfolios/fragments/primary_point_of_contact.html" %} {% endif %} - {% if user_can(permissions.ARCHIVE_PORTFOLIO) %} - {% include "portfolios/fragments/delete_portfolio.html" %} - {% endif %} - {% if user_can(permissions.VIEW_PORTFOLIO_USERS) %} {% include "portfolios/fragments/portfolio_members.html" %} {% endif %} - + {% if user_can(permissions.VIEW_PORTFOLIO_ACTIVITY_LOG) and config.get("USE_AUDIT_LOG", False) %} {% include "fragments/audit_events_log.html" %} {{ Pagination(audit_events, url_for('portfolios.admin', portfolio_id=portfolio.id)) }} diff --git a/templates/portfolios/fragments/delete_portfolio.html b/templates/portfolios/fragments/delete_portfolio.html deleted file mode 100644 index da83b2e7..00000000 --- a/templates/portfolios/fragments/delete_portfolio.html +++ /dev/null @@ -1,42 +0,0 @@ -{% from "components/delete_confirmation.html" import DeleteConfirmation %} -{% from "components/alert.html" import Alert %} -{% from "components/modal.html" import Modal %} - -
-
-

{{ "fragments.delete_portfolio.title" | translate }}

-

{{ "fragments.delete_portfolio.subtitle" | translate }}

- - -
- {{ "common.deactivate" | translate }} -
-
-
- -{% call Modal(name="delete_portfolio") %} -

- {{ 'fragments.delete_portfolio.title' | translate }} -

-
- {{ - Alert( - level="warning", - title=('components.modal.destructive_title' | translate), - message=('components.modal.destructive_message' | translate({"resource": "portfolio"})), - ) - }} - - {{ - DeleteConfirmation( - modal_id='delete_portfolio', - delete_text='Deactivate', - delete_action=url_for('portfolios.delete_portfolio', portfolio_id=portfolio.id), - form=portfolio_form, - confirmation_text="deactivate", - ) - }} -{% endcall %} diff --git a/tests/routes/portfolios/test_index.py b/tests/routes/portfolios/test_index.py index 745430f0..489f73b2 100644 --- a/tests/routes/portfolios/test_index.py +++ b/tests/routes/portfolios/test_index.py @@ -84,35 +84,3 @@ def test_portfolio_reports_with_mock_portfolio(client, user_session): response = client.get(url_for("portfolios.reports", portfolio_id=portfolio.id)) assert response.status_code == 200 assert portfolio.name in response.data.decode() - - -def test_delete_portfolio_success(client, user_session): - portfolio = PortfolioFactory.create() - owner = portfolio.owner - user_session(owner) - - assert len(Portfolios.for_user(user=owner)) == 1 - - response = client.post( - url_for("portfolios.delete_portfolio", portfolio_id=portfolio.id) - ) - - assert response.status_code == 302 - assert url_for("atst.home") in response.location - assert len(Portfolios.for_user(user=owner)) == 0 - - -def test_delete_portfolio_failure(no_debug_client, user_session): - portfolio = PortfolioFactory.create() - application = ApplicationFactory.create(portfolio=portfolio) - owner = portfolio.owner - user_session(owner) - - assert len(Portfolios.for_user(user=owner)) == 1 - - response = no_debug_client.post( - url_for("portfolios.delete_portfolio", portfolio_id=portfolio.id) - ) - - assert response.status_code == 500 - assert len(Portfolios.for_user(user=owner)) == 1 diff --git a/tests/test_access.py b/tests/test_access.py index 5c8d5ae1..1adcb65d 100644 --- a/tests/test_access.py +++ b/tests/test_access.py @@ -665,34 +665,3 @@ def test_task_orders_new_post_routes(post_url_assert_status): post_url_assert_status(owner, url, 302, data=data) post_url_assert_status(ccpo, url, 302, data=data) post_url_assert_status(rando, url, 404, data=data) - - -def test_portfolio_delete_access(post_url_assert_status): - rando = UserFactory.create() - owner = UserFactory.create() - ccpo = UserFactory.create_ccpo() - - post_url_assert_status( - ccpo, - url_for( - "portfolios.delete_portfolio", portfolio_id=PortfolioFactory.create().id - ), - 302, - ) - - post_url_assert_status( - owner, - url_for( - "portfolios.delete_portfolio", - portfolio_id=PortfolioFactory.create(owner=owner).id, - ), - 302, - ) - - post_url_assert_status( - rando, - url_for( - "portfolios.delete_portfolio", portfolio_id=PortfolioFactory.create().id - ), - 404, - ) From 83690ccf1a22266e2e03dee414fd1710ba0562fa Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 15:14:22 -0500 Subject: [PATCH 13/26] 169163334 - Adds redis module Adds basic redis module. --- terraform/modules/redis/main.tf | 24 +++++++++++ terraform/modules/redis/outputs.tf | 0 terraform/modules/redis/variables.tf | 60 ++++++++++++++++++++++++++++ terraform/providers/dev/redis.tf | 7 ++++ 4 files changed, 91 insertions(+) create mode 100644 terraform/modules/redis/main.tf create mode 100644 terraform/modules/redis/outputs.tf create mode 100644 terraform/modules/redis/variables.tf create mode 100644 terraform/providers/dev/redis.tf diff --git a/terraform/modules/redis/main.tf b/terraform/modules/redis/main.tf new file mode 100644 index 00000000..1e47f767 --- /dev/null +++ b/terraform/modules/redis/main.tf @@ -0,0 +1,24 @@ +resource "azurerm_resource_group" "redis" { + name = "${var.name}-${var.environment}-redis" + location = var.region +} + +# NOTE: the Name used for Redis needs to be globally unique +resource "azurerm_redis_cache" "redis" { + name = "${var.name}-${var.environment}-redis" + location = azurerm_resource_group.redis.location + resource_group_name = azurerm_resource_group.redis.name + capacity = var.capacity + family = var.family + sku_name = var.sku_name + enable_non_ssl_port = var.enable_non_ssl_port + minimum_tls_version = var.minimum_tls_version + + redis_configuration { + enable_authentication = var.enable_authentication + } + tags = { + environment = var.environment + owner = var.owner + } +} diff --git a/terraform/modules/redis/outputs.tf b/terraform/modules/redis/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/redis/variables.tf b/terraform/modules/redis/variables.tf new file mode 100644 index 00000000..ecdb7636 --- /dev/null +++ b/terraform/modules/redis/variables.tf @@ -0,0 +1,60 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "capacity" { + type = string + default = 2 + description = "The capacity of the redis cache" + +} + +variable "family" { + type = string + default = "C" + description = "The subscription family for redis" + +} + +variable "sku_name" { + type = string + default = "Standard" + description = "The sku to use" + +} + +variable "enable_non_ssl_port" { + type = bool + default = false + description = "Enable non TLS port (default: false)" + +} + +variable "minimum_tls_version" { + type = string + default = "1.2" + description = "Minimum TLS version to use" + +} + +variable "enable_authentication" { + type = bool + default = true + description = "Enable or disable authentication (default: true)" +} diff --git a/terraform/providers/dev/redis.tf b/terraform/providers/dev/redis.tf new file mode 100644 index 00000000..fca3a4e3 --- /dev/null +++ b/terraform/providers/dev/redis.tf @@ -0,0 +1,7 @@ +module "redis" { + source = "../../modules/redis" + owner = var.owner + environment = var.environment + region = var.region + name = var.name +} From d247620c514eb2c15cc93c98241555dd02a3f4b3 Mon Sep 17 00:00:00 2001 From: graham-dds Date: Wed, 18 Dec 2019 12:04:38 -0500 Subject: [PATCH 14/26] Slience output from curl for integration tests We use curl in our integration test script to make sure the application container is available before moving on. We expect many connection errors and don't care about the output of curl, so this will just swallow all of the output. --- script/integration_tests | 7 +++++-- uitests/README.md | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/script/integration_tests b/script/integration_tests index e84b103a..cb0d813a 100755 --- a/script/integration_tests +++ b/script/integration_tests @@ -72,15 +72,18 @@ $CONTAINER_IMAGE \ # Use curl to wait for application container to become available docker pull curlimages/curl:latest +echo "Waiting for application container to become available" docker run --network atat \ curlimages/curl:latest \ - curl --connect-timeout 3 \ + curl \ + --silent \ + --connect-timeout 3 \ --max-time 5 \ --retry $CONTAINER_TIMEOUT \ --retry-connrefused \ --retry-delay 1 \ --retry-max-time $CONTAINER_TIMEOUT \ - test-atat:8000 + test-atat:8000 >/dev/null # Run Ghost Inspector tests docker pull ghostinspector/test-runner-standalone:latest diff --git a/uitests/README.md b/uitests/README.md index aa1dfd93..c05b92b2 100644 --- a/uitests/README.md +++ b/uitests/README.md @@ -58,6 +58,5 @@ NGROK_TOKEN= GI_API_KEY= GI_SUITE= CONTAINER_IMAGE=atat:b - If you get errors regarding ports being in use, make sure you don't have instances of the Flask app, Postgres, or Redis running locally using those ports. - If the curl command used to wait for the application container times out and fails, you can increase the timeout by setting a CONTAINER_TIMEOUT environment variable. It defaults to 200 in the script. -- The curl command will print errors until it successfully connects to the application container. These are normal and expected. When it finally connects, it will print the ATAT home page HTML to STDOUT. - You may see errors like "No such container". The script attempts to clean up any previous incarnations of the containers before it starts, and it may print errors when it doesn't find them. This is fine. - The script is, for the most part, a series of docker commands, so try running the commands individually and debugging that way. From 8166c05ec25c2273e6586dc99ad8442a1c27406b Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 14:17:03 -0500 Subject: [PATCH 15/26] Always show side nav and update styling --- styles/elements/_sidenav.scss | 52 ++++++++++++++++-------- templates/base.html | 4 +- templates/navigation/global_sidenav.html | 34 ++++++++-------- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/styles/elements/_sidenav.scss b/styles/elements/_sidenav.scss index 0a6b201c..224895fb 100644 --- a/styles/elements/_sidenav.scss +++ b/styles/elements/_sidenav.scss @@ -1,8 +1,3 @@ -@mixin sidenav__header { - padding: $gap ($gap * 2); - font-weight: bold; -} - .sidenav-container { box-shadow: $box-shadow; overflow: hidden; @@ -26,34 +21,58 @@ margin: 0px; } - &__title { - @include sidenav__header; + &__header { + padding: $gap ($gap * 2); + font-weight: bold; + border-bottom: 1px solid $color-gray-lighter; - font-size: $h3-font-size; + &--minimized { + @extend .sidenav__header; + + padding: $gap; + width: $sidenav-collapsed-width; + } + } + + &__title { + font-size: $h6-font-size; text-transform: uppercase; width: 50%; color: $color-gray-dark; opacity: 0.54; + white-space: nowrap; + padding: $gap; + display: inline-flex; + align-items: center; } &__toggle { - @include sidenav__header; - font-size: $small-font-size; - line-height: 2.8rem; - float: right; - color: $color-blue-darker; + color: $color-blue; + text-decoration: none; + padding: $gap; + display: inline-flex; + align-items: center; .toggle-arrows { vertical-align: middle; + @include icon-size(20); + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } } } ul { &.sidenav__list--padded { - margin-top: 4 * $gap; + margin-top: 3 * $gap; margin-bottom: $footer-height; - padding-bottom: $gap; + padding: 0 $gap ($gap * 2); position: fixed; overflow-y: scroll; top: $topbar-height + $usa-banner-height + 4rem; @@ -69,6 +88,7 @@ li { margin: 0; display: block; + color: $color-black-light; } } @@ -90,7 +110,7 @@ display: block; padding: $gap ($gap * 2); color: $color-black; - text-decoration: underline; + text-decoration: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/templates/base.html b/templates/base.html index fabcb92c..f4964add 100644 --- a/templates/base.html +++ b/templates/base.html @@ -21,9 +21,7 @@ {% include 'navigation/topbar.html' %}
- {% if portfolios %} - {% include 'navigation/global_sidenav.html' %} - {% endif %} + {% include 'navigation/global_sidenav.html' %}
{% block sidenav %}{% endblock %} diff --git a/templates/navigation/global_sidenav.html b/templates/navigation/global_sidenav.html index c6141641..84ce99e6 100644 --- a/templates/navigation/global_sidenav.html +++ b/templates/navigation/global_sidenav.html @@ -7,29 +7,29 @@
- +
- +
-
Portfolios
    - {% if portfolios %} - {% for other_portfolio in portfolios|sort(attribute='name') %} - {{ SidenavItem(other_portfolio.name, - href=url_for("applications.portfolio_applications", portfolio_id=other_portfolio.id), - active=(other_portfolio.id | string) == request.view_args.get('portfolio_id') - ) }} - {% endfor %} - {% else %} -
  • You have no portfolios yet
  • - {% endif %} + {% for other_portfolio in portfolios|sort(attribute='name') %} + {{ SidenavItem(other_portfolio.name, + href=url_for("applications.portfolio_applications", portfolio_id=other_portfolio.id), + active=(other_portfolio.id | string) == request.view_args.get('portfolio_id') + ) }} + {% endfor %}
From 2584c43c90af23641e0a99ac20b8a587c99a4726 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 15:29:10 -0500 Subject: [PATCH 16/26] Home page styling updates: - Update copy - Update menu description section --- styles/core/_variables.scss | 1 + styles/elements/_icons.scss | 15 +++++ styles/sections/_home.scss | 54 ++++-------------- templates/home.html | 107 +++++++++++++----------------------- translations.yaml | 10 ++-- 5 files changed, 71 insertions(+), 116 deletions(-) diff --git a/styles/core/_variables.scss b/styles/core/_variables.scss index fe81b498..44fc53c8 100644 --- a/styles/core/_variables.scss +++ b/styles/core/_variables.scss @@ -17,6 +17,7 @@ $usa-banner-height: 2.8rem; $sidenav-expanded-width: 25rem; $sidenav-collapsed-width: 10rem; $max-panel-width: 80rem; +$home-pg-icon-width: 6rem; /* * USWDS Variables diff --git a/styles/elements/_icons.scss b/styles/elements/_icons.scss index c7a43414..b2980227 100644 --- a/styles/elements/_icons.scss +++ b/styles/elements/_icons.scss @@ -94,4 +94,19 @@ &--primary { @include icon-color($color-primary); } + + &--home-pg-badge { + @include icon-size(27); + @include icon-color($color-white); + + background-color: $color-primary; + height: $home-pg-icon-width; + width: $home-pg-icon-width; + border-radius: 100%; + display: inline-flex; + + svg { + margin: auto; + } + } } diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index 1ca33efc..25aac6e3 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -2,48 +2,23 @@ .sticky-cta { margin: -1.6rem -1.6rem 0 -1.6rem; } -} -.about-cloud { - margin: 4rem auto; - max-width: 900px; -} + &__content { + margin: 4rem auto; + max-width: 900px; -.your-project { - margin-top: 3rem; - padding: 3rem; - background-color: $color-gray-lightest; + &--descriptions { + .col { + margin-left: $home-pg-icon-width; + padding: ($gap * 2) ($gap * 4); + position: relative; - h2 { - margin-top: 0; - } - - .links { - justify-content: flex-start; - - .icon-link { - padding: $gap ($gap * 4); - - &:first-child { - padding-left: 0; - } - - &:last-child { - padding-right: 0; - } - - &:hover { - background-color: transparent; - color: $color-gray-dark; - - .svg * { - fill: $color-gray-dark; + .icon--home-pg-badge { + position: absolute; + left: -$home-pg-icon-width; + top: $gap * 3; } } - - &.active:hover { - color: $color-blue; - } } } } @@ -112,8 +87,3 @@ } } } - -#jedi-heirarchy { - max-width: 65rem; - margin-top: $gap * 8; -} diff --git a/templates/home.html b/templates/home.html index aadcd2a8..03dfd0fd 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,8 +1,7 @@ {% extends "base.html" %} -{% from "components/sticky_cta.html" import StickyCTA %} {% from "components/icon.html" import Icon %} -{% from "components/semi_collapsible_text.html" import SemiCollapsibleText %} +{% from "components/sticky_cta.html" import StickyCTA %} {% block content %} @@ -13,80 +12,50 @@ {% set sticky_header = "home.get_started" | translate %} {% endif %} -
+
{% include "fragments/flash.html" %}

{{ "home.head" | translate }}

+

Set up a Portfolio

+

New Portfolios will be visible in the left side bar of this page.

+

All TOs associated to a specific Application or set of related Applications will be entered at the Portfolio level. Funding is applied and managed at the Portfolio level as well.

+
- {{ SemiCollapsibleText(first_half=("home.about_cloud.part1"|translate), second_half=("home.about_cloud.part2"|translate)) }} - -
-

{{ "home.your_project" | translate }}

-

{{ "home.your_project_descrip" | translate }}

- -
- - {% macro Link(icon, text, section, default=False) %} - {% if default %} -
- {% else %} -
- {% endif %} -
- - -
+
+
+
+ {{ Icon('funding', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.funding" | translate }}

+

+ {{ "home.funding_descrip" | translate }} +

- {% endmacro %} - - -
-
- -
- {% macro Description(section, default=False) %} - {% if default %} -

- {% else %} -

- {% endif %} - - {{ "navigation.portfolio_navigation.breadcrumbs.%s" | format(section) | translate }} - - {{ "home.%s_descrip" | format(section) | translate }} -

- {% endmacro %} -
- {{ Description('funding', default=True) }} - {{ Description('applications') }} - {{ Description('reports') }} - {{ Description('admin') }} -
+
+ {{ Icon('chart-pie', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.reports" | translate }}

+

+ {{ "home.reports_descrip" | translate }} +

- +
+
+
+ {{ Icon('applications', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.applications" | translate }}

+

+ {{ "home.applications_descrip" | translate }} +

+
+
+ {{ Icon('cog', classes="icon--home-pg-badge") }} +

{{ "navigation.portfolio_navigation.breadcrumbs.admin" | translate }}

+

+ {{ "home.admin_descrip" | translate }} +

+
+
+ {{ "home.add_portfolio_button_text" | translate }} diff --git a/translations.yaml b/translations.yaml index 773202bd..b7c0ffae 100644 --- a/translations.yaml +++ b/translations.yaml @@ -22,13 +22,13 @@ home: add_portfolio_button_text: Add New Portfolio new_portfolio: New Portfolio get_started: Get Started - head: About Cloud Services + head: JEDI Cloud Services your_project: Your Project your_project_descrip: Your portfolio is where all task orders pertaining to a specific project or set of related projects live. In JEDI, every task order in your portfolio has four components. - funding_descrip: is information about all approved task orders associated to your portfolio. - applications_descrip: ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod - reports_descrip: enim ad minim veniam, quis nostrud exercitation ullamco - admin_descrip: aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + funding_descrip: The Task Orders section allows you to enter, manage, and edit awarded TOs associated to a specific Portfolio. + applications_descrip: The Applications section allows you to easily create and define new Applications within a Portfolio, as well as manage user permissions and Environments. + reports_descrip: The Reports section allows you to view and monitor funding usage within a specific Portfolio. + admin_descrip: Within the Settings section, you can manage your Portfolio name and description, as well as add, edit, and delete Portfolio managers. ccpo: users_title: CCPO Users add_user: Add new CCPO user From 217a29b0dcb120341ebb02b4e473644bddc9028d Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:18:47 -0500 Subject: [PATCH 17/26] Adjust margins on home page, globally fix hr elements to default to having margins, and add class for hr elements to span full width of their container --- styles/core/_util.scss | 6 +++++- styles/sections/_home.scss | 1 + templates/applications/fragments/member_form_fields.html | 2 +- templates/applications/fragments/members.html | 4 ++-- .../applications/fragments/new_member_modal_content.html | 2 +- .../portfolios/fragments/add_new_portfolio_member.html | 4 ++-- templates/portfolios/fragments/change_ppoc.html | 4 ++-- 7 files changed, 14 insertions(+), 9 deletions(-) diff --git a/styles/core/_util.scss b/styles/core/_util.scss index ff6e8e3f..5203da45 100644 --- a/styles/core/_util.scss +++ b/styles/core/_util.scss @@ -88,5 +88,9 @@ p { hr { border: 0; border-bottom: 1px solid $color-gray-light; - margin: ($gap * 3) ($site-margins * -4); + margin: ($gap * 3) 0; + + &.full-width { + margin: ($gap * 3) ($site-margins * -4); + } } diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index 25aac6e3..a721b71c 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -1,4 +1,5 @@ .home { + margin: $gap * 3; .sticky-cta { margin: -1.6rem -1.6rem 0 -1.6rem; } diff --git a/templates/applications/fragments/member_form_fields.html b/templates/applications/fragments/member_form_fields.html index 20ecc210..3aa97687 100644 --- a/templates/applications/fragments/member_form_fields.html +++ b/templates/applications/fragments/member_form_fields.html @@ -100,7 +100,7 @@ {{ CheckboxInput(form.perms_env_mgmt, classes="input__inline-fields", key=env_mgmt, id=env_mgmt, optional=True) }} {{ CheckboxInput(form.perms_del_env, classes="input__inline-fields", key=del_env, id=del_env, optional=True) }}
-
+

{{ "portfolios.applications.members.form.env_access.title" | translate }}

diff --git a/templates/applications/fragments/members.html b/templates/applications/fragments/members.html index 1a7bcb4a..be312351 100644 --- a/templates/applications/fragments/members.html +++ b/templates/applications/fragments/members.html @@ -40,7 +40,7 @@ {% call Modal(modal_name, classes="form-content--app-mem") %}

-
+
{{ TextInput(form.description, paragraph=True, optional=True) }} diff --git a/templates/applications/new/step_2.html b/templates/applications/new/step_2.html index bb622f8f..9adfddca 100644 --- a/templates/applications/new/step_2.html +++ b/templates/applications/new/step_2.html @@ -19,7 +19,7 @@

{{ 'portfolios.applications.new.step_2_description' | translate }}

-
+
{{ 'portfolios.applications.environments_heading' | translate }}
diff --git a/templates/applications/new/step_3.html b/templates/applications/new/step_3.html index 06dd4e0d..a4e1aa53 100644 --- a/templates/applications/new/step_3.html +++ b/templates/applications/new/step_3.html @@ -15,7 +15,7 @@

{{ ('portfolios.applications.new.step_3_description' | translate) }}

-
+
{{ MemberManagementTemplate( application, From 8fbb0e99ae153013bba6e9a39465bad1b6c2b313 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:49:58 -0500 Subject: [PATCH 19/26] Fix side nav to match designs and delete unused html and css --- styles/elements/_sidenav.scss | 91 ++------------------------ templates/applications/new/step_2.html | 4 +- templates/components/sidenav_item.html | 34 ++-------- 3 files changed, 12 insertions(+), 117 deletions(-) diff --git a/styles/elements/_sidenav.scss b/styles/elements/_sidenav.scss index 224895fb..d4a538f0 100644 --- a/styles/elements/_sidenav.scss +++ b/styles/elements/_sidenav.scss @@ -72,7 +72,7 @@ &.sidenav__list--padded { margin-top: 3 * $gap; margin-bottom: $footer-height; - padding: 0 $gap ($gap * 2); + padding-bottom: ($gap * 2); position: fixed; overflow-y: scroll; top: $topbar-height + $usa-banner-height + 4rem; @@ -109,100 +109,19 @@ &__link { display: block; padding: $gap ($gap * 2); - color: $color-black; - text-decoration: none; white-space: nowrap; overflow: hidden; + color: $color-black-light; + text-decoration: none; text-overflow: ellipsis; - &-icon { - margin-left: -($gap * 0.5); - } - - &--disabled { - color: $color-shadow; - pointer-events: none; - } - - &--add { - color: $color-blue; - font-size: $small-font-size; - - .icon { - @include icon-color($color-blue); - @include icon-size(14); - } - } - &--active { @include h4; - color: $color-primary; background-color: $color-aqua-lightest; - box-shadow: inset ($gap / 2) 0 0 0 $color-primary; - - .sidenav__link-icon { - @include icon-style-active; - } - + box-shadow: inset ($gap / 2) 0 0 0 $color-primary-darker; position: relative; - - &_indicator .icon { - @include icon-color($color-primary); - - position: absolute; - right: 0; - } - - + ul { - background-color: $color-primary; - - .sidenav__link { - color: $color-white; - background-color: $color-primary; - - &:hover { - background-color: $color-blue-darker; - } - - &--active { - @include h5; - - color: $color-white; - background-color: $color-primary; - box-shadow: none; - } - - .icon { - @include icon-color($color-white); - } - } - } - } - - + ul { - li { - .sidenav__link { - @include h5; - - padding: $gap * 0.75; - padding-left: 4.5rem; - border: 0; - font-weight: normal; - - .sidenav__link-icon { - @include icon-size(12); - - flex-shrink: 0; - margin-right: 1.5rem; - margin-left: -3rem; - } - - .sidenav__link-label { - padding-left: 0; - } - } - } + color: $color-primary-darker; } &:hover { diff --git a/templates/applications/new/step_2.html b/templates/applications/new/step_2.html index 9adfddca..462c0f46 100644 --- a/templates/applications/new/step_2.html +++ b/templates/applications/new/step_2.html @@ -58,9 +58,9 @@ {{ Icon("plus") }}
-
+
-
+
{% block next_button %} {{ SaveButton(text=('portfolios.applications.new.step_2_button_text' | translate)) }} diff --git a/templates/components/sidenav_item.html b/templates/components/sidenav_item.html index 8e3c5135..ec6be364 100644 --- a/templates/components/sidenav_item.html +++ b/templates/components/sidenav_item.html @@ -1,35 +1,11 @@ {% from "components/icon.html" import Icon %} -{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} +{% macro SidenavItem(label, href, active=False) -%}
  • - - {% if icon %} - {{ Icon(icon, classes="sidenav__link-icon") }} - {% endif %} - - - {{label}} - - {% if active %} - - {{ Icon("caret_right") }} + + + {{label}} - {% endif %} - - - {% if subnav and active %} - - {% endif %} +
  • {%- endmacro %} From a231ba5210289772a4e7df6d24d848260ccd0175 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:54:55 -0500 Subject: [PATCH 20/26] Update styling for add new portfolio button on home page --- templates/home.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/templates/home.html b/templates/home.html index 03dfd0fd..986c6e41 100644 --- a/templates/home.html +++ b/templates/home.html @@ -55,10 +55,13 @@
    - - - {{ "home.add_portfolio_button_text" | translate }} - +
    From c642708c44afb15da3d70edfd088ba92cf9df666 Mon Sep 17 00:00:00 2001 From: leigh-mil Date: Wed, 18 Dec 2019 16:57:15 -0500 Subject: [PATCH 21/26] Left align home page content --- styles/sections/_home.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/sections/_home.scss b/styles/sections/_home.scss index a721b71c..b0d715d2 100644 --- a/styles/sections/_home.scss +++ b/styles/sections/_home.scss @@ -5,7 +5,7 @@ } &__content { - margin: 4rem auto; + margin: 4rem; max-width: 900px; &--descriptions { From 6d64665474b0aaa440ed2b8672a56d25dd086f70 Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 18:45:25 -0500 Subject: [PATCH 22/26] 169163334 - Adds CDN module Basic CDN module with configurable origin. --- terraform/modules/cdn/main.tf | 31 ++++++++++++++++++++++++++++++ terraform/modules/cdn/outputs.tf | 0 terraform/modules/cdn/variables.tf | 31 ++++++++++++++++++++++++++++++ terraform/providers/dev/cdn.tf | 8 ++++++++ 4 files changed, 70 insertions(+) create mode 100644 terraform/modules/cdn/main.tf create mode 100644 terraform/modules/cdn/outputs.tf create mode 100644 terraform/modules/cdn/variables.tf create mode 100644 terraform/providers/dev/cdn.tf diff --git a/terraform/modules/cdn/main.tf b/terraform/modules/cdn/main.tf new file mode 100644 index 00000000..5debd443 --- /dev/null +++ b/terraform/modules/cdn/main.tf @@ -0,0 +1,31 @@ +resource "random_id" "server" { + keepers = { + azi_id = 1 + } + + byte_length = 8 +} + +resource "azurerm_resource_group" "cdn" { + name = "${var.name}-${var.environment}-cdn" + location = var.region +} + +resource "azurerm_cdn_profile" "cdn" { + name = "${var.name}-${var.environment}-profile" + location = azurerm_resource_group.cdn.location + resource_group_name = azurerm_resource_group.cdn.name + sku = var.sku +} + +resource "azurerm_cdn_endpoint" "cdn" { + name = "${var.name}-${var.environment}-${random_id.server.hex}" + profile_name = azurerm_cdn_profile.cdn.name + location = azurerm_resource_group.cdn.location + resource_group_name = azurerm_resource_group.cdn.name + + origin { + name = "${var.name}-${var.environment}-origin" + host_name = var.origin_host_name + } +} diff --git a/terraform/modules/cdn/outputs.tf b/terraform/modules/cdn/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/cdn/variables.tf b/terraform/modules/cdn/variables.tf new file mode 100644 index 00000000..a026ffed --- /dev/null +++ b/terraform/modules/cdn/variables.tf @@ -0,0 +1,31 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "sku" { + type = string + description = "SKU of which CDN to use" + default = "Standard_Verizon" +} + +variable "origin_host_name" { + type = string + description = "Subdomain to use for the origin in requests to the CDN" +} + diff --git a/terraform/providers/dev/cdn.tf b/terraform/providers/dev/cdn.tf new file mode 100644 index 00000000..3b379b90 --- /dev/null +++ b/terraform/providers/dev/cdn.tf @@ -0,0 +1,8 @@ +module "cdn" { + source = "../../modules/cdn" + origin_host_name = "staging.atat.code.mil" + owner = var.owner + environment = var.environment + name = var.name + region = var.region +} From 0925c73c6878eec2e596d3dad92b9fde1c1b264d Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 18:47:02 -0500 Subject: [PATCH 23/26] Terraform fmt across new modules --- terraform/modules/cdn/variables.tf | 10 +++--- terraform/modules/redis/main.tf | 6 ++-- terraform/modules/redis/variables.tf | 46 ++++++++++++++-------------- terraform/providers/dev/cdn.tf | 10 +++--- terraform/providers/dev/redis.tf | 8 ++--- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/terraform/modules/cdn/variables.tf b/terraform/modules/cdn/variables.tf index a026ffed..3abe4851 100644 --- a/terraform/modules/cdn/variables.tf +++ b/terraform/modules/cdn/variables.tf @@ -19,13 +19,13 @@ variable "owner" { } variable "sku" { - type = string - description = "SKU of which CDN to use" - default = "Standard_Verizon" + type = string + description = "SKU of which CDN to use" + default = "Standard_Verizon" } variable "origin_host_name" { - type = string - description = "Subdomain to use for the origin in requests to the CDN" + type = string + description = "Subdomain to use for the origin in requests to the CDN" } diff --git a/terraform/modules/redis/main.tf b/terraform/modules/redis/main.tf index 1e47f767..90a88a2b 100644 --- a/terraform/modules/redis/main.tf +++ b/terraform/modules/redis/main.tf @@ -15,10 +15,10 @@ resource "azurerm_redis_cache" "redis" { minimum_tls_version = var.minimum_tls_version redis_configuration { - enable_authentication = var.enable_authentication + enable_authentication = var.enable_authentication } tags = { - environment = var.environment - owner = var.owner + environment = var.environment + owner = var.owner } } diff --git a/terraform/modules/redis/variables.tf b/terraform/modules/redis/variables.tf index ecdb7636..dac8819b 100644 --- a/terraform/modules/redis/variables.tf +++ b/terraform/modules/redis/variables.tf @@ -19,42 +19,42 @@ variable "owner" { } variable "capacity" { - type = string - default = 2 - description = "The capacity of the redis cache" - + type = string + default = 2 + description = "The capacity of the redis cache" + } variable "family" { - type = string - default = "C" - description = "The subscription family for redis" - + type = string + default = "C" + description = "The subscription family for redis" + } variable "sku_name" { - type = string - default = "Standard" - description = "The sku to use" - + type = string + default = "Standard" + description = "The sku to use" + } variable "enable_non_ssl_port" { - type = bool - default = false - description = "Enable non TLS port (default: false)" - + type = bool + default = false + description = "Enable non TLS port (default: false)" + } variable "minimum_tls_version" { - type = string - default = "1.2" - description = "Minimum TLS version to use" - + type = string + default = "1.2" + description = "Minimum TLS version to use" + } variable "enable_authentication" { - type = bool - default = true - description = "Enable or disable authentication (default: true)" + type = bool + default = true + description = "Enable or disable authentication (default: true)" } diff --git a/terraform/providers/dev/cdn.tf b/terraform/providers/dev/cdn.tf index 3b379b90..02c17e3d 100644 --- a/terraform/providers/dev/cdn.tf +++ b/terraform/providers/dev/cdn.tf @@ -1,8 +1,8 @@ module "cdn" { - source = "../../modules/cdn" + source = "../../modules/cdn" origin_host_name = "staging.atat.code.mil" - owner = var.owner - environment = var.environment - name = var.name - region = var.region + owner = var.owner + environment = var.environment + name = var.name + region = var.region } diff --git a/terraform/providers/dev/redis.tf b/terraform/providers/dev/redis.tf index fca3a4e3..bfe47a84 100644 --- a/terraform/providers/dev/redis.tf +++ b/terraform/providers/dev/redis.tf @@ -1,7 +1,7 @@ module "redis" { - source = "../../modules/redis" - owner = var.owner + source = "../../modules/redis" + owner = var.owner environment = var.environment - region = var.region - name = var.name + region = var.region + name = var.name } From 7aeda9377e9a810cc542d5866bbb238f4eaaeb8c Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Wed, 18 Dec 2019 20:55:58 -0500 Subject: [PATCH 24/26] 169163334 - Adds LB module --- terraform/modules/lb/main.tf | 22 ++++++++++++++++++++++ terraform/modules/lb/outputs.tf | 0 terraform/modules/lb/variables.tf | 19 +++++++++++++++++++ terraform/providers/dev/k8s.tf | 7 +++++++ 4 files changed, 48 insertions(+) create mode 100644 terraform/modules/lb/main.tf create mode 100644 terraform/modules/lb/outputs.tf create mode 100644 terraform/modules/lb/variables.tf diff --git a/terraform/modules/lb/main.tf b/terraform/modules/lb/main.tf new file mode 100644 index 00000000..1c9acace --- /dev/null +++ b/terraform/modules/lb/main.tf @@ -0,0 +1,22 @@ +resource "azurerm_resource_group" "lb" { + name = "${var.name}-${var.environment}-lb" + location = var.region +} + +resource "azurerm_public_ip" "lb" { + name = "${var.name}-${var.environment}-ip" + location = var.region + resource_group_name = azurerm_resource_group.lb.name + allocation_method = "Static" +} + +resource "azurerm_lb" "lb" { + name = "${var.name}-${var.environment}-lb" + location = var.region + resource_group_name = azurerm_resource_group.lb.name + + frontend_ip_configuration { + name = "${var.name}-${var.environment}-ip" + public_ip_address_id = azurerm_public_ip.lb.id + } +} diff --git a/terraform/modules/lb/outputs.tf b/terraform/modules/lb/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/lb/variables.tf b/terraform/modules/lb/variables.tf new file mode 100644 index 00000000..10fa56e9 --- /dev/null +++ b/terraform/modules/lb/variables.tf @@ -0,0 +1,19 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} \ No newline at end of file diff --git a/terraform/providers/dev/k8s.tf b/terraform/providers/dev/k8s.tf index b41df8a4..22120c93 100644 --- a/terraform/providers/dev/k8s.tf +++ b/terraform/providers/dev/k8s.tf @@ -9,3 +9,10 @@ module "k8s" { vnet_subnet_id = module.vpc.subnets #FIXME - output from module.vpc.subnets should be map } +module "lb" { + source = "../../modules/lb" + region = var.region + name = var.name + environment = var.environment + owner = var.owner +} From 74b2510730e4bbbecb271304265ce3cc43bc6bbd Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Thu, 19 Dec 2019 20:12:20 -0500 Subject: [PATCH 25/26] 169163334 - Adds Azure Container Registry Adds the ACR. Georeplication disabled for the moment until we add the DR site. --- terraform/modules/container_registry/main.tf | 13 +++++++ .../modules/container_registry/outputs.tf | 0 .../modules/container_registry/variables.tf | 37 +++++++++++++++++++ terraform/providers/dev/container_registry.tf | 8 ++++ terraform/providers/dev/variables.tf | 5 +++ 5 files changed, 63 insertions(+) create mode 100644 terraform/modules/container_registry/main.tf create mode 100644 terraform/modules/container_registry/outputs.tf create mode 100644 terraform/modules/container_registry/variables.tf create mode 100644 terraform/providers/dev/container_registry.tf diff --git a/terraform/modules/container_registry/main.tf b/terraform/modules/container_registry/main.tf new file mode 100644 index 00000000..a22bacf0 --- /dev/null +++ b/terraform/modules/container_registry/main.tf @@ -0,0 +1,13 @@ +resource "azurerm_resource_group" "acr" { + name = "${var.name}-${var.environment}-acr" + location = var.region +} + +resource "azurerm_container_registry" "acr" { + name = "${var.name}${var.environment}registry" # Alpha Numeric Only + resource_group_name = azurerm_resource_group.acr.name + location = azurerm_resource_group.acr.location + sku = var.sku + admin_enabled = var.admin_enabled + #georeplication_locations = [azurerm_resource_group.acr.location, var.backup_region] +} \ No newline at end of file diff --git a/terraform/modules/container_registry/outputs.tf b/terraform/modules/container_registry/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/terraform/modules/container_registry/variables.tf b/terraform/modules/container_registry/variables.tf new file mode 100644 index 00000000..6fe16ad5 --- /dev/null +++ b/terraform/modules/container_registry/variables.tf @@ -0,0 +1,37 @@ +variable "region" { + type = string + description = "Region this module and resources will be created in" +} + +variable "name" { + type = string + description = "Unique name for the services in this module" +} + +variable "environment" { + type = string + description = "Environment these resources reside (prod, dev, staging, etc)" +} + +variable "owner" { + type = string + description = "Owner of the environment and resources created in this module" +} + +variable "backup_region" { + type = string + description = "Backup region for georeplicating the container registry" +} + +variable "sku" { + type = string + description = "SKU to use for the container registry service" + default = "Premium" +} + +variable "admin_enabled" { + type = string + description = "Admin enabled? (true/false default: false)" + default = false + +} diff --git a/terraform/providers/dev/container_registry.tf b/terraform/providers/dev/container_registry.tf new file mode 100644 index 00000000..0bbf0901 --- /dev/null +++ b/terraform/providers/dev/container_registry.tf @@ -0,0 +1,8 @@ +module "container_registry" { + source = "../../modules/container_registry" + name = var.name + region = var.region + environment = var.environment + owner = var.owner + backup_region = var.backup_region +} diff --git a/terraform/providers/dev/variables.tf b/terraform/providers/dev/variables.tf index 7a9eea21..0a16e69b 100644 --- a/terraform/providers/dev/variables.tf +++ b/terraform/providers/dev/variables.tf @@ -7,6 +7,11 @@ variable "region" { } +variable "backup_region" { + default = "westus2" +} + + variable "owner" { default = "dev" } From 866b789b6c1c829f9debb8e6423b96749d26623b Mon Sep 17 00:00:00 2001 From: Rob Gil Date: Thu, 19 Dec 2019 22:33:27 -0500 Subject: [PATCH 26/26] 169163334 - Adds Virtual Network Gateway for VPN The Virtual Network Gateway is required for OpenVPN connectivity. The change to the VPC module also adds a subnet which is exclusively used for the Gateway. --- terraform/modules/vpc/main.tf | 58 ++++++++++++++++++++++++---- terraform/modules/vpc/variables.tf | 5 +++ terraform/providers/dev/variables.tf | 6 +++ terraform/providers/dev/vpc.tf | 1 + 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/terraform/modules/vpc/main.tf b/terraform/modules/vpc/main.tf index e614b9e4..629be9f1 100644 --- a/terraform/modules/vpc/main.tf +++ b/terraform/modules/vpc/main.tf @@ -36,9 +36,9 @@ resource "azurerm_subnet" "subnet" { address_prefix = element(split(",", each.value), 0) # See https://github.com/terraform-providers/terraform-provider-azurerm/issues/3471 - lifecycle { - ignore_changes = [route_table_id] - } + lifecycle { + ignore_changes = [route_table_id] + } #delegation { # name = "acctestdelegation" # @@ -57,16 +57,58 @@ resource "azurerm_route_table" "route_table" { } resource "azurerm_subnet_route_table_association" "route_table" { - for_each = var.networks - subnet_id = azurerm_subnet.subnet[each.key].id + for_each = var.networks + subnet_id = azurerm_subnet.subnet[each.key].id route_table_id = azurerm_route_table.route_table[each.key].id } resource "azurerm_route" "route" { - for_each = var.route_tables - name = "${var.name}-${var.environment}-default" + for_each = var.route_tables + name = "${var.name}-${var.environment}-default" resource_group_name = azurerm_resource_group.vpc.name - route_table_name = azurerm_route_table.route_table[each.key].name + route_table_name = azurerm_route_table.route_table[each.key].name address_prefix = "0.0.0.0/0" next_hop_type = each.value } + +# Required for the gateway +resource "azurerm_subnet" "gateway" { + name = "GatewaySubnet" + resource_group_name = azurerm_resource_group.vpc.name + virtual_network_name = azurerm_virtual_network.vpc.name + address_prefix = var.gateway_subnet +} + + +resource "azurerm_public_ip" "vpn_ip" { + name = "test" + location = azurerm_resource_group.vpc.location + resource_group_name = azurerm_resource_group.vpc.name + + allocation_method = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "vnet_gateway" { + name = "test" + location = azurerm_resource_group.vpc.location + resource_group_name = azurerm_resource_group.vpc.name + + type = "Vpn" + vpn_type = "RouteBased" + + active_active = false + enable_bgp = false + sku = "Standard" + + ip_configuration { + name = "vnetGatewayConfig" + public_ip_address_id = azurerm_public_ip.vpn_ip.id + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.gateway.id + } + + vpn_client_configuration { + address_space = ["172.16.1.0/24"] + vpn_client_protocols = ["OpenVPN"] + } +} \ No newline at end of file diff --git a/terraform/modules/vpc/variables.tf b/terraform/modules/vpc/variables.tf index ab2aa894..9f331534 100644 --- a/terraform/modules/vpc/variables.tf +++ b/terraform/modules/vpc/variables.tf @@ -41,3 +41,8 @@ variable "route_tables" { type = map description = "A map with the route tables to create" } + +variable "gateway_subnet" { + type = string + description = "The Subnet CIDR that we'll use for the virtual_network_gateway 'GatewaySubnet'" +} diff --git a/terraform/providers/dev/variables.tf b/terraform/providers/dev/variables.tf index 7a9eea21..164577ef 100644 --- a/terraform/providers/dev/variables.tf +++ b/terraform/providers/dev/variables.tf @@ -31,6 +31,12 @@ variable "networks" { } } +variable "gateway_subnet" { + type = string + default = "10.1.20.0/24" +} + + variable "route_tables" { description = "Route tables and their default routes" type = map diff --git a/terraform/providers/dev/vpc.tf b/terraform/providers/dev/vpc.tf index 0b930a0d..b7fac8ae 100644 --- a/terraform/providers/dev/vpc.tf +++ b/terraform/providers/dev/vpc.tf @@ -4,6 +4,7 @@ module "vpc" { region = var.region virtual_network = var.virtual_network networks = var.networks + gateway_subnet = var.gateway_subnet route_tables = var.route_tables owner = var.owner name = var.name