Spaces:
Running
Running
| import os | |
| from datetime import timedelta | |
| from flask import Flask | |
| from flask_wtf import CSRFProtect | |
| # Import our configuration logic | |
| from .config import init_firebase, FIREBASE_WEB_API_KEY | |
| def create_app(): | |
| app = Flask(__name__) | |
| secret_key = os.environ.get('FLASK_SECRET_KEY') | |
| if not secret_key: | |
| print("⚠️ FLASK_SECRET_KEY not set — using a random key for this process. " | |
| "All sessions will be invalidated on every restart. Set FLASK_SECRET_KEY " | |
| "in your environment for stable, persistent sessions.") | |
| secret_key = os.urandom(24).hex() | |
| app.secret_key = secret_key | |
| # Cookie settings | |
| app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=30) | |
| app.config['SESSION_REFRESH_EACH_REQUEST'] = True | |
| app.config['SESSION_COOKIE_SAMESITE'] = 'None' | |
| app.config['SESSION_COOKIE_SECURE'] = True | |
| # Cap request body size (uploads, JSON payloads) to guard against | |
| # accidental/malicious resource exhaustion. 25MB comfortably covers a | |
| # Coinalyze export PDF. | |
| app.config['MAX_CONTENT_LENGTH'] = 25 * 1024 * 1024 | |
| # CSRF protection for all state-changing (POST/PUT/PATCH/DELETE) routes. | |
| # Tokens are bound to the session, which already lives for up to 30 days, | |
| # so we don't impose a separate short expiry on top of that. | |
| app.config['WTF_CSRF_TIME_LIMIT'] = None | |
| CSRFProtect(app) | |
| # Baseline security headers (defense in depth alongside proper escaping). | |
| def set_security_headers(response): | |
| response.headers.setdefault('X-Content-Type-Options', 'nosniff') | |
| response.headers.setdefault('X-Frame-Options', 'DENY') | |
| response.headers.setdefault('Referrer-Policy', 'strict-origin-when-cross-origin') | |
| return response | |
| # Initialize Database | |
| try: | |
| init_firebase() | |
| except Exception as e: | |
| print(f"❌ FATAL: {e}") | |
| # Register Blueprints | |
| from .blueprints.auth import auth_bp | |
| from .blueprints.main import main_bp | |
| from .blueprints.tasks import tasks_bp | |
| app.register_blueprint(auth_bp) | |
| app.register_blueprint(main_bp) | |
| app.register_blueprint(tasks_bp) | |
| return app |