99 lines
3.9 KiB
Python
99 lines
3.9 KiB
Python
from flask import Flask, request, session
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
from flask_migrate import Migrate
|
|
from flask_cors import CORS
|
|
from flask_babel import Babel, gettext as _
|
|
from config.config import Config
|
|
|
|
# Initialize extensions
|
|
db = SQLAlchemy()
|
|
migrate = Migrate()
|
|
cors = CORS()
|
|
babel = Babel()
|
|
|
|
def create_app(config_class=Config):
|
|
app = Flask(__name__)
|
|
app.config.from_object(config_class)
|
|
|
|
# Initialize extensions with app
|
|
db.init_app(app)
|
|
migrate.init_app(app, db)
|
|
cors.init_app(app)
|
|
|
|
# Import models to ensure they are registered
|
|
from app.models import user
|
|
# Register REST API (v1) Blueprints with Stateless JWT support
|
|
from app.routes.api.auth import api_auth_bp
|
|
from app.routes.api.classrooms import api_classrooms_bp
|
|
from app.routes.api.reservations import api_reservations_bp
|
|
from app.routes.api.optimizer import api_optimizer_bp
|
|
from app.routes.api.dashboard import api_dashboard_bp
|
|
from app.routes.api.admin import api_admin_bp
|
|
from app.routes.api.openapi import api_openapi_bp
|
|
from app.security import SecurityFilterChain
|
|
|
|
# Register API v1 blueprints
|
|
app.register_blueprint(api_auth_bp)
|
|
app.register_blueprint(api_classrooms_bp)
|
|
app.register_blueprint(api_reservations_bp)
|
|
app.register_blueprint(api_optimizer_bp)
|
|
app.register_blueprint(api_dashboard_bp)
|
|
app.register_blueprint(api_openapi_bp)
|
|
app.register_blueprint(api_admin_bp, url_prefix='/api/v1')
|
|
app.register_blueprint(api_admin_bp, url_prefix='/api/v1/admin', name='api_admin_prefixed')
|
|
|
|
# Initialize Enterprise Security Pipeline (SecurityFilterChain)
|
|
SecurityFilterChain(app)
|
|
|
|
# Language selector function
|
|
def get_locale():
|
|
# 1. Si el usuario está autenticado y tiene idioma configurado explícitamente en su perfil, prevalece.
|
|
from flask_login import current_user
|
|
if current_user.is_authenticated:
|
|
if getattr(current_user, 'preferred_language', None) and current_user.preferred_language in app.config['LANGUAGES']:
|
|
return current_user.preferred_language
|
|
# El idioma por defecto siempre será español a menos que se configure a mano
|
|
return app.config['BABEL_DEFAULT_LOCALE']
|
|
|
|
# 2. Parámetro explícito en la URL (?lang=es o ?lang=en) (para usuarios no autenticados o login)
|
|
lang = request.args.get('lang')
|
|
if lang and lang in app.config['LANGUAGES']:
|
|
session['language'] = lang
|
|
return lang
|
|
|
|
# 3. Si ya hay un idioma guardado en la sesión
|
|
if 'language' in session and session['language'] in app.config['LANGUAGES']:
|
|
return session['language']
|
|
|
|
# 4. Primera vez que se accede a la web (sin sesión): respetar el idioma del navegador
|
|
if request.accept_languages:
|
|
for accepted_lang, _quality in request.accept_languages:
|
|
primary = accepted_lang.split('-')[0].lower()
|
|
if primary in app.config['LANGUAGES']:
|
|
session['language'] = primary # Se guarda para la sesión actual
|
|
return primary
|
|
|
|
# Fallback del sistema: Español
|
|
return app.config['BABEL_DEFAULT_LOCALE']
|
|
|
|
|
|
# Babel context processor
|
|
@app.context_processor
|
|
def inject_conf_vars():
|
|
return dict(
|
|
languages=app.config['LANGUAGES'],
|
|
current_lang=str(get_locale())
|
|
)
|
|
|
|
|
|
# Configure Babel
|
|
babel.init_app(app, locale_selector=get_locale)
|
|
|
|
# Register localized date and datetime formatters for Jinja2 templates
|
|
from flask_babel import format_date, format_datetime
|
|
app.jinja_env.globals['format_date'] = format_date
|
|
app.jinja_env.globals['format_datetime'] = format_datetime
|
|
app.jinja_env.filters['format_date'] = format_date
|
|
app.jinja_env.filters['format_datetime'] = format_datetime
|
|
|
|
return app |