Namenskonsistenz + Ablauf der Lizenzen

Dieser Commit ist enthalten in:
2025-06-22 23:58:39 +02:00
Ursprung cdf81e2de5
Commit 5b71a1d60d
4 geänderte Dateien mit 100 neuen und 26 gelöschten Zeilen

Datei anzeigen

@@ -53,13 +53,13 @@ init_error_handlers(app)
init_monitoring(app) init_monitoring(app)
ErrorHandlingMiddleware(app) ErrorHandlingMiddleware(app)
# Scheduler für automatische Backups
scheduler = BackgroundScheduler()
scheduler.start()
# Logging konfigurieren # Logging konfigurieren
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
# Initialize scheduler from scheduler module
from scheduler import init_scheduler
scheduler = init_scheduler()
# Import and register blueprints # Import and register blueprints
try: try:
from routes.auth_routes import auth_bp from routes.auth_routes import auth_bp
@@ -119,26 +119,7 @@ def debug_routes():
routes.append(f"{rule.endpoint}: {rule.rule}") routes.append(f"{rule.endpoint}: {rule.rule}")
return "<br>".join(sorted(routes)) return "<br>".join(sorted(routes))
# Scheduled Backup Job # Scheduled backup job is now handled by scheduler module
def scheduled_backup():
"""Erstellt ein automatisches Backup"""
try:
backup_file = create_backup()
logging.info(f"Scheduled backup created: {backup_file}")
except Exception as e:
logging.error(f"Scheduled backup failed: {str(e)}")
# Schedule daily backup at 3 AM
scheduler.add_job(
func=scheduled_backup,
trigger="cron",
hour=3,
minute=0,
id='daily_backup',
name='Daily backup',
replace_existing=True
)
# Error handlers are now managed by the error handling system in core/error_handlers.py # Error handlers are now managed by the error handling system in core/error_handlers.py

Datei anzeigen

@@ -1417,3 +1417,25 @@ def test_license_types():
cur.close() cur.close()
if 'conn' in locals(): if 'conn' in locals():
conn.close() conn.close()
@admin_bp.route("/admin/licenses/check-expiration", methods=["POST"])
@login_required
def check_license_expiration():
"""Manually trigger license expiration check"""
if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
return jsonify({'error': 'Zugriff verweigert'}), 403
try:
from scheduler import deactivate_expired_licenses
deactivate_expired_licenses()
flash('License expiration check completed successfully', 'success')
log_audit('MANUAL_LICENSE_EXPIRATION_CHECK', 'system',
additional_info="Manual license expiration check triggered")
return jsonify({'success': True, 'message': 'License expiration check completed'})
except Exception as e:
current_app.logger.error(f"Error in manual license expiration check: {str(e)}")
return jsonify({'error': str(e)}), 500

Datei anzeigen

@@ -5,7 +5,7 @@ import logging
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
import config import config
from utils.backup import create_backup from utils.backup import create_backup
from utils.db_utils import get_connection from db import get_connection
def scheduled_backup(): def scheduled_backup():
@@ -64,6 +64,66 @@ def cleanup_expired_sessions():
conn.rollback() conn.rollback()
def deactivate_expired_licenses():
"""Deactivate licenses that have expired"""
try:
conn = get_connection()
cur = conn.cursor()
# Find active licenses that have expired
# Check valid_until < today (at midnight)
cur.execute("""
SELECT id, license_key, customer_id, valid_until
FROM licenses
WHERE is_active = true
AND valid_until IS NOT NULL
AND valid_until < CURRENT_DATE
AND is_fake = false
""")
expired_licenses = cur.fetchall()
if expired_licenses:
logging.info(f"Found {len(expired_licenses)} expired licenses to deactivate")
for license in expired_licenses:
license_id, license_key, customer_id, valid_until = license
# Deactivate the license
cur.execute("""
UPDATE licenses
SET is_active = false,
updated_at = CURRENT_TIMESTAMP
WHERE id = %s
""", (license_id,))
# Log to audit trail
cur.execute("""
INSERT INTO audit_log
(timestamp, username, action, entity_type, entity_id,
old_values, new_values, additional_info)
VALUES (CURRENT_TIMESTAMP, 'system', 'DEACTIVATE', 'license', %s,
jsonb_build_object('is_active', true),
jsonb_build_object('is_active', false),
%s)
""", (license_id, f"License automatically deactivated due to expiration. Valid until: {valid_until}"))
logging.info(f"Deactivated expired license: {license_key} (ID: {license_id})")
conn.commit()
logging.info(f"Successfully deactivated {len(expired_licenses)} expired licenses")
else:
logging.debug("No expired licenses found to deactivate")
cur.close()
conn.close()
except Exception as e:
logging.error(f"Error deactivating expired licenses: {str(e)}")
if 'conn' in locals():
conn.rollback()
def init_scheduler(): def init_scheduler():
"""Initialize and configure the scheduler""" """Initialize and configure the scheduler"""
scheduler = BackgroundScheduler() scheduler = BackgroundScheduler()
@@ -87,8 +147,19 @@ def init_scheduler():
replace_existing=True replace_existing=True
) )
# Configure license expiration job - runs daily at midnight
scheduler.add_job(
deactivate_expired_licenses,
'cron',
hour=0,
minute=0,
id='license_expiration_check',
replace_existing=True
)
scheduler.start() scheduler.start()
logging.info(f"Scheduler started. Daily backup scheduled at {config.SCHEDULER_CONFIG['backup_hour']:02d}:{config.SCHEDULER_CONFIG['backup_minute']:02d}") logging.info(f"Scheduler started. Daily backup scheduled at {config.SCHEDULER_CONFIG['backup_hour']:02d}:{config.SCHEDULER_CONFIG['backup_minute']:02d}")
logging.info("Session cleanup job scheduled to run every 60 seconds") logging.info("Session cleanup job scheduled to run every 60 seconds")
logging.info("License expiration check scheduled to run daily at midnight")
return scheduler return scheduler

Datei anzeigen

@@ -228,7 +228,7 @@
{% if show_fake %}checked{% endif %} {% if show_fake %}checked{% endif %}
onchange="toggleTestResources()"> onchange="toggleTestResources()">
<label class="form-check-label" for="showTestResources"> <label class="form-check-label" for="showTestResources">
Testressourcen anzeigen Fake-Ressourcen anzeigen
</label> </label>
</div> </div>
</div> </div>