Englische Übersetzungen für die restlichen Admin-Seiten
API-Schlüssel, Integration & Wartung, Voucher-Import, Backup & Restore, Reporting, Sicherheit (2FA) und Audit-Log waren fest auf Deutsch verdrahtet, obwohl in der Kopfzeile ein DE/EN-Umschalter sitzt. Diese Seiten laufen jetzt komplett über lang/de.php bzw. lang/en.php. - rund 200 neue Sprachschlüssel, beide Dateien deckungsgleich - Aktionsnamen im Audit-Log werden übersetzt statt fest ausgegeben - Bestätigungsdialoge und Statusmeldungen in JavaScript ebenfalls - admin/security.php initialisiert jetzt I18n und setzt <html lang> passend zur Auswahl Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
30d0ce3a23
commit
850a04d628
16 changed files with 580 additions and 196 deletions
|
|
@ -49,13 +49,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save'])) {
|
|||
$db->setSetting('cleanup_audit_days', max(0, (int)($_POST['cleanup_audit_days'] ?? 0)));
|
||||
$db->setSetting('cleanup_login_days', max(0, (int)($_POST['cleanup_login_days'] ?? 30)));
|
||||
$auth->writeAuditLog($_SESSION['user_id'], 'settings_update', 'config', null, 'Integration/Wartung gespeichert');
|
||||
$success = 'Einstellungen gespeichert.';
|
||||
$success = __('settings_saved');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['test_webhook']) && isset($_GET['token']) && $auth->validateCsrfToken($_GET['token'])) {
|
||||
Notifier::send('✅ Test-Benachrichtigung vom UniFi Voucher System.', ['type' => 'test']);
|
||||
$success = 'Test-Benachrichtigung gesendet (sofern Webhook aktiv & URL gültig).';
|
||||
$success = __('int_webhook_test_sent');
|
||||
}
|
||||
|
||||
$enforce2fa = $db->getSetting('enforce_2fa_admins', '0') === '1';
|
||||
|
|
@ -92,12 +92,12 @@ $adminBase = '';
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Integration & Wartung – <?= htmlspecialchars($appTitle) ?></title>
|
||||
<title><?= __('int_title') ?> – <?= htmlspecialchars($appTitle) ?></title>
|
||||
<?php require __DIR__ . '/../includes/admin_nav.php'; ?>
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1 class="page-title">Integration & Wartung</h1>
|
||||
<p class="page-subtitle">SSO, Webhooks, SMS-Versand und Aufbewahrungsfristen.</p>
|
||||
<h1 class="page-title"><?= __('int_title') ?></h1>
|
||||
<p class="page-subtitle"><?= __('int_subtitle') ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -108,64 +108,64 @@ $adminBase = '';
|
|||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
|
||||
|
||||
<div class="card">
|
||||
<h2>Sicherheitsrichtlinie</h2>
|
||||
<p class="muted">Erzwingt Zwei-Faktor-Authentifizierung für alle Administrator-Konten (lokale Accounts). Admins ohne 2FA werden bei der nächsten Aktion zur Einrichtung geleitet.</p>
|
||||
<label class="chk"><input type="checkbox" name="enforce_2fa_admins" <?= $enforce2fa ? 'checked' : '' ?>> 2FA für Administratoren verpflichtend</label>
|
||||
<label>Tageslimit Voucher pro Nicht-Admin-Benutzer (0 = unbegrenzt)</label>
|
||||
<h2><?= __('int_security') ?></h2>
|
||||
<p class="muted"><?= __('int_security_hint') ?></p>
|
||||
<label class="chk"><input type="checkbox" name="enforce_2fa_admins" <?= $enforce2fa ? 'checked' : '' ?>> <?= __('int_enforce_2fa') ?></label>
|
||||
<label><?= __('int_daily_limit') ?></label>
|
||||
<input class="input" type="number" min="0" name="user_daily_voucher_limit" value="<?= $dailyLimit ?>" style="max-width:200px;">
|
||||
<label>Session-Speicher</label>
|
||||
<label><?= __('int_session_driver') ?></label>
|
||||
<select class="input" name="session_driver" style="max-width:340px;">
|
||||
<option value="php" <?= $sessionDriver==='php'?'selected':'' ?>>PHP-Standard (Dateien)</option>
|
||||
<option value="db" <?= $sessionDriver==='db'?'selected':'' ?>>Datenbank (ermöglicht „überall abmelden")</option>
|
||||
<option value="php" <?= $sessionDriver==='php'?'selected':'' ?>><?= __('int_session_php') ?></option>
|
||||
<option value="db" <?= $sessionDriver==='db'?'selected':'' ?>><?= __('int_session_db') ?></option>
|
||||
</select>
|
||||
<label>Captcha im öffentlichen Modus</label>
|
||||
<label><?= __('int_captcha') ?></label>
|
||||
<select class="input" name="captcha_mode" style="max-width:340px;">
|
||||
<option value="off" <?= $captchaMode==='off'?'selected':'' ?>>Aus</option>
|
||||
<option value="math" <?= $captchaMode==='math'?'selected':'' ?>>Rechenaufgabe (ohne externen Dienst)</option>
|
||||
<option value="off" <?= $captchaMode==='off'?'selected':'' ?>><?= __('int_captcha_off') ?></option>
|
||||
<option value="math" <?= $captchaMode==='math'?'selected':'' ?>><?= __('int_captcha_math') ?></option>
|
||||
<option value="hcaptcha" <?= $captchaMode==='hcaptcha'?'selected':'' ?>>hCaptcha</option>
|
||||
</select>
|
||||
<div class="row3" style="margin-top:10px;">
|
||||
<div><label>hCaptcha Site-Key</label><input class="input" type="text" name="captcha_site_key" value="<?= htmlspecialchars($captchaSiteKey) ?>"></div>
|
||||
<div><label>hCaptcha Secret<?= $captchaSecretSet ? ' (gesetzt)' : '' ?></label><input class="input" type="password" name="captcha_secret" placeholder="<?= $captchaSecretSet ? '••••••• (leer = unverändert)' : '' ?>"></div>
|
||||
<div><label>hCaptcha Secret<?= $captchaSecretSet ? __('int_secret_set') : '' ?></label><input class="input" type="password" name="captcha_secret" placeholder="<?= $captchaSecretSet ? __('int_secret_placeholder') : '' ?>"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Reverse-Proxy</h2>
|
||||
<p class="muted">IP-Adressen vertrauenswürdiger Proxies (kommasepariert). Nur dann wird die echte Client-IP aus <code>X-Forwarded-For</code> für Rate-Limit & Audit verwendet.</p>
|
||||
<h2><?= __('int_proxy') ?></h2>
|
||||
<p class="muted"><?= __('int_proxy_hint') ?> <code>X-Forwarded-For</code> <?= __('int_proxy_hint2') ?></p>
|
||||
<input class="input" type="text" name="trusted_proxy" value="<?= htmlspecialchars($trustedProxy) ?>" placeholder="z.B. 10.0.0.1, 172.18.0.1">
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Webhook-Benachrichtigungen</h2>
|
||||
<p class="muted">Slack-, Microsoft-Teams- oder generische JSON-Webhook-URL. Wird bei Voucher-Erstellung ausgelöst.</p>
|
||||
<label class="chk"><input type="checkbox" name="webhook_enabled" <?= $webhookEnabled ? 'checked' : '' ?>> Webhook aktiv</label>
|
||||
<label>Webhook-URL</label>
|
||||
<h2><?= __('int_webhook') ?></h2>
|
||||
<p class="muted"><?= __('int_webhook_hint') ?></p>
|
||||
<label class="chk"><input type="checkbox" name="webhook_enabled" <?= $webhookEnabled ? 'checked' : '' ?>> <?= __('int_webhook_active') ?></label>
|
||||
<label><?= __('int_webhook_url') ?></label>
|
||||
<input class="input" type="url" name="webhook_url" value="<?= htmlspecialchars($webhookUrl) ?>" placeholder="https://hooks.slack.com/services/…">
|
||||
<div style="margin-top:12px;">
|
||||
<a class="btn btn-secondary" href="?test_webhook=1&token=<?= urlencode($csrf) ?>">Test senden</a>
|
||||
<a class="btn btn-secondary" href="?test_webhook=1&token=<?= urlencode($csrf) ?>"><?= __('int_webhook_test') ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>SMS-Versand (Twilio)</h2>
|
||||
<p class="muted">Voucher-Codes optional per SMS versenden. Erfordert ein Twilio-Konto.</p>
|
||||
<label class="chk"><input type="checkbox" name="sms_enabled" <?= $smsEnabled ? 'checked' : '' ?>> SMS-Versand aktiv</label>
|
||||
<h2><?= __('int_sms') ?></h2>
|
||||
<p class="muted"><?= __('int_sms_hint') ?></p>
|
||||
<label class="chk"><input type="checkbox" name="sms_enabled" <?= $smsEnabled ? 'checked' : '' ?>> <?= __('int_sms_active') ?></label>
|
||||
<div class="row3" style="margin-top:10px;">
|
||||
<div><label>Account SID</label><input class="input" type="text" name="twilio_sid" value="<?= htmlspecialchars($twilioSid) ?>"></div>
|
||||
<div><label>Auth Token<?= $twilioTokenSet ? ' (gesetzt)' : '' ?></label><input class="input" type="password" name="twilio_token" placeholder="<?= $twilioTokenSet ? '••••••• (leer = unverändert)' : '' ?>"></div>
|
||||
<div><label>Absender (From)</label><input class="input" type="text" name="twilio_from" value="<?= htmlspecialchars($twilioFrom) ?>" placeholder="+49…"></div>
|
||||
<div><label>Auth Token<?= $twilioTokenSet ? __('int_secret_set') : '' ?></label><input class="input" type="password" name="twilio_token" placeholder="<?= $twilioTokenSet ? __('int_secret_placeholder') : '' ?>"></div>
|
||||
<div><label><?= __('int_sms_from') ?></label><input class="input" type="text" name="twilio_from" value="<?= htmlspecialchars($twilioFrom) ?>" placeholder="+49…"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Single Sign-On (OpenID Connect)</h2>
|
||||
<p class="muted">Generischer OIDC-Provider (z.B. Keycloak, Authentik, Google, Auth0). Redirect-URI: <code><?= htmlspecialchars(((!empty($_SERVER['HTTPS'])&&$_SERVER['HTTPS']!=='off')?'https':'http').'://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['SCRIPT_NAME']),'/').'/../oidc_callback.php') ?></code></p>
|
||||
<label class="chk"><input type="checkbox" name="oidc_enabled" <?= $oidcEnabled ? 'checked' : '' ?>> OIDC-Login aktiv</label>
|
||||
<h2><?= __('int_sso') ?></h2>
|
||||
<p class="muted"><?= __('int_sso_hint') ?> <code><?= htmlspecialchars(((!empty($_SERVER['HTTPS'])&&$_SERVER['HTTPS']!=='off')?'https':'http').'://'.$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['SCRIPT_NAME']),'/').'/../oidc_callback.php') ?></code></p>
|
||||
<label class="chk"><input type="checkbox" name="oidc_enabled" <?= $oidcEnabled ? 'checked' : '' ?>> <?= __('int_sso_active') ?></label>
|
||||
<div class="row3" style="margin-top:10px;">
|
||||
<div><label>Button-Text</label><input class="input" type="text" name="oidc_name" value="<?= htmlspecialchars($oidcName) ?>"></div>
|
||||
<div><label><?= __('int_sso_button') ?></label><input class="input" type="text" name="oidc_name" value="<?= htmlspecialchars($oidcName) ?>"></div>
|
||||
<div><label>Client ID</label><input class="input" type="text" name="oidc_client_id" value="<?= htmlspecialchars($oidcClientId) ?>"></div>
|
||||
<div><label>Client Secret<?= $oidcSecretSet ? ' (gesetzt)' : '' ?></label><input class="input" type="password" name="oidc_client_secret" placeholder="<?= $oidcSecretSet ? '••••••• (leer = unverändert)' : '' ?>"></div>
|
||||
<div><label>Client Secret<?= $oidcSecretSet ? __('int_secret_set') : '' ?></label><input class="input" type="password" name="oidc_client_secret" placeholder="<?= $oidcSecretSet ? __('int_secret_placeholder') : '' ?>"></div>
|
||||
</div>
|
||||
<label>Authorization Endpoint</label><input class="input" type="url" name="oidc_auth_url" value="<?= htmlspecialchars($oidcAuthUrl) ?>" placeholder="https://idp/authorize">
|
||||
<label>Token Endpoint</label><input class="input" type="url" name="oidc_token_url" value="<?= htmlspecialchars($oidcTokenUrl) ?>" placeholder="https://idp/token">
|
||||
|
|
@ -174,18 +174,18 @@ $adminBase = '';
|
|||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2>Datenhaltung & Cleanup (DSGVO)</h2>
|
||||
<p class="muted">Aufbewahrungsfristen in Tagen (0 = deaktiviert). Ausführung per <code>cron_cleanup.php</code> (täglich empfohlen).
|
||||
<?php if ($lastCleanup): ?><br>Letzter Lauf: <?= htmlspecialchars($lastCleanup) ?><?php endif; ?>
|
||||
<h2><?= __('int_cleanup') ?></h2>
|
||||
<p class="muted"><?= __('int_cleanup_hint') ?> <code>cron_cleanup.php</code> <?= __('int_cleanup_hint2') ?>
|
||||
<?php if ($lastCleanup): ?><br><?= __('int_cleanup_last') ?> <?= htmlspecialchars($lastCleanup) ?><?php endif; ?>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div><label>Abgelaufene Voucher</label><input class="input" type="number" min="0" name="cleanup_expired_days" value="<?= $cleanupExpired ?>"></div>
|
||||
<div><label>Audit-Log</label><input class="input" type="number" min="0" name="cleanup_audit_days" value="<?= $cleanupAudit ?>"></div>
|
||||
<div><label>Login-Versuche</label><input class="input" type="number" min="0" name="cleanup_login_days" value="<?= $cleanupLogin ?>"></div>
|
||||
<div><label><?= __('int_cleanup_expired') ?></label><input class="input" type="number" min="0" name="cleanup_expired_days" value="<?= $cleanupExpired ?>"></div>
|
||||
<div><label><?= __('int_cleanup_audit') ?></label><input class="input" type="number" min="0" name="cleanup_audit_days" value="<?= $cleanupAudit ?>"></div>
|
||||
<div><label><?= __('int_cleanup_logins') ?></label><input class="input" type="number" min="0" name="cleanup_login_days" value="<?= $cleanupLogin ?>"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary" type="submit" name="save">Speichern</button>
|
||||
<button class="btn btn-primary" type="submit" name="save"><?= __('btn_save') ?></button>
|
||||
</form>
|
||||
|
||||
</main>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue