Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
| # pyright: reportGeneralTypeIssues=false, reportAttributeAccessIssue=false | |
| from flask import Flask | |
| from .config import Config, _is_redis_running | |
| from .extensions import db, celery, socketio, limiter, cache | |
| from flask_cors import CORS | |
| def create_app(): | |
| app = Flask(__name__) | |
| app.config.from_object(Config) | |
| # Initialize extensions | |
| db.init_app(app) | |
| from .extensions import migrate | |
| migrate.init_app(app, db) # type: ignore | |
| socketio.init_app(app, cors_allowed_origins="*") # type: ignore | |
| app.socketio = socketio # type: ignore | |
| # Configure Caching dynamically based on Redis availability | |
| redis_url = app.config.get('CELERY_BROKER_URL', 'redis://localhost:6379/0') | |
| if _is_redis_running(redis_url): | |
| app.config['CACHE_TYPE'] = 'RedisCache' | |
| app.config['CACHE_REDIS_URL'] = redis_url | |
| else: | |
| app.config['CACHE_TYPE'] = 'SimpleCache' | |
| cache.init_app(app) | |
| # Initialize Firebase Cloud Storage (for logos, PDFs, and file uploads) | |
| try: | |
| from backend.utils.firebase_storage import init_firebase | |
| except ImportError: | |
| from utils.firebase_storage import init_firebase | |
| init_firebase() | |
| # Optional Celery config update | |
| celery.conf.update( | |
| broker_url=redis_url, | |
| result_backend=app.config.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0') | |
| ) | |
| CORS(app, resources={r"/api/*": {"origins": "*"}}) # type: ignore | |
| with app.app_context(): | |
| # Import routes to register blueprints | |
| from .routes import api_bp, auth_bp, scans_bp, vuln_bp, reports_bp | |
| app.register_blueprint(api_bp) | |
| app.register_blueprint(auth_bp, url_prefix='/api/auth') | |
| app.register_blueprint(scans_bp, url_prefix='/api/scans') | |
| app.register_blueprint(vuln_bp, url_prefix='/api/vulnerabilities') | |
| app.register_blueprint(reports_bp, url_prefix='/api/reports') | |
| # Create tables | |
| db.create_all() | |
| # Seed superadmin user (created once, never overwritten) | |
| from .models import User | |
| import os | |
| if not User.query.filter_by(email='superadmin@gmail.com').first(): | |
| sa = User(email='superadmin@gmail.com', role='super_admin', org_id=None) | |
| sa.set_password(os.getenv('SUPERADMIN_PASSWORD', 'larshield2025')) | |
| db.session.add(sa) | |
| db.session.commit() | |
| print("[System] Superadmin user seeded (superadmin@gmail.com)") | |
| # Cleanup stale scans that were truly abandoned/interrupted (> 10 mins old) | |
| from .models import Scan | |
| from datetime import datetime, timezone, timedelta | |
| try: | |
| ten_mins_ago = datetime.now(timezone.utc) - timedelta(minutes=10) | |
| stale_scans = Scan.query.filter( | |
| Scan.status.in_(['queued', 'scanning']), | |
| (Scan.started_at < ten_mins_ago) | (Scan.started_at == None) | |
| ).all() | |
| for scan in stale_scans: | |
| scan.status = 'failed' | |
| if stale_scans: | |
| db.session.commit() | |
| print(f"[System] Marked {len(stale_scans)} stale/interrupted scans as failed on startup.") | |
| except Exception as e: | |
| print(f"[System] Failed to clean up stale scans: {e}") | |
| return app | |