diff --git a/migrate_db.py b/migrate_db.py new file mode 100644 index 0000000..fdbb199 --- /dev/null +++ b/migrate_db.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 + +from website import create_app +from website.migrations import add_missing_columns_to_oauth2_code + +if __name__ == '__main__': + app = create_app() + print("Running database migration...") + add_missing_columns_to_oauth2_code(app) + print("Migration completed.") diff --git a/website/__init__.py b/website/__init__.py index d3dcc42..8b493f6 100644 --- a/website/__init__.py +++ b/website/__init__.py @@ -5,12 +5,13 @@ def create_app(): app = Flask(__name__) app.config.from_object(os.environ['APP_SETTINGS']) - # Import models after app creation but before init_db - from .models import db, User - db.init_app(app) - - # Run migrations to fix schema issues - from .migrations import add_missing_columns_to_oauth2_code - add_missing_columns_to_oauth2_code(app) + with app.app_context(): + # Run migrations first, before any database operations + from .migrations import add_missing_columns_to_oauth2_code + add_missing_columns_to_oauth2_code(app) + + # Import models after migration but before init_db + from .models import db + db.create_all() return app \ No newline at end of file diff --git a/website/migrations.py b/website/migrations.py index 4d5e5ee..87c69bd 100644 --- a/website/migrations.py +++ b/website/migrations.py @@ -1,11 +1,14 @@ +import os import sqlite3 from sqlalchemy import inspect from flask import current_app +import logging def add_missing_columns_to_oauth2_code(app): """ Check and add missing columns to oauth2_code table """ + print("Starting database migration check...") with app.app_context(): from website.models import db @@ -15,10 +18,12 @@ def add_missing_columns_to_oauth2_code(app): # Check if oauth2_code table exists if 'oauth2_code' not in inspector.get_table_names(): + print("oauth2_code table doesn't exist yet, skipping migration") return # Table doesn't exist yet # Get existing columns columns = [column['name'] for column in inspector.get_columns('oauth2_code')] + print(f"Existing columns in oauth2_code: {columns}") # Define columns that should be added if missing missing_columns = { @@ -32,23 +37,55 @@ def add_missing_columns_to_oauth2_code(app): columns_to_add = {col: dtype for col, dtype in missing_columns.items() if col not in columns} if not columns_to_add: + print("No columns need to be added, schema is up to date") return # No columns need to be added + print(f"Columns to add: {columns_to_add}") + # Connect directly to SQLite to add columns try: - db_path = current_app.config.get('SQLALCHEMY_DATABASE_URI').replace('sqlite:///', '') + # Get database URI from app config + db_uri = current_app.config.get('SQLALCHEMY_DATABASE_URI') + print(f"Database URI: {db_uri}") + + # Handle both relative and absolute paths + if db_uri.startswith('sqlite:///'): + # Relative path + if db_uri.startswith('sqlite:////'): + # Absolute path + db_path = db_uri.replace('sqlite:////', '/') + else: + # Relative path - may need to be adjusted for Docker + db_path = os.path.join(app.root_path, '..', db_uri.replace('sqlite:///', '')) + else: + # Memory or other type of database + print(f"Unsupported database type: {db_uri}") + return + + print(f"Attempting to connect to database at: {db_path}") + + # Ensure directory exists + db_dir = os.path.dirname(db_path) + if not os.path.exists(db_dir): + print(f"Database directory doesn't exist: {db_dir}") + + # Connect to database conn = sqlite3.connect(db_path) cursor = conn.cursor() for column, dtype in columns_to_add.items(): try: - cursor.execute(f'ALTER TABLE oauth2_code ADD COLUMN {column} {dtype};') - print(f"Added missing column '{column}' to oauth2_code table") + sql = f'ALTER TABLE oauth2_code ADD COLUMN {column} {dtype};' + print(f"Executing SQL: {sql}") + cursor.execute(sql) + print(f"Successfully added column '{column}' to oauth2_code table") except sqlite3.OperationalError as e: - # Column might have been added in a concurrent process - print(f"Note: {str(e)}") + print(f"Error adding column '{column}': {str(e)}") conn.commit() conn.close() + print("Migration completed successfully") except Exception as e: print(f"Error during migration: {str(e)}") + import traceback + traceback.print_exc()