lizenzserver API gedöns

Dieser Commit ist enthalten in:
2025-06-22 00:53:05 +02:00
Ursprung 6d1577c989
Commit b420452551
8 geänderte Dateien mit 914 neuen und 195 gelöschten Zeilen

Datei anzeigen

@@ -931,6 +931,31 @@ def license_config():
conn = get_connection()
cur = conn.cursor()
# Get client configuration
cur.execute("""
SELECT id, client_name, api_key, heartbeat_interval, session_timeout,
current_version, minimum_version, download_url, whats_new,
created_at, updated_at
FROM client_configs
WHERE client_name = 'Account Forger'
""")
client_config = cur.fetchone()
# Get active sessions
cur.execute("""
SELECT ls.id, ls.session_token, l.license_key, c.name as customer_name,
ls.hardware_id, ls.ip_address, ls.client_version,
ls.started_at AT TIME ZONE 'Europe/Berlin' as started_at,
ls.last_heartbeat AT TIME ZONE 'Europe/Berlin' as last_heartbeat,
EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - ls.last_heartbeat)) as seconds_since_heartbeat
FROM license_sessions ls
JOIN licenses l ON ls.license_id = l.id
LEFT JOIN customers c ON l.customer_id = c.id
ORDER BY ls.last_heartbeat DESC
LIMIT 5
""")
active_sessions = cur.fetchall()
# Get feature flags
cur.execute("""
SELECT * FROM feature_flags
@@ -938,14 +963,6 @@ def license_config():
""")
feature_flags = cur.fetchall()
# Get API clients
cur.execute("""
SELECT id, client_name, api_key, is_active, created_at
FROM api_clients
ORDER BY created_at DESC
""")
api_clients = cur.fetchall()
# Get rate limits
cur.execute("""
SELECT * FROM api_rate_limits
@@ -954,8 +971,9 @@ def license_config():
rate_limits = cur.fetchall()
return render_template('license_config.html',
client_config=client_config,
active_sessions=active_sessions,
feature_flags=feature_flags,
api_clients=api_clients,
rate_limits=rate_limits
)
@@ -1006,6 +1024,174 @@ def update_feature_flag(flag_id):
return redirect(url_for('admin.license_config'))
@admin_bp.route("/lizenzserver/config/update", methods=["POST"])
@login_required
def update_client_config():
"""Update client configuration"""
if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
flash('Zugriff verweigert', 'error')
return redirect(url_for('admin.dashboard'))
try:
conn = get_connection()
cur = conn.cursor()
# Update configuration
cur.execute("""
UPDATE client_configs
SET current_version = %s,
minimum_version = %s,
download_url = %s,
whats_new = %s,
heartbeat_interval = %s,
session_timeout = %s,
updated_at = CURRENT_TIMESTAMP
WHERE client_name = 'Account Forger'
""", (
request.form.get('current_version'),
request.form.get('minimum_version'),
'', # download_url - no longer used
'', # whats_new - no longer used
30, # heartbeat_interval - fixed
60 # session_timeout - fixed
))
conn.commit()
flash('Client-Konfiguration wurde aktualisiert', 'success')
# Log action
log_action(
username=session.get('username'),
action='UPDATE',
entity_type='client_config',
entity_id=1,
new_values={
'current_version': request.form.get('current_version'),
'minimum_version': request.form.get('minimum_version')
}
)
except Exception as e:
flash(f'Fehler beim Aktualisieren: {str(e)}', 'error')
finally:
if 'cur' in locals():
cur.close()
if 'conn' in locals():
conn.close()
return redirect(url_for('admin.license_config'))
@admin_bp.route("/lizenzserver/sessions")
@login_required
def license_sessions():
"""Show active license sessions"""
try:
conn = get_connection()
cur = conn.cursor()
# Get active sessions
cur.execute("""
SELECT ls.id, ls.session_token, l.license_key, c.name as customer_name,
ls.hardware_id, ls.ip_address, ls.client_version,
ls.started_at AT TIME ZONE 'Europe/Berlin' as started_at,
ls.last_heartbeat AT TIME ZONE 'Europe/Berlin' as last_heartbeat,
EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - ls.last_heartbeat)) as seconds_since_heartbeat
FROM license_sessions ls
JOIN licenses l ON ls.license_id = l.id
LEFT JOIN customers c ON l.customer_id = c.id
ORDER BY ls.last_heartbeat DESC
""")
sessions = cur.fetchall()
# Get session history (last 24h)
cur.execute("""
SELECT sh.id, l.license_key, c.name as customer_name,
sh.hardware_id, sh.ip_address, sh.client_version,
sh.started_at AT TIME ZONE 'Europe/Berlin' as started_at,
sh.ended_at AT TIME ZONE 'Europe/Berlin' as ended_at,
sh.end_reason,
EXTRACT(EPOCH FROM (sh.ended_at - sh.started_at)) as duration_seconds
FROM session_history sh
JOIN licenses l ON sh.license_id = l.id
LEFT JOIN customers c ON l.customer_id = c.id
WHERE sh.ended_at > CURRENT_TIMESTAMP - INTERVAL '24 hours'
ORDER BY sh.ended_at DESC
LIMIT 100
""")
history = cur.fetchall()
return render_template('license_sessions.html',
active_sessions=sessions,
session_history=history)
except Exception as e:
flash(f'Fehler beim Laden der Sessions: {str(e)}', 'error')
return render_template('license_sessions.html')
finally:
if 'cur' in locals():
cur.close()
if 'conn' in locals():
conn.close()
@admin_bp.route("/lizenzserver/sessions/<int:session_id>/terminate", methods=["POST"])
@login_required
def terminate_session(session_id):
"""Force terminate a session"""
if session.get('username') not in ['rac00n', 'w@rh@mm3r']:
flash('Zugriff verweigert', 'error')
return redirect(url_for('admin.license_sessions'))
try:
conn = get_connection()
cur = conn.cursor()
# Get session info
cur.execute("""
SELECT license_id, hardware_id, ip_address, client_version, started_at
FROM license_sessions
WHERE id = %s
""", (session_id,))
session_info = cur.fetchone()
if session_info:
# Log to history
cur.execute("""
INSERT INTO session_history
(license_id, hardware_id, ip_address, client_version, started_at, ended_at, end_reason)
VALUES (%s, %s, %s, %s, %s, CURRENT_TIMESTAMP, 'forced')
""", session_info)
# Delete session
cur.execute("DELETE FROM license_sessions WHERE id = %s", (session_id,))
conn.commit()
flash('Session wurde beendet', 'success')
# Log action
log_action(
username=session.get('username'),
action='TERMINATE_SESSION',
entity_type='license_session',
entity_id=session_id,
additional_info={'hardware_id': session_info[1]}
)
else:
flash('Session nicht gefunden', 'error')
except Exception as e:
flash(f'Fehler beim Beenden der Session: {str(e)}', 'error')
finally:
if 'cur' in locals():
cur.close()
if 'conn' in locals():
conn.close()
return redirect(url_for('admin.license_sessions'))
@admin_bp.route("/api/admin/lizenzserver/live-stats")
@login_required
def license_live_stats():
@@ -1024,27 +1210,36 @@ def license_live_stats():
""")
stats = cur.fetchone()
# Get latest validations
# Get active sessions count
cur.execute("""
SELECT l.license_key, lh.hardware_id, lh.ip_address, lh.timestamp
FROM license_heartbeats lh
JOIN licenses l ON lh.license_id = l.id
ORDER BY lh.timestamp DESC
SELECT COUNT(*) FROM license_sessions
""")
active_count = cur.fetchone()[0]
# Get latest sessions
cur.execute("""
SELECT ls.id, l.license_key, c.name as customer_name,
ls.client_version, ls.last_heartbeat AT TIME ZONE 'Europe/Berlin' as last_heartbeat,
EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - ls.last_heartbeat)) as seconds_since
FROM license_sessions ls
JOIN licenses l ON ls.license_id = l.id
LEFT JOIN customers c ON l.customer_id = c.id
ORDER BY ls.last_heartbeat DESC
LIMIT 5
""")
latest_validations = cur.fetchall()
latest_sessions = cur.fetchall()
return jsonify({
'active_licenses': stats[0] or 0,
'active_licenses': active_count,
'validations_per_minute': stats[1] or 0,
'active_devices': stats[2] or 0,
'latest_validations': [
'latest_sessions': [
{
'license_key': v[0][:8] + '...',
'hardware_id': v[1][:8] + '...',
'ip_address': v[2] or 'Unknown',
'timestamp': v[3].strftime('%H:%M:%S')
} for v in latest_validations
'customer_name': s[2],
'version': s[3],
'last_heartbeat': s[4].strftime('%H:%M:%S'),
'seconds_since': int(s[5])
} for s in latest_sessions
]
})