From 83d25e1b1a89ef2ca9b71b3b2db06a0fd2a00814 Mon Sep 17 00:00:00 2001 From: Taka Date: Sun, 22 Mar 2020 17:07:12 +0000 Subject: [PATCH] Allow the user to link to user-defined files. --- asl_articles/config/site.cfg.example | 3 +++ asl_articles/docs.py | 15 ++++++++++++ docker-compose.yml | 20 +++------------- docker/config/site.cfg | 1 + run-containers.sh | 34 ++++++++++++++++++++-------- web/docker/nginx-default.conf | 6 ++++- web/src/setupProxy.js | 5 ++++ 7 files changed, 57 insertions(+), 27 deletions(-) diff --git a/asl_articles/config/site.cfg.example b/asl_articles/config/site.cfg.example index 4f89fbd..6e8b515 100644 --- a/asl_articles/config/site.cfg.example +++ b/asl_articles/config/site.cfg.example @@ -8,5 +8,8 @@ DB_CONN_STRING = ... ; Base directory for external documents. EXTERNAL_DOCS_BASEDIR = ... +; Base directory for user files. +USER_FILES_BASEDIR = ... + ; Base URL for the eASLRB. ASLRB_BASE_URL = ... diff --git a/asl_articles/docs.py b/asl_articles/docs.py index 7782494..f75b040 100644 --- a/asl_articles/docs.py +++ b/asl_articles/docs.py @@ -20,3 +20,18 @@ def get_external_doc( path ): fname = os.path.join( os.environ["EXTERNAL_DOCS_BASEDIR"], path ) abort( 404, "Can't find file: {}".format( fname ) ) return send_from_directory( base_dir, path ) + +# --------------------------------------------------------------------- + +@app.route( "/user-files/" ) +def get_user_file( path ): + """Return a user-defined file.""" + base_dir = app.config.get( "USER_FILES_BASEDIR" ) + if not base_dir: + abort( 404, "USER_FILES_BASEDIR not configured." ) + fname = os.path.join( base_dir, path ) + if not os.path.isfile( fname ): + if app.config["_IS_CONTAINER"]: + fname = os.path.join( os.environ["USER_FILES_BASEDIR"], path ) + abort( 404, "Can't find file: {}".format( fname ) ) + return send_from_directory( base_dir, path ) diff --git a/docker-compose.yml b/docker-compose.yml index 0a5fd9c..168fe54 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,20 +1,4 @@ -# Set the TAG environment variable to set the image tag e.g. -# TAG=testing docker-compose build ... -# -# Set the ENABLE_TESTS build argument to support test functionality in the containers e.g. -# docker-compose build --build-arg ENABLE_TESTS=1 -# -# DBCONN is a database connection string that is passed straight through to the Flask container. -# However, if we're talking to a SQLite database, we also need to mount the file into the container. -# This is done via the SQLITE variable, but since Docker doesn't allow any way to do things conditionally, -# it needs to be set even if it's not being used :-/ -# -# Similarly, EXTERNAL_DOCS_BASEDIR is the base directory for external documents that we want to link to, -# but it needs to be set even if it's not being used :-/ -# -## Similary, ASLRB_BASE_URL is the base URL for an external eASLRB. -# -# See the run-containers.sh script that manages all of this. +# IMPORTANT: Use run-containers.sh to set up the necessary environment variables. version: "3" @@ -35,8 +19,10 @@ services: volumes: - $SQLITE:/data/sqlite.db - $EXTERNAL_DOCS_BASEDIR:/data/docs/ + - $USER_FILES_BASEDIR:/data/user-files/ - $AUTHOR_ALIASES:/app/asl_articles/config/author-aliases.cfg environment: - DBCONN - EXTERNAL_DOCS_BASEDIR + - USER_FILES_BASEDIR - ASLRB_BASE_URL diff --git a/docker/config/site.cfg b/docker/config/site.cfg index 958c7ec..aa0d235 100644 --- a/docker/config/site.cfg +++ b/docker/config/site.cfg @@ -4,3 +4,4 @@ FLASK_HOST = 0.0.0.0 IS_CONTAINER = 1 EXTERNAL_DOCS_BASEDIR = /data/docs/ +USER_FILES_BASEDIR = /data/user-files/ diff --git a/run-containers.sh b/run-containers.sh index 03212a0..1f3127c 100755 --- a/run-containers.sh +++ b/run-containers.sh @@ -7,13 +7,14 @@ function print_help { echo "`basename "$0"` {options}" echo " Build and launch the \"asl-articles\" containers." echo - echo " -t --tag Docker container tag e.g. \"testing\" or \"latest\"." - echo " -d --dbconn Database connection string e.g." - echo " ~/asl-articles.db (path to a SQLite database)" - echo " postgresql://USER:PASS@host/dbname (database connection string)" - echo " Note that the database server address is relative to the container i.e. NOT \"localhost\"." - echo " -e --extdocs Base directory for external documents (to allow articles to link to them)." - echo " -r --aslrb Base URL for an eASLRB." + echo " -t --tag Docker container tag e.g. \"testing\" or \"latest\"." + echo " -d --dbconn Database connection string e.g." + echo " ~/asl-articles.db (path to a SQLite database)" + echo " postgresql://USER:PASS@host/dbname (database connection string)" + echo " Note that the database server address is relative to the container i.e. NOT \"localhost\"." + echo " -e --extdocs Base directory for external documents (to allow articles to link to them)." + echo " -u --user-files Base directory for user files." + echo " -r --aslrb Base URL for an eASLRB." echo " -a --author-aliases Author aliases config file (see config/author-aliases.cfg.example)." echo echo " The TAG env variable can also be set to specify which containers to run e.g." @@ -28,6 +29,7 @@ export TAG= export DBCONN= export SQLITE= export EXTERNAL_DOCS_BASEDIR= +export USER_FILES_BASEDIR= export ASLRB_BASE_URL= export AUTHOR_ALIASES= export ENABLE_TESTS= @@ -37,7 +39,7 @@ if [ $# -eq 0 ]; then print_help exit 0 fi -params="$(getopt -o t:d:e:r:a:h -l tag:,dbconn:,extdocs:,aslrb:,author-aliases:,help --name "$0" -- "$@")" +params="$(getopt -o t:d:e:u:r:a:h -l tag:,dbconn:,extdocs:,user-files:,aslrb:,author-aliases:,help --name "$0" -- "$@")" if [ $? -ne 0 ]; then exit 1; fi eval set -- "$params" while true; do @@ -51,6 +53,9 @@ while true; do -e | --extdocs ) EXTERNAL_DOCS_BASEDIR=$2 shift 2 ;; + -u | --user-files ) + USER_FILES_BASEDIR=$2 + shift 2 ;; -r | --aslrb ) ASLRB_BASE_URL=$2 shift 2 ;; @@ -95,7 +100,7 @@ fi # check the external documents directory if [ -n "$EXTERNAL_DOCS_BASEDIR" ]; then if [ ! -d "$EXTERNAL_DOCS_BASEDIR" ]; then - echo "Can't find the document base directory: $EXTERNAL_DOCS_BASEDIR" + echo "Can't find the external documents base directory: $EXTERNAL_DOCS_BASEDIR" exit 1 fi else @@ -103,6 +108,17 @@ else EXTERNAL_DOCS_BASEDIR=/dev/null fi +# check the user files directory +if [ -n "$USER_FILES_BASEDIR" ]; then + if [ ! -d "$USER_FILES_BASEDIR" ]; then + echo "Can't find the user files base directory: $USER_FILES_BASEDIR" + exit 1 + fi +else + # FUDGE! This needs to be set, even if it's not being used :-/ + USER_FILES_BASEDIR=/dev/null +fi + # check the author aliases if [ -n "$AUTHOR_ALIASES" ]; then if [ ! -f "$AUTHOR_ALIASES" ]; then diff --git a/web/docker/nginx-default.conf b/web/docker/nginx-default.conf index dd0eaf1..2594859 100644 --- a/web/docker/nginx-default.conf +++ b/web/docker/nginx-default.conf @@ -8,11 +8,15 @@ server { try_files $uri $uri/ /index.html ; } + # nb: we access the backend server via the network bridge that docker-compose creates for us location /api { - # nb: we access the backend server via the network bridge that docker-compose creates for us proxy_pass http://flask:5000 ; rewrite ^/api/(.*) /$1 break ; } + location /user { + proxy_pass http://flask:5000 ; + rewrite ^/user/(.*) /user-files/$1 break ; + } error_page 500 502 503 504 /50x.html ; location = /50x.html { diff --git a/web/src/setupProxy.js b/web/src/setupProxy.js index cf21cc6..3a53786 100644 --- a/web/src/setupProxy.js +++ b/web/src/setupProxy.js @@ -8,4 +8,9 @@ module.exports = function( app ) { pathRewrite: { "^/api/": "/" }, changeOrigin: true, } ) ) ; + app.use( "/user", proxy( { + target: process.env.REACT_APP_FLASK_URL, + pathRewrite: { "^/user/": "/user-files/" }, + changeOrigin: true, + } ) ) ; }