from flask import Flask from datetime import datetime import os def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = 'your_secret_key' # Initialize logging first from app.logging_config import setup_logging log_dir = os.path.join(app.instance_path, '..', 'logs') logger = setup_logging(app=app, log_dir=log_dir) logger.info("Flask app initialization started") # Configure session persistence from datetime import timedelta app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7) app.config['SESSION_COOKIE_SECURE'] = False # Set to True in production with HTTPS app.config['SESSION_COOKIE_HTTPONLY'] = True app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' # Set max upload size to 10GB for large database backups app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 * 1024 # 10GB # Note: Database connection pool is lazily initialized on first use # This is to avoid trying to read configuration before it's created # during application startup. See app.db_pool.get_db_pool() for details. logger.info("Database connection pool will be lazily initialized on first use") # Application uses direct MariaDB connections via external_server.conf # Connection pooling via DBUtils prevents connection exhaustion logger.info("Registering Flask blueprints...") from app.routes import bp as main_bp, warehouse_bp from app.daily_mirror import daily_mirror_bp app.register_blueprint(main_bp, url_prefix='/') app.register_blueprint(warehouse_bp, url_prefix='/warehouse') app.register_blueprint(daily_mirror_bp) logger.info("Blueprints registered successfully") # Add 'now' function to Jinja2 globals app.jinja_env.globals['now'] = datetime.now # Add license check middleware @app.before_request def check_license_middleware(): from flask import session, request, redirect, url_for, flash, render_template import os import json from datetime import datetime # Skip license check for static files, login page, and superadmin users if request.endpoint and ( request.endpoint == 'static' or request.endpoint == 'main.login' or request.path.startswith('/static/') ): return None # Skip if user is not logged in (will be redirected to login by other means) if 'user' not in session: return None # Skip license check for superadmin if session.get('role') == 'superadmin': return None # Check license validity license_path = os.path.join(app.instance_path, 'app_license.json') if not os.path.exists(license_path): session.clear() flash('⚠️ Application License Missing - Please contact your superadmin to generate a license key.', 'danger') return redirect(url_for('main.login')) try: with open(license_path, 'r') as f: license_data = json.load(f) valid_until = datetime.strptime(license_data['valid_until'], '%Y-%m-%d') if datetime.utcnow().date() > valid_until.date(): session.clear() flash(f'⚠️ Application License Expired on {license_data["valid_until"]} - Please contact your superadmin to renew the license.', 'danger') return redirect(url_for('main.login')) except Exception as e: session.clear() flash('⚠️ License Validation Error - Please contact your superadmin.', 'danger') return redirect(url_for('main.login')) return None # Initialize user modules validation and repair on app startup def validate_user_modules_on_startup(): """Validate and repair user modules during app startup""" try: import mariadb import json import os # Get database config from instance folder instance_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../instance')) config_path = os.path.join(instance_path, 'external_server.conf') if not os.path.exists(config_path): print("⚠️ Database config not found, skipping user modules validation") return # Parse config db_config = {} try: with open(config_path, 'r') as f: for line in f: if '=' in line: key, value = line.strip().split('=', 1) db_config[key] = value db_config = { 'user': db_config.get('username', 'trasabilitate'), 'password': db_config.get('password', 'Initial01!'), 'host': db_config.get('server_domain', 'localhost'), 'port': int(db_config.get('port', 3306)), 'database': db_config.get('database_name', 'trasabilitate') } except Exception as e: print(f"⚠️ Could not parse database config: {e}") return # Connect and validate users conn = mariadb.connect(**db_config) cursor = conn.cursor() # Check if users table exists cursor.execute("SHOW TABLES LIKE 'users'") if not cursor.fetchone(): print("⚠️ Users table not found, skipping validation") conn.close() return # Get all users and validate/repair modules cursor.execute("SELECT id, username, role, modules FROM users") users = cursor.fetchall() users_repaired = 0 for user_id, username, role, modules in users: # Determine correct modules if role == 'superadmin': correct_modules = None elif role == 'admin': correct_modules = json.dumps(['quality', 'warehouse', 'labels', 'daily_mirror']) elif role in ['manager', 'quality_manager', 'warehouse_manager']: correct_modules = json.dumps(['quality', 'warehouse']) else: correct_modules = json.dumps([]) # Repair if needed if modules != correct_modules: cursor.execute("UPDATE users SET modules = %s WHERE id = %s", (correct_modules, user_id)) users_repaired += 1 if users_repaired > 0: conn.commit() print(f"✅ User modules validation complete: {users_repaired} users repaired") cursor.close() conn.close() except Exception as e: print(f"⚠️ Error during user modules validation: {e}") # Run validation on startup with app.app_context(): validate_user_modules_on_startup() # Initialize automatic backup scheduler from app.backup_scheduler import init_backup_scheduler init_backup_scheduler(app) print("✅ Automatic backup scheduler initialized") return app