From ff619855f0e922e95ec7c34931036243f936cd2a Mon Sep 17 00:00:00 2001 From: Paul Bugni Date: Thu, 20 Apr 2017 12:56:03 -0700 Subject: [PATCH 01/65] initdb is now safe to call on existing dbs, and stamps the migration Fixes as per https://www.pivotaltracker.com/story/show/134463297 --- manage.py | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/manage.py b/manage.py index 9e601b1437..e9388ae5f6 100644 --- a/manage.py +++ b/manage.py @@ -5,6 +5,7 @@ """ import os +import alembic.config from flask_script import Manager from flask_migrate import Migrate, MigrateCommand @@ -24,20 +25,42 @@ app = create_app() manager = Manager(app) -migrate = Migrate( - app, - db, - directory=os.path.join(app.root_path, 'migrations') -) +MIGRATIONS_DIR = os.path.join(app.root_path, 'migrations') +migrate = Migrate(app, db, directory=MIGRATIONS_DIR) manager.add_command('db', MigrateCommand) manager.add_command('runserver', ConfigServer(host='0.0.0.0', threaded=True)) +def stamp_db(): + """Run the alembic command to stamp the db with the current head""" + # if the alembic_version table exists, this db has been stamped, + # don't update to head, as it would potentially skip steps. + if db.engine.dialect.has_table(db.engine.connect(), 'alembic_version'): + return + + alembic_args = [ + '--raiseerr', + 'stamp', + 'head'] + # Alembic looks for the alembic.ini file in CWD + # hop over there and then return to CWD + cwd = os.getcwd() + os.chdir(MIGRATIONS_DIR) + alembic.config.main(argv=alembic_args) + os.chdir(cwd) + + @manager.command def initdb(): - """Init/reset database.""" - db.drop_all() + """Init database. + + To re/create the database, [delete and] create within the DBMS itself, + then invoke this function. + """ db.create_all() + # Stamp the current alembic version, so subesquent upgrades know + # the correct starting point + stamp_db() seed(include_interventions=True) From 0e9fcf332fee245871c3229d365a9d565a832bd2 Mon Sep 17 00:00:00 2001 From: Paul Bugni Date: Thu, 20 Apr 2017 13:01:49 -0700 Subject: [PATCH 02/65] Whitespace patches missed in previous commit. --- manage.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/manage.py b/manage.py index e9388ae5f6..b1dbd915f7 100644 --- a/manage.py +++ b/manage.py @@ -38,15 +38,13 @@ def stamp_db(): if db.engine.dialect.has_table(db.engine.connect(), 'alembic_version'): return - alembic_args = [ - '--raiseerr', - 'stamp', - 'head'] # Alembic looks for the alembic.ini file in CWD # hop over there and then return to CWD cwd = os.getcwd() os.chdir(MIGRATIONS_DIR) - alembic.config.main(argv=alembic_args) + + alembic.config.main(argv=['--raiseerr', 'stamp', 'head']) + os.chdir(cwd) From 79d536c16cacf0287e9cc26307e3e49b42a4c1c2 Mon Sep 17 00:00:00 2001 From: Paul Bugni Date: Thu, 20 Apr 2017 14:44:27 -0700 Subject: [PATCH 03/65] Eliminate confusing paths - just call `sync` initdb has been replaced with sync, which will safely initialze the db if needed (w/o destroying existing data), stamp and run outstanding migration scripts and pull in site_persistence. --- manage.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/manage.py b/manage.py index b1dbd915f7..060981886e 100644 --- a/manage.py +++ b/manage.py @@ -31,6 +31,18 @@ manager.add_command('runserver', ConfigServer(host='0.0.0.0', threaded=True)) +def _run_alembic_command(args): + """Helper to manage working directory and run given alembic commands""" + # Alembic looks for the alembic.ini file in CWD + # hop over there and then return to CWD + cwd = os.getcwd() + os.chdir(MIGRATIONS_DIR) + + alembic.config.main(argv=args) + + os.chdir(cwd) # restore cwd + + def stamp_db(): """Run the alembic command to stamp the db with the current head""" # if the alembic_version table exists, this db has been stamped, @@ -38,27 +50,27 @@ def stamp_db(): if db.engine.dialect.has_table(db.engine.connect(), 'alembic_version'): return - # Alembic looks for the alembic.ini file in CWD - # hop over there and then return to CWD - cwd = os.getcwd() - os.chdir(MIGRATIONS_DIR) + _run_alembic_command(['--raiseerr', 'stamp', 'head']) - alembic.config.main(argv=['--raiseerr', 'stamp', 'head']) - os.chdir(cwd) +def upgrade_db(): + """Run any outstanding migration scripts""" + _run_alembic_command(['--raiseerr', 'upgrade', 'head']) @manager.command -def initdb(): - """Init database. +def sync(): + """Synchronize database with latest schema and persistence data. + + Idempotent function takes necessary steps to build tables, migrate + schema and run `seed`. Safe to run on existing or brand new databases. To re/create the database, [delete and] create within the DBMS itself, then invoke this function. """ db.create_all() - # Stamp the current alembic version, so subesquent upgrades know - # the correct starting point stamp_db() + upgrade_db() seed(include_interventions=True) From e0ef328d66a243c3a03e340508c9ce488eea9ed6 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 15:07:10 -0700 Subject: [PATCH 04/65] Use sync command after Heroku Button deployments --- app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.json b/app.json index c4a6f3f56c..e16afd00ec 100644 --- a/app.json +++ b/app.json @@ -30,6 +30,6 @@ } ], "scripts": { - "postdeploy": "python manage.py initdb" + "postdeploy": "python manage.py sync" } } From 60ae7acd5578819c7863c9281b2ed62855ff7ad3 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 15:08:09 -0700 Subject: [PATCH 05/65] Simplify database actions for Docker --- docker/Dockerfile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c6e85b6bb4..0a62f6a549 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -81,9 +81,5 @@ CMD \ . /etc/apache2/envvars && \ . ${PROJECT_DIR}/bin/activate && \ env && \ - if [ -n "$(flask db current)" ]; then \ - flask db migrate; \ - else \ - python ${FLASK_APP} initdb; \ - fi && \ + python ${FLASK_APP} sync && \ /usr/sbin/apache2 -D FOREGROUND From afbafd220e5259e47e556172283ee0e05028ca08 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 15:08:34 -0700 Subject: [PATCH 06/65] Consolidate database deployment --- bin/deploy.sh | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/bin/deploy.sh b/bin/deploy.sh index 48eb9b0bdf..a3367d9e2f 100755 --- a/bin/deploy.sh +++ b/bin/deploy.sh @@ -7,7 +7,6 @@ usage() { echo -e "-s\n 'seed' the database" >&2 echo -e "-v\n Be verbose" >&2 echo -e "-f\n Force all conditional deployment processes" >&2 - echo -e "-i\n Run initial deployment procedure" >&2 exit 1 } @@ -48,9 +47,6 @@ while getopts ":b:p:ivsf" option; do v) VERBOSE=true ;; - i) - INIT=true - ;; s) SEED=true ;; @@ -107,8 +103,7 @@ fi # DB Changes if [[ - ($FORCE || ( -n $(git diff $old_head $new_head -- ${GIT_WORK_TREE}/portal/migrations) && $? -eq 0 )) && - -z $INIT + ($FORCE || ( -n $(git diff $old_head $new_head -- ${GIT_WORK_TREE}/portal/migrations) && $? -eq 0 )) ]]; then activate_once @@ -121,14 +116,8 @@ fi # New seed data if [[ $FORCE || $SEED || ( -n $(git diff $old_head $new_head -- ${GIT_WORK_TREE}/portal/models) && $? -eq 0 ) ]]; then activate_once - - if [[ $INIT ]]; then - echo "Initializing database" - python "${GIT_WORK_TREE}/manage.py" initdb - else - echo "Seeding database" - python "${GIT_WORK_TREE}/manage.py" seed - fi + echo "Running database maintenance" + python "${GIT_WORK_TREE}/manage.py" sync fi From 404dcc7c5637e953be546d2af6193ffcf4bf4cd8 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Fri, 21 Apr 2017 13:48:07 -0700 Subject: [PATCH 07/65] Update selenium from 3.3.3 to 3.4.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2662b88adf..fe58044a1e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -78,7 +78,7 @@ redis==2.10.5 requests==2.13.0 requests-cache==0.4.13 requests-oauthlib==0.8.0 -selenium==3.3.3 +selenium==3.4.0 simplegeneric==0.8.1 six==1.10.0 snowballstemmer==1.2.1 From 6753c9271395ad0fa28c6431c323824e73717943 Mon Sep 17 00:00:00 2001 From: Amy Chen Date: Fri, 21 Apr 2017 19:54:44 -0700 Subject: [PATCH 08/65] fix UI issues when no consent text is found for any org --- portal/static/js/main.js | 18 +++++++++++------- portal/templates/initial_queries.html | 27 +++++++++++++++++---------- portal/templates/profile_macros.html | 6 +++++- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/portal/static/js/main.js b/portal/static/js/main.js index 76e182dfc1..c190744e7d 100644 --- a/portal/static/js/main.js +++ b/portal/static/js/main.js @@ -643,7 +643,7 @@ var fillContent = { var isAdmin = typeof _isAdmin != "undefined" && _isAdmin ? true: false; var userTimeZone = getUserTimeZone(userId); var userLocale = getUserLocale(userId); - + $.ajax ({ type: "GET", url: '/api/organization', @@ -845,12 +845,13 @@ var fillContent = { var msg = " You do not have permission to edit this patient record."; $("#profileConsentList").html("

