requireAdmin(); I18n::init(); $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' => __('error_csrf')]); exit; } $to = trim($_POST['test_email'] ?? ''); if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { echo json_encode(['success' => false, 'message' => __('error_email_invalid')]); 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.' ]); exit; } $error = ''; $success = ''; // Einstellungen speichern if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_settings'])) { if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) { $error = __('error_csrf'); } else { try { $settings = []; $formType = $_POST['form_type'] ?? ''; if ($formType === 'general') { $settings['app_title'] = trim($_POST['app_title'] ?? ''); $settings['logo_url'] = Upload::resolveField('logo_url', (string)$db->getSetting('logo_url', ''), 'image'); $settings['favicon_url'] = Upload::resolveField('favicon_url', (string)$db->getSetting('favicon_url', ''), 'favicon'); $settings['instruction_header'] = trim($_POST['instruction_header'] ?? ''); $settings['instruction_text'] = $_POST['instruction_text'] ?? ''; $settings['public_access'] = isset($_POST['public_access']) ? '1' : '0'; } if ($formType === 'branding') { foreach (['brand_accent', 'brand_accent_dark', 'brand_gradient_from', 'brand_gradient_to'] as $key) { $value = strtolower(trim($_POST[$key] ?? '')); $settings[$key] = preg_match('/^#[0-9a-f]{6}$/', $value) ? $value : ''; } $radius = (int)($_POST['brand_radius'] ?? Ui::DEFAULT_RADIUS); $settings['brand_radius'] = (string)max(0, min(28, $radius)); } if ($formType === 'login') { $settings['login_panel_enabled'] = isset($_POST['login_panel_enabled']) ? '1' : '0'; $settings['login_brand_name'] = trim($_POST['login_brand_name'] ?? ''); $settings['login_logo_url'] = Upload::resolveField('login_logo_url', (string)$db->getSetting('login_logo_url', ''), 'image'); $settings['login_claim_title'] = trim($_POST['login_claim_title'] ?? ''); $settings['login_claim_text'] = trim($_POST['login_claim_text'] ?? ''); $settings['login_features'] = trim($_POST['login_features'] ?? ''); $settings['login_footer'] = trim($_POST['login_footer'] ?? ''); $settings['login_bg_image'] = Upload::resolveField('login_bg_image', (string)$db->getSetting('login_bg_image', ''), 'image'); $settings['login_bg_from'] = trim($_POST['login_bg_from'] ?? ''); $settings['login_bg_to'] = trim($_POST['login_bg_to'] ?? ''); $overlay = (int)($_POST['login_bg_overlay'] ?? 40); $settings['login_bg_overlay'] = (string)max(0, min(90, $overlay)); } if ($formType === 'defaults') { $expMin = (int)($_POST['default_expire_minutes'] ?? 480); $defDev = (int)($_POST['default_max_uses'] ?? 1); $maxDev = (int)($_POST['max_uses_limit'] ?? 10); if ($expMin < 1) $expMin = 480; if ($defDev < 1) $defDev = 1; if ($maxDev < 1) $maxDev = 10; $settings['default_expire_minutes'] = (string)$expMin; $settings['default_max_uses'] = (string)$defDev; $settings['max_uses_limit'] = (string)$maxDev; } 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'] ?? ''); } 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'] ?? ''); } 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'] ?? ''); } if ($formType === 'system') { $settings['print_template'] = $_POST['print_template'] ?? ''; } foreach ($settings as $key => $value) { $db->setSetting($key, $value); } $success = __('settings_saved'); } catch (RuntimeException $e) { $error = $e->getMessage(); } catch (Exception $e) { $error = 'Fehler: ' . $e->getMessage(); } } } // Cron-Token generieren/löschen if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['generate_cron_token'])) { if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) { $error = __('error_csrf'); } else { $db->setSetting('cron_token', bin2hex(random_bytes(32))); $success = 'Neuer Cron-Token wurde generiert!'; } } if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_cron_token'])) { if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) { $error = __('error_csrf'); } else { $db->setSetting('cron_token', ''); $success = 'Cron-Token wurde gelöscht!'; } } // Passwort ändern if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['change_password'])) { if (!$auth->validateCsrfToken($_POST['csrf_token'] ?? '')) { $error = __('error_csrf'); } else { try { $user = $auth->getCurrentUser(); if (!password_verify($_POST['current_password'], $user['password_hash'])) { throw new Exception('Aktuelles Passwort ist falsch'); } if (strlen($_POST['new_password']) < 8) { throw new Exception(__('settings_pw_minlength')); } if ($_POST['new_password'] !== $_POST['confirm_password']) { throw new Exception('Passwörter stimmen nicht überein'); } $db->query("UPDATE users SET password_hash = ? WHERE id = ?", [password_hash($_POST['new_password'], PASSWORD_DEFAULT), $user['id']]); $success = __('settings_pw_changed'); } catch (Exception $e) { $error = $e->getMessage(); } } } $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; $cs = [ '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', ''), 'public_access' => $db->getSetting('public_access', '0'), 'default_expire_minutes' => $db->getSetting('default_expire_minutes', '480'), 'default_max_uses' => $db->getSetting('default_max_uses', '1'), 'max_uses_limit' => $db->getSetting('max_uses_limit', '10'), '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\nhier ist Ihr WLAN-Zugangscode:\n{VOUCHER_CARD}\nMaximale Geräte: {MAX_USES}
\nStandort: {SITE_NAME}\n\n{INSTRUCTIONS}\n\nViele Grüße\n{APP_TITLE}"), '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}"), 'print_template' => $db->getSetting('print_template', Ui::defaultPrintTemplate()), 'brand_accent' => $db->getSetting('brand_accent', '') ?: Ui::DEFAULT_ACCENT, 'brand_accent_dark' => $db->getSetting('brand_accent_dark', '') ?: Ui::DEFAULT_ACCENT_DARK, 'brand_gradient_from' => $db->getSetting('brand_gradient_from', '') ?: Ui::DEFAULT_GRADIENT_FROM, 'brand_gradient_to' => $db->getSetting('brand_gradient_to', '') ?: Ui::DEFAULT_GRADIENT_TO, 'brand_radius' => $db->getSetting('brand_radius', (string)Ui::DEFAULT_RADIUS), 'login_panel_enabled' => $db->getSetting('login_panel_enabled', '1'), 'login_brand_name' => $db->getSetting('login_brand_name', ''), 'login_logo_url' => $db->getSetting('login_logo_url', ''), 'login_claim_title' => $db->getSetting('login_claim_title', ''), 'login_claim_text' => $db->getSetting('login_claim_text', ''), 'login_features' => $db->getSetting('login_features', ''), 'login_footer' => $db->getSetting('login_footer', ''), 'login_bg_image' => $db->getSetting('login_bg_image', ''), 'login_bg_from' => $db->getSetting('login_bg_from', '#3b2f8f'), 'login_bg_to' => $db->getSetting('login_bg_to', '#6d5ce7'), 'login_bg_overlay' => $db->getSetting('login_bg_overlay', '40'), 'cron_token' => $db->getSetting('cron_token', ''), 'last_cron_sync' => $db->getSetting('last_cron_sync', ''), ]; $currentPage = 'settings'; $adminBase = ''; ?> <?= __('settings_title') ?> - <?= htmlspecialchars($appTitle) ?>


