prepare('INSERT INTO license_products (slug, name, default_cache_ttl_hours, notes) VALUES (:s, :n, :t, :notes)');
$stmt->execute([':s' => $slug, ':n' => $name, ':t' => $ttl, ':notes' => $notes]);
$msg = "Produkt '{$name}' (Slug: {$slug}) wurde erfolgreich angelegt.";
} catch (Throwable $e) {
$msg = "Fehler beim Erstellen des Produkts: " . $e->getMessage();
$msgType = 'danger';
}
}
}
// Create License Key
if ($action === 'create_license') {
$productId = (int)($_POST['product_id'] ?? 0);
$customerName = trim($_POST['customer_name'] ?? '');
$customerEmail = trim($_POST['customer_email'] ?? '');
$maxActivations = (int)($_POST['max_activations'] ?? 2);
$expiresAt = !empty($_POST['expires_at']) ? $_POST['expires_at'] . ' 23:59:59' : null;
$notes = trim($_POST['notes'] ?? '');
if ($productId > 0) {
$licenseKey = KeyGen::generateKey();
try {
$stmt = $pdo->prepare('
INSERT INTO license_licenses (product_id, license_key, customer_name, customer_email, max_activations, expires_at, notes)
VALUES (:pid, :key, :cname, :cemail, :max, :exp, :notes)
');
$stmt->execute([
':pid' => $productId,
':key' => $licenseKey,
':cname' => $customerName,
':cemail' => $customerEmail,
':max' => $maxActivations,
':exp' => $expiresAt,
':notes' => $notes
]);
// Audit log
$pdo->prepare('INSERT INTO license_audit_log (actor, action, details) VALUES ("admin", "license.create", :d)')
->execute([':d' => json_encode(['key' => $licenseKey, 'customer' => $customerName])]);
$msg = "Lizenzschlüssel erfolgreich generiert: {$licenseKey} ";
} catch (Throwable $e) {
$msg = "Fehler bei Generierung: " . $e->getMessage();
$msgType = 'danger';
}
}
}
// Revoke License
if ($action === 'revoke_license') {
$licId = (int)($_POST['license_id'] ?? 0);
if ($licId > 0) {
$stmt = $pdo->prepare('UPDATE license_licenses SET status = "revoked" WHERE id = :id');
$stmt->execute([':id' => $licId]);
$pdo->prepare('INSERT INTO license_audit_log (actor, action, details) VALUES ("admin", "license.revoke", :d)')
->execute([':d' => json_encode(['license_id' => $licId])]);
$msg = "Lizenz wurde widerrufen.";
}
}
// Block / Unblock Hardware Activation
if ($action === 'toggle_block_activation') {
$actId = (int)($_POST['activation_id'] ?? 0);
$block = (int)($_POST['block_state'] ?? 0);
if ($actId > 0) {
$stmt = $pdo->prepare('UPDATE license_activations SET is_blocked = :b WHERE id = :id');
$stmt->execute([':b' => $block, ':id' => $actId]);
$msg = $block ? "Hardware-Aktivierung wurde gesperrt." : "Hardware-Aktivierung wurde entsperrt.";
}
}
// Extend License Expiration
if ($action === 'extend_license') {
$licId = (int)($_POST['license_id'] ?? 0);
$newExp = !empty($_POST['new_expires_at']) ? $_POST['new_expires_at'] . ' 23:59:59' : null;
if ($licId > 0) {
$stmt = $pdo->prepare('UPDATE license_licenses SET expires_at = :exp, status = "active" WHERE id = :id');
$stmt->execute([':exp' => $newExp, ':id' => $licId]);
$msg = "Ablaufdatum der Lizenz wurde aktualisiert.";
}
}
// Create Agent Token (Watchdog)
if ($action === 'create_agent_token') {
$source = trim($_POST['token_source'] ?? '');
$name = trim($_POST['token_name'] ?? '');
if ($name) {
$tokMgr = new TokenManager($pdo);
$res = $tokMgr->createToken($source, $name);
$msg = "Agent-Token für '{$name}' generiert: {$res['raw_token']} (Bitte sicher aufbewahren!)";
}
}
// Revoke Agent Token
if ($action === 'revoke_agent_token') {
$tokId = trim($_POST['token_id'] ?? '');
if ($tokId) {
$stmt = $pdo->prepare('UPDATE watchdog_agent_tokens SET revoked = 1 WHERE token_id = :id');
$stmt->execute([':id' => $tokId]);
$msg = "Agent-Token wurde widerrufen.";
}
}
// Add Update Release
if ($action === 'add_release') {
$productSlug = trim($_POST['product_slug'] ?? '');
$version = trim($_POST['version'] ?? '');
$url = trim($_POST['download_url'] ?? '');
$hash = trim($_POST['sha256_hash'] ?? '');
$notes = trim($_POST['release_notes'] ?? '');
$critical = isset($_POST['is_critical']);
if ($productSlug && $version && $url) {
$updMgr = new UpdateManager($pdo);
if ($updMgr->addRelease($productSlug, $version, $notes, $url, $hash, $critical)) {
$msg = "Release v{$version} für '{$productSlug}' gespeichert.";
} else {
$msg = "Fehler beim Speichern des Releases.";
$msgType = 'danger';
}
}
}
}
// Fetch all Data
$products = $pdo->query('SELECT * FROM license_products ORDER BY name ASC')->fetchAll();
$licenses = $pdo->query('
SELECT l.*, p.name as product_name, p.slug as product_slug,
(SELECT COUNT(*) FROM license_activations a WHERE a.license_id = l.id) as active_count
FROM license_licenses l
JOIN license_products p ON l.product_id = p.id
ORDER BY l.created_at DESC
')->fetchAll();
$activations = $pdo->query('
SELECT a.*, l.license_key, p.slug as product_slug, p.name as product_name
FROM license_activations a
JOIN license_licenses l ON a.license_id = l.id
JOIN license_products p ON l.product_id = p.id
ORDER BY a.last_seen DESC
')->fetchAll();
$auditLogs = $pdo->query('SELECT * FROM license_audit_log ORDER BY created_at DESC LIMIT 100')->fetchAll();
$monitorRepo = new MonitorRepo($pdo);
$monitors = $monitorRepo->getAllMonitors();
$monitorsUp = 0; $monitorsWarning = 0; $monitorsDown = 0;
foreach ($monitors as $m) {
if ($m['state'] === 'up') $monitorsUp++;
elseif ($m['state'] === 'warning') $monitorsWarning++;
else $monitorsDown++;
}
$eventLog = new EventLog($pdo);
$recentEvents = $eventLog->getRecentEvents(100);
$agentTokens = $pdo->query('SELECT * FROM watchdog_agent_tokens ORDER BY created_at_utc DESC')->fetchAll();
$updateMgr = new UpdateManager($pdo);
$releases = $updateMgr->getReleases();
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'] ?? 'dc.mhdf.de';
$baseUrl = $protocol . '://' . $host;
?>
Deploymentcenter - Central Platform
= $msg ?>
Globales Plattform Dashboard
Letzte Aktualisierung: = date('H:i:s') ?> Uhr
= $monitorsUp ?> /
= $monitorsWarning ?> /
= $monitorsDown ?>
Source / Instanz
Typ
Gruppe
Status
Letzte Meldung
Zuletzt Gesehen
= htmlspecialchars($m['source']) ?> (= htmlspecialchars($m['instance']) ?>)
= htmlspecialchars($m['type']) ?>
= htmlspecialchars($m['group_key'] ?? 'Default') ?>
● = strtoupper($m['state']) ?>
= htmlspecialchars($m['last_message'] ?? '-') ?>
= htmlspecialchars($m['last_seen_utc'] ?? 'Nie') ?>
📊 Dashboard
📦 Produkte
🔑 Lizenzen
🔍 Lizenz-Details
💾 Offline-Lizenzen
📜 Audit-Log
💻 Integration & Prompts
⚙️ Einstellungen
= count(array_filter($licenses, fn($l) => $l['status'] === 'active')) ?>
ID
Slug
Produkt Name
Cache TTL
Erstellt am
= $p['id'] ?>
= htmlspecialchars($p['slug']) ?>
= htmlspecialchars($p['name']) ?>
= $p['default_cache_ttl_hours'] ?> h (= round($p['default_cache_ttl_hours']/24, 1) ?> Tage)
= $p['created_at'] ?>
Produkt
Lizenzschlüssel
Kunde
Aktivierungen
Status
Ablaufdatum
Aktionen
= htmlspecialchars($l['product_name']) ?>
= htmlspecialchars($l['license_key']) ?>
= htmlspecialchars($l['customer_name'] ?? '-') ?>
= $l['active_count'] ?> / = $l['max_activations'] ?>
= strtoupper($l['status']) ?>
= $l['expires_at'] ? htmlspecialchars($l['expires_at']) : 'Unbefristet' ?>
Produkt
Lizenzschlüssel
Hardware-ID
Hostname
App-Version
Zuletzt gesehen
Sperr-Status
Aktion
= htmlspecialchars($a['product_name']) ?>
= htmlspecialchars($a['license_key']) ?>
= htmlspecialchars($a['hardware_id']) ?>
= htmlspecialchars($a['hostname'] ?? '-') ?>
= htmlspecialchars($a['app_version'] ?? '-') ?>
= htmlspecialchars($a['last_seen']) ?>
GESPERRT
AKTIV
Generiert eine verschlüsselte/signierte .lic Offline-Lizenzdatei für Air-Gapped Kundensysteme ohne Internetverbindung.
Offline Payload Generieren
Generierte Offline .lic Payload (JSON)
Wählen Sie oben eine Lizenz aus und klicken Sie auf 'Offline Payload Generieren'.
ID
Zeitpunkt
Akteur
Aktion
Details
= $log['id'] ?>
= $log['created_at'] ?>
= htmlspecialchars($log['actor']) ?>
= htmlspecialchars($log['action']) ?>
= htmlspecialchars($log['details'] ?? '-') ?>
Kopieren Sie diese vorgefertigten Prompts und übergeben Sie sie Ihrem KI-Coding-Assistenten (GitHub Copilot, Antigravity, ChatGPT), um die Lizenzprüfung in Ihre Anwendungen einzubauen:
C# / .NET Project Prompt
Ich möchte mein C# / .NET Projekt mit dem LicenseLabrador Modul des Deploymentcenters verbinden.
Server-Konfiguration:
- Base API URL: = $baseUrl ?>/api/license/v1
- Endpunkte: /validate (POST), /deactivate (POST)
- Produkt-Slug: myapp
Anforderungen:
1. Erstelle eine C# Klasse `LicenseValidator.cs`.
2. Sende beim Anwendungsstart einen POST-Request an `= $baseUrl ?>/api/license/v1/validate` mit JSON:
{ "product": "myapp", "license_key": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", "hardware_id": getHardwareId(), "nonce": Guid.NewGuid().ToString() }
3. Werte den Status aus ("valid", "revoked", "expired", "activation_limit").
4. Bei Server-Unerreichbarkeit: Erlaube Offline-Nutzung innerhalb des Cache-TTL Zeitraums.
📋 Prompt Kopieren (C#)
Python Project Prompt
Ich möchte meine Python-Anwendung mit dem LicenseLabrador Modul des Deploymentcenters verbinden.
Server URL: = $baseUrl ?>/api/license/v1/validate
Anforderungen:
- Erstelle ein Python-Skript `license_checker.py`.
- Generiere die Machine-GUID / Hardware-ID.
- Sende einen HTTP POST im JSON-Format mit `product`, `license_key`, `hardware_id`, `nonce`.
- Binde eine lokale Fallback-Logik bei Offline-Zeiten ein.
📋 Prompt Kopieren (Python)
📊 Dashboard
⏱️ Uptime Monitor
⚙️ Services
💻 Applications
🖥️ Machines
☁️ Hypervisors
📜 Event-Log
🔑 Agent-Tokens
💻 Integration & Prompts
= htmlspecialchars($m['source']) ?> (= htmlspecialchars($m['os'] ?? 'Host') ?>)
= strtoupper($m['state']) ?>
CPU Auslastung = $metrics['cpu'] ?? 0 ?>%
= $pct ? (($metrics['cpu']??0)>85?'filled-crit':(($metrics['cpu']??0)>70?'filled-warn':'filled-ok')) : ''; ?>
RAM Auslastung = $metrics['ram'] ?? 0 ?>%
= $pct ? (($metrics['ram']??0)>85?'filled-crit':(($metrics['ram']??0)>70?'filled-warn':'filled-ok')) : ''; ?>
Monitor
Gruppe
Erwartetes Intervall
Status
Zuletzt Gesehen
= htmlspecialchars($m['source']) ?>
= htmlspecialchars($m['group_key'] ?? 'Default') ?>
Alle = $m['expected_interval_sec'] ?>s
= strtoupper($m['state']) ?>
= htmlspecialchars($m['last_seen_utc'] ?? 'Nie') ?>
Dienst-Name
Gruppe
Status
Letzte Meldung
$m['group_key'] === 'Services') as $m): ?>
= htmlspecialchars($m['source']) ?>
= htmlspecialchars($m['group_key']) ?>
= strtoupper($m['state']) ?>
= htmlspecialchars($m['last_message'] ?? '-') ?>
Anwendung
Umgebung / OS
Status
Letztes Signal
$m['group_key'] === 'Applications') as $m): ?>
= htmlspecialchars($m['source']) ?>
= htmlspecialchars($m['os'] ?? '.NET') ?>
ONLINE
= htmlspecialchars($m['last_seen_utc']) ?>
Host Name
Betriebssystem
Status
CPU / RAM Snapshot
$m['type'] === 'host') as $m): ?>
= htmlspecialchars($m['source']) ?>
= htmlspecialchars($m['os'] ?? 'Linux/Windows') ?>
ONLINE
CPU: = $metrics['cpu'] ?? 0 ?>% | RAM: = $metrics['ram'] ?? 0 ?>%
Node / Guest
Typ
Zugehöriger Node
Status
in_array($m['type'], ['hypervisor_node', 'guest'])) as $m): ?>
= htmlspecialchars($m['source']) ?>
= htmlspecialchars($m['type']) ?>
= htmlspecialchars($m['group_key'] ?? '-') ?>
= strtoupper($m['state']) ?>
Zeitpunkt (UTC)
Source
Kind
Severity
Nachricht
= htmlspecialchars($e['at_utc']) ?>
= htmlspecialchars($e['source']) ?>
= htmlspecialchars($e['kind']) ?>
= strtoupper($e['severity']) ?>
= htmlspecialchars($e['message'] ?? '-') ?>
Token ID
Bezeichnung
Gebundene Source
Erstellt am
Status
Aktion
= htmlspecialchars($tok['token_id']) ?>
= htmlspecialchars($tok['name']) ?>
= htmlspecialchars($tok['monitor_source'] ?? 'Alle Sources') ?>
= htmlspecialchars($tok['created_at_utc']) ?>
= $tok['revoked'] ? 'WIDERUFEN' : 'AKTIV' ?>
C# Background Service Heartbeat Prompt
Ich möchte in meinem C# .NET Worker Service einen Watchdog-Heartbeat einbauen.
Ping-URL: = $baseUrl ?>/api/watchdog/v1/ping
HTTP Method: POST
JSON-Payload:
{
"source": "MyWorkerService",
"status": "ok",
"message": "Processing queue",
"expected_interval_sec": 60
}
Bitte schreibe einen IHostedService in C#, der alle 30 Sekunden automatisch diesen Heartbeat-Ping an das Deploymentcenter sendet.
📋 Prompt Kopieren (C# Worker)
📊 Releases Overview
➕ Release Veröffentlichen
💻 Integration & Prompts
Produkt
Version
Release Notes
Download URL
Datum
= htmlspecialchars($r['product_slug']) ?>
v= htmlspecialchars($r['version']) ?>
= htmlspecialchars($r['release_notes'] ?? '-') ?>
= htmlspecialchars($r['download_url']) ?>
= htmlspecialchars($r['created_at']) ?>
Ich möchte in meiner Client-Anwendung eine automatische Update-Prüfung einbauen.
Update-Check URL: = $baseUrl ?>/api/updateservice/v1/check?product=myapp&version=1.0.0
Bitte erstelle ein Modul, das beim Start prüft, ob `update_available` true ist, und dem Nutzer den Download-Link sowie die Release Notes anzeigt.
📋 Prompt Kopieren
⚙️ System-Status
🗄️ Daten-Migration & Repair