feat: Initial commit of KeyHelp Manager module

This commit is contained in:
Kevin Feiler
2025-10-15 22:29:11 +02:00
parent 4df2eddc6a
commit 351da5fe19
8 changed files with 2584 additions and 0 deletions

70
.gitignore vendored Normal file
View File

@@ -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

216
CHANGELOG.md Normal file
View File

@@ -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

631
INSTALLATION.md Normal file
View File

@@ -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.

21
LICENSE Normal file
View File

@@ -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.

373
PROJECT_STRUCTURE.md Normal file
View File

@@ -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

54
composer.json Normal file
View File

@@ -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
}

View File

@@ -0,0 +1,961 @@
<?php
/**
* WHMCS KeyHelp Manager Provisioning Module
*
* @author Kevin Feiler <info@avvgo.de>
* @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);
}

View File

@@ -0,0 +1,258 @@
{**
* KeyHelp Manager - Client Area Template
*
* Zeigt Login-Details und Account-Statistiken für Kunden an
*}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<i class="fas fa-server"></i> KeyHelp Hosting Account
</h3>
</div>
<div class="panel-body">
{if $error}
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle"></i> {$error}
</div>
{else}
{* Login-Informationen *}
<div class="row">
<div class="col-md-12">
<h4><i class="fas fa-sign-in-alt"></i> Login-Informationen</h4>
<hr>
</div>
</div>
<div class="row">
<div class="col-sm-4 text-right">
<strong>KeyHelp Login-URL:</strong>
</div>
<div class="col-sm-8">
<a href="{$login_url}" target="_blank" class="btn btn-success btn-sm">
<i class="fas fa-external-link-alt"></i> {$login_url}
</a>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="col-sm-4 text-right">
<strong>Benutzername:</strong>
</div>
<div class="col-sm-8">
<div class="input-group">
<input type="text" class="form-control" value="{$username}" readonly id="kh-username">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="copyToClipboard('kh-username')" title="Kopieren">
<i class="fas fa-copy"></i>
</button>
</span>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="col-sm-4 text-right">
<strong>Passwort:</strong>
</div>
<div class="col-sm-8">
<div class="input-group">
<input type="password" class="form-control" value="{$password}" readonly id="kh-password">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="togglePassword('kh-password')" title="Anzeigen/Verbergen">
<i class="fas fa-eye" id="kh-password-icon"></i>
</button>
<button class="btn btn-default" type="button" onclick="copyToClipboard('kh-password')" title="Kopieren">
<i class="fas fa-copy"></i>
</button>
</span>
</div>
</div>
</div>
<div class="row" style="margin-top: 10px;">
<div class="col-sm-4 text-right">
<strong>Domain:</strong>
</div>
<div class="col-sm-8">
<code>{$domain}</code>
</div>
</div>
{* Account-Statistiken *}
{if $stats}
<div class="row" style="margin-top: 30px;">
<div class="col-md-12">
<h4><i class="fas fa-chart-bar"></i> Account-Statistiken</h4>
<hr>
</div>
</div>
{* Speicherplatz *}
{if $stats.disk_used}
<div class="row" style="margin-top: 15px;">
<div class="col-sm-4 text-right">
<strong>Speicherplatz:</strong>
</div>
<div class="col-sm-8">
<div class="progress" style="margin-bottom: 5px;">
<div class="progress-bar {if $stats.disk_percent >= 90}progress-bar-danger{elseif $stats.disk_percent >= 75}progress-bar-warning{else}progress-bar-success{/if}"
role="progressbar"
aria-valuenow="{$stats.disk_percent}"
aria-valuemin="0"
aria-valuemax="100"
style="width: {$stats.disk_percent}%">
{$stats.disk_percent}%
</div>
</div>
<small class="text-muted">
{$stats.disk_used} von {$stats.disk_limit} verwendet
</small>
</div>
</div>
{/if}
{* Bandbreite / Traffic *}
{if $stats.bandwidth_used}
<div class="row" style="margin-top: 15px;">
<div class="col-sm-4 text-right">
<strong>Traffic (Monat):</strong>
</div>
<div class="col-sm-8">
<div class="progress" style="margin-bottom: 5px;">
<div class="progress-bar {if $stats.bandwidth_percent >= 90}progress-bar-danger{elseif $stats.bandwidth_percent >= 75}progress-bar-warning{else}progress-bar-info{/if}"
role="progressbar"
aria-valuenow="{$stats.bandwidth_percent}"
aria-valuemin="0"
aria-valuemax="100"
style="width: {$stats.bandwidth_percent}%">
{$stats.bandwidth_percent}%
</div>
</div>
<small class="text-muted">
{$stats.bandwidth_used} von {$stats.bandwidth_limit} verwendet
</small>
</div>
</div>
{/if}
{* Weitere Statistiken *}
<div class="row" style="margin-top: 20px;">
<div class="col-sm-4 col-xs-6 text-center">
<div class="panel panel-default">
<div class="panel-body">
<h3 class="text-primary" style="margin: 0;">
<i class="fas fa-globe"></i> {$stats.domains}
</h3>
<small class="text-muted">Domains</small>
</div>
</div>
</div>
<div class="col-sm-4 col-xs-6 text-center">
<div class="panel panel-default">
<div class="panel-body">
<h3 class="text-success" style="margin: 0;">
<i class="fas fa-database"></i> {$stats.databases}
</h3>
<small class="text-muted">Datenbanken</small>
</div>
</div>
</div>
<div class="col-sm-4 col-xs-12 text-center">
<div class="panel panel-default">
<div class="panel-body">
<h3 class="text-info" style="margin: 0;">
<i class="fas fa-envelope"></i> {$stats.email_accounts}
</h3>
<small class="text-muted">E-Mail-Konten</small>
</div>
</div>
</div>
</div>
{/if}
{* Schnellzugriff-Button *}
<div class="row" style="margin-top: 20px;">
<div class="col-md-12 text-center">
<a href="{$login_url}" target="_blank" class="btn btn-primary btn-lg">
<i class="fas fa-sign-in-alt"></i> Jetzt zu KeyHelp einloggen
</a>
</div>
</div>
{/if}
</div>
</div>
{* JavaScript für Funktionalität *}
<script type="text/javascript">
function togglePassword(fieldId) {
var field = document.getElementById(fieldId);
var icon = document.getElementById(fieldId + '-icon');
if (field.type === "password") {
field.type = "text";
icon.classList.remove('fa-eye');
icon.classList.add('fa-eye-slash');
} else {
field.type = "password";
icon.classList.remove('fa-eye-slash');
icon.classList.add('fa-eye');
}
}
function copyToClipboard(fieldId) {
var field = document.getElementById(fieldId);
field.select();
field.setSelectionRange(0, 99999); // Für mobile Geräte
try {
document.execCommand('copy');
// Visuelles Feedback
var btn = event.target.closest('button');
var originalHTML = btn.innerHTML;
btn.innerHTML = '<i class="fas fa-check"></i>';
btn.classList.add('btn-success');
setTimeout(function() {
btn.innerHTML = originalHTML;
btn.classList.remove('btn-success');
}, 1500);
} catch (err) {
alert('Kopieren fehlgeschlagen. Bitte manuell kopieren.');
}
// Deselektiere das Feld
window.getSelection().removeAllRanges();
}
</script>
<style>
.panel {
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.input-group-btn button {
border-left: 0;
}
.progress {
height: 24px;
}
.progress-bar {
line-height: 24px;
font-weight: bold;
}
@media (max-width: 768px) {
.text-right {
text-align: left !important;
margin-bottom: 5px;
}
}
</style>