" + msg + "

"); } else { - if (typeof TERMS_URL != "undefined" && hasValue(TERMS_URL)) { + if (ctop && typeof TERMS_URL != "undefined" && hasValue(TERMS_URL)) { content = "" content += ""; content += ""; content += ""; content += ""; + $("#profileConsentList").html(content); } else $("#profileConsentList").html("No Consent Record Found"); }; }; @@ -1472,7 +1473,7 @@ var OrgTool = function() { }; this.getDefaultModal = function(o) { if (!o) return false; - var orgId = $(o).val(), orgName = $(o).attr("data-parent-name"); + var orgId = this.getElementParentOrg(o), orgName = $(o).attr("data-parent-name"); if (hasValue(orgId) && $("#" + orgId + "_defaultConsentModal").length == 0) { var s = ''; - $("#consentContainer").append(s); + $("#defaultConsentContainer").append(s); $("#" + orgId + "_defaultConsentModal input[name='defaultToConsent']").each(function() { $(this).on("click", function(e) { e.stopPropagation(); @@ -1508,7 +1509,10 @@ var OrgTool = function() { $("#" + orgId + "_loader").show(); if ($(this).val() == "yes") { setTimeout("tnthAjax.setDefaultConsent(" + userId + "," + orgId + ");", 100); - } else tnthAjax.deleteConsent(userId, {"org":orgId}); + } else { + tnthAjax.deleteConsent(userId, {"org":orgId}); + setTimeout("tnthAjax.removeObsoleteConsent();", 100); + } if (typeof reloadConsentList != "undefined") setTimeout("reloadConsentList();", 500); setTimeout('$(".modal").modal("hide");', 250); }); @@ -1864,7 +1868,7 @@ var tnthAjax = { var orgId = $(this).val(); var userId = $("#fillOrgs").attr("userId"); if (!hasValue(userId)) userId = $("#userOrgs").attr("userId"); - + var cto = (typeof CONSENT_WITH_TOP_LEVEL_ORG != "undefined") && CONSENT_WITH_TOP_LEVEL_ORG; if ($(this).prop("checked")){ if ($(this).attr("id") !== "noOrgs") { @@ -1878,7 +1882,7 @@ var tnthAjax = { setTimeout("tnthAjax.removeObsoleteConsent();", 200); } else { if (cto) { - tnthAjax.setDefaultConsent(userId, parentOrg); + tnthAjax.setDefaultConsent(userId, parentOrg); }; }; }; diff --git a/portal/templates/initial_queries.html b/portal/templates/initial_queries.html index 5a0a81692c..8691296d09 100644 --- a/portal/templates/initial_queries.html +++ b/portal/templates/initial_queries.html @@ -353,6 +353,8 @@

