requireAdmin();
$db = Database::getInstance();
$appTitle = $db->getSetting('app_title', 'UniFi Voucher System');
// AJAX: SMTP-Test-E-Mail senden
if (isset($_POST['ajax_smtp_test'])) {
header('Content-Type: application/json');
if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) {
echo json_encode(['success' => false, 'message' => 'Ungültiges Token']);
exit;
}
$to = trim($_POST['test_email'] ?? '');
if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
echo json_encode(['success' => false, 'message' => 'Ungültige E-Mail-Adresse']);
exit;
}
$mailer = new Mailer();
$ok = $mailer->sendTestEmail($to);
echo json_encode([
'success' => $ok,
'message' => $ok ? "Test-E-Mail wurde an {$to} gesendet." : 'Versand fehlgeschlagen. Prüfen Sie die SMTP-Einstellungen und den PHP-Fehlerlog.'
]);
exit;
}
$error = '';
$success = '';
// Einstellungen speichern
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_settings'])) {
if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) {
$error = 'Ungültiges Sicherheits-Token';
} else {
try {
$settings = [];
$formType = $_POST['form_type'] ?? '';
// Allgemeine Einstellungen
if ($formType === 'general') {
$settings['app_title'] = trim($_POST['app_title'] ?? '');
$settings['logo_url'] = trim($_POST['logo_url'] ?? '');
$settings['favicon_url'] = trim($_POST['favicon_url'] ?? '');
$settings['instruction_header'] = trim($_POST['instruction_header'] ?? '');
$settings['instruction_text'] = $_POST['instruction_text'] ?? '';
$settings['public_access'] = isset($_POST['public_access']) ? '1' : '0';
}
// M365 Einstellungen
if ($formType === 'm365') {
$settings['m365_client_id'] = trim($_POST['m365_client_id'] ?? '');
$settings['m365_client_secret'] = trim($_POST['m365_client_secret'] ?? '');
$settings['m365_tenant_id'] = trim($_POST['m365_tenant_id'] ?? '');
}
// SMTP Einstellungen
if ($formType === 'smtp') {
$settings['smtp_enabled'] = isset($_POST['smtp_enabled']) ? '1' : '0';
$settings['smtp_host'] = trim($_POST['smtp_host'] ?? '');
$settings['smtp_port'] = trim($_POST['smtp_port'] ?? '587');
$settings['smtp_username'] = trim($_POST['smtp_username'] ?? '');
if (!empty($_POST['smtp_password'])) {
$settings['smtp_password'] = trim($_POST['smtp_password']);
}
$settings['smtp_encryption'] = trim($_POST['smtp_encryption'] ?? 'tls');
$settings['smtp_from_email'] = trim($_POST['smtp_from_email'] ?? '');
$settings['smtp_from_name'] = trim($_POST['smtp_from_name'] ?? '');
}
// E-Mail Templates
if ($formType === 'templates') {
$settings['email_voucher_subject'] = trim($_POST['email_voucher_subject'] ?? '');
$settings['email_voucher_body'] = $_POST['email_voucher_body'] ?? '';
$settings['email_user_notification_subject'] = trim($_POST['email_user_notification_subject'] ?? '');
$settings['email_user_notification_body'] = $_POST['email_user_notification_body'] ?? '';
$settings['system_url'] = trim($_POST['system_url'] ?? '');
}
// System Einstellungen
if ($formType === 'system') {
$settings['tinymce_api_key'] = trim($_POST['tinymce_api_key'] ?? '');
$settings['print_template'] = $_POST['print_template'] ?? '';
}
foreach ($settings as $key => $value) {
$db->setSetting($key, $value);
}
$success = 'Einstellungen erfolgreich gespeichert!';
} catch (Exception $e) {
$error = 'Fehler: ' . $e->getMessage();
}
}
}
// Cron-Token generieren
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['generate_cron_token'])) {
if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) {
$error = 'Ungültiges Sicherheits-Token';
} else {
try {
// Sicheren Token generieren
$newToken = bin2hex(random_bytes(32));
$db->setSetting('cron_token', $newToken);
$success = 'Neuer Cron-Token wurde generiert!';
} catch (Exception $e) {
$error = 'Fehler: ' . $e->getMessage();
}
}
}
// Cron-Token löschen
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_cron_token'])) {
if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) {
$error = 'Ungültiges Sicherheits-Token';
} else {
try {
$db->setSetting('cron_token', '');
$success = 'Cron-Token wurde gelöscht!';
} catch (Exception $e) {
$error = 'Fehler: ' . $e->getMessage();
}
}
}
// Passwort ändern
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_password'])) {
if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) {
$error = 'Ungültiges Sicherheits-Token';
} else {
try {
$currentPassword = $_POST['current_password'];
$newPassword = $_POST['new_password'];
$confirmPassword = $_POST['confirm_password'];
$user = $auth->getCurrentUser();
if (!password_verify($currentPassword, $user['password_hash'])) {
throw new Exception('Aktuelles Passwort ist falsch');
}
if (strlen($newPassword) < 8) {
throw new Exception('Neues Passwort muss mindestens 8 Zeichen lang sein');
}
if ($newPassword !== $confirmPassword) {
throw new Exception('Passwörter stimmen nicht überein');
}
$newHash = password_hash($newPassword, PASSWORD_DEFAULT);
$db->query("UPDATE users SET password_hash = ? WHERE id = ?", [$newHash, $user['id']]);
$success = 'Passwort erfolgreich geändert!';
} catch (Exception $e) {
$error = $e->getMessage();
}
}
}
// Aktuelle Einstellungen laden
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$scriptPath = dirname($_SERVER['SCRIPT_NAME'], 2);
$scriptPath = $scriptPath === '/' ? '' : $scriptPath;
$autoDetectedUrl = $protocol . '://' . $host . $scriptPath;
$currentSettings = [
'app_title' => $db->getSetting('app_title', 'UniFi Voucher System'),
'logo_url' => $db->getSetting('logo_url', ''),
'favicon_url' => $db->getSetting('favicon_url', ''),
'instruction_header' => $db->getSetting('instruction_header', 'So verwenden Sie Ihren Code'),
'instruction_text' => $db->getSetting('instruction_text', 'Verbinden Sie sich mit dem WLAN und geben Sie den Code ein.'),
'public_access' => $db->getSetting('public_access', '0'),
'm365_client_id' => $db->getSetting('m365_client_id', ''),
'm365_client_secret' => $db->getSetting('m365_client_secret', ''),
'm365_tenant_id' => $db->getSetting('m365_tenant_id', ''),
'smtp_enabled' => $db->getSetting('smtp_enabled', '0'),
'smtp_host' => $db->getSetting('smtp_host', ''),
'smtp_port' => $db->getSetting('smtp_port', '587'),
'smtp_username' => $db->getSetting('smtp_username', ''),
'smtp_password' => $db->getSetting('smtp_password', ''),
'smtp_encryption' => $db->getSetting('smtp_encryption', 'tls'),
'smtp_from_email' => $db->getSetting('smtp_from_email', ''),
'smtp_from_name' => $db->getSetting('smtp_from_name', ''),
'system_url' => $db->getSetting('system_url', $autoDetectedUrl),
'email_voucher_subject' => $db->getSetting('email_voucher_subject', '{APP_TITLE} - Ihr WLAN-Zugang'),
'email_voucher_body' => $db->getSetting('email_voucher_body', "Hallo,\n\nIhr Code: {VOUCHER_CODE}\n\nGültigkeit: 8h\nGeräte: {MAX_USES}\nSite: {SITE_NAME}"),
'email_user_notification_subject' => $db->getSetting('email_user_notification_subject', '{APP_TITLE} - Berechtigungen geändert'),
'email_user_notification_body' => $db->getSetting('email_user_notification_body', "Hallo {USER_NAME},\n\n{CHANGES}"),
'tinymce_api_key' => $db->getSetting('tinymce_api_key', ''),
'print_template' => $db->getSetting('print_template', '
{APP_TITLE} WLAN Code {VOUCHER_CODE}
Gültig bis: {EXPIRY_DATE} {EXPIRY_TIME}
Site: {SITE_NAME}
Geräte: {MAX_USES}
{INSTRUCTIONS}
'),
'cron_token' => $db->getSetting('cron_token', ''),
'last_cron_sync' => $db->getSetting('last_cron_sync', '')
];
$currentUser = $auth->getCurrentUser();
$faviconUrl = $db->getSetting('favicon_url', '');
?>
Einstellungen - = htmlspecialchars($appTitle) ?>
= htmlspecialchars($error) ?>
= htmlspecialchars($success) ?>
Allgemein
Cron-Sync
Microsoft 365
SMTP
Templates
System
Passwort
Automatische Voucher-Synchronisation
Was macht der Cron-Job?
Der Cron-Job synchronisiert automatisch alle Voucher von Ihren UniFi Controllern in die lokale Datenbank.
Dadurch werden Dashboard und Voucher-Übersicht sofort beim Öffnen angezeigt, ohne auf die API warten zu müssen.
Cron-Token
Kein Token konfiguriert. Generieren Sie einen Token, um den Cron-Job zu aktivieren.
Token generieren
Token ist aktiv
= htmlspecialchars($currentSettings['cron_token']) ?>
Token kopieren
Neu generieren
Löschen
Cron-Job einrichten
Crontab-Eintrag (Linux/Mac)
Fügen Sie diese Zeile in Ihre Crontab ein (crontab -e):
*/30 * * * * curl -s "= htmlspecialchars($cronUrl) ?>" > /dev/null 2>&1
Dies führt die Synchronisation alle 30 Minuten aus.
Windows Task Scheduler
Erstellen Sie eine geplante Aufgabe mit diesem Befehl:
powershell -Command "Invoke-WebRequest -Uri '= htmlspecialchars($cronUrl) ?>' -UseBasicParsing"
Status
Letzte Synchronisation:
= date('d.m.Y H:i:s', strtotime($currentSettings['last_cron_sync'])) ?>
Noch nie ausgeführt
Token-Status:
Aktiv
Nicht konfiguriert
Jetzt manuell ausführen
E-Mail Templates
Voucher E-Mail
Platzhalter:
{VOUCHER_CODE}
{SITE_NAME}
{MAX_USES}
{APP_TITLE}
{INSTRUCTIONS}
Betreff
E-Mail Text
= htmlspecialchars($currentSettings['email_voucher_body']) ?>
Benutzer-Benachrichtigung
Platzhalter:
{USER_NAME}
{CHANGES}
{APP_TITLE}
{SYSTEM_URL}
Betreff
E-Mail Text
= htmlspecialchars($currentSettings['email_user_notification_body']) ?>
Speichern
System & Erweitert
TinyMCE API Key
Kostenlosen API Key erhalten: tiny.cloud/signup
Ohne Key wird eine eingeschränkte Version geladen.
Druck-Template
Platzhalter:
{VOUCHER_CODE}
{EXPIRY_DATE}
{EXPIRY_TIME}
{SITE_NAME}
{MAX_USES}
{APP_TITLE}
{INSTRUCTIONS}
Speichern
System-Information
PHP Version: = phpversion() ?>
Datenbank: = DB_NAME ?>
Installiert: = date('d.m.Y H:i', filectime(__DIR__ . '/../config.php')) ?>
Version: 2.0.0