>

Gültigkeits-Referenz

60 Min = 1 Stunde  |  480 Min = 8 Stunden  |  1440 Min = 1 Tag  |  10080 Min = 1 Woche  |  43200 Min = 30 Tage

>


Der Cron-Job synchronisiert automatisch alle Voucher von Ihren UniFi Controllern in die lokale Datenbank.


Kein Token konfiguriert.

Crontab-Eintrag (alle 30 Min)

*/30 * * * * curl -s "" > /dev/null 2>&1

Letzte Synchronisation:

Microsoft 365

Azure AD App

Redirect URI: /m365_callback.php

SMTP

>

SMTP testen

E-Mail Templates

Auto:

{VOUCHER_CARD}{VOUCHER_CODE}{SITE_NAME}{MAX_USES}{APP_TITLE}{INSTRUCTIONS}


{USER_NAME}{CHANGES}{APP_TITLE}{SYSTEM_URL}

System & Erweitert

WYSIWYG-Editor

assets/vendor/


Druck-Template

{QR_CODE}{VOUCHER_CODE}{EXPIRY_DATE}{EXPIRY_TIME}{SITE_NAME}{MAX_USES}{APP_TITLE}{INSTRUCTIONS}


System-Information

PHP Version:
Datenbank:
Version:2.1.0