@@ -28,6 +28,126 @@ def timeout(seconds):
2828 signal .signal (signal .SIGALRM , old_handler )
2929 signal .alarm (0 )
3030
31+ def migrate_database ():
32+ """Automatically migrate database schema to support new features"""
33+ try :
34+ from sqlalchemy import text , inspect
35+
36+ inspector = inspect (db .engine )
37+
38+ # Detect database type for appropriate SQL syntax
39+ db_dialect = db .engine .dialect .name
40+ print (f"🔍 Detected database: { db_dialect } " )
41+
42+ # Check if webhook_notifications column exists in user_settings table
43+ user_settings_columns = [col ['name' ] for col in inspector .get_columns ('user_settings' )]
44+
45+ migrations_applied = []
46+
47+ # Migration 1: Add webhook_notifications column to user_settings
48+ if 'webhook_notifications' not in user_settings_columns :
49+ try :
50+ # Use appropriate SQL for different databases
51+ if db_dialect == 'postgresql' :
52+ alter_sql = 'ALTER TABLE user_settings ADD COLUMN webhook_notifications BOOLEAN DEFAULT FALSE'
53+ elif db_dialect == 'mysql' :
54+ alter_sql = 'ALTER TABLE user_settings ADD COLUMN webhook_notifications BOOLEAN DEFAULT FALSE'
55+ else : # SQLite
56+ alter_sql = 'ALTER TABLE user_settings ADD COLUMN webhook_notifications BOOLEAN DEFAULT FALSE'
57+
58+ with db .engine .connect () as conn :
59+ conn .execute (text (alter_sql ))
60+ conn .commit ()
61+ migrations_applied .append ("Added webhook_notifications column to user_settings" )
62+ except Exception as e :
63+ print (f"⚠️ Could not add webhook_notifications column (may already exist): { e } " )
64+
65+ # Migration 2: Create webhook table if it doesn't exist
66+ if not inspector .has_table ('webhook' ):
67+ try :
68+ # Create webhook table with database-specific syntax
69+ if db_dialect == 'postgresql' :
70+ create_webhook_table = text ("""
71+ CREATE TABLE webhook (
72+ id SERIAL PRIMARY KEY,
73+ name VARCHAR(100) NOT NULL,
74+ webhook_type VARCHAR(50) NOT NULL,
75+ url VARCHAR(500) NOT NULL,
76+ auth_header VARCHAR(200),
77+ auth_username VARCHAR(100),
78+ auth_password VARCHAR(200),
79+ custom_headers TEXT,
80+ is_active BOOLEAN DEFAULT TRUE,
81+ user_id INTEGER NOT NULL,
82+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
83+ last_used TIMESTAMP,
84+ FOREIGN KEY (user_id) REFERENCES "user"(id)
85+ )
86+ """ )
87+ elif db_dialect == 'mysql' :
88+ create_webhook_table = text ("""
89+ CREATE TABLE webhook (
90+ id INT AUTO_INCREMENT PRIMARY KEY,
91+ name VARCHAR(100) NOT NULL,
92+ webhook_type VARCHAR(50) NOT NULL,
93+ url VARCHAR(500) NOT NULL,
94+ auth_header VARCHAR(200),
95+ auth_username VARCHAR(100),
96+ auth_password VARCHAR(200),
97+ custom_headers TEXT,
98+ is_active BOOLEAN DEFAULT TRUE,
99+ user_id INTEGER NOT NULL,
100+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
101+ last_used DATETIME,
102+ FOREIGN KEY (user_id) REFERENCES user(id)
103+ )
104+ """ )
105+ else : # SQLite
106+ create_webhook_table = text ("""
107+ CREATE TABLE webhook (
108+ id INTEGER PRIMARY KEY AUTOINCREMENT,
109+ name VARCHAR(100) NOT NULL,
110+ webhook_type VARCHAR(50) NOT NULL,
111+ url VARCHAR(500) NOT NULL,
112+ auth_header VARCHAR(200),
113+ auth_username VARCHAR(100),
114+ auth_password VARCHAR(200),
115+ custom_headers TEXT,
116+ is_active BOOLEAN DEFAULT 1,
117+ user_id INTEGER NOT NULL,
118+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
119+ last_used DATETIME,
120+ FOREIGN KEY (user_id) REFERENCES user(id)
121+ )
122+ """ )
123+
124+ with db .engine .connect () as conn :
125+ conn .execute (create_webhook_table )
126+ conn .commit ()
127+ migrations_applied .append ("Created webhook table" )
128+ except Exception as e :
129+ print (f"⚠️ Could not create webhook table (may already exist): { e } " )
130+
131+ # Migration 3: Update existing user_settings to have webhook_notifications = FALSE if NULL
132+ try :
133+ with db .engine .connect () as conn :
134+ conn .execute (text ('UPDATE user_settings SET webhook_notifications = FALSE WHERE webhook_notifications IS NULL' ))
135+ conn .commit ()
136+ migrations_applied .append ("Updated existing user settings with default webhook_notifications value" )
137+ except Exception as e :
138+ print (f"⚠️ Could not update existing user settings: { e } " )
139+
140+ if migrations_applied :
141+ print ("🔄 Database migrations applied:" )
142+ for migration in migrations_applied :
143+ print (f" ✅ { migration } " )
144+ else :
145+ print ("✅ Database schema is up to date" )
146+
147+ except Exception as e :
148+ print (f"❌ Database migration failed: { e } " )
149+ print ("⚠️ The application may not work correctly until database schema is updated" )
150+
31151def create_app ():
32152 app = Flask (__name__ )
33153 app .config .from_object (Config )
@@ -161,6 +281,9 @@ def inject_user_date_format():
161281 app .register_blueprint (main )
162282
163283 with app .app_context ():
284+ # Run automatic database migrations before creating tables
285+ migrate_database ()
286+
164287 db .create_all ()
165288
166289 # Create default admin user if no admin users exist
0 commit comments