From 3c6c2ddb9c66bef9d2ad3627603b27b20072a8a7 Mon Sep 17 00:00:00 2001 From: Christian Krakau-Louis Date: Sun, 17 May 2026 15:46:20 +0200 Subject: [PATCH] fix: harden container startup and user admin migration --- docker-entrypoint.sh | 28 +++++++++++------- migrations/add_user_is_admin.py | 52 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 migrations/add_user_is_admin.py diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index d2b7654..815acc3 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,23 +1,29 @@ #!/bin/bash set -e -# Start the Flask application with better error reporting +# Start the Flask application with better error reporting. echo "Starting Flask application..." export PYTHONUNBUFFERED=1 -export FLASK_DEBUG=1 +: "${FLASK_DEBUG:=0}" echo "Flask environment: $FLASK_ENV" echo "Database URI: $SQLALCHEMY_DATABASE_URI" echo "Database path: $DATABASE_PATH" -echo "Available environment variables:" -env | grep -v PASSWORD | grep -v SECRET -# Use flask run with explicit reload for better hot reloading +if [ "${LOG_ENV:-0}" = "1" ]; then + echo "Available non-sensitive environment variables:" + env | grep -Evi '(PASSWORD|PASS|SECRET|TOKEN|KEY|AUTH|CREDENTIAL|PRIVATE)' +fi + export PYTHONFAULTHANDLER=1 export PYTHONDONTWRITEBYTECODE=1 -echo "Starting Flask development server with hot reload..." -exec python -m flask run --host=0.0.0.0 --port=5000 --reload --debug || { - echo "Flask application failed to start. Error details:" - python -c "import traceback; traceback.print_exc()" - exit 1 -} \ No newline at end of file +case "${FLASK_DEBUG,,}" in + 1|true|yes|on) + echo "Starting Flask development server with hot reload..." + exec python -m flask run --host=0.0.0.0 --port=5000 --reload --debug + ;; + *) + echo "Starting Flask application server..." + exec python run.py + ;; +esac diff --git a/migrations/add_user_is_admin.py b/migrations/add_user_is_admin.py new file mode 100644 index 0000000..d79927c --- /dev/null +++ b/migrations/add_user_is_admin.py @@ -0,0 +1,52 @@ +""" +Migration script to add the is_admin flag expected by the current User model. +""" +import logging + +from sqlalchemy import inspect, text + +logger = logging.getLogger(__name__) + + +def run_migration(): + """ + Add user.is_admin and backfill it from the existing admin role assignment. + Returns: + - True: if changes were made successfully + - None: if no changes were needed + - False: if errors occurred + """ + from musicround import db + + try: + inspector = inspect(db.engine) + existing_columns = [column["name"] for column in inspector.get_columns("user")] + + if "is_admin" in existing_columns: + logger.info("is_admin column already exists") + return None + + with db.engine.connect() as conn: + logger.info("Adding is_admin column") + conn.execute(text('ALTER TABLE "user" ADD COLUMN is_admin BOOLEAN DEFAULT 0')) + conn.execute( + text( + """ + UPDATE "user" + SET is_admin = 1 + WHERE id IN ( + SELECT ur.user_id + FROM user_roles ur + JOIN role r ON r.id = ur.role_id + WHERE lower(r.name) = 'admin' + ) + """ + ) + ) + conn.commit() + + logger.info("Added is_admin column") + return True + except Exception as e: + logger.error(f"Migration add_user_is_admin failed: {str(e)}") + return False