from flask import Flask, jsonify, request from flask_jwt_extended import get_jwt_identity, verify_jwt_in_request from common.extensions import db, api_rest, jwt, minio_client, simple_encryption import os import logging.config from common.utils.database import Database from config.logging_config import LOGGING from .api.document_api import document_ns from .api.auth import auth_ns from config.config import get_config from common.utils.celery_utils import make_celery, init_celery from common.utils.eveai_exceptions import EveAIException def create_app(config_file=None): app = Flask(__name__) 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_api_' app.celery = make_celery(app.name, app.config) init_celery(app.celery, app) logging.config.dictConfig(LOGGING) logger = logging.getLogger(__name__) logger.info("eveai_api starting up") # Register Necessary Extensions register_extensions(app) # register Namespaces register_namespaces(api_rest) # Register Blueprints register_blueprints(app) # Error handler for the API @app.errorhandler(EveAIException) def handle_eveai_exception(error): return {'message': str(error)}, error.status_code @app.before_request def before_request(): app.logger.debug(f'Before request: {request.method} {request.path}') app.logger.debug(f'Request URL: {request.url}') app.logger.debug(f'Request headers: {dict(request.headers)}') # Log request arguments app.logger.debug(f'Request args: {request.args}') # Log form data if it's a POST request if request.method == 'POST': app.logger.debug(f'Form data: {request.form}') # Log JSON data if the content type is application/json if request.is_json: app.logger.debug(f'JSON data: {request.json}') # Log raw data for other content types if request.data: app.logger.debug(f'Raw data: {request.data}') # Check if this is a request to the token endpoint if request.path == '/api/v1/auth/token' and request.method == 'POST': app.logger.debug('Token request detected, skipping JWT verification') return # Check if this a health check request if request.path.startswith('/_healthz') or request.path.startswith('/healthz'): app.logger.debug('Health check request detected, skipping JWT verification') else: try: verify_jwt_in_request(optional=True) tenant_id = get_jwt_identity() app.logger.debug(f'Tenant ID from JWT: {tenant_id}') if tenant_id: Database(tenant_id).switch_schema() app.logger.debug(f'Switched to schema for tenant {tenant_id}') else: app.logger.debug('No tenant ID found in JWT') except Exception as e: app.logger.error(f'Error in before_request: {str(e)}') # Don't raise the exception here, let the request continue # The appropriate error handling will be done in the specific endpoints return app def register_extensions(app): db.init_app(app) api_rest.init_app(app, title='EveAI API', version='1.0', description='EveAI API') jwt.init_app(app) minio_client.init_app(app) simple_encryption.init_app(app) def register_namespaces(app): api_rest.add_namespace(document_ns, path='/api/v1/documents') api_rest.add_namespace(auth_ns, path='/api/v1/auth') def register_blueprints(app): from .views.healthz_views import healthz_bp app.register_blueprint(healthz_bp)