{{ _("Thank you.") }}

if (hasValue(parentOrg)) { var cModal = $("#" + parentOrg + "_consentModal"); if (cModal.length > 0) cModal.modal("show"); + var dModal = $("#" + parentOrg + "_defaultConsentModal"); + if (dModal.length > 0) dModal.modal("show"); } else { if (!found) continueToFinish(); }; @@ -647,6 +649,21 @@

{{ _("Thank you.") }}

}; }; + $("#defaultConsentContainer .modal").each(function() { + $(this).on("hidden.bs.modal", function() { + if ($(this).find("input[name='defaultToConsent']:checked").length > 0) { + if (fc.allFieldsCompleted()) { + continueToFinish(); + } else { + if (fc.sectionCompleted("orgsContainer")) continueToNext("orgsContainer"); + else stopContinue("orgsContainer"); + }; + } else { + $("#consentContainer input[name='defaultToConsent']:checked").prop("checked", false); + }; + }); + }); + $("#consentContainer .modal").each(function() { $(this).on("hidden.bs.modal", function() { if ($("#consentContainer input[name='toConsent']:checked").length > 0) { @@ -662,16 +679,6 @@

{{ _("Thank you.") }}

} else { $("#consentContainer input[name='toConsent']:checked").prop("checked", false); }; - if ($("#consentContainer input[name='defaultToConsent']:checked").length > 0) { - if (fc.allFieldsCompleted()) { - continueToFinish(); - } else { - if (fc.sectionCompleted("orgsContainer")) continueToNext("orgsContainer"); - else stopContinue("orgsContainer"); - }; - } else { - $("#consentContainer input[name='defaultToConsent']:checked").prop("checked", false); - }; }); }); diff --git a/portal/templates/profile_macros.html b/portal/templates/profile_macros.html index 093a9073a7..b88bb97b4f 100644 --- a/portal/templates/profile_macros.html +++ b/portal/templates/profile_macros.html @@ -507,6 +507,7 @@

