app
This commit is contained in:
99
app.py
99
app.py
@@ -17,6 +17,7 @@ import config
|
|||||||
from cve_handler import CVEHandler, update_all_vendors
|
from cve_handler import CVEHandler, update_all_vendors
|
||||||
import api
|
import api
|
||||||
|
|
||||||
|
|
||||||
def setup_logging():
|
def setup_logging():
|
||||||
log_level = getattr(logging, config.LOG_LEVEL.upper(), logging.INFO)
|
log_level = getattr(logging, config.LOG_LEVEL.upper(), logging.INFO)
|
||||||
|
|
||||||
@@ -60,16 +61,19 @@ if not config.DEBUG:
|
|||||||
app.register_blueprint(api.api_bp, url_prefix='/api')
|
app.register_blueprint(api.api_bp, url_prefix='/api')
|
||||||
cve_handler = CVEHandler()
|
cve_handler = CVEHandler()
|
||||||
|
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_config():
|
def inject_config():
|
||||||
return {'config': config}
|
return {'config': config}
|
||||||
|
|
||||||
|
|
||||||
def add_security_headers(response):
|
def add_security_headers(response):
|
||||||
if config.ENABLE_SECURITY_HEADERS:
|
if config.ENABLE_SECURITY_HEADERS:
|
||||||
for header, value in config.SECURITY_HEADERS.items():
|
for header, value in config.SECURITY_HEADERS.items():
|
||||||
response.headers[header] = value
|
response.headers[header] = value
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def gzip_response(f):
|
def gzip_response(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
@@ -99,6 +103,7 @@ def gzip_response(f):
|
|||||||
return response
|
return response
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
|
|
||||||
def etag_support(f):
|
def etag_support(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
@@ -121,12 +126,14 @@ def etag_support(f):
|
|||||||
|
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@gzip_response
|
@gzip_response
|
||||||
@etag_support
|
@etag_support
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html', vendors=config.VENDORS)
|
return render_template('index.html', vendors=config.VENDORS)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/health')
|
@app.route('/health')
|
||||||
def health():
|
def health():
|
||||||
try:
|
try:
|
||||||
@@ -166,10 +173,12 @@ def health():
|
|||||||
'error': str(e)
|
'error': str(e)
|
||||||
}), 503
|
}), 503
|
||||||
|
|
||||||
|
|
||||||
@app.route('/favicon.ico')
|
@app.route('/favicon.ico')
|
||||||
def favicon():
|
def favicon():
|
||||||
return '', 204
|
return '', 204
|
||||||
|
|
||||||
|
|
||||||
@app.route('/version')
|
@app.route('/version')
|
||||||
def version():
|
def version():
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -179,12 +188,14 @@ def version():
|
|||||||
'flask_version': '3.0.2'
|
'flask_version': '3.0.2'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(404)
|
@app.errorhandler(404)
|
||||||
def not_found(error):
|
def not_found(error):
|
||||||
if request.path.startswith('/api/'):
|
if request.path.startswith('/api/'):
|
||||||
return jsonify({'error': 'Endpoint not found'}), 404
|
return jsonify({'error': 'Endpoint not found'}), 404
|
||||||
return render_template('404.html'), 404
|
return render_template('404.html'), 404
|
||||||
|
|
||||||
|
|
||||||
@app.errorhandler(500)
|
@app.errorhandler(500)
|
||||||
def internal_error(error):
|
def internal_error(error):
|
||||||
logger.error(f"Internal error: {error}")
|
logger.error(f"Internal error: {error}")
|
||||||
@@ -192,6 +203,7 @@ def internal_error(error):
|
|||||||
return jsonify({'error': 'Internal server error'}), 500
|
return jsonify({'error': 'Internal server error'}), 500
|
||||||
return render_template('500.html'), 500
|
return render_template('500.html'), 500
|
||||||
|
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def after_request(response):
|
def after_request(response):
|
||||||
response = add_security_headers(response)
|
response = add_security_headers(response)
|
||||||
@@ -204,6 +216,7 @@ def after_request(response):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def background_update_task():
|
def background_update_task():
|
||||||
logger.info("Background update task started")
|
logger.info("Background update task started")
|
||||||
time.sleep(60)
|
time.sleep(60)
|
||||||
@@ -225,31 +238,68 @@ def background_update_task():
|
|||||||
|
|
||||||
|
|
||||||
def start_background_tasks():
|
def start_background_tasks():
|
||||||
if config.ENABLE_AUTO_UPDATE:
|
is_gunicorn = (
|
||||||
update_thread = threading.Thread(
|
'gunicorn' in os.environ.get('SERVER_SOFTWARE', '').lower() or
|
||||||
target=background_update_task,
|
os.environ.get('GUNICORN_CMD_ARGS') is not None
|
||||||
daemon=True,
|
)
|
||||||
name="CVE-Update-Thread"
|
|
||||||
)
|
is_dev_mode = __name__ == '__main__'
|
||||||
update_thread.start()
|
|
||||||
logger.info("Auto-update enabled: background task started")
|
if is_gunicorn:
|
||||||
else:
|
logger.info("=" * 70)
|
||||||
logger.info("Auto-update disabled")
|
logger.info("PRODUCTION MODE (Gunicorn)")
|
||||||
|
logger.info("=" * 70)
|
||||||
|
logger.info("Background tasks handled by separate containers:")
|
||||||
|
logger.info(" Scheduler: cve-monitor-scheduler")
|
||||||
|
logger.info(" Discord Bot: cve-monitor-discord")
|
||||||
|
logger.info("=" * 70)
|
||||||
|
return
|
||||||
|
|
||||||
|
if is_dev_mode:
|
||||||
|
logger.info("=" * 70)
|
||||||
|
logger.info("DEVELOPMENT MODE (Standalone Flask)")
|
||||||
|
logger.info("=" * 70)
|
||||||
|
logger.info("Starting background tasks in threads...")
|
||||||
|
logger.info("")
|
||||||
|
|
||||||
|
if config.ENABLE_AUTO_UPDATE:
|
||||||
|
try:
|
||||||
|
update_thread = threading.Thread(
|
||||||
|
target=background_update_task,
|
||||||
|
daemon=True,
|
||||||
|
name="CVE-Update-Thread"
|
||||||
|
)
|
||||||
|
update_thread.start()
|
||||||
|
logger.info(" Scheduler thread: STARTED")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f" Scheduler thread: FAILED - {e}")
|
||||||
|
else:
|
||||||
|
logger.info(" Scheduler thread: DISABLED")
|
||||||
|
|
||||||
|
if config.DISCORD_BOT_ENABLED:
|
||||||
|
try:
|
||||||
|
from discord_bot import start_discord_bot
|
||||||
|
|
||||||
|
discord_thread = threading.Thread(
|
||||||
|
target=start_discord_bot,
|
||||||
|
daemon=True,
|
||||||
|
name="Discord-Bot-Thread"
|
||||||
|
)
|
||||||
|
discord_thread.start()
|
||||||
|
logger.info(" Discord bot thread: STARTED")
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
logger.warning(" Discord bot thread: FAILED - discord.py not installed")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f" Discord bot thread: FAILED - {e}")
|
||||||
|
else:
|
||||||
|
logger.info(" Discord bot thread: DISABLED")
|
||||||
|
|
||||||
|
logger.info("")
|
||||||
|
logger.info("=" * 70)
|
||||||
|
else:
|
||||||
|
logger.info("Production mode: background tasks in separate containers")
|
||||||
|
|
||||||
if config.DISCORD_BOT_ENABLED:
|
|
||||||
try:
|
|
||||||
from discord_bot import start_discord_bot
|
|
||||||
discord_thread = threading.Thread(
|
|
||||||
target=start_discord_bot,
|
|
||||||
daemon=True,
|
|
||||||
name="Discord-Bot-Thread"
|
|
||||||
)
|
|
||||||
discord_thread.start()
|
|
||||||
logger.info("Discord bot started")
|
|
||||||
except ImportError:
|
|
||||||
logger.warning("discord.py not installed, Discord bot disabled")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Failed to start Discord bot: {e}", exc_info=True)
|
|
||||||
|
|
||||||
def initialize_app():
|
def initialize_app():
|
||||||
logger.info(f"{'='*60}")
|
logger.info(f"{'='*60}")
|
||||||
@@ -282,6 +332,7 @@ def initialize_app():
|
|||||||
logger.info(f"{'='*60}")
|
logger.info(f"{'='*60}")
|
||||||
start_background_tasks()
|
start_background_tasks()
|
||||||
|
|
||||||
|
|
||||||
_initialized = False
|
_initialized = False
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
Reference in New Issue
Block a user