From 7dadff74817043f76472060686583a1c854b1038 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Sun, 8 Jul 2018 14:30:49 -0400 Subject: [PATCH 01/77] Refactor JEDI request form logic into new class --- atst/handlers/request_new.py | 211 +++++++++++++++++++--------- templates/requests/screen-4.html.to | 6 - templates/requests/sidebar.html.to | 38 ++--- 3 files changed, 164 insertions(+), 91 deletions(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index fbf51f98..d38e6b8d 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -1,43 +1,14 @@ import tornado + from atst.handler import BaseHandler from atst.forms.request import RequestForm from atst.forms.org import OrgForm from atst.forms.poc import POCForm from atst.forms.review import ReviewForm from atst.forms.financial import FinancialForm -import tornado.httputil class RequestNew(BaseHandler): - screens = [ - { - "title": "Details of Use", - "section": "details_of_use", - "form": RequestForm, - "subitems": [ - {"title": "Overall request details", "id": "overall-request-details"}, - {"title": "Cloud Resources", "id": "cloud-resources"}, - {"title": "Support Staff", "id": "support-staff"}, - ], - }, - { - "title": "Information About You", - "section": "information_about_you", - "form": OrgForm, - }, - { - "title": "Primary Point of Contact", - "section": "primary_poc", - "form": POCForm, - }, - {"title": "Review & Submit", "section": "review_submit", "form": ReviewForm}, - { - "title": "Financial Verification", - "section": "financial_verification", - "form": FinancialForm, - }, - ] - def initialize(self, page, requests_client): self.page = page self.requests_client = requests_client @@ -47,57 +18,60 @@ class RequestNew(BaseHandler): def post(self, screen=1, request_id=None): self.check_xsrf_cookie() screen = int(screen) - form_metadata = self.screens[screen - 1] - form_section = form_metadata["section"] - form = form_metadata["form"](self.request.arguments) + post_data = self.request.arguments + jedi_flow = JEDIRequestFlow( + self.requests_client, screen, post_data=post_data, request_id=request_id + ) - if form.validate(): - response = yield self.create_or_update_request( - form_section, form.data, request_id - ) + if jedi_flow.validate(): + response = yield jedi_flow.create_or_update_request(self.get_current_user()) if response.ok: where = self.application.default_router.reverse_url( - "request_form_update", - str(screen + 1), - request_id or response.json["id"], + "request_form_update", str(screen + 1), jedi_flow.request_id ) self.redirect(where) else: self.set_status(response.code) else: - self.show_form(screen, form) + self.render( + "requests/screen-%d.html.to" % int(screen), + f=jedi_flow.form(), + data=post_data, + page=self.page, + screens=jedi_flow.screens, + current=screen, + next_screen=jedi_flow.next_screen, + request_id=jedi_flow.request_id, + ) @tornado.web.authenticated @tornado.gen.coroutine def get(self, screen=1, request_id=None): - form = None - form_data = None - is_review_section = screen == 4 + screen = int(screen) + request = None if request_id: - request = yield self.get_request(request_id) - if request.ok: - if is_review_section: - form_data = request.json["body"] - else: - form_metadata = self.screens[int(screen) - 1] - section = form_metadata["section"] - form_data = request.json["body"].get(section, request.json["body"]) - form = form_metadata["form"](data=form_data) + response = yield self.requests_client.get( + "/users/{}/requests/{}".format( + self.get_current_user()["id"], request_id + ), + raise_error=False, + ) + if response.ok: + request = response.json - self.show_form(screen=screen, form=form, request_id=request_id, data=form_data) + jedi_flow = JEDIRequestFlow( + self.requests_client, screen, request, request_id=request_id + ) - def show_form(self, screen=1, form=None, request_id=None, data=None): - if not form: - form = self.screens[int(screen) - 1]["form"](self.request.arguments) self.render( "requests/screen-%d.html.to" % int(screen), - f=form, - data=data, + f=jedi_flow.form(), + data=jedi_flow.current_step_data, page=self.page, - screens=self.screens, - current=int(screen), - next_screen=int(screen) + 1, + screens=jedi_flow.screens, + current=screen, + next_screen=screen + 1, request_id=request_id, ) @@ -109,16 +83,119 @@ class RequestNew(BaseHandler): ) return request + +class JEDIRequestFlow(object): + def __init__( + self, + requests_client, + current_step, + request=None, + post_data=None, + request_id=None, + ): + self.requests_client = requests_client + + self.current_step = current_step + self.request = request + + self.post_data = post_data + self.is_post = self.post_data is not None + + self.request_id = request_id + + def form(self): + if self.is_post: + return self.form_class()(self.post_data) + elif self.request: + return self.form_class()(data=self.current_step_data) + else: + return self.form_class()() + + def validate(self): + return self.form().validate() + + @property + def current_screen(self): + return self.screens[self.current_step - 1] + + @property + def form_section(self): + return self.current_screen["section"] + + def form_class(self): + return self.current_screen["form"] + + @property + def current_step_data(self): + if self.is_post: + return self.post_data + elif self.form_section == "review_submit": + return self.request["body"] + elif self.request: + return self.request["body"].get(self.form_section, {}) + else: + return {} + + @property + def next_screen(self): + return self.current_step + 1 + + @property + def screens(self): + return [ + { + "title": "Details of Use", + "section": "details_of_use", + "form": RequestForm, + "subitems": [ + { + "title": "Overall request details", + "id": "overall-request-details", + }, + {"title": "Cloud Resources", "id": "cloud-resources"}, + {"title": "Support Staff", "id": "support-staff"}, + ], + "show": True, + }, + { + "title": "Information About You", + "section": "information_about_you", + "form": OrgForm, + "show": True, + }, + { + "title": "Primary Point of Contact", + "section": "primary_poc", + "form": POCForm, + "show": True, + }, + { + "title": "Review & Submit", + "section": "review_submit", + "form": ReviewForm, + "show": self.request and self.request["status"] == "pending_submission", + }, + { + "title": "Financial Verification", + "section": "financial_verification", + "form": FinancialForm, + "show": self.request and self.request["status"] == "approved", + }, + ] + @tornado.gen.coroutine - def create_or_update_request(self, form_section, form_data, request_id=None): + def create_or_update_request(self, user): request_data = { - "creator_id": self.get_current_user()["id"], - "request": {form_section: form_data}, + "creator_id": user["id"], + "request": {self.form_section: self.form().data}, } - if request_id: + if self.request_id: response = yield self.requests_client.patch( - "/requests/{}".format(request_id), json=request_data + "/requests/{}".format(self.request_id), json=request_data ) else: response = yield self.requests_client.post("/requests", json=request_data) + self.request = response.json + self.request_id = self.request["id"] + return response diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index 97b89859..469dff15 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -29,12 +29,6 @@ {{ data.get('details_of_use', {}).get('supported_organizations') }} - -{{ data.get('details_of_use', {}).get('uii_ids') }} - - -{{ data.get('details_of_use', {}).get('pe_id') }} -

Cloud Resources