{{_('registered')}}

No clinic found in selected clinic.
+
{% if consent_agreements %}{{consent(person, consent_agreements, current_user, True)}}{% endif %} @@ -780,7 +781,10 @@

Terms

setTimeout("tnthAjax.setConsent({{person.id}}, " + JSON.stringify(params) + ");", 10); setTimeout("tnthAjax.removeObsoleteConsent();", 100); } - else tnthAjax.deleteConsent({{person.id}}, {"org":orgId}); + else { + tnthAjax.deleteConsent({{person.id}}, {"org":orgId}); + setTimeout("tnthAjax.removeObsoleteConsent();", 100); + }; if (typeof reloadConsentList != "undefined") setTimeout("reloadConsentList();", 500); setTimeout('$(".modal").modal("hide");', 250); }); From 377b540859d769e12c49e901d9dc2f92987785b7 Mon Sep 17 00:00:00 2001 From: pyup-bot Date: Sat, 22 Apr 2017 04:05:58 -0700 Subject: [PATCH 09/65] Update ipdb from 0.10.2 to 0.10.3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2662b88adf..059ff49303 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,7 +40,7 @@ functools32==3.2.3.post2 future==0.16.0 fuzzywuzzy==0.15.0 imagesize==0.7.1 -ipdb==0.10.2 +ipdb==0.10.3 ipython==5.3.0 ipython-genutils==0.2.0 itsdangerous==0.24 From 5e91d8480ecd98d1cd9b4ca3a8344e405c136bc9 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:13:12 -0700 Subject: [PATCH 10/65] Rename variable --- portal/audit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/portal/audit.py b/portal/audit.py index 1bff0bacde..2a585703fd 100644 --- a/portal/audit.py +++ b/portal/audit.py @@ -56,8 +56,8 @@ def configure_audit_log(app): # pragma: no cover logging.addLevelName('AUDIT', AUDIT) audit_log = os.path.join(app.config['LOG_FOLDER'], 'audit.log') - audit_file_handler = logging.FileHandler(audit_log, delay=True) - audit_file_handler.setLevel(AUDIT) - audit_file_handler.setFormatter( + audit_log_handler = logging.FileHandler(audit_log, delay=True) + audit_log_handler.setLevel(AUDIT) + audit_log_handler.setFormatter( logging.Formatter('%(asctime)s: %(message)s')) - app.logger.addHandler(audit_file_handler) + app.logger.addHandler(audit_log_handler) From 1a22e6779109747312b7f0ba144b21680243500f Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:58:01 -0700 Subject: [PATCH 11/65] Do not set LOG_FOLDER config value by default --- portal/config.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/portal/config.py b/portal/config.py index e5dd7525f5..f87415ce05 100644 --- a/portal/config.py +++ b/portal/config.py @@ -50,10 +50,7 @@ class BaseConfig(object): CELERY_RESULT_BACKEND = 'redis' DEBUG = False DEFAULT_MAIL_SENDER = 'dontreply@truenth-demo.cirg.washington.edu' - LOG_FOLDER = os.environ.get( - 'LOG_FOLDER', - os.path.join('/var/log', __package__) - ) + LOG_FOLDER = os.environ.get('LOG_FOLDER', None) LOG_LEVEL = 'DEBUG' MAIL_USERNAME = 'portal@truenth-demo.cirg.washington.edu' From 7c1190176cca8789164923d978cef7d68345e3bb Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:16:17 -0700 Subject: [PATCH 12/65] Write all logging to stdout if LOG_FOLDER unconfigured --- portal/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portal/app.py b/portal/app.py index 5666d8aab6..45a9553f22 100644 --- a/portal/app.py +++ b/portal/app.py @@ -161,7 +161,7 @@ def configure_logging(app): # pragma: no cover sql_log.setLevel(logging.INFO) sql_log.addHandler(sql_file_handler) - if app.testing: + if app.testing or not app.config.get('LOG_FOLDER', None): # Skip test mode. Just check standard output. return From 23cb20a82cd725df104d39fa12b1a71d4b54d459 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:16:40 -0700 Subject: [PATCH 13/65] Write audit log to stdout if LOG_FOLDER unconfigured --- portal/audit.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/portal/audit.py b/portal/audit.py index 2a585703fd..a857e426e4 100644 --- a/portal/audit.py +++ b/portal/audit.py @@ -55,8 +55,12 @@ def configure_audit_log(app): # pragma: no cover return logging.addLevelName('AUDIT', AUDIT) - audit_log = os.path.join(app.config['LOG_FOLDER'], 'audit.log') - audit_log_handler = logging.FileHandler(audit_log, delay=True) + + audit_log_handler = logging.StreamHandler(sys.stdout) + if app.config.get('LOG_FOLDER', None): + audit_log = os.path.join(app.config['LOG_FOLDER'], 'audit.log') + audit_log_handler = logging.FileHandler(audit_log, delay=True) + audit_log_handler.setLevel(AUDIT) audit_log_handler.setFormatter( logging.Formatter('%(asctime)s: %(message)s')) From 3a4cc4e21763d399af2b24bf574971a8516bf5bf Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:23:04 -0700 Subject: [PATCH 14/65] Write logging to stdout on TravisCI --- .travis.yml | 1 - tox.ini | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5f8752811a..8757a6f0dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,6 @@ env: - TOXENV=py27 global: - SQLALCHEMY_DATABASE_TEST_URI='postgresql://postgres:@localhost/portal_unit_tests' - - LOG_FOLDER='/tmp/shared_service_log' - PACKAGE_NAME=${PACKAGE_NAME:-true_nth_usa_portal} - IMAGE_NAME=${IMAGE_NAME:-portal_web} - DEB_REPO=${DEB_REPO:-portal-deb} diff --git a/tox.ini b/tox.ini index 636fcbdf0c..b2ed331620 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ commands = [testenv] deps = -rrequirements.txt -passenv = TRAVIS* SQLALCHEMY_DATABASE* LOG_FOLDER PERSISTENCE_FILE +passenv = TRAVIS* SQLALCHEMY_DATABASE* PERSISTENCE_FILE whitelist_externals = /bin/bash commands = {[base]commands} From 55408b4ee280d49e894e75659e29c97f5cef50b4 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:23:30 -0700 Subject: [PATCH 15/65] Write logging to stdout on Heroku --- app.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app.json b/app.json index c4a6f3f56c..5a1f95e597 100644 --- a/app.json +++ b/app.json @@ -7,10 +7,6 @@ "logo": "https://github.com/uwcirg/true_nth_usa_portal/raw/develop/portal/static/img/logo.png", "success_url": "/about", "env": { - "LOG_FOLDER": { - "description": "Temporary log directory override; should write to stdout if unconfigured", - "value": "/tmp/logs" - }, "SERVER_NAME": { "description": "Fully qualified domain name of system, excluding protocol (HTTP/S). See App Name", "value": "HEROKU_APP_NAME.herokuapp.com" From 6416fdffe8ebadfeba93667e202b927605c7ca4c Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 16:24:10 -0700 Subject: [PATCH 16/65] Write logging to stdout in Docker images --- docker/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c6e85b6bb4..88e1a0085a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -55,15 +55,13 @@ COPY portal.wsgi /var/www/ ENV \ APACHE_RUN_USER="${APACHE_RUN_USER:-www-data}" \ - LOG_FOLDER="/tmp/shared_service_log" \ PORT="${PORT:-8008}" \ PROJECT_DIR="/opt/venvs/portal" RUN \ - mkdir -p ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ && \ + mkdir -p ${PROJECT_DIR}/var/portal-instance/ && \ chown $APACHE_RUN_USER:$APACHE_RUN_USER \ /var/run/apache2/ \ - ${LOG_FOLDER} \ ${PROJECT_DIR}/var/portal-instance/ && \ sed -i 's|Listen [[:digit:]]\+|Listen ${PORT}|g' /etc/apache2/ports.conf && \ a2ensite portal && a2dissite 000-default && a2disconf other-vhosts-access-log From 2272e3f05532ced40698a1ccc30baaea6f826969 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 22:07:28 -0700 Subject: [PATCH 17/65] Rename Apache env var --- docker/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c6e85b6bb4..a823c19e59 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -21,7 +21,7 @@ ErrorLog /dev/stdout\n\ ErrorLog /dev/stdout\n\ CustomLog /dev/stdout combined\n\ WSGIPassAuthorization On\n\ - WSGIDaemonProcess stg_cs user=${APACHE_RUN_USER} group=${APACHE_RUN_GROUP} threads=5\n\ + WSGIDaemonProcess stg_cs user=${RUN_USER} group=${APACHE_RUN_GROUP} threads=5\n\ WSGIScriptAlias / /var/www/portal.wsgi\n\ \n\ WSGIProcessGroup stg_cs\n\ @@ -54,21 +54,21 @@ RUN \ COPY portal.wsgi /var/www/ ENV \ - APACHE_RUN_USER="${APACHE_RUN_USER:-www-data}" \ + RUN_USER="${RUN_USER:-www-data}" \ LOG_FOLDER="/tmp/shared_service_log" \ PORT="${PORT:-8008}" \ PROJECT_DIR="/opt/venvs/portal" RUN \ mkdir -p ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ && \ - chown $APACHE_RUN_USER:$APACHE_RUN_USER \ + chown $RUN_USER:$RUN_USER \ /var/run/apache2/ \ ${LOG_FOLDER} \ ${PROJECT_DIR}/var/portal-instance/ && \ sed -i 's|Listen [[:digit:]]\+|Listen ${PORT}|g' /etc/apache2/ports.conf && \ a2ensite portal && a2dissite 000-default && a2disconf other-vhosts-access-log -USER ${APACHE_RUN_USER} +USER ${RUN_USER} ENV \ SERVER_NAME=${SERVER_NAME:-localhost} \ From aff405fb86656ad661c35fb6ae16c741eea65e3f Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 22:20:15 -0700 Subject: [PATCH 18/65] Replace Apache with gunicorn in Dockerfile --- docker/Dockerfile | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a823c19e59..8f1e6bea2d 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -6,32 +6,10 @@ RUN \ apt-get update && \ apt-get dist-upgrade --yes && \ apt-get install --yes --force-yes --no-install-recommends \ - apache2 \ - libapache2-mod-wsgi \ libpq5 \ python2.7 && \ apt-get clean -RUN printf '\n\ -Listen 0.0.0.0:${PORT}\n\ -ServerName ${SERVER_NAME}\n\ -ErrorLog /dev/stdout\n\ -\n\ - LogLevel info\n\ - ErrorLog /dev/stdout\n\ - CustomLog /dev/stdout combined\n\ - WSGIPassAuthorization On\n\ - WSGIDaemonProcess stg_cs user=${RUN_USER} group=${APACHE_RUN_GROUP} threads=5\n\ - WSGIScriptAlias / /var/www/portal.wsgi\n\ - \n\ - WSGIProcessGroup stg_cs\n\ - WSGIApplicationGroup %%{GLOBAL}\n\ - Require all granted\n\ - \n\ -\n\ -\n'\ -> /etc/apache2/sites-available/portal.conf - ARG debian_repo="http://dl.bintray.com/v1/content/uwcirg/truenth" COPY artifacts /tmp/artifacts @@ -51,8 +29,6 @@ RUN \ apt-get clean && \ rm --force --recursive --verbose /tmp/artifacts -COPY portal.wsgi /var/www/ - ENV \ RUN_USER="${RUN_USER:-www-data}" \ LOG_FOLDER="/tmp/shared_service_log" \ @@ -61,12 +37,7 @@ ENV \ RUN \ mkdir -p ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ && \ - chown $RUN_USER:$RUN_USER \ - /var/run/apache2/ \ - ${LOG_FOLDER} \ - ${PROJECT_DIR}/var/portal-instance/ && \ - sed -i 's|Listen [[:digit:]]\+|Listen ${PORT}|g' /etc/apache2/ports.conf && \ - a2ensite portal && a2dissite 000-default && a2disconf other-vhosts-access-log + chown $RUN_USER:$RUN_USER ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ USER ${RUN_USER} @@ -78,7 +49,6 @@ ENV \ EXPOSE ${PORT} CMD \ - . /etc/apache2/envvars && \ . ${PROJECT_DIR}/bin/activate && \ env && \ if [ -n "$(flask db current)" ]; then \ @@ -86,4 +56,6 @@ CMD \ else \ python ${FLASK_APP} initdb; \ fi && \ - /usr/sbin/apache2 -D FOREGROUND + gunicorn \ + --bind "0.0.0.0:${PORT}" \ + manage:app From 994420c486a5d587e6437903ffe9a2d89d4cc089 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Thu, 20 Apr 2017 22:22:45 -0700 Subject: [PATCH 19/65] Always install gunicorn --- requirements.txt | 1 + setup.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 83d96e4729..f9d9e0ccfc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -39,6 +39,7 @@ Flask-WTF==0.14.2 functools32==3.2.3.post2 future==0.16.0 fuzzywuzzy==0.15.0 +gunicorn==19.7.1 imagesize==0.7.1 ipdb==0.10.3 ipython==5.3.0 diff --git a/setup.py b/setup.py index 5378469063..c37d0b7f38 100644 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ "Flask-User", "Flask-WebTest", "fuzzywuzzy", + "gunicorn", "jsonschema", "oauthlib", "pkginfo", @@ -103,8 +104,6 @@ build_version = BUILD_DIR.split("-")[-1] version_kwargs = {"version": "0+ng"+build_version} - # Install gunicorn WSGI server - setup_kwargs["install_requires"].append("gunicorn") else: version_kwargs = dict(version='0+d'+datetime.date.today().strftime('%Y%m%d')) From 560deae36fd01bfe87ed32e3ce6198da7c74e4b7 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 15:26:20 -0700 Subject: [PATCH 20/65] Move env var --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8f1e6bea2d..e23e85dcfd 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -32,7 +32,6 @@ RUN \ ENV \ RUN_USER="${RUN_USER:-www-data}" \ LOG_FOLDER="/tmp/shared_service_log" \ - PORT="${PORT:-8008}" \ PROJECT_DIR="/opt/venvs/portal" RUN \ @@ -43,6 +42,7 @@ USER ${RUN_USER} ENV \ SERVER_NAME=${SERVER_NAME:-localhost} \ + PORT="${PORT:-8008}" \ FLASK_APP="${PROJECT_DIR}/bin/manage.py" \ PERSISTENCE_FILE="${PERSISTENCE_FILE:-https://raw.githubusercontent.com/uwcirg/TrueNTH-USA-site-config/develop/site_persistence_file.json}" From 731f170d4b0bf25911c968e6c44d368426faa648 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sat, 22 Apr 2017 15:26:39 -0700 Subject: [PATCH 21/65] Use long option --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e23e85dcfd..67fd5e6cd7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -35,7 +35,7 @@ ENV \ PROJECT_DIR="/opt/venvs/portal" RUN \ - mkdir -p ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ && \ + mkdir --parents ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ && \ chown $RUN_USER:$RUN_USER ${LOG_FOLDER} ${PROJECT_DIR}/var/portal-instance/ USER ${RUN_USER} From 28ef18ddf9fa7f0688d668f7c7a2696379c195f6 Mon Sep 17 00:00:00 2001 From: Ivan Cvitkovic Date: Sun, 23 Apr 2017 15:14:28 -0700 Subject: [PATCH 22/65] Run database migrations after build on Datica --- .catalyze/post-build | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 .catalyze/post-build diff --git a/.catalyze/post-build b/.catalyze/post-build new file mode 100755 index 0000000000..4a54884cbe --- /dev/null +++ b/.catalyze/post-build @@ -0,0 +1,5 @@ +#!/bin/sh -e +# Datica post-build hook script +# https://resources.datica.com/compliant-cloud/articles/buildpacks-custom/#pre-and-post-build-hooks + +python manage.py sync From af1cfd26294daab3119f4638f6302309e99ece1a Mon Sep 17 00:00:00 2001 From: Amy Chen Date: Sun, 23 Apr 2017 21:57:31 -0700 Subject: [PATCH 23/65] access code check fix, re-factor/consolidate code in main.js --- portal/static/js/main.js | 81 +++++++++++++++++---------- portal/templates/initial_queries.html | 34 +++++------ portal/templates/profile_macros.html | 2 +- portal/views/portal.py | 18 ++++-- 4 files changed, 80 insertions(+), 55 deletions(-) diff --git a/portal/static/js/main.js b/portal/static/js/main.js index c190744e7d..72dfd131e4 100644 --- a/portal/static/js/main.js +++ b/portal/static/js/main.js @@ -608,6 +608,7 @@ var fillContent = { ckOrg.prop("checked", true); $("#stateSelector").find("option[value='" + state + "']").prop("selected", true).val(state); }); + $(".noOrg-container").show(); } else { var ckOrg = $("body").find("#userOrgs input.clinic[value="+orgID+"]"); if (ckOrg.length > 0) ckOrg.prop('checked', true); @@ -811,14 +812,14 @@ var fillContent = { }); } else { if (ctop) { - if (typeof TERMS_URL != "undefined" && hasValue(TERMS_URL)) { - content = "
OrganizationConsent StatusAgreement
TrueNTH USAAgreed to termsTrueNTH USA Terms of Use  View
" - content += ""; - content += ""; - content += ""; - content += ""; - $("#profileConsentList").html(content); - } else $("#profileConsentList").html("No Consent Record Found"); + if (typeof TERMS_URL != "undefined" && hasValue(TERMS_URL)) { + content = "
OrganizationConsent StatusAgreement
TrueNTH USAAgreed to termsTrueNTH USA Terms of Use  View
" + content += ""; + content += ""; + content += ""; + content += ""; + $("#profileConsentList").html(content); + } else $("#profileConsentList").html("No Consent Record Found"); } else $("#profileConsentList").html("No Consent Record Found"); }; @@ -1475,7 +1476,7 @@ var OrgTool = function() { if (!o) return false; var orgId = this.getElementParentOrg(o), orgName = $(o).attr("data-parent-name"); if (hasValue(orgId) && $("#" + orgId + "_defaultConsentModal").length == 0) { - var s = '
OrganizationConsent StatusAgreement
TrueNTH USAAgreed to termsTrueNTH USA Terms of Use  View