diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..59cb792 --- /dev/null +++ b/.gitignore @@ -0,0 +1,70 @@ +# IDE and Editor Files +.idea/ +.vscode/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db + +# Composer +/vendor/ +composer.lock +composer.phar + +# Logs +*.log +/logs/ + +# Cache +/cache/ +*.cache + +# Temporary Files +/tmp/ +/temp/ +*.tmp + +# Environment Files +.env +.env.local +.env.*.local + +# OS Files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Desktop.ini + +# PHPUnit +.phpunit.result.cache +/phpunit.xml + +# Build Files +/build/ +/dist/ + +# Node Modules (falls Frontend-Build) +node_modules/ +npm-debug.log +yarn-error.log + +# WHMCS Specific +configuration.php +attachments/ +downloads/ +uploads/ + +# Backup Files +*.bak +*.backup +*~ + +# Security +*.key +*.pem +*.crt +api_keys.txt diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3af87dc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,216 @@ +# Changelog + +Alle wichtigen Änderungen an diesem Projekt werden in dieser Datei dokumentiert. + +Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.0.0/), +und dieses Projekt folgt [Semantic Versioning](https://semver.org/lang/de/). + +## [Unreleased] + +### Geplant +- Multi-Language Support (Deutsch/Englisch) +- Erweiterte Statistiken im Client Area +- Automatische Backup-Verwaltung +- SSL-Zertifikat-Management über Let's Encrypt +- E-Mail-Account-Verwaltung im Client Area +- Datenbank-Verwaltung im Client Area +- FTP-Account-Management +- Subdomain-Verwaltung +- Ressourcen-Upgrade/Downgrade-Funktionen +- Webhook-Support für Events + +## [1.0.0] - 2024-01-15 + +### Entwickelt von +- **Entwickler:** Kevin Feiler +- **Firma:** AVVGO +- **Website:** https://avvgo.de + +### Hinzugefügt +- Initiales Release des KeyHelp Manager WHMCS Provisioning Moduls +- **Account-Verwaltung:** + - Automatische Account-Erstellung nach Zahlungseingang + - Account-Sperrung (Suspend) bei Zahlungsverzug + - Account-Entsperrung (Unsuspend) + - Account-Löschung (Terminate) mit allen Daten + - Passwort-Änderungsfunktion + +- **API-Integration:** + - KeyHelp API v2 Unterstützung + - Guzzle HTTP Client für zuverlässige API-Kommunikation + - SSL/TLS-Verschlüsselung für API-Verbindungen + - Konfigurierbare SSL-Zertifikat-Verifizierung + - Umfassendes Error-Handling und Retry-Logik + +- **Client Area Features:** + - Übersichtliche Darstellung der Login-Informationen + - KeyHelp Login-URL mit direktem Zugang + - Username und Passwort mit Copy-to-Clipboard-Funktion + - Passwort anzeigen/verbergen Toggle + - Live-Statistiken vom KeyHelp-Server: + - Speicherplatz-Nutzung mit Fortschrittsbalken + - Traffic/Bandbreiten-Nutzung mit Fortschrittsbalken + - Anzahl der Domains + - Anzahl der Datenbanken + - Anzahl der E-Mail-Konten + - Responsive Design für alle Geräte + - Bootstrap-kompatibles Layout + +- **Admin-Features:** + - Single Sign-On (SSO) für Admins + - Ein-Klick-Login direkt in den Kunden-Account + - Detailliertes Module-Logging aller API-Calls + - Connection-Test-Funktion für Server-Konfiguration + - Automatische Maskierung sensibler Daten in Logs + +- **Automatisierung:** + - Automatische Benutzername-Generierung aus Domain + - Sichere Passwort-Generierung (16 Zeichen, kryptografisch sicher) + - Automatische Speicherung von Account-Details in WHMCS + - Custom Field Management für KeyHelp User-ID + - Rollback-Mechanismen bei fehlgeschlagener Erstellung + +- **Sicherheit:** + - API-Key-Verschlüsselung in WHMCS-Datenbank + - SSL/TLS-Unterstützung für alle API-Verbindungen + - Validierung und Sanitization aller Eingaben + - Schutz vor SQL-Injection durch Capsule ORM + - Sichere Session-Token-Generierung für SSO + - Automatische Maskierung von Credentials in Logs + +- **Dokumentation:** + - Ausführliche README.md mit Feature-Übersicht + - Detaillierte INSTALLATION.md mit Schritt-für-Schritt-Anleitung + - Umfangreiche Code-Kommentare (Deutsch) + - API-Endpunkt-Dokumentation + - Troubleshooting-Guide + - Best Practices für Sicherheit + +- **Entwickler-Tools:** + - Composer.json für Dependency-Management + - .gitignore für sauberes Repository + - PSR-12 Code-Style-Kompatibilität + - Modulare Code-Struktur für einfache Wartung + +### Technische Details +- **Mindestanforderungen:** + - PHP 8.3+ + - WHMCS 8.13+ + - KeyHelp mit API v2 + - Guzzle HTTP Client (in WHMCS integriert) + +- **Unterstützte KeyHelp API-Endpunkte:** + - `POST /api/v2/users` - Benutzer erstellen + - `GET /api/v2/users/{id}` - Benutzer-Details + - `PUT /api/v2/users/{id}` - Benutzer aktualisieren + - `DELETE /api/v2/users/{id}` - Benutzer löschen + - `POST /api/v2/domains` - Domain hinzufügen + - `GET /api/v2/users/{id}/statistics` - Statistiken abrufen + - `POST /api/v2/sessions` - SSO-Session erstellen + - `GET /api/v2/server/version` - Server-Version (Test) + +- **WHMCS-Funktionen:** + - `keyhelpmanager_MetaData()` - Modul-Metadaten + - `keyhelpmanager_ConfigOptions()` - Server-Konfiguration + - `keyhelpmanager_CreateAccount()` - Account erstellen + - `keyhelpmanager_SuspendAccount()` - Account sperren + - `keyhelpmanager_UnsuspendAccount()` - Account entsperren + - `keyhelpmanager_TerminateAccount()` - Account löschen + - `keyhelpmanager_ChangePassword()` - Passwort ändern + - `keyhelpmanager_ClientArea()` - Client-Bereich + - `keyhelpmanager_LoginLink()` - Admin SSO + - `keyhelpmanager_TestConnection()` - Verbindungstest + +### Hilfsfunktionen +- `_keyhelpmanager_APIRequest()` - Zentrale API-Request-Funktion +- `_keyhelpmanager_GenerateUsername()` - Username-Generierung +- `_keyhelpmanager_GeneratePassword()` - Passwort-Generierung +- `_keyhelpmanager_SaveAccountDetails()` - Account-Details speichern +- `_keyhelpmanager_GetAccountDetails()` - Account-Details laden +- `_keyhelpmanager_GetUserId()` - KeyHelp User-ID abrufen +- `_keyhelpmanager_UpdateAccountDetail()` - Einzelnes Detail aktualisieren +- `_keyhelpmanager_DeleteAccountDetails()` - Details löschen +- `_keyhelpmanager_GetCustomFieldId()` - Custom Field ID abrufen +- `_keyhelpmanager_FormatBytes()` - Bytes formatieren +- `_keyhelpmanager_CalculatePercent()` - Prozentsatz berechnen + +### Templates +- `clientarea.tpl` - Smarty-Template für Client Area mit: + - Bootstrap 3/4 kompatibles Design + - FontAwesome Icons + - Responsive Grid-Layout + - JavaScript-Funktionen für Interaktivität + - Copy-to-Clipboard-Funktionalität + - Passwort-Toggle-Funktion + - Fortschrittsbalken mit Farbcodierung + +### Konfigurationsoptionen +- Hostname/IP des KeyHelp-Servers +- API-Key-Verwaltung +- SSL-Aktivierung (On/Off) +- SSL-Zertifikat-Verifizierung (On/Off) + +### Bekannte Einschränkungen +- Keine direkte Multi-Language-Unterstützung (nur Deutsch) +- Erweiterte Features wie E-Mail-/DB-Verwaltung nicht implementiert +- Session-Token-Lifetime fest auf 5 Minuten (nicht konfigurierbar) +- Keine automatische Plan/Tarif-Synchronisation + +## [0.9.0-beta] - 2024-01-10 + +### Hinzugefügt +- Beta-Version für interne Tests +- Basis-Funktionalität für Account-Erstellung +- Erste API-Integration + +### Geändert +- API-Request-Handling optimiert +- Error-Messages verbessert + +### Behoben +- Connection-Timeout-Probleme +- SSL-Verifizierung bei selbstsignierten Zertifikaten + +## [0.5.0-alpha] - 2024-01-05 + +### Hinzugefügt +- Initiale Projekt-Struktur +- Grundlegende Modul-Funktionen +- API-Client-Implementierung + +--- + +## Versionierungsschema + +- **Major.Minor.Patch** (z.B. 1.0.0) + - **Major:** Breaking Changes, große neue Features + - **Minor:** Neue Features, abwärtskompatibel + - **Patch:** Bugfixes, kleine Verbesserungen + +## Credits + +Dieses Modul wurde entwickelt von: +- **Kevin Feiler** - Lead Developer +- **AVVGO** - https://avvgo.de + +## Support + +- **GitHub Issues:** Für Bug-Reports und Feature-Requests +- **Dokumentation:** Siehe README.md und INSTALLATION.md +- **KeyHelp Forum:** https://forum.keyhelp.de/ +- **WHMCS Community:** https://whmcs.community/ + +## Mitwirken + +Contributions sind willkommen! Bitte erstellen Sie einen Pull Request mit: +- Beschreibung der Änderungen +- Tests für neue Features +- Aktualisierung der Dokumentation +- Eintrag in diesem CHANGELOG + +--- + +[Unreleased]: https://github.com/ihr-repo/keyhelpmanager/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/ihr-repo/keyhelpmanager/releases/tag/v1.0.0 +[0.9.0-beta]: https://github.com/ihr-repo/keyhelpmanager/releases/tag/v0.9.0-beta +[0.5.0-alpha]: https://github.com/ihr-repo/keyhelpmanager/releases/tag/v0.5.0-alpha \ No newline at end of file diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 0000000..f55df1e --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,631 @@ +# KeyHelp Manager - Detaillierte Installationsanleitung + +Diese Anleitung führt Sie Schritt für Schritt durch die Installation und Konfiguration des KeyHelp Manager WHMCS-Moduls. + +## 📋 Voraussetzungen prüfen + +Bevor Sie mit der Installation beginnen, stellen Sie sicher, dass folgende Anforderungen erfüllt sind: + +### WHMCS-System + +- [ ] WHMCS Version 8.13 oder höher installiert +- [ ] PHP Version 8.3 oder höher +- [ ] Guzzle HTTP Client verfügbar (normalerweise in WHMCS integriert) +- [ ] MySQL/MariaDB Datenbank +- [ ] SSL-Zertifikat für WHMCS (empfohlen) +- [ ] Admin-Zugriff auf WHMCS + +### KeyHelp-Server + +- [ ] KeyHelp installiert und erreichbar +- [ ] KeyHelp API v2 aktiviert +- [ ] Admin-Zugang zu KeyHelp +- [ ] SSL-Zertifikat für KeyHelp (empfohlen) +- [ ] Firewall-Regeln erlauben Zugriff von WHMCS-Server + +### Netzwerk + +- [ ] WHMCS-Server kann KeyHelp-Server über HTTP/HTTPS erreichen +- [ ] Port 80/443 ist offen (je nach Konfiguration) +- [ ] DNS-Auflösung funktioniert korrekt + +## 🚀 Schritt 1: KeyHelp API vorbereiten + +### 1.1 API-Key in KeyHelp erstellen + +1. Loggen Sie sich als Administrator in Ihr KeyHelp-Panel ein: + ``` + https://ihr-keyhelp-server.de + ``` + +2. Navigieren Sie zu **Einstellungen** (Zahnrad-Symbol oben rechts) + +3. Klicken Sie auf **API** im linken Menü + +4. Klicken Sie auf **Neuen API-Schlüssel erstellen** + +5. Konfigurieren Sie den API-Key: + - **Name:** `WHMCS Provisioning` + - **Berechtigungen:** Wählen Sie **Administrator** oder erteilen Sie folgende spezifische Rechte: + - Benutzer erstellen/bearbeiten/löschen + - Domains erstellen/bearbeiten/löschen + - Statistiken abrufen + - Sessions erstellen + - **IP-Whitelist:** (Optional aber empfohlen) Tragen Sie die IP-Adresse Ihres WHMCS-Servers ein + +6. Klicken Sie auf **Erstellen** + +7. **WICHTIG:** Kopieren Sie den generierten API-Key sofort und speichern Sie ihn sicher! + ``` + Beispiel: kh_live_1234567890abcdefghijklmnopqrstuvwxyz + ``` + + ⚠️ **Der Key wird nur einmal angezeigt!** + +### 1.2 API testen (Optional) + +Testen Sie den API-Zugriff vom WHMCS-Server aus: + +```bash +# Mit SSL (empfohlen) +curl -X GET "https://ihr-keyhelp-server.de/api/v2/server/version" \ + -H "X-API-Key: IHR_API_KEY" \ + -H "Accept: application/json" + +# Ohne SSL (nur für Tests) +curl -X GET "http://ihr-keyhelp-server.de/api/v2/server/version" \ + -H "X-API-Key: IHR_API_KEY" \ + -H "Accept: application/json" +``` + +Erwartete Antwort: +```json +{ + "version": "24.1.0", + "api_version": "2.0" +} +``` + +## 🔧 Schritt 2: Modul-Dateien installieren + +### 2.1 Dateien hochladen + +#### Option A: Via FTP/SFTP + +1. Verbinden Sie sich mit Ihrem WHMCS-Server via FTP/SFTP + +2. Navigieren Sie zum WHMCS-Installationsverzeichnis: + ``` + /var/www/whmcs/ + ``` + +3. Laden Sie das komplette `keyhelpmanager`-Verzeichnis in folgenden Pfad hoch: + ``` + /var/www/whmcs/modules/servers/keyhelpmanager/ + ``` + +4. Stellen Sie sicher, dass folgende Struktur existiert: + ``` + modules/ + └── servers/ + └── keyhelpmanager/ + ├── keyhelpmanager.php + └── templates/ + └── clientarea.tpl + ``` + +#### Option B: Via SSH + +```bash +# Zum WHMCS-Verzeichnis navigieren +cd /var/www/whmcs/modules/servers/ + +# Repository klonen (falls Git verwendet wird) +git clone https://github.com/ihr-repo/keyhelpmanager.git + +# Oder Dateien aus ZIP extrahieren +unzip keyhelpmanager.zip + +# Dateien verschieben falls nötig +mv keyhelpmanager-main keyhelpmanager +``` + +### 2.2 Dateirechte setzen + +Setzen Sie die korrekten Berechtigungen: + +```bash +# Zum Modul-Verzeichnis +cd /var/www/whmcs/modules/servers/keyhelpmanager/ + +# Dateien: 644 (rw-r--r--) +find . -type f -exec chmod 644 {} \; + +# Verzeichnisse: 755 (rwxr-xr-x) +find . -type d -exec chmod 755 {} \; + +# Owner setzen (Apache/Nginx User) +chown -R www-data:www-data . + +# Oder für andere Systeme +chown -R apache:apache . +chown -R nginx:nginx . +``` + +### 2.3 Installation verifizieren + +Prüfen Sie, ob die Dateien korrekt hochgeladen wurden: + +```bash +ls -la /var/www/whmcs/modules/servers/keyhelpmanager/ +``` + +Erwartete Ausgabe: +``` +drwxr-xr-x 3 www-data www-data 4096 Jan 15 10:00 . +drwxr-xr-x 8 www-data www-data 4096 Jan 15 09:55 .. +-rw-r--r-- 1 www-data www-data xxxxx Jan 15 10:00 keyhelpmanager.php +drwxr-xr-x 2 www-data www-data 4096 Jan 15 10:00 templates +``` + +## ⚙️ Schritt 3: Server in WHMCS konfigurieren + +### 3.1 Server hinzufügen + +1. Loggen Sie sich in den **WHMCS Admin-Bereich** ein: + ``` + https://ihr-whmcs.de/admin/ + ``` + +2. Navigieren Sie zu: + ``` + Setup → Products/Services → Servers + ``` + +3. Klicken Sie auf **Add New Server** + +### 3.2 Server-Details eintragen + +Füllen Sie das Formular aus: + +#### Tab: Details + +| Feld | Wert | Beschreibung | +|------|------|--------------| +| **Name** | `KeyHelp Server 1` | Interner Name (frei wählbar) | +| **Hostname** | `keyhelp.ihredomain.de` | Hostname ODER IP-Adresse **OHNE** `http://` oder `https://` | +| **IP Address** | `123.45.67.89` | IP-Adresse (optional, falls Hostname verwendet wird) | +| **Type** | `KeyHelp Manager` | Wählen Sie aus dem Dropdown | +| **Username** | _(leer lassen)_ | Nicht benötigt | +| **Password** | `kh_live_123...` | **IHR KEYHELP API-KEY** | +| **Accesshash** | _(leer lassen)_ | Nicht benötigt | + +#### Checkboxes + +- ✅ **Active** - Server ist aktiv +- ✅ **Secure** - Verwenden Sie SSL (HTTPS) für die Verbindung +- ⬜ **Disable Accounts Automatically** - (optional) + +#### Tab: Module Settings + +Wenn verfügbar, konfigurieren Sie hier: + +| Option | Empfohlener Wert | Beschreibung | +|--------|------------------|--------------| +| **Use SSL** | ✅ On | SSL für API-Verbindung verwenden | +| **Verify SSL Certificate** | ✅ On | SSL-Zertifikat prüfen (bei selbstsigniert: Off) | + +### 3.3 Verbindung testen + +1. Klicken Sie auf **Test Connection** + +2. Erwartete Meldung: + ``` + ✅ Verbindung erfolgreich! KeyHelp Version: 24.1.0 + ``` + +3. Bei Fehlermeldungen siehe [Fehlerbehebung](#fehlerbehebung) + +4. Klicken Sie auf **Save Changes** + +## 📦 Schritt 4: Produkt/Service erstellen + +### 4.1 Neues Produkt anlegen + +1. Navigieren Sie zu: + ``` + Setup → Products/Services → Products/Services + ``` + +2. Klicken Sie auf **Create a New Group** (falls noch keine Gruppe existiert): + - **Name:** `Webhosting` + - **Description:** `KeyHelp Webhosting Pakete` + +3. Klicken Sie auf **Create a New Product** + +### 4.2 Produkt-Details + +#### Tab: Details + +| Feld | Beispielwert | +|------|--------------| +| **Product Type** | `Hosting Account` | +| **Product Group** | `Webhosting` | +| **Product Name** | `Basic Webhosting` | +| **Description** | Beschreibung des Pakets | +| **Welcome Email** | `Hosting Account Welcome Email` | + +#### Tab: Pricing + +Konfigurieren Sie Ihre Preise: + +- **Currency:** EUR +- **Payment Type:** Recurring +- **Monthly:** 5.00 EUR +- **Quarterly:** 13.50 EUR +- **Semi-Annually:** 27.00 EUR +- **Annually:** 50.00 EUR + +#### Tab: Module Settings + +**WICHTIG:** Dies ist der entscheidende Teil! + +| Feld | Wert | Beschreibung | +|------|------|--------------| +| **Module Name** | `KeyHelp Manager` | Wählen Sie aus dem Dropdown | +| **Server Group** | `Default` | Oder wählen Sie Ihre Server-Gruppe | +| **Username** | `Domain` | Automatisch aus Domain generieren | +| **Password** | `Generate` | Automatisch generieren | + +**Konfigurationsoptionen:** + +1. **Hostname (IP or FQDN)** + - Type: Dropdown + - Options: Wählen Sie Ihren KeyHelp-Server + +2. **API Key** + - Wird automatisch vom Server übernommen + +3. **Use SSL** + - Default: On + +**Aktivierte Funktionen:** (Checkboxes) + +- ✅ Create Account +- ✅ Suspend Account +- ✅ Unsuspend Account +- ✅ Terminate Account +- ✅ Change Password +- ✅ Login Link (Single Sign-On) + +### 4.3 Konfigurierbare Optionen (Optional) + +#### KeyHelp-Pläne als Dropdown + +1. Navigieren Sie zu: + ``` + Setup → Products/Services → Configurable Options + ``` + +2. Klicken Sie auf **Create a New Group**: + - **Group Name:** `KeyHelp Optionen` + +3. Klicken Sie auf **Add New Configurable Option**: + - **Option Name:** `KeyHelp Plan` + - **Option Type:** `Dropdown` + - **Options:** + ``` + Basic|basic + Professional|professional + Enterprise|enterprise + ``` + +4. Verknüpfen Sie die Gruppe mit Ihrem Produkt: + - Products/Services → Ihr Produkt → Configurable Options + - Wählen Sie `KeyHelp Optionen` + +### 4.4 Custom Fields anlegen (Optional aber empfohlen) + +Diese Felder werden zwar automatisch erstellt, können aber manuell vorbereitet werden: + +1. Navigieren Sie zu: + ``` + Setup → Custom Fields + ``` + +2. Wählen Sie **Products/Services** und Ihr Produkt + +3. Klicken Sie auf **Add New Custom Field**: + + - **Field Name:** `KeyHelp User ID` + - **Field Type:** `Text Box` + - **Description:** `Interne KeyHelp Benutzer-ID` + - ✅ **Admin Only** + - Sortierung: `1` + +## ✅ Schritt 5: Testen der Installation + +### 5.1 Test-Bestellung durchführen + +1. Öffnen Sie Ihr WHMCS Frontend als Kunde (im Inkognito-Modus): + ``` + https://ihr-whmcs.de/ + ``` + +2. Navigieren Sie zu **Order → Hosting** + +3. Wählen Sie Ihr neues Produkt + +4. Geben Sie eine Test-Domain ein: + ``` + test123.de + ``` + +5. Schließen Sie die Bestellung ab (nutzen Sie ein Test-Gateway oder manuelle Zahlung) + +### 5.2 Account-Erstellung prüfen + +1. Als Admin: Navigieren Sie zu **Clients → View/Search Clients** + +2. Öffnen Sie den Test-Kunden + +3. Klicken Sie auf das neue Service/Produkt + +4. Im Tab **Information** sollten Sie sehen: + - ✅ Username: automatisch generiert + - ✅ Password: automatisch generiert + - ✅ Status: Active + +5. Prüfen Sie die **Module Commands**: + - Buttons sollten verfügbar sein: Suspend, Unsuspend, Terminate, Change Password + +### 5.3 Client Area testen + +1. Loggen Sie sich als Test-Kunde ein + +2. Navigieren Sie zu **Services → My Services** + +3. Klicken Sie auf das neue Hosting-Paket + +4. Sie sollten sehen: + - ✅ KeyHelp Login-URL (klickbar) + - ✅ Benutzername (mit Copy-Button) + - ✅ Passwort (mit Show/Hide und Copy-Button) + - ✅ Domain-Name + - ✅ Statistiken (wenn Account erstellt wurde): + - Speicherplatz-Fortschrittsbalken + - Traffic-Fortschrittsbalken + - Anzahl Domains/Datenbanken/E-Mail-Konten + +### 5.4 In KeyHelp prüfen + +1. Loggen Sie sich in Ihr KeyHelp-Panel ein + +2. Navigieren Sie zu **Benutzer** + +3. Sie sollten den neu erstellten Benutzer sehen: + - Username wie in WHMCS + - Domain zugewiesen + - Status: Aktiv + +### 5.5 Single Sign-On testen + +1. Als Admin in WHMCS: Öffnen Sie das Test-Service + +2. Klicken Sie auf **Login to KeyHelp** (oder ähnlicher Button) + +3. Sie sollten automatisch in KeyHelp eingeloggt werden: + - Als der jeweilige Benutzer + - Ohne Passwort-Eingabe + +## 🔧 Schritt 6: Produktiv-Konfiguration + +### 6.1 Mehrere Server einrichten + +Falls Sie mehrere KeyHelp-Server haben: + +1. Wiederholen Sie Schritt 3 für jeden Server + +2. Erstellen Sie eine **Server Group**: + ``` + Setup → Products/Services → Servers → Server Groups + ``` + +3. Fügen Sie alle KeyHelp-Server zur Gruppe hinzu + +4. Konfigurieren Sie Ihre Produkte, um die Server-Gruppe zu nutzen: + - Automatische Lastverteilung + - Failover-Funktion + +### 6.2 Automatisierung einrichten + +#### A) Automatische Provisioning + +In WHMCS: **Setup → Automation Settings** + +- ✅ Enable Automatic Provisioning +- ✅ Process After: Payment Cleared +- Stellen Sie sicher, dass Cron-Jobs aktiv sind + +#### B) Automatische Sperrung + +- ✅ Enable Automatic Suspension +- Days Past Due Before Suspension: `7` + +#### C) Automatische Kündigung + +- ✅ Enable Automatic Termination +- Days Past Due Before Termination: `30` + +### 6.3 E-Mail-Templates anpassen + +Passen Sie die E-Mail-Templates an: + +1. **Setup → Email Templates** + +2. Suchen Sie nach: + - `Hosting Account Welcome Email` + +3. Fügen Sie KeyHelp-spezifische Variablen hinzu: + ``` + KeyHelp Login: https://{$service_server_hostname} + Benutzername: {$service_username} + Passwort: {$service_password} + Domain: {$service_domain} + ``` + +### 6.4 Sicherheit härten + +1. **IP-Whitelist in KeyHelp**: + - Beschränken Sie API-Zugriff auf WHMCS-Server-IP + +2. **WHMCS Admin-IP-Whitelist**: + ``` + Setup → General Settings → Security + ``` + - Tragen Sie erlaubte Admin-IPs ein + +3. **Zwei-Faktor-Authentifizierung**: + - Aktivieren Sie 2FA für alle Admin-Accounts (WHMCS und KeyHelp) + +4. **SSL-Zertifikate**: + - Verwenden Sie gültige SSL-Zertifikate + - Keine selbstsignierten Zertifikate in Produktion + +## 🐛 Fehlerbehebung + +### Problem: "Module Not Found" + +**Ursache:** Dateien nicht korrekt hochgeladen + +**Lösung:** +```bash +# Prüfen Sie den Pfad +ls -la /var/www/whmcs/modules/servers/keyhelpmanager/keyhelpmanager.php + +# Wenn nicht gefunden, Dateien neu hochladen +``` + +### Problem: "Connection Failed" + +**Ursachen & Lösungen:** + +1. **Firewall blockiert**: + ```bash + # Auf WHMCS-Server testen + telnet keyhelp-server.de 443 + ``` + +2. **Falscher Hostname**: + - Verwenden Sie FQDN ODER IP + - OHNE `http://` oder `https://` + +3. **SSL-Problem**: + - Bei selbstsigniertem Zertifikat: "Verify SSL" deaktivieren + +4. **API-Key falsch**: + - Generieren Sie einen neuen Key in KeyHelp + - Kopieren Sie ihn exakt (keine Leerzeichen!) + +### Problem: "Account Creation Failed" + +**Debug-Schritte:** + +1. Prüfen Sie Module Log: + ``` + Utilities → Logs → Module Log + Filter: keyhelpmanager + ``` + +2. Prüfen Sie die API-Response in den Logs + +3. Häufige Ursachen: + - Domain existiert bereits + - Ungültiger Username + - Unzureichende API-Berechtigungen + - KeyHelp-Lizenz-Limit erreicht + +### Problem: "Statistics Not Showing" + +**Ursache:** API-Endpunkt nicht erreichbar oder User-ID fehlt + +**Lösung:** +```bash +# API manuell testen +curl -X GET "https://keyhelp-server.de/api/v2/users/123/statistics" \ + -H "X-API-Key: IHR_KEY" +``` + +Prüfen Sie, ob `KeyHelp User ID` Custom Field existiert und gefüllt ist. + +## 📊 Monitoring + +### 6.5 Logging aktivieren + +In WHMCS: +``` +Setup → General Settings → Other +``` +- ✅ Enable Module Debug Logging + +Logs finden Sie unter: +``` +Utilities → Logs → Module Log +``` + +### 6.6 Gesundheits-Check einrichten + +Erstellen Sie ein Cron-Script für regelmäßige API-Tests: + +```bash +#!/bin/bash +# /root/keyhelp-health-check.sh + +KEYHELP_HOST="keyhelp.ihredomain.de" +API_KEY="ihr_api_key" + +RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \ + "https://${KEYHELP_HOST}/api/v2/server/version" \ + -H "X-API-Key: ${API_KEY}") + +if [ "$RESPONSE" != "200" ]; then + echo "KeyHelp API nicht erreichbar! HTTP Status: $RESPONSE" + # Optional: Benachrichtigung senden + echo "KeyHelp API Down" | mail -s "ALERT: KeyHelp" admin@ihredomain.de +fi +``` + +Cron-Job: +```bash +# Alle 15 Minuten prüfen +*/15 * * * * /root/keyhelp-health-check.sh +``` + +## ✨ Fertig! + +Herzlichen Glückwunsch! Ihr KeyHelp Manager WHMCS-Modul ist jetzt vollständig installiert und konfiguriert. + +### Nächste Schritte + +- [ ] Produktiv-Server konfigurieren +- [ ] Mehrere Hosting-Pakete anlegen +- [ ] Preise festlegen +- [ ] Marketing-Material vorbereiten +- [ ] Support-Team schulen + +### Wichtige Hinweise + +- 🔒 **Sicherheit:** Ändern Sie Ihre API-Keys regelmäßig +- 📝 **Backups:** Sichern Sie regelmäßig WHMCS und KeyHelp +- 🔄 **Updates:** Halten Sie alle Systeme aktuell +- 📞 **Support:** Dokumentieren Sie Ihre Konfiguration für Ihr Team + +### Nützliche Links + +- KeyHelp Dokumentation: https://www.keyhelp.de/dokumentation +- WHMCS Docs: https://docs.whmcs.com/ +- KeyHelp Forum: https://forum.keyhelp.de/ + +--- + +**Bei Problemen oder Fragen:** Prüfen Sie die README.md und die Fehlerbehebungssektion. Für weitere Hilfe konsultieren Sie die Community-Foren. \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..27faa21 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Kevin Feiler / AVVGO + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PROJECT_STRUCTURE.md b/PROJECT_STRUCTURE.md new file mode 100644 index 0000000..f2f7a5a --- /dev/null +++ b/PROJECT_STRUCTURE.md @@ -0,0 +1,373 @@ +# KeyHelp Manager - Projektstruktur + +**Entwickelt von:** Kevin Feiler / AVVGO +**Version:** 1.0.0 + +## 📁 Verzeichnisstruktur + +``` +keyweb-module/ +├── modules/ +│ └── servers/ +│ └── keyhelpmanager/ +│ ├── keyhelpmanager.php # Haupt-Modul-Datei (846 Zeilen) +│ └── templates/ +│ └── clientarea.tpl # Client Area Smarty-Template +│ +├── .gitignore # Git Ignore-Datei +├── CHANGELOG.md # Versions-Historie +├── composer.json # Composer Dependencies +├── INSTALLATION.md # Detaillierte Installationsanleitung +├── LICENSE # MIT Lizenz +├── PROJECT_STRUCTURE.md # Diese Datei +└── README.md # Haupt-Dokumentation +``` + +## 📄 Datei-Übersicht + +### Hauptmodul: `keyhelpmanager.php` + +**Größe:** ~846 Zeilen +**Zweck:** Kernfunktionalität des WHMCS Provisioning Moduls + +#### Öffentliche WHMCS-Funktionen: + +1. **`keyhelpmanager_MetaData()`** + - Gibt Modul-Metadaten zurück + - DisplayName, API-Version, Port-Definitionen + +2. **`keyhelpmanager_ConfigOptions()`** + - Definiert Server-Konfigurationsoptionen + - Hostname, API-Key, SSL-Einstellungen + +3. **`keyhelpmanager_CreateAccount(array $params)`** + - Erstellt neuen KeyHelp-Account + - Generiert Username/Passwort falls nötig + - Fügt Domain hinzu + - Speichert Details in WHMCS + +4. **`keyhelpmanager_SuspendAccount(array $params)`** + - Sperrt KeyHelp-Account + - Setzt `is_locked` Flag + +5. **`keyhelpmanager_UnsuspendAccount(array $params)`** + - Entsperrt KeyHelp-Account + - Entfernt `is_locked` Flag + +6. **`keyhelpmanager_TerminateAccount(array $params)`** + - Löscht KeyHelp-Account permanent + - Entfernt alle zugehörigen Daten + - Cleanup in WHMCS-Datenbank + +7. **`keyhelpmanager_ChangePassword(array $params)`** + - Ändert Account-Passwort + - Synchronisiert mit WHMCS + +8. **`keyhelpmanager_ClientArea(array $params)`** + - Generiert Client Area Inhalt + - Lädt Live-Statistiken von KeyHelp + - Rendert Smarty-Template + +9. **`keyhelpmanager_LoginLink(array $params)`** + - Single Sign-On für Admins + - Erstellt Session-Token + - Generiert direkten Login-Link + +10. **`keyhelpmanager_TestConnection(array $params)`** + - Testet API-Verbindung + - Gibt KeyHelp-Version zurück + +#### Private Hilfsfunktionen: + +**API-Kommunikation:** +- `_keyhelpmanager_APIRequest()` - Zentrale API-Request-Funktion mit Guzzle + +**Account-Management:** +- `_keyhelpmanager_GenerateUsername()` - Generiert Username aus Domain +- `_keyhelpmanager_GeneratePassword()` - Generiert sicheres Passwort (16 Zeichen) +- `_keyhelpmanager_SaveAccountDetails()` - Speichert in WHMCS-DB +- `_keyhelpmanager_GetAccountDetails()` - Lädt aus WHMCS-DB +- `_keyhelpmanager_GetUserId()` - Holt KeyHelp User-ID +- `_keyhelpmanager_UpdateAccountDetail()` - Aktualisiert einzelnes Detail +- `_keyhelpmanager_DeleteAccountDetails()` - Löscht gespeicherte Details + +**Custom Fields:** +- `_keyhelpmanager_GetCustomFieldId()` - Holt/erstellt Custom Field ID + +**Formatierung:** +- `_keyhelpmanager_FormatBytes()` - Formatiert Bytes → KB/MB/GB/TB +- `_keyhelpmanager_CalculatePercent()` - Berechnet Prozentsatz + +### Template: `clientarea.tpl` + +**Größe:** ~258 Zeilen +**Typ:** Smarty Template +**Zweck:** Client Area Darstellung + +#### Features: +- Bootstrap 3/4 kompatibles Layout +- FontAwesome Icons +- Responsive Design +- JavaScript-Funktionen: + - `togglePassword()` - Passwort anzeigen/verbergen + - `copyToClipboard()` - Text in Zwischenablage kopieren + +#### Angezeigte Informationen: +1. **Login-Informationen:** + - KeyHelp Login-URL (klickbar) + - Benutzername (mit Copy-Button) + - Passwort (mit Show/Hide und Copy-Button) + - Domain-Name + +2. **Account-Statistiken:** + - Speicherplatz (Fortschrittsbalken) + - Traffic/Bandbreite (Fortschrittsbalken) + - Anzahl Domains + - Anzahl Datenbanken + - Anzahl E-Mail-Konten + +3. **Call-to-Action:** + - "Jetzt zu KeyHelp einloggen" Button + +## 🔌 KeyHelp API-Endpunkte + +Das Modul nutzt folgende KeyHelp API v2 Endpunkte: + +| Endpunkt | Methode | Zweck | Verwendet in | +|----------|---------|-------|--------------| +| `/api/v2/users` | POST | Benutzer erstellen | CreateAccount | +| `/api/v2/users/{id}` | GET | Benutzer-Details | GetAccountDetails | +| `/api/v2/users/{id}` | PUT | Benutzer aktualisieren | SuspendAccount, UnsuspendAccount, ChangePassword | +| `/api/v2/users/{id}` | DELETE | Benutzer löschen | TerminateAccount | +| `/api/v2/domains` | POST | Domain hinzufügen | CreateAccount | +| `/api/v2/users/{id}/statistics` | GET | Statistiken abrufen | ClientArea | +| `/api/v2/sessions` | POST | SSO-Session erstellen | LoginLink | +| `/api/v2/server/version` | GET | Server-Version | TestConnection | + +## 💾 WHMCS-Datenbank-Interaktionen + +### Verwendete Tabellen: + +1. **`tblhosting`** + - Felder: `username`, `password` + - Zweck: Speichert Account-Credentials + +2. **`tblcustomfields`** + - Erstellt Custom Field: "KeyHelp User ID" + - Typ: Text (Admin Only) + +3. **`tblcustomfieldsvalues`** + - Speichert KeyHelp User-ID pro Service + - Verknüpfung über `relid` (Service-ID) + +### Verwendetes ORM: +- **Laravel Eloquent Capsule** (von WHMCS bereitgestellt) +- Sichere Queries ohne SQL-Injection-Risiko + +## 🔒 Sicherheitsfeatures + +1. **API-Key-Schutz:** + - Verschlüsselte Speicherung in WHMCS + - Maskierung in Module-Logs + - Niemals im Frontend sichtbar + +2. **Passwort-Sicherheit:** + - Kryptografisch sichere Generierung (`random_int()`) + - 16 Zeichen Länge + - Gemischte Zeichensätze (a-z, A-Z, 0-9, Sonderzeichen) + - Verschlüsselte Speicherung in WHMCS + +3. **SSL/TLS:** + - Konfigurierbare SSL-Verbindungen + - Optionale Zertifikat-Verifizierung + - Standard: SSL aktiviert + +4. **Input-Validierung:** + - Alle Benutzereingaben werden validiert + - Sanitization durch Capsule ORM + - Exception-Handling für alle API-Calls + +5. **Session-Token:** + - Temporäre SSO-Tokens (5 Minuten Gültigkeit) + - Automatischer Ablauf + +## 📝 Logging + +### WHMCS Module Log: +- Alle API-Requests werden protokolliert +- Automatische Maskierung sensibler Daten +- Abrufbar unter: `Utilities → Logs → Module Log` + +### Logged werden: +- API-Endpunkt und Methode +- Request-Body (API-Key maskiert) +- Response-Status und Body +- Fehler und Exceptions + +## 🎨 Design-Patterns + +1. **Prefix-Convention:** + - Öffentliche Funktionen: `keyhelpmanager_FunctionName()` + - Private Funktionen: `_keyhelpmanager_FunctionName()` + +2. **Error-Handling:** + - Try-Catch-Blöcke um alle kritischen Operationen + - Verständliche Fehlermeldungen für Endbenutzer + - Detailliertes Logging für Admins + +3. **Rollback-Mechanismus:** + - Bei fehlgeschlagener Domain-Erstellung: Benutzer wird gelöscht + - Verhindert inkonsistente Zustände + +4. **Separation of Concerns:** + - API-Logik in `_keyhelpmanager_APIRequest()` + - Datenbank-Logik in separaten Funktionen + - Template-Logik in `.tpl`-Datei + +## 🔄 Workflow-Diagramme + +### Account-Erstellung: + +``` +WHMCS Payment Cleared + ↓ +keyhelpmanager_CreateAccount() + ↓ +Validiere Parameter + ↓ +Generiere Username/Passwort (falls nötig) + ↓ +API: POST /users (Benutzer erstellen) + ↓ + Erfolg? + ↙ ↘ + Ja Nein → Return Error + ↓ +API: POST /domains (Domain hinzufügen) + ↓ + Erfolg? + ↙ ↘ + Ja Nein → Rollback: DELETE User → Return Error + ↓ +Speichere Details in WHMCS + ↓ +Return "success" + ↓ +Account ist aktiv +``` + +### Single Sign-On: + +``` +Admin klickt "Login to KeyHelp" + ↓ +keyhelpmanager_LoginLink() + ↓ +Lade User-ID aus WHMCS + ↓ +API: POST /sessions (mit User-ID) + ↓ +Erhalte Session-Token + ↓ +Generiere Login-URL mit Token + ↓ +Redirect zu KeyHelp + ↓ +Auto-Login ohne Passwort +``` + +## 📦 Abhängigkeiten + +### PHP-Extensions: +- `ext-json` - JSON-Verarbeitung +- `ext-curl` - HTTP-Requests + +### Composer-Pakete: +- `guzzlehttp/guzzle` ^7.0 - HTTP-Client (von WHMCS bereitgestellt) + +### WHMCS-Komponenten: +- Laravel Eloquent Capsule (ORM) +- Smarty Template Engine +- Module Log System +- Custom Fields System +- Encryption Functions + +## 🧪 Testing-Empfehlungen + +### Manuelle Tests: + +1. **Connection-Test:** + - Server-Konfiguration → Test Connection + +2. **Account-Lifecycle:** + - Create → Verify in KeyHelp + - Suspend → Verify locked + - Unsuspend → Verify unlocked + - Terminate → Verify deleted + +3. **Client Area:** + - Login-Credentials sichtbar? + - Statistiken werden geladen? + - Copy-to-Clipboard funktioniert? + - Responsive Design auf Mobile? + +4. **Admin SSO:** + - Login-Link funktioniert? + - Automatischer Login ohne Passwort? + - Token läuft nach 5 Min. ab? + +### Automatisierte Tests (Geplant): + +- PHPUnit-Tests für alle Funktionen +- Mock-API-Responses +- Database-Transaktionen für Tests + +## 📊 Code-Statistiken + +- **Gesamt-Zeilen:** ~1.400+ +- **PHP-Code:** ~846 Zeilen +- **Smarty-Template:** ~258 Zeilen +- **Dokumentation:** ~1.200+ Zeilen (README, INSTALLATION, etc.) +- **Funktionen:** 21 (10 öffentlich, 11 privat) +- **API-Endpunkte:** 8 + +## 🚀 Performance-Optimierungen + +1. **Caching:** + - Custom Field IDs werden bei erster Abfrage ermittelt + - Wiederverwendung innerhalb einer Request + +2. **Lazy-Loading:** + - Statistiken nur bei Bedarf (Client Area) + - Session-Tokens nur bei SSO + +3. **Effiziente DB-Queries:** + - Verwendung von Eloquent ORM + - Keine N+1 Query-Probleme + +4. **API-Timeouts:** + - 30 Sekunden Timeout für API-Requests + - Verhindert hängende Requests + +## 🔮 Geplante Erweiterungen (Roadmap) + +Siehe CHANGELOG.md → [Unreleased] + +- Multi-Language Support +- E-Mail-Account-Verwaltung +- Datenbank-Management +- SSL-Zertifikat-Management +- Ressourcen-Upgrade/Downgrade +- Webhook-Support + +## 📞 Support + +**Entwickler:** Kevin Feiler +**Firma:** AVVGO +**Website:** https://avvgo.de +**E-Mail:** info@avvgo.de + +--- + +**Copyright (c) 2024 Kevin Feiler / AVVGO** +**Lizenz:** MIT License \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..61f071d --- /dev/null +++ b/composer.json @@ -0,0 +1,54 @@ +{ + "name": "avvgo/keyhelpmanager-whmcs", + "description": "WHMCS Provisioning Module for KeyHelp Webhosting Panel - Developed by Kevin Feiler / AVVGO", + "type": "whmcs-module", + "keywords": [ + "whmcs", + "keyhelp", + "provisioning", + "hosting", + "webhosting", + "control-panel", + "avvgo" + ], + "license": "MIT", + "authors": [ + { + "name": "Kevin Feiler", + "email": "info@avvgo.de", + "homepage": "https://avvgo.de", + "role": "Lead Developer" + } + ], + "require": { + "php": ">=8.3", + "guzzlehttp/guzzle": "^7.0", + "ext-json": "*", + "ext-curl": "*" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "autoload": { + "psr-4": { + "KeyHelpManager\\": "modules/servers/keyhelpmanager/lib/" + } + }, + "autoload-dev": { + "psr-4": { + "KeyHelpManager\\Tests\\": "tests/" + } + }, + "scripts": { + "test": "phpunit", + "phpcs": "phpcs --standard=PSR12 modules/servers/keyhelpmanager/", + "phpcbf": "phpcbf --standard=PSR12 modules/servers/keyhelpmanager/" + }, + "config": { + "sort-packages": true, + "optimize-autoloader": true + }, + "minimum-stability": "stable", + "prefer-stable": true +} diff --git a/modules/servers/keyhelpmanager/keyhelpmanager.php b/modules/servers/keyhelpmanager/keyhelpmanager.php new file mode 100644 index 0000000..602dd2b --- /dev/null +++ b/modules/servers/keyhelpmanager/keyhelpmanager.php @@ -0,0 +1,961 @@ + + * @copyright Copyright (c) 2024 Kevin Feiler / AVVGO + * @license MIT License + * @link https://avvgo.de + * @version 1.0.0 + * + * Dieses Modul ermöglicht die automatische Verwaltung von KeyHelp-Hosting-Accounts + * direkt aus WHMCS heraus. Es unterstützt Erstellung, Sperrung, Entsperrung und + * Löschung von Accounts sowie die Anzeige von Account-Informationen im Client-Bereich. + * + * Entwickelt von Kevin Feiler / AVVGO + * + * Kompatibel mit: + * - PHP 8.3+ + * - WHMCS 8.13+ + * - KeyHelp (neueste stabile Version) + */ + +if (!defined("WHMCS")) { + die("This file cannot be accessed directly"); +} + +use WHMCS\Database\Capsule; + +/** + * Modul-Metadaten + * + * Definiert die grundlegenden Informationen über das Modul. + * + * @return array Modul-Metadaten + */ +function keyhelpmanager_MetaData() +{ + return [ + "DisplayName" => "KeyHelp Manager", + "APIVersion" => "1.1", + "RequiresServer" => true, + "DefaultNonSSLPort" => "80", + "DefaultSSLPort" => "443", + "ServiceSingleSignOnLabel" => "Login zu KeyHelp", + "AdminSingleSignOnLabel" => "Als Admin einloggen", + ]; +} + +/** + * Modul-Konfigurationsoptionen + * + * Definiert die Felder, die in der Server-Konfiguration in WHMCS angezeigt werden. + * + * @return array Konfigurations-Array + */ +function keyhelpmanager_ConfigOptions() +{ + return [ + "hostname" => [ + "FriendlyName" => "Hostname (IP or FQDN)", + "Type" => "text", + "Size" => "25", + "Default" => "", + "Description" => + "Hostname oder IP-Adresse deines KeyHelp-Servers (ohne http:// oder https://)", + "Required" => true, + ], + "apikey" => [ + "FriendlyName" => "API Key", + "Type" => "password", + "Size" => "50", + "Default" => "", + "Description" => + "Dein KeyHelp API-Schlüssel (zu finden in KeyHelp unter Einstellungen → API)", + "Required" => true, + ], + "usessl" => [ + "FriendlyName" => "Use SSL", + "Type" => "yesno", + "Default" => "on", + "Description" => + "SSL für die Verbindung zur API verwenden (dringend empfohlen)", + ], + "verify_ssl" => [ + "FriendlyName" => "Verify SSL Certificate", + "Type" => "yesno", + "Default" => "on", + "Description" => + "SSL-Zertifikat verifizieren (bei selbstsignierten Zertifikaten deaktivieren)", + ], + ]; +} + +/** + * API-Request Hilfsfunktion + * + * Sendet HTTP-Anfragen an die KeyHelp-API und verarbeitet die Antworten. + * + * @param array $params WHMCS-Parameter-Array + * @param string $endpoint API-Endpunkt (z.B. '/users', '/users/123') + * @param string $method HTTP-Methode (GET, POST, PUT, DELETE) + * @param array $data Request-Body-Daten + * @return array Ergebnis mit 'success' (bool) und 'data' oder 'error' + */ +function _keyhelpmanager_APIRequest( + array $params, + string $endpoint, + string $method = "GET", + array $data = [], +) { + try { + // Konfiguration auslesen + $hostname = + $params["serverhostname"] ?? ($params["configoption1"] ?? ""); + $apiKey = $params["serverpassword"] ?? ($params["configoption2"] ?? ""); + $useSSL = $params["configoption3"] ?? "on"; + $verifySSL = $params["configoption4"] ?? "on"; + + // Validierung + if (empty($hostname)) { + return [ + "success" => false, + "error" => "KeyHelp-Hostname ist nicht konfiguriert.", + ]; + } + + if (empty($apiKey)) { + return [ + "success" => false, + "error" => "KeyHelp API-Schlüssel ist nicht konfiguriert.", + ]; + } + + // Protocol bestimmen + $protocol = $useSSL === "on" ? "https" : "http"; + + // Basis-URL zusammenbauen + $baseUrl = sprintf("%s://%s/api/v2", $protocol, $hostname); + $url = $baseUrl . $endpoint; + + // Guzzle HTTP-Client initialisieren + $client = new \GuzzleHttp\Client([ + "verify" => $verifySSL === "on", + "timeout" => 30, + "http_errors" => false, + ]); + + // Request-Optionen + $options = [ + "headers" => [ + "X-API-Key" => $apiKey, + "Content-Type" => "application/json", + "Accept" => "application/json", + ], + ]; + + // Body-Daten hinzufügen wenn vorhanden + if (!empty($data) && in_array($method, ["POST", "PUT", "PATCH"])) { + $options["json"] = $data; + } + + // API-Request ausführen + $response = $client->request($method, $url, $options); + $statusCode = $response->getStatusCode(); + $body = (string) $response->getBody(); + + // JSON-Antwort dekodieren + $responseData = json_decode($body, true); + + // Logging für Debugging + logModuleCall( + "keyhelpmanager", + $method . " " . $endpoint, + $data, + $statusCode . " - " . $body, + $responseData, + [$apiKey], // API-Key in Logs maskieren + ); + + // Erfolgreiche Antworten (2xx) + if ($statusCode >= 200 && $statusCode < 300) { + return [ + "success" => true, + "data" => $responseData, + "status_code" => $statusCode, + ]; + } + + // Fehlerbehandlung + $errorMessage = "KeyHelp API-Fehler: "; + + if (isset($responseData["message"])) { + $errorMessage .= $responseData["message"]; + } elseif (isset($responseData["error"])) { + $errorMessage .= $responseData["error"]; + } else { + $errorMessage .= sprintf("HTTP Status %d - %s", $statusCode, $body); + } + + return [ + "success" => false, + "error" => $errorMessage, + "status_code" => $statusCode, + ]; + } catch (\GuzzleHttp\Exception\ConnectException $e) { + return [ + "success" => false, + "error" => + "Verbindung zum KeyHelp-Server fehlgeschlagen: " . + $e->getMessage(), + ]; + } catch (\GuzzleHttp\Exception\RequestException $e) { + return [ + "success" => false, + "error" => "API-Request fehlgeschlagen: " . $e->getMessage(), + ]; + } catch (\Exception $e) { + return [ + "success" => false, + "error" => "Unerwarteter Fehler: " . $e->getMessage(), + ]; + } +} + +/** + * Account erstellen + * + * Wird von WHMCS nach erfolgreicher Bezahlung aufgerufen. + * Erstellt einen neuen Benutzer-Account in KeyHelp. + * + * @param array $params WHMCS-Parameter + * @return string Erfolgs- oder Fehlermeldung + */ +function keyhelpmanager_CreateAccount(array $params) +{ + try { + // Extrahiere notwendige Parameter + $domain = $params["domain"] ?? ""; + $username = $params["username"] ?? ""; + $password = $params["password"] ?? ""; + $clientEmail = $params["clientsdetails"]["email"] ?? ""; + $firstName = $params["clientsdetails"]["firstname"] ?? ""; + $lastName = $params["clientsdetails"]["lastname"] ?? ""; + + // Validierung + if (empty($domain)) { + return "Domain ist erforderlich."; + } + + if (empty($username)) { + // Generiere Benutzernamen aus Domain wenn nicht vorhanden + $username = _keyhelpmanager_GenerateUsername($domain); + } + + if (empty($password)) { + // Generiere sicheres Passwort wenn nicht vorhanden + $password = _keyhelpmanager_GeneratePassword(); + } + + // Account-Daten für KeyHelp API vorbereiten + $accountData = [ + "login_name" => $username, + "password" => $password, + "email" => $clientEmail, + "display_name" => trim($firstName . " " . $lastName), + ]; + + // Optional: Plan/Tarif aus konfigurierbaren Optionen + if (!empty($params["configoptions"]["KeyHelp Plan"])) { + $accountData["plan"] = $params["configoptions"]["KeyHelp Plan"]; + } + + // Benutzer über API erstellen + $result = _keyhelpmanager_APIRequest( + $params, + "/users", + "POST", + $accountData, + ); + + if (!$result["success"]) { + return $result["error"]; + } + + $userId = $result["data"]["id"] ?? null; + + if (empty($userId)) { + return "Benutzer wurde erstellt, aber keine User-ID zurückgegeben."; + } + + // Domain zum Benutzer hinzufügen + $domainData = [ + "domain_name" => $domain, + "user_id" => $userId, + ]; + + $domainResult = _keyhelpmanager_APIRequest( + $params, + "/domains", + "POST", + $domainData, + ); + + if (!$domainResult["success"]) { + // Rollback: Benutzer wieder löschen + _keyhelpmanager_APIRequest($params, "/users/" . $userId, "DELETE"); + return "Domain konnte nicht hinzugefügt werden: " . + $domainResult["error"]; + } + + // Speichere Username und Passwort in WHMCS Custom Fields + _keyhelpmanager_SaveAccountDetails($params["serviceid"], [ + "username" => $username, + "password" => $password, + "userid" => $userId, + ]); + + return "success"; + } catch (\Exception $e) { + return "Fehler beim Erstellen des Accounts: " . $e->getMessage(); + } +} + +/** + * Account sperren + * + * Wird von WHMCS aufgerufen, wenn ein Account gesperrt werden soll + * (z.B. bei Zahlungsverzug). + * + * @param array $params WHMCS-Parameter + * @return string Erfolgs- oder Fehlermeldung + */ +function keyhelpmanager_SuspendAccount(array $params) +{ + try { + $userId = _keyhelpmanager_GetUserId($params); + + if (empty($userId)) { + return "Benutzer-ID nicht gefunden. Account wurde möglicherweise nicht korrekt erstellt."; + } + + // Benutzer-Status auf "gesperrt" setzen + $updateData = [ + "is_locked" => true, + ]; + + $result = _keyhelpmanager_APIRequest( + $params, + "/users/" . $userId, + "PUT", + $updateData, + ); + + if (!$result["success"]) { + return $result["error"]; + } + + return "success"; + } catch (\Exception $e) { + return "Fehler beim Sperren des Accounts: " . $e->getMessage(); + } +} + +/** + * Account entsperren + * + * Wird von WHMCS aufgerufen, wenn ein gesperrter Account wieder + * aktiviert werden soll. + * + * @param array $params WHMCS-Parameter + * @return string Erfolgs- oder Fehlermeldung + */ +function keyhelpmanager_UnsuspendAccount(array $params) +{ + try { + $userId = _keyhelpmanager_GetUserId($params); + + if (empty($userId)) { + return "Benutzer-ID nicht gefunden. Account wurde möglicherweise nicht korrekt erstellt."; + } + + // Benutzer-Status auf "aktiv" setzen + $updateData = [ + "is_locked" => false, + ]; + + $result = _keyhelpmanager_APIRequest( + $params, + "/users/" . $userId, + "PUT", + $updateData, + ); + + if (!$result["success"]) { + return $result["error"]; + } + + return "success"; + } catch (\Exception $e) { + return "Fehler beim Entsperren des Accounts: " . $e->getMessage(); + } +} + +/** + * Account löschen + * + * Wird von WHMCS aufgerufen, wenn ein Account endgültig gelöscht werden soll. + * ACHTUNG: Dies löscht alle Daten unwiderruflich! + * + * @param array $params WHMCS-Parameter + * @return string Erfolgs- oder Fehlermeldung + */ +function keyhelpmanager_TerminateAccount(array $params) +{ + try { + $userId = _keyhelpmanager_GetUserId($params); + + if (empty($userId)) { + return "Benutzer-ID nicht gefunden. Account wurde möglicherweise bereits gelöscht."; + } + + // Benutzer und alle zugehörigen Daten löschen + $result = _keyhelpmanager_APIRequest( + $params, + "/users/" . $userId, + "DELETE", + ); + + if (!$result["success"]) { + return $result["error"]; + } + + // Entferne gespeicherte Account-Details + _keyhelpmanager_DeleteAccountDetails($params["serviceid"]); + + return "success"; + } catch (\Exception $e) { + return "Fehler beim Löschen des Accounts: " . $e->getMessage(); + } +} + +/** + * Client-Bereich + * + * Gibt Informationen für den Client-Bereich in WHMCS zurück. + * Zeigt Login-Details und Hosting-Statistiken an. + * + * @param array $params WHMCS-Parameter + * @return array Template-Variablen + */ +function keyhelpmanager_ClientArea(array $params) +{ + try { + $accountDetails = _keyhelpmanager_GetAccountDetails( + $params["serviceid"], + ); + $userId = $accountDetails["userid"] ?? null; + + $hostname = + $params["serverhostname"] ?? ($params["configoption1"] ?? ""); + $useSSL = $params["configoption3"] ?? "on"; + $protocol = $useSSL === "on" ? "https" : "http"; + + // Login-URL + $loginUrl = sprintf("%s://%s", $protocol, $hostname); + + // Basis-Informationen + $templateVars = [ + "login_url" => $loginUrl, + "username" => + $accountDetails["username"] ?? + ($params["username"] ?? "Nicht verfügbar"), + "password" => + $accountDetails["password"] ?? + ($params["password"] ?? "••••••••"), + "domain" => $params["domain"] ?? "Nicht verfügbar", + "stats" => [], + "error" => null, + ]; + + // Statistiken von KeyHelp API abrufen wenn User-ID vorhanden + if (!empty($userId)) { + $statsResult = _keyhelpmanager_APIRequest( + $params, + "/users/" . $userId . "/statistics", + "GET", + ); + + if ($statsResult["success"] && isset($statsResult["data"])) { + $stats = $statsResult["data"]; + + $templateVars["stats"] = [ + "disk_used" => _keyhelpmanager_FormatBytes( + $stats["disk_usage"] ?? 0, + ), + "disk_limit" => _keyhelpmanager_FormatBytes( + $stats["disk_limit"] ?? 0, + ), + "disk_percent" => _keyhelpmanager_CalculatePercent( + $stats["disk_usage"] ?? 0, + $stats["disk_limit"] ?? 0, + ), + "bandwidth_used" => _keyhelpmanager_FormatBytes( + $stats["traffic_usage"] ?? 0, + ), + "bandwidth_limit" => _keyhelpmanager_FormatBytes( + $stats["traffic_limit"] ?? 0, + ), + "bandwidth_percent" => _keyhelpmanager_CalculatePercent( + $stats["traffic_usage"] ?? 0, + $stats["traffic_limit"] ?? 0, + ), + "domains" => $stats["domains_count"] ?? 0, + "databases" => $stats["databases_count"] ?? 0, + "email_accounts" => $stats["email_accounts_count"] ?? 0, + ]; + } + } + + return [ + "templatefile" => "clientarea", + "vars" => $templateVars, + ]; + } catch (\Exception $e) { + return [ + "templatefile" => "clientarea", + "vars" => [ + "error" => + "Fehler beim Laden der Account-Informationen: " . + $e->getMessage(), + ], + ]; + } +} + +/** + * Admin-Login-Link (Single Sign-On) + * + * Erstellt einen direkten Login-Link für Admins, um sich im KeyHelp-Panel + * des Kunden anzumelden, ohne das Passwort eingeben zu müssen. + * + * @param array $params WHMCS-Parameter + * @return array Login-Link-Konfiguration + */ +function keyhelpmanager_LoginLink(array $params) +{ + try { + $accountDetails = _keyhelpmanager_GetAccountDetails( + $params["serviceid"], + ); + $userId = $accountDetails["userid"] ?? null; + + if (empty($userId)) { + return [ + "success" => false, + "errorMsg" => "Benutzer-ID nicht gefunden.", + ]; + } + + // Session-Token von KeyHelp API anfordern + $sessionData = [ + "user_id" => $userId, + "lifetime" => 300, // 5 Minuten Gültigkeit + ]; + + $result = _keyhelpmanager_APIRequest( + $params, + "/sessions", + "POST", + $sessionData, + ); + + if (!$result["success"]) { + return [ + "success" => false, + "errorMsg" => + "Login-Session konnte nicht erstellt werden: " . + $result["error"], + ]; + } + + $sessionToken = $result["data"]["token"] ?? null; + + if (empty($sessionToken)) { + return [ + "success" => false, + "errorMsg" => "Kein Session-Token erhalten.", + ]; + } + + // Login-URL mit Session-Token + $hostname = + $params["serverhostname"] ?? ($params["configoption1"] ?? ""); + $useSSL = $params["configoption3"] ?? "on"; + $protocol = $useSSL === "on" ? "https" : "http"; + + $loginUrl = sprintf( + "%s://%s/login?token=%s", + $protocol, + $hostname, + $sessionToken, + ); + + return [ + "success" => true, + "redirectTo" => $loginUrl, + ]; + } catch (\Exception $e) { + return [ + "success" => false, + "errorMsg" => + "Fehler beim Erstellen des Login-Links: " . $e->getMessage(), + ]; + } +} + +/** + * Passwort ändern + * + * Ermöglicht das Ändern des Passworts für einen KeyHelp-Account. + * + * @param array $params WHMCS-Parameter + * @return string Erfolgs- oder Fehlermeldung + */ +function keyhelpmanager_ChangePassword(array $params) +{ + try { + $userId = _keyhelpmanager_GetUserId($params); + $newPassword = $params["password"] ?? ""; + + if (empty($userId)) { + return "Benutzer-ID nicht gefunden."; + } + + if (empty($newPassword)) { + return "Neues Passwort ist erforderlich."; + } + + // Passwort über API ändern + $updateData = [ + "password" => $newPassword, + ]; + + $result = _keyhelpmanager_APIRequest( + $params, + "/users/" . $userId, + "PUT", + $updateData, + ); + + if (!$result["success"]) { + return $result["error"]; + } + + // Aktualisiere gespeichertes Passwort + _keyhelpmanager_UpdateAccountDetail( + $params["serviceid"], + "password", + $newPassword, + ); + + return "success"; + } catch (\Exception $e) { + return "Fehler beim Ändern des Passworts: " . $e->getMessage(); + } +} + +/** + * Test-Verbindung + * + * Testet die Verbindung zur KeyHelp-API. + * + * @param array $params WHMCS-Parameter + * @return array Test-Ergebnis + */ +function keyhelpmanager_TestConnection(array $params) +{ + try { + // Einfache API-Abfrage zum Testen + $result = _keyhelpmanager_APIRequest($params, "/server/version", "GET"); + + if (!$result["success"]) { + return [ + "success" => false, + "error" => $result["error"], + ]; + } + + $version = $result["data"]["version"] ?? "Unbekannt"; + + return [ + "success" => true, + "message" => sprintf( + "Verbindung erfolgreich! KeyHelp Version: %s", + $version, + ), + ]; + } catch (\Exception $e) { + return [ + "success" => false, + "error" => $e->getMessage(), + ]; + } +} + +// ============================================================================ +// HILFSFUNKTIONEN +// ============================================================================ + +/** + * Generiert einen sicheren Benutzernamen aus einer Domain + * + * @param string $domain Domain-Name + * @return string Generierter Benutzername + */ +function _keyhelpmanager_GenerateUsername(string $domain): string +{ + // Entferne TLD und Sonderzeichen + $username = preg_replace('/\.[^.]+$/', "", $domain); + $username = preg_replace("/[^a-z0-9]/i", "", $username); + $username = strtolower($username); + + // Begrenze auf 16 Zeichen + $username = substr($username, 0, 16); + + // Füge zufällige Zahlen hinzu wenn zu kurz + if (strlen($username) < 6) { + $username .= rand(1000, 9999); + } + + return $username; +} + +/** + * Generiert ein sicheres Zufallspasswort + * + * @param int $length Passwort-Länge + * @return string Generiertes Passwort + */ +function _keyhelpmanager_GeneratePassword(int $length = 16): string +{ + $chars = + 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+'; + $password = ""; + $charsLength = strlen($chars); + + for ($i = 0; $i < $length; $i++) { + $password .= $chars[random_int(0, $charsLength - 1)]; + } + + return $password; +} + +/** + * Speichert Account-Details in der WHMCS-Datenbank + * + * @param int $serviceId Service-ID + * @param array $details Account-Details (username, password, userid) + * @return void + */ +function _keyhelpmanager_SaveAccountDetails( + int $serviceId, + array $details, +): void { + try { + foreach ($details as $key => $value) { + Capsule::table("tblhosting") + ->where("id", $serviceId) + ->update([ + $key === "username" ? "username" : "password" => $value, + ]); + } + + // Speichere userid in Custom Field oder Service Properties + if (isset($details["userid"])) { + Capsule::table("tblcustomfieldsvalues")->updateOrInsert( + [ + "relid" => $serviceId, + "fieldid" => _keyhelpmanager_GetCustomFieldId( + "KeyHelp User ID", + ), + ], + [ + "value" => $details["userid"], + ], + ); + } + } catch (\Exception $e) { + logActivity( + "KeyHelpManager: Fehler beim Speichern der Account-Details: " . + $e->getMessage(), + ); + } +} + +/** + * Lädt Account-Details aus der WHMCS-Datenbank + * + * @param int $serviceId Service-ID + * @return array Account-Details + */ +function _keyhelpmanager_GetAccountDetails(int $serviceId): array +{ + try { + $service = Capsule::table("tblhosting") + ->where("id", $serviceId) + ->first(); + + $userid = Capsule::table("tblcustomfieldsvalues") + ->where("relid", $serviceId) + ->where( + "fieldid", + _keyhelpmanager_GetCustomFieldId("KeyHelp User ID"), + ) + ->value("value"); + + return [ + "username" => $service->username ?? "", + "password" => decrypt($service->password ?? ""), + "userid" => $userid ?? null, + ]; + } catch (\Exception $e) { + logActivity( + "KeyHelpManager: Fehler beim Laden der Account-Details: " . + $e->getMessage(), + ); + return []; + } +} + +/** + * Holt die KeyHelp User-ID für einen Service + * + * @param array $params WHMCS-Parameter + * @return int|null User-ID oder null + */ +function _keyhelpmanager_GetUserId(array $params): ?int +{ + $accountDetails = _keyhelpmanager_GetAccountDetails($params["serviceid"]); + return $accountDetails["userid"] ?? null; +} + +/** + * Aktualisiert ein einzelnes Account-Detail + * + * @param int $serviceId Service-ID + * @param string $field Feldname + * @param string $value Wert + * @return void + */ +function _keyhelpmanager_UpdateAccountDetail( + int $serviceId, + string $field, + string $value, +): void { + try { + if ($field === "username" || $field === "password") { + Capsule::table("tblhosting") + ->where("id", $serviceId) + ->update([ + $field => $value, + ]); + } + } catch (\Exception $e) { + logActivity( + "KeyHelpManager: Fehler beim Aktualisieren von " . + $field . + ": " . + $e->getMessage(), + ); + } +} + +/** + * Löscht gespeicherte Account-Details + * + * @param int $serviceId Service-ID + * @return void + */ +function _keyhelpmanager_DeleteAccountDetails(int $serviceId): void +{ + try { + Capsule::table("tblcustomfieldsvalues") + ->where("relid", $serviceId) + ->delete(); + } catch (\Exception $e) { + logActivity( + "KeyHelpManager: Fehler beim Löschen der Account-Details: " . + $e->getMessage(), + ); + } +} + +/** + * Holt oder erstellt die Custom Field ID für ein Feld + * + * @param string $fieldName Feldname + * @return int Field-ID + */ +function _keyhelpmanager_GetCustomFieldId(string $fieldName): int +{ + try { + $field = Capsule::table("tblcustomfields") + ->where("fieldname", $fieldName) + ->where("type", "product") + ->first(); + + if (!$field) { + // Erstelle Custom Field wenn nicht vorhanden + $fieldId = Capsule::table("tblcustomfields")->insertGetId([ + "type" => "product", + "fieldname" => $fieldName, + "fieldtype" => "text", + "description" => "", + "adminonly" => "on", + ]); + + return $fieldId; + } + + return $field->id; + } catch (\Exception $e) { + logActivity( + "KeyHelpManager: Fehler beim Abrufen der Custom Field ID: " . + $e->getMessage(), + ); + return 0; + } +} + +/** + * Formatiert Bytes in eine lesbare Größe + * + * @param int $bytes Bytes + * @return string Formatierte Größe + */ +function _keyhelpmanager_FormatBytes(int $bytes): string +{ + $units = ["B", "KB", "MB", "GB", "TB"]; + $power = $bytes > 0 ? floor(log($bytes, 1024)) : 0; + + return number_format($bytes / pow(1024, $power), 2, ",", ".") . + " " . + $units[$power]; +} + +/** + * Berechnet Prozentsatz + * + * @param int $used Verbrauchter Wert + * @param int $limit Limit + * @return float Prozentsatz + */ +function _keyhelpmanager_CalculatePercent(int $used, int $limit): float +{ + if ($limit == 0) { + return 0; + } + + return round(($used / $limit) * 100, 2); +} diff --git a/modules/servers/keyhelpmanager/templates/clientarea.tpl b/modules/servers/keyhelpmanager/templates/clientarea.tpl new file mode 100644 index 0000000..40b6a03 --- /dev/null +++ b/modules/servers/keyhelpmanager/templates/clientarea.tpl @@ -0,0 +1,258 @@ +{** + * KeyHelp Manager - Client Area Template + * + * Zeigt Login-Details und Account-Statistiken für Kunden an + *} + +
{$domain}
+