Gerätelimit drin

Dieser Commit ist enthalten in:
2025-06-11 01:13:40 +02:00
Ursprung 4b66d8b4b4
Commit a878d9b29c
9 geänderte Dateien mit 549 neuen und 19 gelöschten Zeilen

Datei anzeigen

@@ -1485,6 +1485,7 @@ def create_license():
domain_count = int(request.form.get("domain_count", 1))
ipv4_count = int(request.form.get("ipv4_count", 1))
phone_count = int(request.form.get("phone_count", 1))
device_limit = int(request.form.get("device_limit", 3))
conn = get_connection()
cur = conn.cursor()
@@ -1536,11 +1537,11 @@ def create_license():
# Lizenz hinzufügen
cur.execute("""
INSERT INTO licenses (license_key, customer_id, license_type, valid_from, valid_until, is_active,
domain_count, ipv4_count, phone_count, is_test)
VALUES (%s, %s, %s, %s, %s, TRUE, %s, %s, %s, %s)
domain_count, ipv4_count, phone_count, device_limit, is_test)
VALUES (%s, %s, %s, %s, %s, TRUE, %s, %s, %s, %s, %s)
RETURNING id
""", (license_key, customer_id, license_type, valid_from, valid_until,
domain_count, ipv4_count, phone_count, is_test))
domain_count, ipv4_count, phone_count, device_limit, is_test))
license_id = cur.fetchone()[0]
# Ressourcen zuweisen
@@ -1652,6 +1653,7 @@ def create_license():
'license_type': license_type,
'valid_from': valid_from,
'valid_until': valid_until,
'device_limit': device_limit,
'is_test': is_test
})
@@ -1711,6 +1713,7 @@ def batch_licenses():
domain_count = int(request.form.get("domain_count", 1))
ipv4_count = int(request.form.get("ipv4_count", 1))
phone_count = int(request.form.get("phone_count", 1))
device_limit = int(request.form.get("device_limit", 3))
# Sicherheitslimit
if quantity < 1 or quantity > 100:
@@ -1803,11 +1806,11 @@ def batch_licenses():
cur.execute("""
INSERT INTO licenses (license_key, customer_id, license_type, is_test,
valid_from, valid_until, is_active,
domain_count, ipv4_count, phone_count)
VALUES (%s, %s, %s, %s, %s, %s, true, %s, %s, %s)
domain_count, ipv4_count, phone_count, device_limit)
VALUES (%s, %s, %s, %s, %s, %s, true, %s, %s, %s, %s)
RETURNING id
""", (license_key, customer_id, license_type, is_test, valid_from, valid_until,
domain_count, ipv4_count, phone_count))
domain_count, ipv4_count, phone_count, device_limit))
license_id = cur.fetchone()[0]
# Ressourcen für diese Lizenz zuweisen
@@ -1983,7 +1986,7 @@ def edit_license(license_id):
if request.method == "POST":
# Alte Werte für Audit-Log abrufen
cur.execute("""
SELECT license_key, license_type, valid_from, valid_until, is_active, is_test
SELECT license_key, license_type, valid_from, valid_until, is_active, is_test, device_limit
FROM licenses WHERE id = %s
""", (license_id,))
old_license = cur.fetchone()
@@ -1995,13 +1998,14 @@ def edit_license(license_id):
valid_until = request.form["valid_until"]
is_active = request.form.get("is_active") == "on"
is_test = request.form.get("is_test") == "on"
device_limit = int(request.form.get("device_limit", 3))
cur.execute("""
UPDATE licenses
SET license_key = %s, license_type = %s, valid_from = %s,
valid_until = %s, is_active = %s, is_test = %s
valid_until = %s, is_active = %s, is_test = %s, device_limit = %s
WHERE id = %s
""", (license_key, license_type, valid_from, valid_until, is_active, is_test, license_id))
""", (license_key, license_type, valid_from, valid_until, is_active, is_test, device_limit, license_id))
conn.commit()
@@ -2013,7 +2017,8 @@ def edit_license(license_id):
'valid_from': str(old_license[2]),
'valid_until': str(old_license[3]),
'is_active': old_license[4],
'is_test': old_license[5]
'is_test': old_license[5],
'device_limit': old_license[6]
},
new_values={
'license_key': license_key,
@@ -2021,7 +2026,8 @@ def edit_license(license_id):
'valid_from': valid_from,
'valid_until': valid_until,
'is_active': is_active,
'is_test': is_test
'is_test': is_test,
'device_limit': device_limit
})
cur.close()
@@ -2048,7 +2054,7 @@ def edit_license(license_id):
# Get license data
cur.execute("""
SELECT l.id, l.license_key, c.name, c.email, l.license_type,
l.valid_from, l.valid_until, l.is_active, c.id, l.is_test
l.valid_from, l.valid_until, l.is_active, c.id, l.is_test, l.device_limit
FROM licenses l
JOIN customers c ON l.customer_id = c.id
WHERE l.id = %s
@@ -2343,7 +2349,9 @@ def customers_licenses():
END as status,
l.domain_count,
l.ipv4_count,
l.phone_count
l.phone_count,
l.device_limit,
(SELECT COUNT(*) FROM device_registrations WHERE license_id = l.id AND is_active = TRUE) as active_devices
FROM licenses l
WHERE l.customer_id = %s
ORDER BY l.created_at DESC, l.id DESC
@@ -2384,7 +2392,9 @@ def api_customer_licenses(customer_id):
END as status,
l.domain_count,
l.ipv4_count,
l.phone_count
l.phone_count,
l.device_limit,
(SELECT COUNT(*) FROM device_registrations WHERE license_id = l.id AND is_active = TRUE) as active_devices
FROM licenses l
WHERE l.customer_id = %s
ORDER BY l.created_at DESC, l.id DESC
@@ -2434,6 +2444,8 @@ def api_customer_licenses(customer_id):
'domain_count': row[7],
'ipv4_count': row[8],
'phone_count': row[9],
'device_limit': row[10],
'active_devices': row[11],
'resources': resources
})
@@ -3711,6 +3723,218 @@ def bulk_deactivate_licenses():
except Exception as e:
return jsonify({'success': False, 'message': str(e)}), 500
@app.route("/api/license/<int:license_id>/devices")
@login_required
def get_license_devices(license_id):
"""Hole alle registrierten Geräte einer Lizenz"""
try:
conn = get_connection()
cur = conn.cursor()
# Prüfe ob Lizenz existiert und hole device_limit
cur.execute("""
SELECT device_limit FROM licenses WHERE id = %s
""", (license_id,))
license_data = cur.fetchone()
if not license_data:
return jsonify({'success': False, 'message': 'Lizenz nicht gefunden'}), 404
device_limit = license_data[0]
# Hole alle Geräte für diese Lizenz
cur.execute("""
SELECT id, hardware_id, device_name, operating_system,
first_seen, last_seen, is_active, ip_address
FROM device_registrations
WHERE license_id = %s
ORDER BY is_active DESC, last_seen DESC
""", (license_id,))
devices = []
for row in cur.fetchall():
devices.append({
'id': row[0],
'hardware_id': row[1],
'device_name': row[2] or 'Unbekanntes Gerät',
'operating_system': row[3] or 'Unbekannt',
'first_seen': row[4].strftime('%d.%m.%Y %H:%M') if row[4] else '',
'last_seen': row[5].strftime('%d.%m.%Y %H:%M') if row[5] else '',
'is_active': row[6],
'ip_address': row[7] or '-'
})
cur.close()
conn.close()
return jsonify({
'success': True,
'devices': devices,
'device_limit': device_limit,
'active_count': sum(1 for d in devices if d['is_active'])
})
except Exception as e:
logging.error(f"Fehler beim Abrufen der Geräte: {str(e)}")
return jsonify({'success': False, 'message': 'Fehler beim Abrufen der Geräte'}), 500
@app.route("/api/license/<int:license_id>/register-device", methods=["POST"])
def register_device(license_id):
"""Registriere ein neues Gerät für eine Lizenz"""
try:
data = request.get_json()
hardware_id = data.get('hardware_id')
device_name = data.get('device_name', '')
operating_system = data.get('operating_system', '')
if not hardware_id:
return jsonify({'success': False, 'message': 'Hardware-ID fehlt'}), 400
conn = get_connection()
cur = conn.cursor()
# Prüfe ob Lizenz existiert und aktiv ist
cur.execute("""
SELECT device_limit, is_active, valid_until
FROM licenses
WHERE id = %s
""", (license_id,))
license_data = cur.fetchone()
if not license_data:
return jsonify({'success': False, 'message': 'Lizenz nicht gefunden'}), 404
device_limit, is_active, valid_until = license_data
# Prüfe ob Lizenz aktiv und gültig ist
if not is_active:
return jsonify({'success': False, 'message': 'Lizenz ist deaktiviert'}), 403
if valid_until < datetime.now(ZoneInfo("Europe/Berlin")).date():
return jsonify({'success': False, 'message': 'Lizenz ist abgelaufen'}), 403
# Prüfe ob Gerät bereits registriert ist
cur.execute("""
SELECT id, is_active FROM device_registrations
WHERE license_id = %s AND hardware_id = %s
""", (license_id, hardware_id))
existing_device = cur.fetchone()
if existing_device:
device_id, is_device_active = existing_device
if is_device_active:
# Gerät ist bereits aktiv, update last_seen
cur.execute("""
UPDATE device_registrations
SET last_seen = CURRENT_TIMESTAMP,
ip_address = %s,
user_agent = %s
WHERE id = %s
""", (get_client_ip(), request.headers.get('User-Agent', ''), device_id))
conn.commit()
return jsonify({'success': True, 'message': 'Gerät bereits registriert', 'device_id': device_id})
else:
# Gerät war deaktiviert, prüfe ob wir es reaktivieren können
cur.execute("""
SELECT COUNT(*) FROM device_registrations
WHERE license_id = %s AND is_active = TRUE
""", (license_id,))
active_count = cur.fetchone()[0]
if active_count >= device_limit:
return jsonify({'success': False, 'message': f'Gerätelimit erreicht ({device_limit} Geräte)'}), 403
# Reaktiviere das Gerät
cur.execute("""
UPDATE device_registrations
SET is_active = TRUE,
last_seen = CURRENT_TIMESTAMP,
deactivated_at = NULL,
deactivated_by = NULL,
ip_address = %s,
user_agent = %s
WHERE id = %s
""", (get_client_ip(), request.headers.get('User-Agent', ''), device_id))
conn.commit()
return jsonify({'success': True, 'message': 'Gerät reaktiviert', 'device_id': device_id})
# Neues Gerät - prüfe Gerätelimit
cur.execute("""
SELECT COUNT(*) FROM device_registrations
WHERE license_id = %s AND is_active = TRUE
""", (license_id,))
active_count = cur.fetchone()[0]
if active_count >= device_limit:
return jsonify({'success': False, 'message': f'Gerätelimit erreicht ({device_limit} Geräte)'}), 403
# Registriere neues Gerät
cur.execute("""
INSERT INTO device_registrations
(license_id, hardware_id, device_name, operating_system, ip_address, user_agent)
VALUES (%s, %s, %s, %s, %s, %s)
RETURNING id
""", (license_id, hardware_id, device_name, operating_system,
get_client_ip(), request.headers.get('User-Agent', '')))
device_id = cur.fetchone()[0]
conn.commit()
# Audit Log
log_audit('DEVICE_REGISTER', 'device', device_id,
new_values={'license_id': license_id, 'hardware_id': hardware_id})
cur.close()
conn.close()
return jsonify({'success': True, 'message': 'Gerät erfolgreich registriert', 'device_id': device_id})
except Exception as e:
logging.error(f"Fehler bei Geräte-Registrierung: {str(e)}")
return jsonify({'success': False, 'message': 'Fehler bei der Registrierung'}), 500
@app.route("/api/license/<int:license_id>/deactivate-device/<int:device_id>", methods=["POST"])
@login_required
def deactivate_device(license_id, device_id):
"""Deaktiviere ein registriertes Gerät"""
try:
conn = get_connection()
cur = conn.cursor()
# Prüfe ob das Gerät zu dieser Lizenz gehört
cur.execute("""
SELECT id FROM device_registrations
WHERE id = %s AND license_id = %s AND is_active = TRUE
""", (device_id, license_id))
if not cur.fetchone():
return jsonify({'success': False, 'message': 'Gerät nicht gefunden oder bereits deaktiviert'}), 404
# Deaktiviere das Gerät
cur.execute("""
UPDATE device_registrations
SET is_active = FALSE,
deactivated_at = CURRENT_TIMESTAMP,
deactivated_by = %s
WHERE id = %s
""", (session['username'], device_id))
conn.commit()
# Audit Log
log_audit('DEVICE_DEACTIVATE', 'device', device_id,
old_values={'is_active': True},
new_values={'is_active': False})
cur.close()
conn.close()
return jsonify({'success': True, 'message': 'Gerät erfolgreich deaktiviert'})
except Exception as e:
logging.error(f"Fehler beim Deaktivieren des Geräts: {str(e)}")
return jsonify({'success': False, 'message': 'Fehler beim Deaktivieren'}), 500
@app.route("/api/licenses/bulk-delete", methods=["POST"])
@login_required
def bulk_delete_licenses():