diff --git a/templates/requests/sidebar.html.to b/templates/requests/sidebar.html.to index c9ed12f3..f8516917 100644 --- a/templates/requests/sidebar.html.to +++ b/templates/requests/sidebar.html.to @@ -7,25 +7,27 @@ - \ No newline at end of file + From 613db619486c56764f70d128ef39b71057f35750 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 9 Jul 2018 14:59:08 -0400 Subject: [PATCH 02/77] Add status attribute to mock request --- tests/mocks.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/mocks.py b/tests/mocks.py index be8805c3..2fefbf64 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -49,6 +49,7 @@ class MockRequestsClient(MockApiClient): "id": "66b8ef71-86d3-48ef-abc2-51bfa1732b6b", "creator": "49903ae7-da4a-49bf-a6dc-9dff5d004238", "body": {}, + "status": "incomplete" } return self._get_response("GET", path, 200, json=json) From 9f3012cdc3ff7df180b1ea57a1c626e66b62689a Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 9 Jul 2018 15:03:04 -0400 Subject: [PATCH 03/77] Save form instance in JEDIRequestFlow --- atst/handlers/request_new.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index d38e6b8d..a53ebf8b 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -35,7 +35,7 @@ class RequestNew(BaseHandler): else: self.render( "requests/screen-%d.html.to" % int(screen), - f=jedi_flow.form(), + f=jedi_flow.form, data=post_data, page=self.page, screens=jedi_flow.screens, @@ -66,7 +66,7 @@ class RequestNew(BaseHandler): self.render( "requests/screen-%d.html.to" % int(screen), - f=jedi_flow.form(), + f=jedi_flow.form, data=jedi_flow.current_step_data, page=self.page, screens=jedi_flow.screens, @@ -102,8 +102,9 @@ class JEDIRequestFlow(object): self.is_post = self.post_data is not None self.request_id = request_id + self.form = self._form() - def form(self): + def _form(self): if self.is_post: return self.form_class()(self.post_data) elif self.request: @@ -112,7 +113,7 @@ class JEDIRequestFlow(object): return self.form_class()() def validate(self): - return self.form().validate() + return self.form.validate() @property def current_screen(self): @@ -187,7 +188,7 @@ class JEDIRequestFlow(object): def create_or_update_request(self, user): request_data = { "creator_id": user["id"], - "request": {self.form_section: self.form().data}, + "request": {self.form_section: self.form.data}, } if self.request_id: response = yield self.requests_client.patch( From 405c34546b6af0fc7632f6cc92766bfbdd2d542f Mon Sep 17 00:00:00 2001 From: richard-dds Date: Mon, 9 Jul 2018 15:08:34 -0400 Subject: [PATCH 04/77] Remove unused import --- atst/forms/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atst/forms/request.py b/atst/forms/request.py index 36aa2043..d6aa1039 100644 --- a/atst/forms/request.py +++ b/atst/forms/request.py @@ -2,7 +2,7 @@ from wtforms.fields.html5 import IntegerField from wtforms.fields import RadioField, StringField, TextAreaField from wtforms.validators import NumberRange, InputRequired from wtforms_tornado import Form -from .fields import DateField, NewlineListField +from .fields import DateField from .validators import DateRange import pendulum From 86d9db74c31c1827c59bd9d3131d0d2694924f65 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 10 Jul 2018 10:30:18 -0400 Subject: [PATCH 05/77] Allow user to submit request --- atst/app.py | 7 +++++++ atst/handlers/request_submit.py | 17 +++++++++++++++++ templates/requests/screen-4.html.to | 5 ++++- templates/requests_new.html.to | 22 +++++++--------------- 4 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 atst/handlers/request_submit.py diff --git a/atst/app.py b/atst/app.py index 094a61b1..a0b3e491 100644 --- a/atst/app.py +++ b/atst/app.py @@ -10,6 +10,7 @@ from atst.handlers.login import Login from atst.handlers.workspace import Workspace from atst.handlers.request import Request from atst.handlers.request_new import RequestNew +from atst.handlers.request_submit import RequestsSubmit from atst.handlers.dev import Dev from atst.home import home from atst.api_client import ApiClient @@ -71,6 +72,12 @@ def make_app(config, deps, **kwargs): {"page": "requests_new", "requests_client": deps["requests_client"]}, name="request_form_update", ), + url( + r"/requests/submit/(\S+)", + RequestsSubmit, + {"requests_client": deps["requests_client"]}, + name="requests_submit", + ), url(r"/users", MainHandler, {"page": "users"}, name="users"), url(r"/reports", MainHandler, {"page": "reports"}, name="reports"), url(r"/calculator", MainHandler, {"page": "calculator"}, name="calculator"), diff --git a/atst/handlers/request_submit.py b/atst/handlers/request_submit.py new file mode 100644 index 00000000..ed842449 --- /dev/null +++ b/atst/handlers/request_submit.py @@ -0,0 +1,17 @@ +import tornado + +from atst.handler import BaseHandler + + +class RequestsSubmit(BaseHandler): + def initialize(self, requests_client): + self.requests_client = requests_client + + @tornado.web.authenticated + @tornado.gen.coroutine + def post(self, request_id): + yield self.requests_client.post( + "/requests/{}/submit".format(request_id), + allow_nonstandard_methods=True + ) + self.redirect("/requests") diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index 469dff15..a23fb68b 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -1,5 +1,9 @@ {% extends '../requests_new.html.to' %} +{% block form_action %} +
+{% end %} + {% block form %} {% autoescape None %} @@ -8,7 +12,6 @@ {% end %}

Review & Submit

-

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem ullam veritatis fuga non repellendus repellat dolorum labore nulla iure aspernatur ipsam recusandae saepe harum iste, dolorem adipisci dolores eum, doloribus?

Details of Use Edit

diff --git a/templates/requests_new.html.to b/templates/requests_new.html.to index 5437a8a6..25431889 100644 --- a/templates/requests_new.html.to +++ b/templates/requests_new.html.to @@ -9,20 +9,20 @@ {% block content %}
- +

New Request

- - - {% if request_id %} - - {% else %} - + {% block form_action %} + {% if request_id %} + + {% else %} + + {% end %} {% end %} {% module xsrf_form_html() %} @@ -34,18 +34,10 @@ {% end %} - - -
-
- - - - {% end %} From 649987a33b5c582cedc985d2a8db14a270daba03 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:07:29 -0400 Subject: [PATCH 06/77] Add file with basic command all scripts should run --- script/include/global_header.inc.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100755 script/include/global_header.inc.sh diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh new file mode 100755 index 00000000..67a048b2 --- /dev/null +++ b/script/include/global_header.inc.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# scriptz/global_header.inc: Any basic things that should be executed at the +# beginning of any and every script + +# If any command fails, immediately exit the script +set -e + +# Ensure the working directory is the app root directory +cd "$(dirname "${0}")/.." + +# Source all function definition files +source ./script/include/*_functions.inc.sh From 04d073329a15ad7b3be6f6da84e90a89181b96b6 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:07:45 -0400 Subject: [PATCH 07/77] Add file with general helper functions for use by other scripts --- script/include/helper_functions.inc.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 script/include/helper_functions.inc.sh diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh new file mode 100644 index 00000000..18968aae --- /dev/null +++ b/script/include/helper_functions.inc.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# helper_functions.inc.sh: General helper functions + +# Check pip to see if the given package is installed +# (returns 0 if installed, 2 if not installed) +check_pip_for () { + return $(pip list --format=columns --disable-pip-version-check | \ + grep -Fe "${1}" >/dev/null 2>&1) +} From 16de4f829e2d99191bf70511e76cadc17144fd83 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:08:02 -0400 Subject: [PATCH 08/77] Add file to contain functions used by setup --- script/include/setup_functions.inc.sh | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 script/include/setup_functions.inc.sh diff --git a/script/include/setup_functions.inc.sh b/script/include/setup_functions.inc.sh new file mode 100644 index 00000000..7c4a6741 --- /dev/null +++ b/script/include/setup_functions.inc.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# setup_functions.inc.sh: Functions used by the setup script + +install_pipenv() { + exit_code=0 + + # Ensure we are not in a virtual env already + if [ -z "${VIRTUAL_ENV+xxxx}" ]; then + if ! check_pip_for pipenv; then + # pipenv is not installed, so install it + echo "Installing pipenv..." + pip install pipenv + # Capture pip exit code + exit_code="${?}" + fi + fi + + return "${exit_code}" +} + +create_virtual_environment() { + default_python_version=3.6 + # Parse out the required Python version from the Pipfile + python_version=$(grep python_version ./Pipfile | cut -d '"' -f 2) + + # If we ended up with an empty string for the required Python version, + # specify the default version + if [ -z "${python_version}" ]; then + python_version="${default_python_version}" + fi + + # Create a new virtual environment for the app + # The environment will be in a directory called .venv off the app + # root directory + echo "Creating virtual environment using Python version ${python_version}..." + return $(PIPENV_VENV_IN_PROJECT=true pipenv --python "${python_version}") +} + +install_sass() { + if ! type sass >/dev/null; then + if type gem >/dev/null; then + echo 'Installing a sass compiler (gem)...' + gem install sass + else + echo 'Could not install a sass compiler. Please install a version of sass.' + fi + fi +} From c4283fe1a4e55dfbe74b64c485117eaebada9d7d Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:17:03 -0400 Subject: [PATCH 09/77] Remove interpreter specification These script fragments should only ever be sourced rather then directly executed --- script/include/global_header.inc.sh | 6 ++---- script/include/helper_functions.inc.sh | 3 +-- script/include/setup_functions.inc.sh | 2 -- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh index 67a048b2..443b5c03 100755 --- a/script/include/global_header.inc.sh +++ b/script/include/global_header.inc.sh @@ -1,7 +1,5 @@ -#!/bin/bash - -# scriptz/global_header.inc: Any basic things that should be executed at the -# beginning of any and every script +# global_header.inc: Any basic things that should be executed at the +# beginning of any and every script # If any command fails, immediately exit the script set -e diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh index 18968aae..3c427a0f 100644 --- a/script/include/helper_functions.inc.sh +++ b/script/include/helper_functions.inc.sh @@ -1,10 +1,9 @@ -#!/bin/bash - # helper_functions.inc.sh: General helper functions # Check pip to see if the given package is installed # (returns 0 if installed, 2 if not installed) check_pip_for () { + # Use 'pip list' to see if the requested package is already installed return $(pip list --format=columns --disable-pip-version-check | \ grep -Fe "${1}" >/dev/null 2>&1) } diff --git a/script/include/setup_functions.inc.sh b/script/include/setup_functions.inc.sh index 7c4a6741..50b12af3 100644 --- a/script/include/setup_functions.inc.sh +++ b/script/include/setup_functions.inc.sh @@ -1,5 +1,3 @@ -#!/bin/bash - # setup_functions.inc.sh: Functions used by the setup script install_pipenv() { From 516feb2cd4975f546136395b54d97988018ad91a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:18:51 -0400 Subject: [PATCH 10/77] Add script that runs all the setup commands --- script/include/run_setup | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 script/include/run_setup diff --git a/script/include/run_setup b/script/include/run_setup new file mode 100755 index 00000000..b9240644 --- /dev/null +++ b/script/include/run_setup @@ -0,0 +1,24 @@ +# include/setup: Set up application for the first time after cloning, or set it +# back to the initial first unused state. + +# If CREATE_VENV is not set, set it to "true" +if [ -z "${CREATE_VENV+is_set}" ]; then + CREATE_VENV="true" +fi + +# If INSTALL_SASS is not set, set it to "false" +if [ -z "${INSTALL_SASS+is_set}" ]; then + INSTALL_SASS="false" +fi + +if [ "${CREATE_VENV}" = "true" ]; then + install_pipenv + create_virtual_environment +fi + +if [ "${INSTALL_SASS}" = "true" ]; then + install_sass +fi + +# Install application dependencies +source ./script/bootstrap From 1ea184f049461820921443bd53b12a3784913555 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 6 Jul 2018 13:19:35 -0400 Subject: [PATCH 11/77] Update script to use shared fragments from the include dir --- script/setup | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/script/setup b/script/setup index 0fae92e6..925ced94 100755 --- a/script/setup +++ b/script/setup @@ -3,24 +3,10 @@ # script/setup: Set up application for the first time after cloning, or set it # back to the initial first unused state. -# If a command fails, exit the script -set -e +source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +# Turn on sass compiler installation +INSTALL_SASS="true" -# Install virtualenv -pip install pipenv -pipenv --python 3.6 - -if ! type sass > /dev/null; then - if type gem > /dev/null; then - echo 'installing a sass compiler...' - gem install sass - else - echo 'Could not install a sass compiler. Please install a version of sass.' - fi -fi - -# Install application dependencies -script/bootstrap +# Run the shared setup script +source ./script/include/run_setup From 958f453442dad73254a900d5ed4a54c0e2d4029c Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 11:04:26 -0400 Subject: [PATCH 12/77] Fix function snippet sourcing --- script/include/global_header.inc.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh index 443b5c03..571967fd 100755 --- a/script/include/global_header.inc.sh +++ b/script/include/global_header.inc.sh @@ -8,4 +8,8 @@ set -e cd "$(dirname "${0}")/.." # Source all function definition files -source ./script/include/*_functions.inc.sh + +for function_snippet in ./script/include/*_functions.inc.sh +do + source "${function_snippet}" +done From 6e4c5911c33de82169096426894e64a2c18f6bfb Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 11:04:39 -0400 Subject: [PATCH 13/77] Add comments --- script/include/run_setup | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/script/include/run_setup b/script/include/run_setup index b9240644..25e5fc7f 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -1,6 +1,7 @@ # include/setup: Set up application for the first time after cloning, or set it # back to the initial first unused state. +## Option defaults # If CREATE_VENV is not set, set it to "true" if [ -z "${CREATE_VENV+is_set}" ]; then CREATE_VENV="true" @@ -11,6 +12,7 @@ if [ -z "${INSTALL_SASS+is_set}" ]; then INSTALL_SASS="false" fi +## Main if [ "${CREATE_VENV}" = "true" ]; then install_pipenv create_virtual_environment @@ -21,4 +23,4 @@ if [ "${INSTALL_SASS}" = "true" ]; then fi # Install application dependencies -source ./script/bootstrap +./script/bootstrap From 6b31da0a0b62e5667076cf52d62d85090595ce65 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:10:42 -0400 Subject: [PATCH 14/77] Update global: only source the helper_functions --- script/include/global_header.inc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh index 571967fd..01e1709d 100755 --- a/script/include/global_header.inc.sh +++ b/script/include/global_header.inc.sh @@ -9,7 +9,7 @@ cd "$(dirname "${0}")/.." # Source all function definition files -for function_snippet in ./script/include/*_functions.inc.sh +for function_snippet in ./script/include/helper_functions.inc.sh do source "${function_snippet}" done From 05c42e5988f850db0a0419366a35eb3b1b57ccac Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:10:56 -0400 Subject: [PATCH 15/77] Update helper_functions - Modify check pip to make it clear it checks the system python - Add generic sounding "run_command", in case we switch away from pipenv --- script/include/helper_functions.inc.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh index 3c427a0f..57415ba1 100644 --- a/script/include/helper_functions.inc.sh +++ b/script/include/helper_functions.inc.sh @@ -2,8 +2,18 @@ # Check pip to see if the given package is installed # (returns 0 if installed, 2 if not installed) -check_pip_for () { +check_system_pip_for () { + local package_name="${1}" + # Use 'pip list' to see if the requested package is already installed - return $(pip list --format=columns --disable-pip-version-check | \ - grep -Fe "${1}" >/dev/null 2>&1) + pip list --format=columns --disable-pip-version-check | \ + grep -Fe "${package_name}" >/dev/null 2>&1 + return $? +} + +# Used whenever an environment sensitive command is being run +run_command () { + local cmd="${1}" + pipenv ${cmd} + return $? } From adb41337e3f701a502fe0551a96de4d9e7de56b2 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:12:53 -0400 Subject: [PATCH 16/77] Fix function name which was just changed --- script/include/setup_functions.inc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include/setup_functions.inc.sh b/script/include/setup_functions.inc.sh index 50b12af3..ea26d23a 100644 --- a/script/include/setup_functions.inc.sh +++ b/script/include/setup_functions.inc.sh @@ -5,7 +5,7 @@ install_pipenv() { # Ensure we are not in a virtual env already if [ -z "${VIRTUAL_ENV+xxxx}" ]; then - if ! check_pip_for pipenv; then + if ! check_system_pip_for pipenv; then # pipenv is not installed, so install it echo "Installing pipenv..." pip install pipenv From b23c6b15bbc8854a9476ee5d3775e819be030c7a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:13:48 -0400 Subject: [PATCH 17/77] Update script to include sourcing setup specific functions --- script/include/run_setup | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/script/include/run_setup b/script/include/run_setup index 25e5fc7f..97fa0808 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -1,7 +1,10 @@ # include/setup: Set up application for the first time after cloning, or set it # back to the initial first unused state. -## Option defaults +# Load setup functions +source ./script/include/setup_functions.inc.sh + +## Set option defaults # If CREATE_VENV is not set, set it to "true" if [ -z "${CREATE_VENV+is_set}" ]; then CREATE_VENV="true" From 6fa5d7aad1cffefa4d7e9394461c2cb35364e05a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:16:04 -0400 Subject: [PATCH 18/77] Add file containing bootstrap specific functions --- script/include/bootstrap_functions.inc.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 script/include/bootstrap_functions.inc.sh diff --git a/script/include/bootstrap_functions.inc.sh b/script/include/bootstrap_functions.inc.sh new file mode 100644 index 00000000..33e22bf8 --- /dev/null +++ b/script/include/bootstrap_functions.inc.sh @@ -0,0 +1,12 @@ +# bootstrap_functions.inc.sh: Functions used by the bootstrap script + +install_python_packages() { + local install_flags="${1}" + pipenv install ${install_flags} + return $? +} + +install_node_packages() { + npm install + return $? +} From 617c154d01036fe95b16d7a778fa5bc97c491541 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:16:30 -0400 Subject: [PATCH 19/77] Add script to execute bootstrap logic --- script/include/run_bootstrap | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 script/include/run_bootstrap diff --git a/script/include/run_bootstrap b/script/include/run_bootstrap new file mode 100755 index 00000000..2ac48ca9 --- /dev/null +++ b/script/include/run_bootstrap @@ -0,0 +1,24 @@ +# include/run_bootstrap: Install application dependencies + +# Load bootstrap functions +source ./script/include/bootstrap_functions.inc.sh + +## Set option defaults +# If PIPENV_INSTALL_FLAGS is not set, give it the default value of "--dev" +if [ -z "${PIPENV_INSTALL_FLAGS+is_set}" ]; then + CREATE_VENV="--dev" +fi + +## Main + +if [ "${INSTALL_PYTHON_PACKAGES}" = "true" ]; then + install_python_packages "${PIPENV_INSTALL_FLAGS}" +fi + +if [ "${INSTALL_NODE_PACKAGES}" = "true" ]; then + install_node_packages +fi + +if [ -n "${COMPILE_SASS_CMD}" ]; then + run_command "${COMPILE_SASS_CMD}" +fi From cb0564e3e7be5c35d081c5730c4df559a69eb283 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:16:56 -0400 Subject: [PATCH 20/77] Update script to use shared functions and logic --- script/bootstrap | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/script/bootstrap b/script/bootstrap index 78f9391f..7b569239 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -3,33 +3,14 @@ # script/bootstrap: Resolve all dependencies that the application requires to # run. -# If a command fails, exit the script -set -e +source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +# Set sass compiling command for this app +COMPILE_SASS_CMD="webassets -m atst.assets build" -if [ -z "${CIBUILD+xxxx}" ]; then - CMD_PREFIX='pipenv run ' -fi -PIP_CMD="${CMD_PREFIX}pip" -WEBASSETS_CMD="${CMD_PREFIX}webassets" +# Run the shared bootstrap script +source ./script/include/run_bootstrap -PIPENV_INSTALL_FLAGS='--dev' -if [ -n "${CIBUILD}" ]; then - PIPENV_INSTALL_FLAGS+=' --system --ignore-pipfile' -fi - -# Install Python dependencies -${PIP_CMD} install --upgrade pip -pipenv install ${PIPENV_INSTALL_FLAGS} - -# Install uswds node module and dependencies -npm install - -# Relink uswds fonts into the /static directory +# Link USWDS fonts into the /static directory rm -f ./static/fonts -ln -s ../node_modules/uswds/src/fonts ./static/fonts - -# Precompile assets for deployment -${WEBASSETS_CMD} -m atst.assets build +ln -s ../node/modules/uswds/src/fonts ./static/fonts From a31e833fa43e136d83373e479c58f6c3ac3e3d57 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:56:13 -0400 Subject: [PATCH 21/77] Fix pienv run command by actually adding "run" --- script/include/helper_functions.inc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh index 57415ba1..96218f9a 100644 --- a/script/include/helper_functions.inc.sh +++ b/script/include/helper_functions.inc.sh @@ -14,6 +14,6 @@ check_system_pip_for () { # Used whenever an environment sensitive command is being run run_command () { local cmd="${1}" - pipenv ${cmd} + pipenv run ${cmd} return $? } From d70481e425699d8014185c21e29b46b5cd0b30be Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:56:32 -0400 Subject: [PATCH 22/77] Fix variable name --- script/include/run_bootstrap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include/run_bootstrap b/script/include/run_bootstrap index 2ac48ca9..a3d11798 100755 --- a/script/include/run_bootstrap +++ b/script/include/run_bootstrap @@ -6,7 +6,7 @@ source ./script/include/bootstrap_functions.inc.sh ## Set option defaults # If PIPENV_INSTALL_FLAGS is not set, give it the default value of "--dev" if [ -z "${PIPENV_INSTALL_FLAGS+is_set}" ]; then - CREATE_VENV="--dev" + PIPENV_INSTALL_FLAGS="--dev" fi ## Main From 2ba3c68921306119aafb3962634c17431f833c91 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:56:55 -0400 Subject: [PATCH 23/77] Add file containing functions used by the test script --- script/include/test_functions.inc.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 script/include/test_functions.inc.sh diff --git a/script/include/test_functions.inc.sh b/script/include/test_functions.inc.sh new file mode 100644 index 00000000..23e231d8 --- /dev/null +++ b/script/include/test_functions.inc.sh @@ -0,0 +1,18 @@ +# test_functions.inc.sh: Functions used by the run_test script + +run_python_lint() { + local python_files="${1}" + run_command "pylint ${python_files}" + return $? +} + +run_python_static_analysis() { + local python_files="${1}" + run_command "bandit -c ./.bandit_config -r ${python_files}" + return $? +} + +run_python_unit_tests() { + run_command "python -m pytest -s" + return $? +} From b8d3a4536b65522facb67a640f7991ccf4918721 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:57:22 -0400 Subject: [PATCH 24/77] Add test script to execute code checks and unit tests --- script/include/run_test | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 script/include/run_test diff --git a/script/include/run_test b/script/include/run_test new file mode 100755 index 00000000..4187c2d1 --- /dev/null +++ b/script/include/run_test @@ -0,0 +1,17 @@ +# include/run_test: Execute code checkers and unit tests + +# Load test functions +source ./script/include/test_functions.inc.sh + +## Set option defaults +# If PYTHON_FILES is not set, give it the default value of "app.py" +if [ -z "${PYTHON_FILES+is_set}" ]; then + PYTHON_FILES="app.py" +fi + +## Main +if [ "${RUN_PYTHON_TESTS}" = "true" ]; then + run_python_lint "${PYTHON_FILES}" + run_python_static_analysis "${PYTHON_FILES}" + run_python_unit_tests "${PYTHON_FILES}" +fi From 53f27b2ea2c3e5df47caeeb92d89f5b26b578c36 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:57:45 -0400 Subject: [PATCH 25/77] Enable pythong and node dependency installation --- script/bootstrap | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/bootstrap b/script/bootstrap index 7b569239..e30b69da 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -8,6 +8,10 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Set sass compiling command for this app COMPILE_SASS_CMD="webassets -m atst.assets build" +# Enable python and node package installation +INSTALL_PYTHON_PACKAGES="true" +INSTALL_NODE_PACKAGES="true" + # Run the shared bootstrap script source ./script/include/run_bootstrap From 9e89f75b92b44c448984c2bb57481d796cd7573c Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:58:05 -0400 Subject: [PATCH 26/77] Update to use shared test script and functions --- script/test | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/script/test b/script/test index fe2d7ecb..1f6c3380 100755 --- a/script/test +++ b/script/test @@ -2,22 +2,13 @@ # script/test: Run static code checks and unit tests -# If a command fails, exit the script -set -e +source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +# Define all relevant python files and directories for this app +PYTHON_FILES="./app.py ./atst ./config" -if [ -z "${SKIP_PIPENV+xxxx}" ]; then - CMD_PREFIX='pipenv run ' -fi -PYLINT_CMD="${CMD_PREFIX}pylint" -PYTHON_CMD="${CMD_PREFIX}python" +# Enable Python testing +RUN_PYTHON_TESTS="true" -# Run lint check -echo "Running lint..." -${PYLINT_CMD} app.py atst/ tests/ - -# Run unit tests -echo "Running unit tests..." -${PYTHON_CMD} -m pytest -s $* +# Run the shared test script +source ./script/include/run_test From 09cf59ccd18ec949b44cd433623b997a3f9308bc Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 12:58:32 -0400 Subject: [PATCH 27/77] Add default config file for bandit --- .bandit_config | 156 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 .bandit_config diff --git a/.bandit_config b/.bandit_config new file mode 100644 index 00000000..ff68cb98 --- /dev/null +++ b/.bandit_config @@ -0,0 +1,156 @@ +### This config may optionally select a subset of tests to run or skip by +### filling out the 'tests' and 'skips' lists given below. If no tests are +### specified for inclusion then it is assumed all tests are desired. The skips +### set will remove specific tests from the include set. +### Note that the same test ID should not appear in both 'tests' and 'skips', +### this would be nonsensical and is detected by Bandit at runtime. + +# (optional) list included test IDs here, eg '[B101, B406]': +tests: + +# (optional) list skipped test IDs here, eg '[B101, B406]': +skips: + +### (optional) plugin settings - some test plugins require configuration data +### that may be given here, per-plugin. All bandit test plugins have a built in +### set of sensible defaults and these will be used if no configuration is +### provided. It is not necessary to provide settings for every (or any) plugin +### if the defaults are acceptable. + +any_other_function_with_shell_equals_true: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +execute_with_run_as_root_equals_true: + function_names: [ceilometer.utils.execute, cinder.utils.execute, neutron.agent.linux.utils.execute, + nova.utils.execute, nova.utils.trycmd] +hardcoded_tmp_directory: + tmp_dirs: [/tmp, /var/tmp, /dev/shm] +linux_commands_wildcard_injection: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +password_config_option_not_marked_secret: + function_names: [oslo.config.cfg.StrOpt, oslo_config.cfg.StrOpt] +ssl_with_bad_defaults: + bad_protocol_versions: [PROTOCOL_SSLv2, SSLv2_METHOD, SSLv23_METHOD, PROTOCOL_SSLv3, + PROTOCOL_TLSv1, SSLv3_METHOD, TLSv1_METHOD] +ssl_with_bad_version: + bad_protocol_versions: [PROTOCOL_SSLv2, SSLv2_METHOD, SSLv23_METHOD, PROTOCOL_SSLv3, + PROTOCOL_TLSv1, SSLv3_METHOD, TLSv1_METHOD] +start_process_with_a_shell: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +start_process_with_no_shell: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +start_process_with_partial_path: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +subprocess_popen_with_shell_equals_true: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +subprocess_without_shell_equals_true: + no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv, os.execve, os.execvp, + os.execvpe, os.spawnl, os.spawnle, os.spawnlp, os.spawnlpe, os.spawnv, os.spawnve, + os.spawnvp, os.spawnvpe, os.startfile] + shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4, popen2.popen2, popen2.popen3, + popen2.popen4, popen2.Popen3, popen2.Popen4, commands.getoutput, commands.getstatusoutput] + subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call, subprocess.check_output, + utils.execute, utils.execute_with_timeout] +try_except_continue: {check_typed_exception: false} +try_except_pass: {check_typed_exception: false} + +### Reference of Available tests: +# B101 : assert_used +# B102 : exec_used +# B103 : set_bad_file_permissions +# B104 : hardcoded_bind_all_interfaces +# B105 : hardcoded_password_string +# B106 : hardcoded_password_funcarg +# B107 : hardcoded_password_default +# B108 : hardcoded_tmp_directory +# B109 : password_config_option_not_marked_secret +# B110 : try_except_pass +# B111 : execute_with_run_as_root_equals_true +# B112 : try_except_continue +# B201 : flask_debug_true +# B301 : pickle +# B302 : marshal +# B303 : md5 +# B304 : ciphers +# B305 : cipher_modes +# B306 : mktemp_q +# B307 : eval +# B308 : mark_safe +# B309 : httpsconnection +# B310 : urllib_urlopen +# B311 : random +# B312 : telnetlib +# B313 : xml_bad_cElementTree +# B314 : xml_bad_ElementTree +# B315 : xml_bad_expatreader +# B316 : xml_bad_expatbuilder +# B317 : xml_bad_sax +# B318 : xml_bad_minidom +# B319 : xml_bad_pulldom +# B320 : xml_bad_etree +# B321 : ftplib +# B322 : input +# B401 : import_telnetlib +# B402 : import_ftplib +# B403 : import_pickle +# B404 : import_subprocess +# B405 : import_xml_etree +# B406 : import_xml_sax +# B407 : import_xml_expat +# B408 : import_xml_minidom +# B409 : import_xml_pulldom +# B410 : import_lxml +# B411 : import_xmlrpclib +# B412 : import_httpoxy +# B501 : request_with_no_cert_validation +# B502 : ssl_with_bad_version +# B503 : ssl_with_bad_defaults +# B504 : ssl_with_no_version +# B505 : weak_cryptographic_key +# B506 : yaml_load +# B601 : paramiko_calls +# B602 : subprocess_popen_with_shell_equals_true +# B603 : subprocess_without_shell_equals_true +# B604 : any_other_function_with_shell_equals_true +# B605 : start_process_with_a_shell +# B606 : start_process_with_no_shell +# B607 : start_process_with_partial_path +# B608 : hardcoded_sql_expressions +# B609 : linux_commands_wildcard_injection +# B701 : jinja2_autoescape_false +# B702 : use_of_mako_templates From 27cfb3442f49ab7251b71918439cb2a83e4262a9 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 13:00:29 -0400 Subject: [PATCH 28/77] Update to use shared header --- script/cibuild | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/script/cibuild b/script/cibuild index c9fd2975..e9d01564 100755 --- a/script/cibuild +++ b/script/cibuild @@ -2,15 +2,7 @@ # script/cibuild: Run CI related checks and tests -# If a command fails, exit the script -set -e - -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run lint/style checks and unit tests -script/test - -# Run static code analysis security checks -# (excluding the tests and node_modules subdirs) -bandit -r . -x node_modules,tests +source ./script/test From 1a5f9dfc49b5c74cad6910df77a472b87eeb19e9 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 14:57:45 -0400 Subject: [PATCH 29/77] Move docker files and update travis.yml accordingly --- .travis.yml | 6 +++--- {docker => deploy/docker}/prod/Dockerfile | 0 {docker => deploy/docker}/tester/Dockerfile | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename {docker => deploy/docker}/prod/Dockerfile (100%) rename {docker => deploy/docker}/tester/Dockerfile (100%) diff --git a/.travis.yml b/.travis.yml index 9b5500d2..486de5cc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,15 +7,15 @@ env: - TESTER_IMAGE_NAME=atst-tester - PROD_IMAGE_NAME=atst-prod -before_install: +before_script: - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - - docker build --tag "${TESTER_IMAGE_NAME}" . -f docker/tester/Dockerfile + - docker build --tag "${TESTER_IMAGE_NAME}" . -f deploy/docker/tester/Dockerfile script: - docker run "${TESTER_IMAGE_NAME}" before_deploy: - - docker build --tag "${PROD_IMAGE_NAME}" . -f docker/prod/Dockerfile + - docker build --tag "${PROD_IMAGE_NAME}" . -f deploy/docker/prod/Dockerfile - git_sha="$(git rev-parse --short HEAD)" - remote_image_name="${ATAT_DOCKER_REGISTRY_URL}/${PROD_IMAGE_NAME}:${git_sha}" - docker tag "${PROD_IMAGE_NAME}" "${remote_image_name}" diff --git a/docker/prod/Dockerfile b/deploy/docker/prod/Dockerfile similarity index 100% rename from docker/prod/Dockerfile rename to deploy/docker/prod/Dockerfile diff --git a/docker/tester/Dockerfile b/deploy/docker/tester/Dockerfile similarity index 100% rename from docker/tester/Dockerfile rename to deploy/docker/tester/Dockerfile From ada0595f36681538bbb11ad19706f009462c2d7b Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 15:13:27 -0400 Subject: [PATCH 30/77] Add alpine setup functions and sharable script --- script/include/alpine_setup_functions.inc.sh | 32 ++++++++++++++++++++ script/include/run_alpine_setup | 25 +++++++++++++++ 2 files changed, 57 insertions(+) create mode 100755 script/include/alpine_setup_functions.inc.sh create mode 100755 script/include/run_alpine_setup diff --git a/script/include/alpine_setup_functions.inc.sh b/script/include/alpine_setup_functions.inc.sh new file mode 100755 index 00000000..d28b88a3 --- /dev/null +++ b/script/include/alpine_setup_functions.inc.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# alpine_setup_functions: Functions used by the run_alpine_setup script + +update_system_packages() { + apk update + apk upgrade +} + +install_package() { + local package_name=${1} + + apk add ${1} + return $? +} + +add_group() { + local group_name="${1}" + local gid="${2}" + + addgroup -g "${gid}" -S "${group_name}" + return $? +} + +add_user() { + local username="${1}" + local primary_group="${2}" + local uid="${3}" + + adduser -u "${3}" -D -S -G "${primary_group}" "${username}" + return $? +} diff --git a/script/include/run_alpine_setup b/script/include/run_alpine_setup new file mode 100755 index 00000000..c094521a --- /dev/null +++ b/script/include/run_alpine_setup @@ -0,0 +1,25 @@ +# run_alpine_setup: Install basic system requirements for an app to run + +# Load alpine setup functions +source ./script/include/alpine_setup_functions.inc.sh + +## Set option defaults +# If GROUP information is incomplete, use the default one +if [ -z "${APP_GROUP+is_set}" ] || \ + [ -z "${APP_GID+is_set}" ]; then + APP_GROUP="atat" + APP_GROUP_ID="8000" +fi + +# If USER information is incomplete, error out +if [ -z "${APP_USER+is_set}" ] || \ + [ -z "${APP_UID+is_set}" ]; then + exit 1 +fi + +## Main +update_system_packages +install_package "bash" +install_package "dumb-init" +add_group "${APP_GROUP}" "${APP_GID}" +add_user "${APP_USER}" "${APP_GROUP}" "${APP_UID}" From c370063f8d021dd52171f0469028b7989e0eb8ca Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 15:14:05 -0400 Subject: [PATCH 31/77] Update to use shared script --- script/alpine_setup | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/script/alpine_setup b/script/alpine_setup index c029d19b..28f836c2 100755 --- a/script/alpine_setup +++ b/script/alpine_setup @@ -3,20 +3,11 @@ # script/alpine_setup: Adds all the system packages, directors, users, etc. # required to run the application on Alpine -# If a command fails, exit the script -set -e +source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +# Set app specific items +APP_USER="atst" +APP_UID="8010" -APP_USER=${1} -APP_GROUP=${2} - -apk update -apk upgrade - -apk add bash -apk add dumb-init - -addgroup -g 8000 -S "${APP_GROUP}" -adduser -u 8010 -D -S -G "${APP_GROUP}" "${APP_USER}" +# Run the shared alpine setup script +source ./script/include/run_alpine_setup From 5159e3e163d62e54166705576a9fc222a83d5fc8 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 15:14:44 -0400 Subject: [PATCH 32/77] Remove script params; no longer required to pass these values --- deploy/docker/tester/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/docker/tester/Dockerfile b/deploy/docker/tester/Dockerfile index 30c6cc11..69a835e0 100644 --- a/deploy/docker/tester/Dockerfile +++ b/deploy/docker/tester/Dockerfile @@ -28,7 +28,7 @@ COPY script/alpine_setup ./script/ # Add required system packages and app user RUN set -x ; \ - script/alpine_setup "${APP_USER}" "${APP_GROUP}" + script/alpine_setup ### Items that will change almost every build ############################################# From 2ec2eefb4bc22c5287bd07591c43286cb18ec459 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 15:28:41 -0400 Subject: [PATCH 33/77] Fix variable name --- script/include/run_alpine_setup | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include/run_alpine_setup b/script/include/run_alpine_setup index c094521a..532d613b 100755 --- a/script/include/run_alpine_setup +++ b/script/include/run_alpine_setup @@ -8,7 +8,7 @@ source ./script/include/alpine_setup_functions.inc.sh if [ -z "${APP_GROUP+is_set}" ] || \ [ -z "${APP_GID+is_set}" ]; then APP_GROUP="atat" - APP_GROUP_ID="8000" + APP_GID="8000" fi # If USER information is incomplete, error out From 6a4069853a343db612c58022998ab51099765f91 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Mon, 9 Jul 2018 15:29:30 -0400 Subject: [PATCH 34/77] Update first copy to include ALL scripts --- deploy/docker/tester/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/docker/tester/Dockerfile b/deploy/docker/tester/Dockerfile index 69a835e0..c490c6ec 100644 --- a/deploy/docker/tester/Dockerfile +++ b/deploy/docker/tester/Dockerfile @@ -23,8 +23,8 @@ RUN set -x ; \ # Set working dir WORKDIR ${APP_DIR} -# Copy over alpine setup script -COPY script/alpine_setup ./script/ +# Copy over setup scripts +COPY script/ ./script/ # Add required system packages and app user RUN set -x ; \ From 10fa0a7ffad1d4e67fa5d1a861f013e3d640249d Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 09:30:02 -0400 Subject: [PATCH 35/77] Update script to use global header file --- script/update | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/script/update b/script/update index 752ad3ad..8cb772c1 100755 --- a/script/update +++ b/script/update @@ -1,10 +1,8 @@ #!/bin/bash -# If a command fails, exit the script -set -e +# script/update: Update dependencies -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." +source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Update dependencies -script/bootstrap +# Run the bootstrap script +source ./script/bootstrap From 2b95291f936f5988c9cb4924b65044b0d1ad9248 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 09:46:44 -0400 Subject: [PATCH 36/77] Update script to use global header and no trap The server script should just give a clean, foreground execution of the app. A second script has been added to a dev server launch to try to get a backgrounding wrapper in place. --- script/server | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/script/server b/script/server index fa78012d..47e7cbaa 100755 --- a/script/server +++ b/script/server @@ -1,26 +1,8 @@ #!/bin/bash -reap() { - kill -TERM $child - sleep 0.1 - exit -} +# script/server: Launch the server -trap reap TERM INT - -# If a command fails, exit the script -set -e - -# Ensure we are in the app root directory (not the /script directory) -cd "$(dirname "${0}")/.." - -if [ -z "${SKIP_PIPENV+xxxx}" ]; then - CMD_PREFIX='pipenv run ' -fi -PYTHON_CMD="${CMD_PREFIX}python" +source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Launch the app -${PYTHON_CMD} app.py ${@} & -child=$! - -wait $child +run_command "./app.py ${LAUNCH_ARGS}" From 2b426cb784d204305db94795dc15ea4c12a96abc Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 09:48:16 -0400 Subject: [PATCH 37/77] Add script to background a server launch --- script/dev_server_WIP | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100755 script/dev_server_WIP diff --git a/script/dev_server_WIP b/script/dev_server_WIP new file mode 100755 index 00000000..f0a64ae4 --- /dev/null +++ b/script/dev_server_WIP @@ -0,0 +1,26 @@ +#!/bin/bash + +# script/local_server: Launch a local dev version of the server + +source "$(dirname "${0}")"/../script/include/global_header.inc.sh + +# Create a function to trap signals with +reap() { + kill -TERM "${child}" + sleep 0.1 + exit +} + +trap reap TERM INT + +# Set server launch related environment variables +DEBUG=1 +LAUNCH_ARGS="$*" + +# Launch the app +source ./script/server + +# Capture the PID of the child process +child=$! + +wait $child From 263fcd1c35796b04b5aea24ba56ab466d93878b4 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 09:59:12 -0400 Subject: [PATCH 38/77] Update comments --- script/dev_server_WIP | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/script/dev_server_WIP b/script/dev_server_WIP index f0a64ae4..202df4fe 100755 --- a/script/dev_server_WIP +++ b/script/dev_server_WIP @@ -1,6 +1,10 @@ #!/bin/bash -# script/local_server: Launch a local dev version of the server +# script/dev_server: Launch a local dev version of the server in the background + +# +# WIP +# source "$(dirname "${0}")"/../script/include/global_header.inc.sh @@ -11,6 +15,7 @@ reap() { exit } +# Register trap trap reap TERM INT # Set server launch related environment variables From 7adc36eed3f435c54dfe85c92c1df170a2a912bc Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:07:38 -0400 Subject: [PATCH 39/77] Remove interpretor; file should be sourced not executed --- script/include/alpine_setup_functions.inc.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/script/include/alpine_setup_functions.inc.sh b/script/include/alpine_setup_functions.inc.sh index d28b88a3..19d60985 100755 --- a/script/include/alpine_setup_functions.inc.sh +++ b/script/include/alpine_setup_functions.inc.sh @@ -1,5 +1,3 @@ -#!/bin/sh - # alpine_setup_functions: Functions used by the run_alpine_setup script update_system_packages() { From d2c610fbf7cbf7751b892e979bc964efd87881eb Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:08:05 -0400 Subject: [PATCH 40/77] Remove loop: only sourcing one file now --- script/include/global_header.inc.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh index 01e1709d..45989ee1 100755 --- a/script/include/global_header.inc.sh +++ b/script/include/global_header.inc.sh @@ -9,7 +9,4 @@ cd "$(dirname "${0}")/.." # Source all function definition files -for function_snippet in ./script/include/helper_functions.inc.sh -do - source "${function_snippet}" -done +source ./script/include/helper_functions.inc.sh From 40494e8f634b04d744d630cdecf88f60e68da65a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:08:45 -0400 Subject: [PATCH 41/77] Standardize code styling --- script/include/bootstrap_functions.inc.sh | 1 + script/include/helper_functions.inc.sh | 1 + 2 files changed, 2 insertions(+) diff --git a/script/include/bootstrap_functions.inc.sh b/script/include/bootstrap_functions.inc.sh index 33e22bf8..599fc207 100644 --- a/script/include/bootstrap_functions.inc.sh +++ b/script/include/bootstrap_functions.inc.sh @@ -2,6 +2,7 @@ install_python_packages() { local install_flags="${1}" + pipenv install ${install_flags} return $? } diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh index 96218f9a..e24594c2 100644 --- a/script/include/helper_functions.inc.sh +++ b/script/include/helper_functions.inc.sh @@ -14,6 +14,7 @@ check_system_pip_for () { # Used whenever an environment sensitive command is being run run_command () { local cmd="${1}" + pipenv run ${cmd} return $? } From e23b767a721d4bb8c42e47c0f245596aac39bf3d Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:10:38 -0400 Subject: [PATCH 42/77] Standardize code styling --- script/include/run_bootstrap | 3 +-- script/include/run_test | 2 +- script/include/test_functions.inc.sh | 2 ++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/script/include/run_bootstrap b/script/include/run_bootstrap index a3d11798..9115b004 100755 --- a/script/include/run_bootstrap +++ b/script/include/run_bootstrap @@ -1,4 +1,4 @@ -# include/run_bootstrap: Install application dependencies +# run_bootstrap: Install application dependencies # Load bootstrap functions source ./script/include/bootstrap_functions.inc.sh @@ -10,7 +10,6 @@ if [ -z "${PIPENV_INSTALL_FLAGS+is_set}" ]; then fi ## Main - if [ "${INSTALL_PYTHON_PACKAGES}" = "true" ]; then install_python_packages "${PIPENV_INSTALL_FLAGS}" fi diff --git a/script/include/run_test b/script/include/run_test index 4187c2d1..d5f6bc5f 100755 --- a/script/include/run_test +++ b/script/include/run_test @@ -1,4 +1,4 @@ -# include/run_test: Execute code checkers and unit tests +# run_test: Execute code checkers and unit tests # Load test functions source ./script/include/test_functions.inc.sh diff --git a/script/include/test_functions.inc.sh b/script/include/test_functions.inc.sh index 23e231d8..622c0bfb 100644 --- a/script/include/test_functions.inc.sh +++ b/script/include/test_functions.inc.sh @@ -2,12 +2,14 @@ run_python_lint() { local python_files="${1}" + run_command "pylint ${python_files}" return $? } run_python_static_analysis() { local python_files="${1}" + run_command "bandit -c ./.bandit_config -r ${python_files}" return $? } From d2eff80de917e6e7f91005d045770ef91447cb3d Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:10:59 -0400 Subject: [PATCH 43/77] Add error message output before aborting --- script/include/run_alpine_setup | 1 + 1 file changed, 1 insertion(+) diff --git a/script/include/run_alpine_setup b/script/include/run_alpine_setup index 532d613b..837f7e67 100755 --- a/script/include/run_alpine_setup +++ b/script/include/run_alpine_setup @@ -14,6 +14,7 @@ fi # If USER information is incomplete, error out if [ -z "${APP_USER+is_set}" ] || \ [ -z "${APP_UID+is_set}" ]; then + echo "ERROR: Missing app user information! Received: ${APP_USER}:${APP_UID}" exit 1 fi From 89e14268e933825744e72120db58a65b90a5982d Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:11:30 -0400 Subject: [PATCH 44/77] Fix function return value and clean up code style - Fix create_virtual_environment return code; use pipenv exit code not pipenv output - Clean up code style in install_pipenv --- script/include/setup_functions.inc.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/script/include/setup_functions.inc.sh b/script/include/setup_functions.inc.sh index ea26d23a..ef0ff935 100644 --- a/script/include/setup_functions.inc.sh +++ b/script/include/setup_functions.inc.sh @@ -1,20 +1,20 @@ # setup_functions.inc.sh: Functions used by the setup script install_pipenv() { - exit_code=0 + return_code=0 # Ensure we are not in a virtual env already - if [ -z "${VIRTUAL_ENV+xxxx}" ]; then + if [ -z "${VIRTUAL_ENV+is_set}" ]; then if ! check_system_pip_for pipenv; then # pipenv is not installed, so install it echo "Installing pipenv..." pip install pipenv # Capture pip exit code - exit_code="${?}" + return_code="${?}" fi fi - return "${exit_code}" + return "${return_code}" } create_virtual_environment() { @@ -32,7 +32,8 @@ create_virtual_environment() { # The environment will be in a directory called .venv off the app # root directory echo "Creating virtual environment using Python version ${python_version}..." - return $(PIPENV_VENV_IN_PROJECT=true pipenv --python "${python_version}") + PIPENV_VENV_IN_PROJECT=true pipenv --python "${python_version}" + return $? } install_sass() { From bbe9880db367d62fb5e448f08fca0a33042d4101 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:13:24 -0400 Subject: [PATCH 45/77] Ensure node modules get a fresh install on reset --- script/include/run_setup | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/script/include/run_setup b/script/include/run_setup index 97fa0808..fd026477 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -1,5 +1,5 @@ -# include/setup: Set up application for the first time after cloning, or set it -# back to the initial first unused state. +# setup: Set up application for the first time after cloning, or set it +# back to the initial first unused state. # Load setup functions source ./script/include/setup_functions.inc.sh @@ -16,6 +16,9 @@ if [ -z "${INSTALL_SASS+is_set}" ]; then fi ## Main +# Remove any existing node modules as part of initial app setup or reset +rm -rf ./node_modules + if [ "${CREATE_VENV}" = "true" ]; then install_pipenv create_virtual_environment From 628b3dc562961a1591159470fe40f12a6700a474 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:52:55 -0400 Subject: [PATCH 46/77] Modify wrapper to use PGID when terminating app --- script/dev_server_WIP | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/script/dev_server_WIP b/script/dev_server_WIP index 202df4fe..1f5f75a1 100755 --- a/script/dev_server_WIP +++ b/script/dev_server_WIP @@ -8,24 +8,25 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Create a function to trap signals with +# Create a function to run after a trap is triggered reap() { - kill -TERM "${child}" + kill -s SIGTERM -- "-$$" sleep 0.1 exit } -# Register trap -trap reap TERM INT +# Register trapping of SIGTERM and SIGINT +trap reap SIGTERM SIGINT + +# Display the script PID, which will also be the process group ID for all +# child processes +echo "Process Group: $$" # Set server launch related environment variables DEBUG=1 LAUNCH_ARGS="$*" + # Launch the app -source ./script/server - -# Capture the PID of the child process -child=$! - -wait $child +source ./script/server & +wait From f5f809c1673f6288ff22ba759540683ba1013674 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:54:27 -0400 Subject: [PATCH 47/77] Account for new script names and forced pipenv --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 88698d19..64996466 100644 --- a/README.md +++ b/README.md @@ -19,19 +19,19 @@ Additionally, ATST requires a redis instance for session management. Have redis ## Running (development) -To start the app and watch for changes: +To start the app locally in the foreground and watch for changes: - DEBUG=1 script/server + script/dev_server ## Testing -To run unit tests: +To run all linting and tests: script/test -or +To run only the unit tests: - python -m pytest + pipenv run python -m pytest ## Notes From 9dbc6cd1801fe80cf8c2025d6caa107ae6485f07 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 10:54:38 -0400 Subject: [PATCH 48/77] Rename file: no longer a work in progress --- script/{dev_server_WIP => dev_server} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename script/{dev_server_WIP => dev_server} (100%) diff --git a/script/dev_server_WIP b/script/dev_server similarity index 100% rename from script/dev_server_WIP rename to script/dev_server From ab6af09d0546c1ab8f34540cfaace40321d8a662 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 10 Jul 2018 11:47:57 -0400 Subject: [PATCH 49/77] Fix edit links in "review and submit" --- templates/requests/screen-4.html.to | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index a23fb68b..1869aefd 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -13,7 +13,7 @@

Review & Submit

-

Details of Use Edit

+

Details of Use Edit

Overall Request Details

@@ -65,7 +65,7 @@


-

Information About You Edit

+

Information About You Edit

{{ data.get('information_about_you', {}).get('fname_request') }} @@ -94,7 +94,7 @@


-

Primary Government/Military Point of Contact (POC) Edit

+

Primary Government/Military Point of Contact (POC) Edit

From 0535a45bd97b2d032ee6cec3d892ad46af13b686 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 12:01:56 -0400 Subject: [PATCH 50/77] Check for pipenv and error out if not present --- script/include/run_setup | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/script/include/run_setup b/script/include/run_setup index fd026477..2ff7eb52 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -20,7 +20,11 @@ fi rm -rf ./node_modules if [ "${CREATE_VENV}" = "true" ]; then - install_pipenv + # Ensure pipenv is installed + if ! check_system_pip_for pipenv; then + echo "ERROR: pipenv is required but is not present" + exit 1 + fi create_virtual_environment fi From 269f23d56c68bb773f79817d3a58606c8aadecb3 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 10 Jul 2018 14:05:27 -0400 Subject: [PATCH 51/77] Continue showing "review and submit" after request is approved --- atst/handlers/request_new.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index a53ebf8b..2aa6225d 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -174,7 +174,7 @@ class JEDIRequestFlow(object): "title": "Review & Submit", "section": "review_submit", "form": ReviewForm, - "show": self.request and self.request["status"] == "pending_submission", + "show": self.request and self.request["status"] != "incomplete", }, { "title": "Financial Verification", From 2864300a4e7ef27eaa3152ee2e94213a534f745a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 14:55:02 -0400 Subject: [PATCH 52/77] Add function for installing pip packages in the venv --- script/include/helper_functions.inc.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh index e24594c2..84792652 100644 --- a/script/include/helper_functions.inc.sh +++ b/script/include/helper_functions.inc.sh @@ -11,6 +11,14 @@ check_system_pip_for () { return $? } +pip_install () { + local packages="${1}" + local flags="${2}" + + run_command "pip install ${flags} ${packages}" + return $? +} + # Used whenever an environment sensitive command is being run run_command () { local cmd="${1}" From d620fb6cc08a3a637040f65d3816712fd940eff6 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 14:55:26 -0400 Subject: [PATCH 53/77] Add pip update in venv --- script/include/run_setup | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/script/include/run_setup b/script/include/run_setup index 2ff7eb52..c4c691bb 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -15,6 +15,11 @@ if [ -z "${INSTALL_SASS+is_set}" ]; then INSTALL_SASS="false" fi +# If PIP_VERSION is not set, set it to "10.*" +if [ -z "${PIP_VERSION+is_set}" ]; then + PIP_VERSION="10.*" +fi + ## Main # Remove any existing node modules as part of initial app setup or reset rm -rf ./node_modules @@ -26,6 +31,7 @@ if [ "${CREATE_VENV}" = "true" ]; then exit 1 fi create_virtual_environment + pip_install "pip==${PIP_VERSION}" "--upgrade" fi if [ "${INSTALL_SASS}" = "true" ]; then From fc62dcdb65b5126be94a87083302a96fef9c6d08 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Tue, 10 Jul 2018 15:20:21 -0400 Subject: [PATCH 54/77] Update pipenv check to just test the binary --- script/include/run_setup | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/script/include/run_setup b/script/include/run_setup index c4c691bb..376802f8 100755 --- a/script/include/run_setup +++ b/script/include/run_setup @@ -26,8 +26,8 @@ rm -rf ./node_modules if [ "${CREATE_VENV}" = "true" ]; then # Ensure pipenv is installed - if ! check_system_pip_for pipenv; then - echo "ERROR: pipenv is required but is not present" + if ! pipenv --version >/dev/null 2>&1 ; then + echo "ERROR: pipenv is malfunctioning or not present" exit 1 fi create_virtual_environment From 358aa6366c3358e666cd335b36f344ca28b1b370 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Tue, 10 Jul 2018 17:01:39 -0400 Subject: [PATCH 55/77] Always show submit screen, but disable button if form is incomplete --- atst/handlers/request_new.py | 17 ++++++++++++----- templates/requests/screen-4.html.to | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 2aa6225d..63e615af 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -73,6 +73,7 @@ class RequestNew(BaseHandler): current=screen, next_screen=screen + 1, request_id=request_id, + can_submit=jedi_flow.can_submit ) @tornado.gen.coroutine @@ -130,13 +131,19 @@ class JEDIRequestFlow(object): def current_step_data(self): if self.is_post: return self.post_data - elif self.form_section == "review_submit": - return self.request["body"] - elif self.request: - return self.request["body"].get(self.form_section, {}) + + if self.request: + if self.form_section == "review_submit": + return self.request["body"] + else: + return self.request["body"].get(self.form_section, {}) else: return {} + @property + def can_submit(self): + return self.request and self.request["status"] != "incomplete" + @property def next_screen(self): return self.current_step + 1 @@ -174,7 +181,7 @@ class JEDIRequestFlow(object): "title": "Review & Submit", "section": "review_submit", "form": ReviewForm, - "show": self.request and self.request["status"] != "incomplete", + "show":True, }, { "title": "Financial Verification", diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index 1869aefd..2d938a5d 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -116,5 +116,5 @@ {% end %} {% block next %} - + {% end %} From 172e9aae4d36f8ba96fd074bd6ddf262d0887c92 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Wed, 11 Jul 2018 09:58:35 -0400 Subject: [PATCH 56/77] Add pytest-watch dev dependency --- Pipfile | 1 + Pipfile.lock | 47 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/Pipfile b/Pipfile index f772a51a..eb946fb9 100644 --- a/Pipfile +++ b/Pipfile @@ -19,6 +19,7 @@ ipython = "*" ipdb = "*" pylint = "*" black = "*" +pytest-watch = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 2cf47dcc..2fadae1e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "53a2048f5dc853a0ac2d565164c23dcdb2df802e055c1530864bfc8390af3c3e" + "sha256": "3bea02ccdb0e3877f2595d7fb405408114ec8947e0484d5b4aaf14a4c8ff78b2" }, "pipfile-spec": 6, "requires": { @@ -119,6 +119,13 @@ "markers": "sys_platform == 'darwin'", "version": "==0.1.0" }, + "argh": { + "hashes": [ + "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3", + "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65" + ], + "version": "==0.26.2" + }, "astroid": { "hashes": [ "sha256:a8d8c7fe34e34e868426b9bafce852c355a3951eef60bc831b2ed541558f8d37", @@ -170,6 +177,13 @@ ], "version": "==6.7" }, + "colorama": { + "hashes": [ + "sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda", + "sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1" + ], + "version": "==0.3.9" + }, "decorator": { "hashes": [ "sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82", @@ -177,6 +191,12 @@ ], "version": "==4.3.0" }, + "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], + "version": "==0.6.2" + }, "gitdb2": { "hashes": [ "sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09", @@ -280,10 +300,16 @@ }, "parso": { "hashes": [ - "sha256:8105449d86d858e53ce3e0044ede9dd3a395b1c9716c696af8aa3787158ab806", - "sha256:d250235e52e8f9fc5a80cc2a5f804c9fefd886b2e67a2b1099cf085f403f8e33" + "sha256:35704a43a3c113cce4de228ddb39aab374b8004f4f2407d070b6a2ca784ce8a2", + "sha256:895c63e93b94ac1e1690f5fdd40b65f07c8171e3e53cbd7793b5b96c0e0a7f24" ], - "version": "==0.3.0" + "version": "==0.3.1" + }, + "pathtools": { + "hashes": [ + "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0" + ], + "version": "==0.1.2" }, "pbr": { "hashes": [ @@ -370,6 +396,13 @@ "index": "pypi", "version": "==0.5.0" }, + "pytest-watch": { + "hashes": [ + "sha256:06136f03d5b361718b8d0d234042f7b2f203910d8568f63df2f866b547b3d4b9" + ], + "index": "pypi", + "version": "==4.2.0" + }, "pyyaml": { "hashes": [ "sha256:254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb", @@ -460,6 +493,12 @@ "markers": "python_version < '3.7' and implementation_name == 'cpython'", "version": "==1.1.0" }, + "watchdog": { + "hashes": [ + "sha256:7e65882adb7746039b6f3876ee174952f8eaaa34491ba34333ddf1fe35de4162" + ], + "version": "==0.8.3" + }, "wcwidth": { "hashes": [ "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", From 3925007489b4350e1d009de6d989bc9a43e16f95 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Wed, 11 Jul 2018 10:53:49 -0400 Subject: [PATCH 57/77] Add tests for some validators --- tests/conftest.py | 20 +++++++++++ tests/forms/test_validators.py | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/forms/test_validators.py diff --git a/tests/conftest.py b/tests/conftest.py index d0da68f2..a8c45680 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,3 +19,23 @@ def app(): deps.update(TEST_DEPS) return make_app(config, deps) + +class DummyForm(dict): + pass + + +class DummyField(object): + def __init__(self, data=None, errors=(), raw_data=None): + self.data = data + self.errors = list(errors) + self.raw_data = raw_data + + +@pytest.fixture +def dummy_form(): + return DummyForm() + + +@pytest.fixture +def dummy_field(): + return DummyField() diff --git a/tests/forms/test_validators.py b/tests/forms/test_validators.py new file mode 100644 index 00000000..b648cc66 --- /dev/null +++ b/tests/forms/test_validators.py @@ -0,0 +1,61 @@ +from wtforms.validators import ValidationError +import pytest + +from atst.forms.validators import Alphabet, IsNumber, PhoneNumber + + +class TestIsNumber: + + @pytest.mark.parametrize("valid", ["0", "12", "-12"]) + def test_IsNumber_accepts_integers(self, valid, dummy_form, dummy_field): + validator = IsNumber() + dummy_field.data = valid + validator(dummy_form, dummy_field) + + @pytest.mark.parametrize("invalid", ["12.1", "two", ""]) + def test_IsNumber_rejects_anything_else(self, invalid, dummy_form, dummy_field): + validator = IsNumber() + dummy_field.data = invalid + with pytest.raises(ValidationError): + validator(dummy_form, dummy_field) + + +class TestPhoneNumber: + + @pytest.mark.parametrize("valid", [ + "12345", + "1234567890", + "(123) 456-7890", + ]) + def test_PhoneNumber_accepts_valid_numbers(self, valid, dummy_form, dummy_field): + validator = PhoneNumber() + dummy_field.data = valid + validator(dummy_form, dummy_field) + + @pytest.mark.parametrize("invalid", [ + "1234", + "123456", + "1234567abc", + "(123) 456-789012", + ]) + def test_PhoneNumber_rejects_invalid_numbers(self, invalid, dummy_form, dummy_field): + validator = PhoneNumber() + dummy_field.data = invalid + with pytest.raises(ValidationError): + validator(dummy_form, dummy_field) + + +class TestAlphabet: + + @pytest.mark.parametrize("valid", ["a", "abcde"]) + def test_Alphabet_accepts_letters(self, valid, dummy_form, dummy_field): + validator = Alphabet() + dummy_field.data = valid + validator(dummy_form, dummy_field) + + @pytest.mark.parametrize("invalid", ["", "hi mark", "cloud9"]) + def test_Alphabet_rejects_non_letters(self, invalid, dummy_form, dummy_field): + validator = Alphabet() + dummy_field.data = invalid + with pytest.raises(ValidationError): + validator(dummy_form, dummy_field) From 1b7203ce3053984dd66219cb1d999adaadf0a995 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Wed, 11 Jul 2018 10:55:55 -0400 Subject: [PATCH 58/77] Add note to README on pytest-watch use --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 64996466..d759de47 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,10 @@ To run only the unit tests: pipenv run python -m pytest +To re-run tests each time a file is changed: + + pipenv run ptw + ## Notes tornado templates are like mustache templates -- add the From 98915dd69e928ff4a62787ce13bb8100c0c6cf03 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Thu, 12 Jul 2018 08:55:20 -0400 Subject: [PATCH 59/77] Panel grid layout should stop wrapping at the large breakpoint --- scss/elements/_panels.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scss/elements/_panels.scss b/scss/elements/_panels.scss index 6f655012..ce50b515 100644 --- a/scss/elements/_panels.scss +++ b/scss/elements/_panels.scss @@ -47,6 +47,9 @@ @include media($medium-screen) { @include margin(($site-margins * 2) null); + } + + @include media($large-screen) { flex-wrap: nowrap; } From 26cd56c345f71e9d1126c35a1321b8590888ed21 Mon Sep 17 00:00:00 2001 From: Andrew Croce Date: Thu, 12 Jul 2018 08:55:36 -0400 Subject: [PATCH 60/77] Fix margins on sideanv --- scss/sections/_sidenav.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scss/sections/_sidenav.scss b/scss/sections/_sidenav.scss index d695d742..4415c3ae 100644 --- a/scss/sections/_sidenav.scss +++ b/scss/sections/_sidenav.scss @@ -79,6 +79,10 @@ > ul { @include panel-margin; + &:last-child { + margin: 0; + } + > li { &:last-child { > .sidenav__link { From 21c970e4b4ff6276fb8130d8ac531b85a9112447 Mon Sep 17 00:00:00 2001 From: dandds Date: Thu, 12 Jul 2018 11:39:22 -0400 Subject: [PATCH 61/77] rename some handlers with more specificity --- atst/app.py | 26 +++++++++---------- atst/handlers/{login.py => login_redirect.py} | 2 +- atst/handlers/main.py | 2 +- atst/handlers/{home.py => root.py} | 2 +- tests/test_auth.py | 10 +++---- 5 files changed, 21 insertions(+), 21 deletions(-) rename atst/handlers/{login.py => login_redirect.py} (96%) rename atst/handlers/{home.py => root.py} (87%) diff --git a/atst/app.py b/atst/app.py index a0b3e491..0cce9376 100644 --- a/atst/app.py +++ b/atst/app.py @@ -4,9 +4,9 @@ import tornado.web from tornado.web import url from redis import StrictRedis -from atst.handlers.main import MainHandler -from atst.handlers.home import Home -from atst.handlers.login import Login +from atst.handlers.main import Main +from atst.handlers.root import Root +from atst.handlers.login_redirect import LoginRedirect from atst.handlers.workspace import Workspace from atst.handlers.request import Request from atst.handlers.request_new import RequestNew @@ -22,23 +22,23 @@ ENV = os.getenv("TORNADO_ENV", "dev") def make_app(config, deps, **kwargs): routes = [ - url(r"/", Home, {"page": "login"}, name="main"), + url(r"/", Root, {"page": "login"}, name="root"), url( - r"/login", - Login, + r"/login-redirect", + LoginRedirect, {"sessions": deps["sessions"], "authnid_client": deps["authnid_client"]}, - name="login", + name="login_redirect", ), - url(r"/home", MainHandler, {"page": "home"}, name="home"), + url(r"/home", Main, {"page": "home"}, name="home"), url( r"/styleguide", - MainHandler, + Main, {"page": "styleguide"}, name="styleguide", ), url( r"/workspaces/blank", - MainHandler, + Main, {"page": "workspaces_blank"}, name="workspaces_blank", ), @@ -78,9 +78,9 @@ def make_app(config, deps, **kwargs): {"requests_client": deps["requests_client"]}, name="requests_submit", ), - url(r"/users", MainHandler, {"page": "users"}, name="users"), - url(r"/reports", MainHandler, {"page": "reports"}, name="reports"), - url(r"/calculator", MainHandler, {"page": "calculator"}, name="calculator"), + url(r"/users", Main, {"page": "users"}, name="users"), + url(r"/reports", Main, {"page": "reports"}, name="reports"), + url(r"/calculator", Main, {"page": "calculator"}, name="calculator"), ] if not ENV == "production": diff --git a/atst/handlers/login.py b/atst/handlers/login_redirect.py similarity index 96% rename from atst/handlers/login.py rename to atst/handlers/login_redirect.py index 4e8b6f2d..9fa9998f 100644 --- a/atst/handlers/login.py +++ b/atst/handlers/login_redirect.py @@ -2,7 +2,7 @@ import tornado from atst.handler import BaseHandler -class Login(BaseHandler): +class LoginRedirect(BaseHandler): def initialize(self, authnid_client, sessions): self.authnid_client = authnid_client self.sessions = sessions diff --git a/atst/handlers/main.py b/atst/handlers/main.py index 025c3c53..737d3bd7 100644 --- a/atst/handlers/main.py +++ b/atst/handlers/main.py @@ -2,7 +2,7 @@ import tornado from atst.handler import BaseHandler -class MainHandler(BaseHandler): +class Main(BaseHandler): def initialize(self, page): self.page = page diff --git a/atst/handlers/home.py b/atst/handlers/root.py similarity index 87% rename from atst/handlers/home.py rename to atst/handlers/root.py index 483bd161..ec68bfcc 100644 --- a/atst/handlers/home.py +++ b/atst/handlers/root.py @@ -1,7 +1,7 @@ from atst.handler import BaseHandler -class Home(BaseHandler): +class Root(BaseHandler): def initialize(self, page): self.page = page diff --git a/tests/test_auth.py b/tests/test_auth.py index 0f5cd6f3..b5c420e2 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -21,7 +21,7 @@ def test_redirects_when_not_logged_in(http_client, base_url): @pytest.mark.gen_test def test_redirects_when_session_does_not_exist(monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.main.MainHandler.get_secure_cookie", lambda s,c: 'stale cookie!') + monkeypatch.setattr("atst.handlers.main.Main.get_secure_cookie", lambda s,c: 'stale cookie!') response = yield http_client.fetch( base_url + "/home", raise_error=False, follow_redirects=False ) @@ -33,9 +33,9 @@ def test_redirects_when_session_does_not_exist(monkeypatch, http_client, base_ur @pytest.mark.gen_test def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.login.Login._fetch_user_info", _fetch_user_info) + monkeypatch.setattr("atst.handlers.login_redirect.LoginRedirect._fetch_user_info", _fetch_user_info) response = yield http_client.fetch( - base_url + "/login?bearer-token=abc-123", + base_url + "/login-redirect?bearer-token=abc-123", follow_redirects=False, raise_error=False, ) @@ -65,10 +65,10 @@ def test_login_with_invalid_bearer_token(http_client, base_url): @pytest.mark.gen_test def test_valid_login_creates_session(app, monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.login.Login._fetch_user_info", _fetch_user_info) + monkeypatch.setattr("atst.handlers.login_redirect.LoginRedirect._fetch_user_info", _fetch_user_info) assert len(app.sessions.sessions) == 0 yield http_client.fetch( - base_url + "/login?bearer-token=abc-123", + base_url + "/login-redirect?bearer-token=abc-123", follow_redirects=False, raise_error=False, ) From f2b010232d1a57232bcf981bf0f510c8de7040bb Mon Sep 17 00:00:00 2001 From: dandds Date: Thu, 12 Jul 2018 13:45:49 -0400 Subject: [PATCH 62/77] move login template to root --- atst/app.py | 2 +- templates/{login.html.to => root.html.to} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename templates/{login.html.to => root.html.to} (100%) diff --git a/atst/app.py b/atst/app.py index 0cce9376..ed1be4a6 100644 --- a/atst/app.py +++ b/atst/app.py @@ -22,7 +22,7 @@ ENV = os.getenv("TORNADO_ENV", "dev") def make_app(config, deps, **kwargs): routes = [ - url(r"/", Root, {"page": "login"}, name="root"), + url(r"/", Root, {"page": "root"}, name="root"), url( r"/login-redirect", LoginRedirect, diff --git a/templates/login.html.to b/templates/root.html.to similarity index 100% rename from templates/login.html.to rename to templates/root.html.to From 43e427d4ef7826190dc59c5e2e4ad804b59896be Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Tue, 10 Jul 2018 10:24:05 -0400 Subject: [PATCH 63/77] Make PE number input accept single string only --- atst/forms/financial.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atst/forms/financial.py b/atst/forms/financial.py index 5654495b..b4d551a5 100644 --- a/atst/forms/financial.py +++ b/atst/forms/financial.py @@ -15,8 +15,8 @@ class FinancialForm(Form): "Unique Item Identifier (UII)s related to your application(s) if you already have them." ) - pe_id = NewlineListField( - "Program Element (PE) Numbers related to your request" + pe_id = StringField( + "Program Element (PE) Number related to your request" ) fname_co = StringField("Contracting Officer First Name", validators=[Required()]) From 9320b0eac2aee29eb85bd835474982ef2c9470e8 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Tue, 10 Jul 2018 17:27:31 -0400 Subject: [PATCH 64/77] Add treasury code/ba code fields --- atst/forms/financial.py | 4 ++++ templates/requests/screen-5.html.to | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/atst/forms/financial.py b/atst/forms/financial.py index b4d551a5..19866b49 100644 --- a/atst/forms/financial.py +++ b/atst/forms/financial.py @@ -19,6 +19,10 @@ class FinancialForm(Form): "Program Element (PE) Number related to your request" ) + treasury_code = StringField("Please provide your Program Treasury Code") + + ba_code = StringField("Please provide your Program BA Code") + fname_co = StringField("Contracting Officer First Name", validators=[Required()]) lname_co = StringField("Contracting Officer Last Name", validators=[Required()]) diff --git a/templates/requests/screen-5.html.to b/templates/requests/screen-5.html.to index 0a87e206..5fcfc412 100644 --- a/templates/requests/screen-5.html.to +++ b/templates/requests/screen-5.html.to @@ -35,6 +35,21 @@ {% end %} +{{ f.treasury_code.label }} +{{ f.treasury_code(placeholder="Example: 1200") }} +{% for e in f.treasury_code.errors %} +
+ {{ e }} +
+{% end %} + +{{ f.ba_code.label }} +{{ f.ba_code(placeholder="Example: 02") }} +{% for e in f.ba_code.errors %} +
+ {{ e }} +
+{% end %} From fd8629db5b265ecd361841380156e68b49332b44 Mon Sep 17 00:00:00 2001 From: richard-dds Date: Thu, 12 Jul 2018 16:41:06 -0400 Subject: [PATCH 65/77] Use nested defaultdicts to provide more helpful text for unfilled fields --- atst/handlers/request_new.py | 13 +++++--- templates/requests/screen-4.html.to | 52 ++++++++++++++--------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py index 63e615af..d15a1ef4 100644 --- a/atst/handlers/request_new.py +++ b/atst/handlers/request_new.py @@ -1,4 +1,5 @@ import tornado +from collections import defaultdict from atst.handler import BaseHandler from atst.forms.request import RequestForm @@ -129,16 +130,18 @@ class JEDIRequestFlow(object): @property def current_step_data(self): + data = {} + if self.is_post: - return self.post_data + data = self.post_data if self.request: if self.form_section == "review_submit": - return self.request["body"] + data = self.request["body"] else: - return self.request["body"].get(self.form_section, {}) - else: - return {} + data = self.request["body"].get(self.form_section, {}) + + return defaultdict(lambda: defaultdict(lambda: 'Input required'), data) @property def can_submit(self): diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index 2d938a5d..58eb66ba 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -18,78 +18,78 @@

Overall Request Details

-{{ data.get('details_of_use', {}).get('dollar_value') }} +{{ data['details_of_use']['dollar_value'] }} -{{ data.get('details_of_use', {}).get('num_applications') }} +{{ data['details_of_use']['num_applications'] }} -{{ data.get('details_of_use', {}).get('date_start') }} +{{ data['details_of_use']['date_start'] }} -{{ data.get('details_of_use', {}).get('app_description') }} +{{ data['details_of_use']['app_description'] }} -{{ data.get('details_of_use', {}).get('supported_organizations') }} +{{ data['details_of_use']['supported_organizations'] }}

Cloud Resources

-{{ data.get('details_of_use', {}).get('total_cores') }} +{{ data['details_of_use']['total_cores'] }} -{{ data.get('details_of_use', {}).get('total_ram') }} +{{ data['details_of_use']['total_ram'] }} -{{ data.get('details_of_use', {}).get('total_object_storage') }} +{{ data['details_of_use']['total_object_storage'] }} -{{ data.get('details_of_use', {}).get('total_server_storage') }} +{{ data['details_of_use']['total_server_storage'] }}

Support Staff

-{{ data.get('details_of_use', {}).get('has_contractor_advisor') }} +{{ data['details_of_use']['has_contractor_advisor'] }} -{{ data.get('details_of_use', {}).get('is_migrating_application') }} +{{ data['details_of_use']['is_migrating_application'] }} -{{ data.get('details_of_use', {}).get('supporting_organization') }} +{{ data['details_of_use']['supporting_organization'] }} -{{ data.get('details_of_use', {}).get('has_migration_office') }} +{{ data['details_of_use']['has_migration_office'] }} -{{ data.get('details_of_use', {}).get('supporting_organization') }} +{{ data['details_of_use']['supporting_organization'] }}


Information About You Edit

-{{ data.get('information_about_you', {}).get('fname_request') }} +{{ data['information_about_you']['fname_request'] }} -{{ data.get('information_about_you', {}).get('lname_request') }} +{{ data['information_about_you']['lname_request'] }} -{{ data.get('information_about_you', {}).get('email_request') }} +{{ data['information_about_you']['email_request'] }} -{{ data.get('information_about_you', {}).get('phone_number') }} +{{ data['information_about_you']['phone_number'] }} -{{ data.get('information_about_you', {}).get('service_branch') }} +{{ data['information_about_you']['service_branch'] }} -{{ data.get('information_about_you', {}).get('citizenship') }} +{{ data['information_about_you']['citizenship'] }} -{{ data.get('information_about_you', {}).get('designation') }} +{{ data['information_about_you']['designation'] }} -{{ data.get('information_about_you', {}).get('date_latest_training') }} +{{ data['information_about_you']['date_latest_training'] }}


@@ -99,16 +99,16 @@ -{{ data.get('primary_poc', {}).get('fname_poc')}} +{{ data['primary_poc']['fname_poc']}} -{{ data.get('primary_poc', {}).get('lname_poc')}} +{{ data['primary_poc']['lname_poc']}} -{{ data.get('primary_poc', {}).get('email_poc')}} +{{ data['primary_poc']['email_poc']}} -{{ data.get('primary_poc', {}).get('dodid_poc')}} +{{ data['primary_poc']['dodid_poc']}}

From 335bbed94d2e1aec8914d7dcbfe99cddbc06a2f3 Mon Sep 17 00:00:00 2001 From: dandds Date: Thu, 12 Jul 2018 16:43:41 -0400 Subject: [PATCH 66/77] ensure we clear session cookies --- atst/handler.py | 1 + tests/test_auth.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/atst/handler.py b/atst/handler.py index 2ad1acaf..ac6dc4b4 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -23,6 +23,7 @@ class BaseHandler(tornado.web.RequestHandler): try: session = self.application.sessions.get_session(cookie) except SessionNotFoundError: + self.clear_cookie("atat") return None else: return None diff --git a/tests/test_auth.py b/tests/test_auth.py index b5c420e2..a74b92d5 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -26,6 +26,9 @@ def test_redirects_when_session_does_not_exist(monkeypatch, http_client, base_ur base_url + "/home", raise_error=False, follow_redirects=False ) location = response.headers["Location"] + cookie = response.headers._dict.get('Set-Cookie') + # should clear session cookie + assert 'atat=""' in cookie assert response.code == 302 assert response.error assert re.match("/\??", location) From 78c823942283badbbc4f54268a3c33e26bb673c3 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 09:18:49 -0400 Subject: [PATCH 67/77] Remove existing include directory --- script/include/alpine_setup_functions.inc.sh | 30 ------------ script/include/bootstrap_functions.inc.sh | 13 ------ script/include/global_header.inc.sh | 12 ----- script/include/helper_functions.inc.sh | 28 ------------ script/include/run_alpine_setup | 26 ----------- script/include/run_bootstrap | 23 ---------- script/include/run_setup | 42 ----------------- script/include/run_test | 17 ------- script/include/setup_functions.inc.sh | 48 -------------------- script/include/test_functions.inc.sh | 20 -------- 10 files changed, 259 deletions(-) delete mode 100755 script/include/alpine_setup_functions.inc.sh delete mode 100644 script/include/bootstrap_functions.inc.sh delete mode 100755 script/include/global_header.inc.sh delete mode 100644 script/include/helper_functions.inc.sh delete mode 100755 script/include/run_alpine_setup delete mode 100755 script/include/run_bootstrap delete mode 100755 script/include/run_setup delete mode 100755 script/include/run_test delete mode 100644 script/include/setup_functions.inc.sh delete mode 100644 script/include/test_functions.inc.sh diff --git a/script/include/alpine_setup_functions.inc.sh b/script/include/alpine_setup_functions.inc.sh deleted file mode 100755 index 19d60985..00000000 --- a/script/include/alpine_setup_functions.inc.sh +++ /dev/null @@ -1,30 +0,0 @@ -# alpine_setup_functions: Functions used by the run_alpine_setup script - -update_system_packages() { - apk update - apk upgrade -} - -install_package() { - local package_name=${1} - - apk add ${1} - return $? -} - -add_group() { - local group_name="${1}" - local gid="${2}" - - addgroup -g "${gid}" -S "${group_name}" - return $? -} - -add_user() { - local username="${1}" - local primary_group="${2}" - local uid="${3}" - - adduser -u "${3}" -D -S -G "${primary_group}" "${username}" - return $? -} diff --git a/script/include/bootstrap_functions.inc.sh b/script/include/bootstrap_functions.inc.sh deleted file mode 100644 index 599fc207..00000000 --- a/script/include/bootstrap_functions.inc.sh +++ /dev/null @@ -1,13 +0,0 @@ -# bootstrap_functions.inc.sh: Functions used by the bootstrap script - -install_python_packages() { - local install_flags="${1}" - - pipenv install ${install_flags} - return $? -} - -install_node_packages() { - npm install - return $? -} diff --git a/script/include/global_header.inc.sh b/script/include/global_header.inc.sh deleted file mode 100755 index 45989ee1..00000000 --- a/script/include/global_header.inc.sh +++ /dev/null @@ -1,12 +0,0 @@ -# global_header.inc: Any basic things that should be executed at the -# beginning of any and every script - -# If any command fails, immediately exit the script -set -e - -# Ensure the working directory is the app root directory -cd "$(dirname "${0}")/.." - -# Source all function definition files - -source ./script/include/helper_functions.inc.sh diff --git a/script/include/helper_functions.inc.sh b/script/include/helper_functions.inc.sh deleted file mode 100644 index 84792652..00000000 --- a/script/include/helper_functions.inc.sh +++ /dev/null @@ -1,28 +0,0 @@ -# helper_functions.inc.sh: General helper functions - -# Check pip to see if the given package is installed -# (returns 0 if installed, 2 if not installed) -check_system_pip_for () { - local package_name="${1}" - - # Use 'pip list' to see if the requested package is already installed - pip list --format=columns --disable-pip-version-check | \ - grep -Fe "${package_name}" >/dev/null 2>&1 - return $? -} - -pip_install () { - local packages="${1}" - local flags="${2}" - - run_command "pip install ${flags} ${packages}" - return $? -} - -# Used whenever an environment sensitive command is being run -run_command () { - local cmd="${1}" - - pipenv run ${cmd} - return $? -} diff --git a/script/include/run_alpine_setup b/script/include/run_alpine_setup deleted file mode 100755 index 837f7e67..00000000 --- a/script/include/run_alpine_setup +++ /dev/null @@ -1,26 +0,0 @@ -# run_alpine_setup: Install basic system requirements for an app to run - -# Load alpine setup functions -source ./script/include/alpine_setup_functions.inc.sh - -## Set option defaults -# If GROUP information is incomplete, use the default one -if [ -z "${APP_GROUP+is_set}" ] || \ - [ -z "${APP_GID+is_set}" ]; then - APP_GROUP="atat" - APP_GID="8000" -fi - -# If USER information is incomplete, error out -if [ -z "${APP_USER+is_set}" ] || \ - [ -z "${APP_UID+is_set}" ]; then - echo "ERROR: Missing app user information! Received: ${APP_USER}:${APP_UID}" - exit 1 -fi - -## Main -update_system_packages -install_package "bash" -install_package "dumb-init" -add_group "${APP_GROUP}" "${APP_GID}" -add_user "${APP_USER}" "${APP_GROUP}" "${APP_UID}" diff --git a/script/include/run_bootstrap b/script/include/run_bootstrap deleted file mode 100755 index 9115b004..00000000 --- a/script/include/run_bootstrap +++ /dev/null @@ -1,23 +0,0 @@ -# run_bootstrap: Install application dependencies - -# Load bootstrap functions -source ./script/include/bootstrap_functions.inc.sh - -## Set option defaults -# If PIPENV_INSTALL_FLAGS is not set, give it the default value of "--dev" -if [ -z "${PIPENV_INSTALL_FLAGS+is_set}" ]; then - PIPENV_INSTALL_FLAGS="--dev" -fi - -## Main -if [ "${INSTALL_PYTHON_PACKAGES}" = "true" ]; then - install_python_packages "${PIPENV_INSTALL_FLAGS}" -fi - -if [ "${INSTALL_NODE_PACKAGES}" = "true" ]; then - install_node_packages -fi - -if [ -n "${COMPILE_SASS_CMD}" ]; then - run_command "${COMPILE_SASS_CMD}" -fi diff --git a/script/include/run_setup b/script/include/run_setup deleted file mode 100755 index 376802f8..00000000 --- a/script/include/run_setup +++ /dev/null @@ -1,42 +0,0 @@ -# setup: Set up application for the first time after cloning, or set it -# back to the initial first unused state. - -# Load setup functions -source ./script/include/setup_functions.inc.sh - -## Set option defaults -# If CREATE_VENV is not set, set it to "true" -if [ -z "${CREATE_VENV+is_set}" ]; then - CREATE_VENV="true" -fi - -# If INSTALL_SASS is not set, set it to "false" -if [ -z "${INSTALL_SASS+is_set}" ]; then - INSTALL_SASS="false" -fi - -# If PIP_VERSION is not set, set it to "10.*" -if [ -z "${PIP_VERSION+is_set}" ]; then - PIP_VERSION="10.*" -fi - -## Main -# Remove any existing node modules as part of initial app setup or reset -rm -rf ./node_modules - -if [ "${CREATE_VENV}" = "true" ]; then - # Ensure pipenv is installed - if ! pipenv --version >/dev/null 2>&1 ; then - echo "ERROR: pipenv is malfunctioning or not present" - exit 1 - fi - create_virtual_environment - pip_install "pip==${PIP_VERSION}" "--upgrade" -fi - -if [ "${INSTALL_SASS}" = "true" ]; then - install_sass -fi - -# Install application dependencies -./script/bootstrap diff --git a/script/include/run_test b/script/include/run_test deleted file mode 100755 index d5f6bc5f..00000000 --- a/script/include/run_test +++ /dev/null @@ -1,17 +0,0 @@ -# run_test: Execute code checkers and unit tests - -# Load test functions -source ./script/include/test_functions.inc.sh - -## Set option defaults -# If PYTHON_FILES is not set, give it the default value of "app.py" -if [ -z "${PYTHON_FILES+is_set}" ]; then - PYTHON_FILES="app.py" -fi - -## Main -if [ "${RUN_PYTHON_TESTS}" = "true" ]; then - run_python_lint "${PYTHON_FILES}" - run_python_static_analysis "${PYTHON_FILES}" - run_python_unit_tests "${PYTHON_FILES}" -fi diff --git a/script/include/setup_functions.inc.sh b/script/include/setup_functions.inc.sh deleted file mode 100644 index ef0ff935..00000000 --- a/script/include/setup_functions.inc.sh +++ /dev/null @@ -1,48 +0,0 @@ -# setup_functions.inc.sh: Functions used by the setup script - -install_pipenv() { - return_code=0 - - # Ensure we are not in a virtual env already - if [ -z "${VIRTUAL_ENV+is_set}" ]; then - if ! check_system_pip_for pipenv; then - # pipenv is not installed, so install it - echo "Installing pipenv..." - pip install pipenv - # Capture pip exit code - return_code="${?}" - fi - fi - - return "${return_code}" -} - -create_virtual_environment() { - default_python_version=3.6 - # Parse out the required Python version from the Pipfile - python_version=$(grep python_version ./Pipfile | cut -d '"' -f 2) - - # If we ended up with an empty string for the required Python version, - # specify the default version - if [ -z "${python_version}" ]; then - python_version="${default_python_version}" - fi - - # Create a new virtual environment for the app - # The environment will be in a directory called .venv off the app - # root directory - echo "Creating virtual environment using Python version ${python_version}..." - PIPENV_VENV_IN_PROJECT=true pipenv --python "${python_version}" - return $? -} - -install_sass() { - if ! type sass >/dev/null; then - if type gem >/dev/null; then - echo 'Installing a sass compiler (gem)...' - gem install sass - else - echo 'Could not install a sass compiler. Please install a version of sass.' - fi - fi -} diff --git a/script/include/test_functions.inc.sh b/script/include/test_functions.inc.sh deleted file mode 100644 index 622c0bfb..00000000 --- a/script/include/test_functions.inc.sh +++ /dev/null @@ -1,20 +0,0 @@ -# test_functions.inc.sh: Functions used by the run_test script - -run_python_lint() { - local python_files="${1}" - - run_command "pylint ${python_files}" - return $? -} - -run_python_static_analysis() { - local python_files="${1}" - - run_command "bandit -c ./.bandit_config -r ${python_files}" - return $? -} - -run_python_unit_tests() { - run_command "python -m pytest -s" - return $? -} From 3312841ba40125531ebbebbed25b05f315b382af Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 09:21:52 -0400 Subject: [PATCH 68/77] Add scriptz submodule as script/include --- .gitmodules | 4 ++++ script/include | 1 + 2 files changed, 5 insertions(+) create mode 100644 .gitmodules create mode 160000 script/include diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..21e1e4c7 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "script/include"] + path = script/include + url = git@github.com:dod-ccpo/scriptz.git + branch = add-app-scripts diff --git a/script/include b/script/include new file mode 160000 index 00000000..2c725ea1 --- /dev/null +++ b/script/include @@ -0,0 +1 @@ +Subproject commit 2c725ea1f16d20bef6434325566fad63788ab6e8 From e41f828af34c4c5bef24f18ba96dc03aa42da43a Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 09:22:49 -0400 Subject: [PATCH 69/77] Set submodule commit to import branch --- script/include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include b/script/include index 2c725ea1..3e085f00 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 2c725ea1f16d20bef6434325566fad63788ab6e8 +Subproject commit 3e085f0083d33a974268dd02696d255ac1d21072 From 1430ed79b387e3f0f9c1cdb3681560c3a25f26e9 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 09:30:13 -0400 Subject: [PATCH 70/77] Modify submodule config on Travis before update I guess this is a known issue when using Travis and SSH-based submodules. The other option is to change the submodule config to be HTTPS-based, but this should work. --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 486de5cc..02dab0db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,19 @@ sudo: required language: python python: "3.6" services: docker +git: + submodules: false env: global: - TESTER_IMAGE_NAME=atst-tester - PROD_IMAGE_NAME=atst-prod +before_install: + # Use sed to replace the SSH URL with the public URL + - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules + # Manually initialize submodules + - git submodule update --init --recursive + before_script: - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - docker build --tag "${TESTER_IMAGE_NAME}" . -f deploy/docker/tester/Dockerfile From 9333bae369e91d36acded6be420f2b8de0b98a75 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 09:37:50 -0400 Subject: [PATCH 71/77] Switch submodule branch to master --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 21e1e4c7..e2e55be7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "script/include"] path = script/include url = git@github.com:dod-ccpo/scriptz.git - branch = add-app-scripts + branch = master From 821a0ee0e501c5781c710e2bc9df6c89a56e2caa Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 11:08:51 -0400 Subject: [PATCH 72/77] Update submodule to latest master --- script/include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/include b/script/include index 3e085f00..7417942f 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 3e085f0083d33a974268dd02696d255ac1d21072 +Subproject commit 7417942f1614d6a7ad94e94d1621dca9b422dec2 From 66c5ac9cbac2dd0e2693ff4745f357b40c264a37 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 11:20:24 -0400 Subject: [PATCH 73/77] Update README with additional info - Project description - Add submodule related info - Add scriptz README reference - Reformat Installation section --- README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d759de47..3c52ea7d 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,32 @@ [![Build Status](https://travis-ci.org/dod-ccpo/atst.svg?branch=master)](https://travis-ci.org/dod-ccpo/atst) +## Description + +This is the main user-facing web application for the ATAT stack. All end-user +requests are handled by ATST, with it making backend calls to various +microservices when appropriate. + ## Installation +See the [scriptz](https://github.com/dod-ccpo/scriptz) repository for the shared +requirements and guidelines for all ATAT applications. + +This project contains git submodules. Here is an example clone command that will +automatically initialize and update those modules: +`git clone --recurse-submodules git@github.com:dod-ccpo/atst.git` + +This application uses Pipenv to manage Python dependencies and a virtual +environment. Instead of the classic `requirements.txt` file, pipenv uses a +Pipfile and Pipfile.lock, making it more similar to other modern package managers +like yarn or mix. + +To perform the installation, run the setup script: + script/setup -The setup script installs pipenv, which is what this application uses to manage its dependences and virtualenv. Instead of the classic `requirements.txt` file, pipenv uses a Pipfile and Pipfile.lock, making it more similar to other modern package managers like yarn or mix. +The setup script creates the virtual environment, and then calls script/bootstrap +to install all of the Python and Node dependencies. To enter the virtualenv manually (a la `source .venv/bin/activate`): @@ -25,7 +46,7 @@ To start the app locally in the foreground and watch for changes: ## Testing -To run all linting and tests: +To run lint, static analysis, and unit tests: script/test From ccd959e4a96dddc6e74d7ef061f1a966acefb614 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 11:22:04 -0400 Subject: [PATCH 74/77] Move clone command to its own line --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c52ea7d..fc1c4c2d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ requirements and guidelines for all ATAT applications. This project contains git submodules. Here is an example clone command that will automatically initialize and update those modules: -`git clone --recurse-submodules git@github.com:dod-ccpo/atst.git` + + git clone --recurse-submodules git@github.com:dod-ccpo/atst.git This application uses Pipenv to manage Python dependencies and a virtual environment. Instead of the classic `requirements.txt` file, pipenv uses a From 7b839a922b75a73bd3111d66f6147ff59c5f1245 Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Wed, 11 Jul 2018 11:23:55 -0400 Subject: [PATCH 75/77] Group requirements and add section headers --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fc1c4c2d..2a37190e 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,20 @@ microservices when appropriate. ## Installation +### Requirements See the [scriptz](https://github.com/dod-ccpo/scriptz) repository for the shared requirements and guidelines for all ATAT applications. +Additionally, ATST requires a redis instance for session management. Have redis +installed and running. By default, ATST will try to connect to a redis instance +running on localhost on its default port, 6379. +### Cloning This project contains git submodules. Here is an example clone command that will automatically initialize and update those modules: git clone --recurse-submodules git@github.com:dod-ccpo/atst.git +### Setup This application uses Pipenv to manage Python dependencies and a virtual environment. Instead of the classic `requirements.txt` file, pipenv uses a Pipfile and Pipfile.lock, making it more similar to other modern package managers @@ -37,7 +43,6 @@ To enter the virtualenv manually (a la `source .venv/bin/activate`): If you want to automatically load the virtual environment whenever you enter the project directory, take a look at [direnv](https://direnv.net/). An `.envrc` file is included in this repository. direnv will activate and deactivate virtualenvs for you when you enter and leave the directory. -Additionally, ATST requires a redis instance for session management. Have redis installed and running. By default, ATST will try to connect to a redis instance running on localhost on its default port, 6379. ## Running (development) From bfb54ed29fa1e997b879249b65082e9f1efd02db Mon Sep 17 00:00:00 2001 From: Devon Mackay Date: Fri, 13 Jul 2018 09:10:53 -0400 Subject: [PATCH 76/77] Add notice on command for updating existing clones --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a37190e..fbd0daf9 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,11 @@ automatically initialize and update those modules: git clone --recurse-submodules git@github.com:dod-ccpo/atst.git +If you have an existing clone that does not yet contain the submodules, you can +set them up with the following command: + + git submodule update --init --recursive + ### Setup This application uses Pipenv to manage Python dependencies and a virtual environment. Instead of the classic `requirements.txt` file, pipenv uses a @@ -41,7 +46,10 @@ To enter the virtualenv manually (a la `source .venv/bin/activate`): pipenv shell -If you want to automatically load the virtual environment whenever you enter the project directory, take a look at [direnv](https://direnv.net/). An `.envrc` file is included in this repository. direnv will activate and deactivate virtualenvs for you when you enter and leave the directory. +If you want to automatically load the virtual environment whenever you enter the +project directory, take a look at [direnv](https://direnv.net/). An `.envrc` +file is included in this repository. direnv will activate and deactivate +virtualenvs for you when you enter and leave the directory. ## Running (development) From f6533b50b33ceca640da90c728336f3899f39939 Mon Sep 17 00:00:00 2001 From: Patrick Smith Date: Mon, 16 Jul 2018 10:09:26 -0400 Subject: [PATCH 77/77] Show error message on review screen when not complete --- templates/requests/screen-4.html.to | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html.to index 58eb66ba..9f8a7b42 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html.to @@ -116,5 +116,8 @@ {% end %} {% block next %} +{% if not can_submit %} + Please complete all required fields before submitting. +{% end %} {% end %}