diff --git a/scripts/add_security_columns.py b/scripts/add_security_columns.py index 91a2937..fb36406 100644 --- a/scripts/add_security_columns.py +++ b/scripts/add_security_columns.py @@ -3,9 +3,11 @@ Migration: add security columns. users — totp_secret, totp_enabled schwab_connections — refresh_token_expires_at + teller_enrollments — widen access_token VARCHAR(128) → TEXT (needed for Fernet-encrypted values) + schwab_connections — widen access_token / refresh_token TEXT (already TEXT; no-op guard included) Run once: python scripts/add_security_columns.py -Safe to re-run — skips columns that already exist. +Safe to re-run — skips columns that already exist or are already wide enough. """ import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) @@ -38,8 +40,34 @@ CREATE_TABLES = [ """ ] +# Columns whose type must be widened to TEXT to hold Fernet-encrypted values. +# ALTER COLUMN is safe to re-run — widening TEXT→TEXT is a no-op in MySQL. +WIDEN_COLUMNS = [ + ("teller_enrollments", "access_token", "TEXT NOT NULL"), + ("schwab_connections", "access_token", "TEXT NOT NULL"), + ("schwab_connections", "refresh_token", "TEXT NOT NULL"), +] + with app.app_context(): with db.engine.connect() as conn: + for table, column, definition in WIDEN_COLUMNS: + current_type = conn.execute(db.text( + "SELECT DATA_TYPE FROM information_schema.columns " + "WHERE table_schema = DATABASE() " + "AND table_name = :t AND column_name = :c" + ), {"t": table, "c": column}).scalar() + + if current_type and current_type.lower() == 'text': + print(f" {table}.{column} already TEXT — skipped.") + elif current_type: + conn.execute(db.text( + f"ALTER TABLE `{table}` MODIFY COLUMN `{column}` {definition}" + )) + conn.commit() + print(f" Widened {table}.{column} to TEXT.") + else: + print(f" {table}.{column} not found — skipped.") + for table, column, definition in COLUMNS: exists = conn.execute(db.text( "SELECT COUNT(*) FROM information_schema.columns "