import logging import os from flask import Flask, render_template, jsonify, flash, redirect, request from flask_security import SQLAlchemyUserDatastore, LoginForm from flask_security.signals import user_authenticated from werkzeug.middleware.proxy_fix import ProxyFix import logging.config from common.extensions import (db, migrate, bootstrap, security, mail, login_manager, cors, csrf, session, minio_client, simple_encryption, metrics) from common.models.user import User, Role, Tenant, TenantDomain import common.models.interaction from common.utils.nginx_utils import prefixed_url_for from config.logging_config import LOGGING from common.utils.security import set_tenant_session_data from .errors import register_error_handlers from common.utils.celery_utils import make_celery, init_celery from common.utils.template_filters import register_filters from config.config import get_config from eveai_app.views.security_forms import ResetPasswordForm def create_app(config_file=None): app = Flask(__name__, static_url_path='/static') # Ensure all necessary headers are handled app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1) environment = os.getenv('FLASK_ENV', 'development') match environment: case 'development': app.config.from_object(get_config('dev')) case 'production': app.config.from_object(get_config('prod')) case _: app.config.from_object(get_config('dev')) app.config['SESSION_KEY_PREFIX'] = 'eveai_app_' app.config['SECURITY_RESET_PASSWORD_FORM'] = ResetPasswordForm try: os.makedirs(app.instance_path) except OSError: pass logging.config.dictConfig(LOGGING) logger = logging.getLogger(__name__) logger.info("eveai_app starting up") # Register extensions register_extensions(app) # Configure CSRF protection app.config['WTF_CSRF_CHECK_DEFAULT'] = False # Disable global CSRF protection app.config['WTF_CSRF_TIME_LIMIT'] = None # Remove time limit for CSRF tokens app.celery = make_celery(app.name, app.config) init_celery(app.celery, app) # Setup Flask-Security-Too user_datastore = SQLAlchemyUserDatastore(db, User, Role) security.init_app(app, user_datastore) user_authenticated.connect(set_tenant_session_data, app) # Register Blueprints register_blueprints(app) # Register Error Handlers register_error_handlers(app) # Debugging settings if app.config['DEBUG'] is True: app.logger.setLevel(logging.DEBUG) mail_logger = logging.getLogger('flask_mailman') mail_logger.setLevel(logging.DEBUG) security_logger = logging.getLogger('flask_security') security_logger.setLevel(logging.DEBUG) sqlalchemy_logger = logging.getLogger('sqlalchemy.engine') sqlalchemy_logger.setLevel(logging.DEBUG) # log_request_middleware(app) # Add this when debugging nginx or another proxy # Some generic Error Handling Routines @app.errorhandler(Exception) def handle_exception(e): app.logger.error(f"Unhandled Exception: {e}", exc_info=True) response = { "message": str(e), "type": type(e).__name__ } return jsonify(response), 500 # @app.before_request # def before_request(): # # app.logger.debug(f"Before request - Session ID: {session.sid}") # app.logger.debug(f"Before request - Session data: {session}") # app.logger.debug(f"Before request - Request headers: {request.headers}") # Register template filters register_filters(app) app.logger.info("EveAI App Server Started Successfully") app.logger.info("-------------------------------------------------------------------------------------------------") return app def register_extensions(app): db.init_app(app) migrate.init_app(app, db) bootstrap.init_app(app) mail.init_app(app) csrf.init_app(app) login_manager.init_app(app) cors.init_app(app) simple_encryption.init_app(app) session.init_app(app) minio_client.init_app(app) metrics.init_app(app) # Register Blueprints def register_blueprints(app): from .views.user_views import user_bp app.register_blueprint(user_bp) from .views.basic_views import basic_bp app.register_blueprint(basic_bp) from .views.document_views import document_bp app.register_blueprint(document_bp) from .views.security_views import security_bp app.register_blueprint(security_bp) from .views.interaction_views import interaction_bp app.register_blueprint(interaction_bp) from .views.healthz_views import healthz_bp, init_healtz app.register_blueprint(healthz_bp) init_healtz(app)