""" HAProxy Configurator - Main Application SQLAlchemy + Flask-SQLAlchemy Integration """ import os import sys import ssl import configparser from datetime import timedelta from flask import Flask, render_template, redirect, url_for, session from flask_sqlalchemy import SQLAlchemy from config.settings import * from database import db, migrate # ✅ NIE importuj init_db tutaj! from routes.main_routes import main_bp from routes.edit_routes import edit_bp from routes.auth_routes import auth_bp from routes.user_routes import user_bp from routes.vhost_routes import vhost_bp from routes.cert_routes import cert_bp from auth.auth_middleware import setup_auth, login_required from utils.stats_utils import fetch_haproxy_stats, parse_haproxy_stats # ===== BASE DIRECTORY ===== BASE_DIR = os.path.abspath(os.path.dirname(__file__)) # ===== CREATE REQUIRED DIRECTORIES ===== INSTANCE_DIR = os.path.join(BASE_DIR, 'instance') os.makedirs(INSTANCE_DIR, exist_ok=True) os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(HAPROXY_BACKUP_DIR, exist_ok=True) print(f"[APP] Base directory: {BASE_DIR}", flush=True) print(f"[APP] Instance directory: {INSTANCE_DIR}", flush=True) print(f"[APP] Database: {SQLALCHEMY_DATABASE_URI}", flush=True) # ===== CREATE FLASK APP ===== app = Flask( __name__, static_folder=os.path.join(BASE_DIR, 'static'), static_url_path='/static', template_folder=os.path.join(BASE_DIR, 'templates'), instance_path=INSTANCE_DIR ) # ===== LOAD CONFIGURATION ===== app.config.from_object('config.settings') app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7) app.config['SESSION_COOKIE_SECURE'] = True app.config['SESSION_COOKIE_HTTPONLY'] = True app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' # ===== INITIALIZE DATABASE ===== print("[APP] Initializing database...", flush=True) db.init_app(app) migrate.init_app(app, db) # ❌ USUŃ TĘ LINIĘ: init_db(app) print("[APP] Database initialized", flush=True) # ===== REGISTER BLUEPRINTS ===== print("[APP] Registering blueprints...", flush=True) app.register_blueprint(main_bp) app.register_blueprint(edit_bp) app.register_blueprint(auth_bp) app.register_blueprint(user_bp) app.register_blueprint(vhost_bp) app.register_blueprint(cert_bp) print("[APP] Blueprints registered", flush=True) # ===== SETUP AUTHENTICATION MIDDLEWARE ===== print("[APP] Setting up auth middleware...", flush=True) setup_auth(app) print("[APP] Auth middleware setup complete", flush=True) # ===== SSL CONTEXT SETUP ===== certificate_path = None private_key_path = None ssl_context = None try: config_ssl = configparser.ConfigParser() config_ssl.read(SSL_INI) if config_ssl.has_section('ssl'): certificate_path = config_ssl.get('ssl', 'certificate_path') private_key_path = config_ssl.get('ssl', 'private_key_path') if os.path.exists(certificate_path) and os.path.exists(private_key_path): ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ssl_context.load_cert_chain(certfile=certificate_path, keyfile=private_key_path) print("[APP] SSL context loaded successfully", flush=True) else: print(f"[APP] SSL certificate files not found", flush=True) print(f" Certificate: {certificate_path}", flush=True) print(f" Private Key: {private_key_path}", flush=True) else: print(f"[APP] No [ssl] section in {SSL_INI}", flush=True) except Exception as e: print(f"[APP] SSL warning (non-critical): {e}", flush=True) # ===== ROUTES ===== @app.route('/') def index(): """Index/Home - Redirect to login or dashboard""" if 'user_id' not in session: return redirect(url_for('auth.login')) return redirect(url_for('main.index')) @app.route('/statistics') @login_required def display_haproxy_stats(): """Display HAProxy statistics""" try: haproxy_stats = fetch_haproxy_stats() parsed_stats = parse_haproxy_stats(haproxy_stats) return render_template('statistics.html', stats=parsed_stats) except Exception as e: print(f"[STATS] Error: {e}", flush=True) return render_template('statistics.html', stats={}, error=str(e)) @app.route('/dashboard') @login_required def dashboard(): """Dashboard - Overview of vhosts and status""" from database.models import VirtualHost try: vhosts = VirtualHost.query.all() return render_template('dashboard.html', vhosts=vhosts) except Exception as e: print(f"[DASHBOARD] Error: {e}", flush=True) return render_template('dashboard.html', vhosts=[], error=str(e)) # ===== ERROR HANDLERS ===== @app.errorhandler(404) def page_not_found(error): """404 error handler""" return render_template('404.html'), 404 @app.errorhandler(500) def internal_error(error): """500 error handler""" db.session.rollback() return render_template('500.html'), 500 @app.errorhandler(403) def forbidden(error): """403 error handler""" return render_template('403.html'), 403 # ===== SHELL CONTEXT ===== @app.shell_context_processor def make_shell_context(): """Add models to Flask shell context""" from database.models import User, Certificate, VirtualHost, BackendServer, ConfigHistory return { 'db': db, 'User': User, 'Certificate': Certificate, 'VirtualHost': VirtualHost, 'BackendServer': BackendServer, 'ConfigHistory': ConfigHistory } # ===== APPLICATION CONTEXT ===== @app.before_request def before_request(): """Run before each request""" pass @app.after_request def after_request(response): """Run after each request""" return response # ===== CLI COMMANDS ===== @app.cli.command() def init_db_cli(): """Initialize database""" with app.app_context(): from database import init_db init_db(app) print("[CLI] Database initialized successfully") @app.cli.command() def create_admin(): """Create admin user""" import getpass username = input("Username: ") password = getpass.getpass("Password: ") from database.models import User if User.query.filter_by(username=username).first(): print(f"Error: User '{username}' already exists") return user = User(username=username, is_admin=True) user.set_password(password) db.session.add(user) db.session.commit() print(f"[CLI] Admin user '{username}' created successfully") @app.cli.command() def import_config(): """Import existing haproxy.cfg to database""" from database.migration import parse_existing_haproxy_config config_path = HAPROXY_CONFIG_PATH count = parse_existing_haproxy_config(config_path) print(f"[CLI] Successfully imported {count} vhosts from {config_path}") # ===== MAIN ENTRY POINT ===== if __name__ == '__main__': print(""" ╔════════════════════════════════════════╗ ║ HAProxy Configurator & Manager ║ ║ Starting Application... ║ ╚════════════════════════════════════════╝ """, flush=True) print(f"[APP] Environment: {'Development' if DEBUG else 'Production'}", flush=True) print(f"[APP] Running on: https://[::]:5000 (IPv6)", flush=True) # Initialize database before running with app.app_context(): from database import init_db init_db(app) app.run( host='::', port=5000, ssl_context=ssl_context, debug=DEBUG, use_reloader=DEBUG )