Kunden & Lizenzen Fix
Dieser Commit ist enthalten in:
@@ -569,3 +569,25 @@ BEGIN
|
|||||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||||
END IF;
|
END IF;
|
||||||
END $$;
|
END $$;
|
||||||
|
|
||||||
|
|
||||||
|
-- Migration: Add device_type column to device_registrations table
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_name = 'device_registrations' AND column_name = 'device_type') THEN
|
||||||
|
ALTER TABLE device_registrations ADD COLUMN device_type VARCHAR(50) DEFAULT 'unknown';
|
||||||
|
|
||||||
|
-- Update existing records to have a device_type based on operating system
|
||||||
|
UPDATE device_registrations
|
||||||
|
SET device_type = CASE
|
||||||
|
WHEN operating_system ILIKE '%windows%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%mac%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%linux%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%android%' THEN 'mobile'
|
||||||
|
WHEN operating_system ILIKE '%ios%' THEN 'mobile'
|
||||||
|
ELSE 'unknown'
|
||||||
|
END
|
||||||
|
WHERE device_type IS NULL OR device_type = 'unknown';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
|
|||||||
20
v2_adminpanel/migrations/add_device_type.sql
Normale Datei
20
v2_adminpanel/migrations/add_device_type.sql
Normale Datei
@@ -0,0 +1,20 @@
|
|||||||
|
-- Migration: Add device_type column to device_registrations table
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_name = 'device_registrations' AND column_name = 'device_type') THEN
|
||||||
|
ALTER TABLE device_registrations ADD COLUMN device_type VARCHAR(50) DEFAULT 'unknown';
|
||||||
|
|
||||||
|
-- Update existing records to have a device_type based on operating system
|
||||||
|
UPDATE device_registrations
|
||||||
|
SET device_type = CASE
|
||||||
|
WHEN operating_system ILIKE '%windows%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%mac%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%linux%' THEN 'desktop'
|
||||||
|
WHEN operating_system ILIKE '%android%' THEN 'mobile'
|
||||||
|
WHEN operating_system ILIKE '%ios%' THEN 'mobile'
|
||||||
|
ELSE 'unknown'
|
||||||
|
END
|
||||||
|
WHERE device_type IS NULL OR device_type = 'unknown';
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
@@ -227,10 +227,12 @@ def get_license_devices(license_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
'license_key': license_data['license_key'],
|
'license_key': license_data['license_key'],
|
||||||
'device_limit': license_data['device_limit'],
|
'device_limit': license_data['device_limit'],
|
||||||
'devices': devices,
|
'devices': devices,
|
||||||
'device_count': len(devices)
|
'device_count': len(devices),
|
||||||
|
'active_count': len([d for d in devices if d['is_active']])
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -331,7 +333,7 @@ def deactivate_device(license_id, device_id):
|
|||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT dr.device_name, dr.hardware_id, l.license_key
|
SELECT dr.device_name, dr.hardware_id, l.license_key
|
||||||
FROM device_registrations dr
|
FROM device_registrations dr
|
||||||
JOIN licenses l ON dr.license_key = l.license_key
|
JOIN licenses l ON dr.license_id = l.id
|
||||||
WHERE dr.id = %s AND l.id = %s
|
WHERE dr.id = %s AND l.id = %s
|
||||||
""", (device_id, license_id))
|
""", (device_id, license_id))
|
||||||
|
|
||||||
@@ -398,7 +400,7 @@ def bulk_delete_licenses():
|
|||||||
cur.execute("DELETE FROM sessions WHERE license_key = %s", (license_key,))
|
cur.execute("DELETE FROM sessions WHERE license_key = %s", (license_key,))
|
||||||
|
|
||||||
# Lösche Geräte-Registrierungen
|
# Lösche Geräte-Registrierungen
|
||||||
cur.execute("DELETE FROM device_registrations WHERE license_key = %s", (license_key,))
|
cur.execute("DELETE FROM device_registrations WHERE license_id = %s", (license_id,))
|
||||||
|
|
||||||
# Lösche Lizenz
|
# Lösche Lizenz
|
||||||
cur.execute("DELETE FROM licenses WHERE id = %s", (license_id,))
|
cur.execute("DELETE FROM licenses WHERE id = %s", (license_id,))
|
||||||
@@ -543,6 +545,7 @@ def get_license_resources(license_id):
|
|||||||
grouped[res_type].append(resource)
|
grouped[res_type].append(resource)
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
'success': True,
|
||||||
'license_key': license_data['license_key'],
|
'license_key': license_data['license_key'],
|
||||||
'resources': resources,
|
'resources': resources,
|
||||||
'grouped': grouped,
|
'grouped': grouped,
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ def api_customer_licenses(customer_id):
|
|||||||
if not customer:
|
if not customer:
|
||||||
return jsonify({'error': 'Kunde nicht gefunden'}), 404
|
return jsonify({'error': 'Kunde nicht gefunden'}), 404
|
||||||
|
|
||||||
# Hole alle Lizenzen des Kunden
|
# Hole alle Lizenzen des Kunden - vereinfachte Version ohne komplexe Subqueries
|
||||||
cur.execute("""
|
cur.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
l.id,
|
l.id,
|
||||||
@@ -330,36 +330,18 @@ def api_customer_licenses(customer_id):
|
|||||||
l.valid_until,
|
l.valid_until,
|
||||||
l.device_limit,
|
l.device_limit,
|
||||||
l.created_at,
|
l.created_at,
|
||||||
(SELECT COUNT(*) FROM sessions s WHERE s.license_id = l.id AND s.is_active = true) as active_sessions,
|
|
||||||
(SELECT COUNT(DISTINCT hardware_id) FROM device_registrations dr WHERE dr.license_id = l.id) as registered_devices,
|
|
||||||
CASE
|
CASE
|
||||||
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
WHEN l.valid_until < CURRENT_DATE THEN 'abgelaufen'
|
||||||
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
WHEN l.valid_until < CURRENT_DATE + INTERVAL '30 days' THEN 'läuft bald ab'
|
||||||
WHEN l.is_active = false THEN 'inaktiv'
|
WHEN l.is_active = false THEN 'inaktiv'
|
||||||
ELSE 'aktiv'
|
ELSE 'aktiv'
|
||||||
END as status,
|
END as status,
|
||||||
-- License Server Status
|
COALESCE(l.domain_count, 0) as domain_count,
|
||||||
(SELECT COUNT(*) FROM license_heartbeats lh WHERE lh.license_id = l.id AND lh.timestamp > NOW() - INTERVAL '5 minutes') as recent_heartbeats,
|
COALESCE(l.ipv4_count, 0) as ipv4_count,
|
||||||
(SELECT MAX(timestamp) FROM license_heartbeats lh WHERE lh.license_id = l.id) as last_heartbeat,
|
COALESCE(l.phone_count, 0) as phone_count
|
||||||
(SELECT COUNT(DISTINCT hardware_id) FROM license_heartbeats lh WHERE lh.license_id = l.id AND lh.timestamp > NOW() - INTERVAL '15 minutes') as active_server_devices,
|
|
||||||
(SELECT COUNT(*) FROM anomaly_detections ad WHERE ad.license_id = l.id AND ad.resolved = false) as unresolved_anomalies,
|
|
||||||
l.domain_count,
|
|
||||||
l.ipv4_count,
|
|
||||||
l.phone_count,
|
|
||||||
(SELECT COUNT(*) FROM device_registrations WHERE license_id = l.id AND is_active = TRUE) as active_devices,
|
|
||||||
-- Actual resource counts
|
|
||||||
(SELECT COUNT(*) FROM license_resources lr
|
|
||||||
JOIN resource_pools rp ON lr.resource_id = rp.id
|
|
||||||
WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'domain') as actual_domain_count,
|
|
||||||
(SELECT COUNT(*) FROM license_resources lr
|
|
||||||
JOIN resource_pools rp ON lr.resource_id = rp.id
|
|
||||||
WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'ipv4') as actual_ipv4_count,
|
|
||||||
(SELECT COUNT(*) FROM license_resources lr
|
|
||||||
JOIN resource_pools rp ON lr.resource_id = rp.id
|
|
||||||
WHERE lr.license_id = l.id AND lr.is_active = true AND rp.resource_type = 'phone') as actual_phone_count
|
|
||||||
FROM licenses l
|
FROM licenses l
|
||||||
WHERE l.customer_id = %s
|
WHERE l.customer_id = %s
|
||||||
ORDER BY l.created_at DESC
|
ORDER BY l.created_at DESC, l.id DESC
|
||||||
""", (customer_id,))
|
""", (customer_id,))
|
||||||
|
|
||||||
licenses = []
|
licenses = []
|
||||||
@@ -404,28 +386,28 @@ def api_customer_licenses(customer_id):
|
|||||||
'id': row[0],
|
'id': row[0],
|
||||||
'license_key': row[1],
|
'license_key': row[1],
|
||||||
'license_type': row[2],
|
'license_type': row[2],
|
||||||
'is_active': row[3], # Korrigiert von 'is_active' zu 'is_active'
|
'is_active': row[3],
|
||||||
'is_test': row[4],
|
'is_test': row[4],
|
||||||
'valid_from': row[5].strftime('%Y-%m-%d') if row[5] else None,
|
'valid_from': row[5].strftime('%Y-%m-%d') if row[5] else None,
|
||||||
'valid_until': row[6].strftime('%Y-%m-%d') if row[6] else None,
|
'valid_until': row[6].strftime('%Y-%m-%d') if row[6] else None,
|
||||||
'device_limit': row[7],
|
'device_limit': row[7],
|
||||||
'created_at': row[8].strftime('%Y-%m-%d %H:%M:%S') if row[8] else None,
|
'created_at': row[8].strftime('%Y-%m-%d %H:%M:%S') if row[8] else None,
|
||||||
'active_sessions': row[9],
|
'status': row[9],
|
||||||
'registered_devices': row[10],
|
'domain_count': row[10],
|
||||||
'status': row[11],
|
'ipv4_count': row[11],
|
||||||
'domain_count': row[16],
|
'phone_count': row[12],
|
||||||
'ipv4_count': row[17],
|
'active_sessions': 0, # Platzhalter
|
||||||
'phone_count': row[18],
|
'registered_devices': 0, # Platzhalter
|
||||||
'active_devices': row[19],
|
'active_devices': 0, # Platzhalter
|
||||||
'actual_domain_count': row[20],
|
'actual_domain_count': len(resources['domains']),
|
||||||
'actual_ipv4_count': row[21],
|
'actual_ipv4_count': len(resources['ipv4s']),
|
||||||
'actual_phone_count': row[22],
|
'actual_phone_count': len(resources['phones']),
|
||||||
'resources': resources,
|
'resources': resources,
|
||||||
# License Server Data
|
# License Server Data (Platzhalter bis Implementation)
|
||||||
'recent_heartbeats': row[12],
|
'recent_heartbeats': 0,
|
||||||
'last_heartbeat': row[13].strftime('%Y-%m-%d %H:%M:%S') if row[13] else None,
|
'last_heartbeat': None,
|
||||||
'active_server_devices': row[14],
|
'active_server_devices': 0,
|
||||||
'unresolved_anomalies': row[15]
|
'unresolved_anomalies': 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@@ -439,8 +421,10 @@ def api_customer_licenses(customer_id):
|
|||||||
})
|
})
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Fehler beim Laden der Kundenlizenzen: {str(e)}")
|
import traceback
|
||||||
return jsonify({'error': 'Fehler beim Laden der Daten'}), 500
|
error_msg = f"Fehler beim Laden der Kundenlizenzen: {str(e)}\nTraceback: {traceback.format_exc()}"
|
||||||
|
logging.error(error_msg)
|
||||||
|
return jsonify({'error': f'Fehler beim Laden der Daten: {str(e)}', 'details': error_msg}), 500
|
||||||
finally:
|
finally:
|
||||||
cur.close()
|
cur.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
In neuem Issue referenzieren
Einen Benutzer sperren