Erweiterte Features (1/2): Trusted-Proxy-IP, Bandbreitenlimits, 2FA

- Schema: updater/migrations/0002 + database.sql (users.totp_*, voucher_templates
  qos_*, neue Tabelle api_keys)
- Trusted-Proxy-IP: Auth::clientIp() wertet X-Forwarded-For nur hinter
  konfiguriertem trusted_proxy aus (korrektes Rate-Limit/Audit hinter Proxy)
- Bandbreiten-/Datenlimits: UniFiController::createVoucher akzeptiert QoS
  (down/up kbit/s, Datenkontingent MB); Voucher-Profile speichern Limits,
  Voucher-Formular reicht sie via Template-Quick-Select durch
- 2FA (TOTP, RFC 6238): includes/Totp.php (gegen RFC-Testvektoren verifiziert),
  zweistufiger Login, admin/security.php zum Aktivieren/Deaktivieren mit QR,
  Nav-Link + i18n
This commit is contained in:
Claude 2026-06-05 19:39:28 +00:00
parent 51485810b4
commit eec28f77b8
No known key found for this signature in database
12 changed files with 458 additions and 16 deletions

View file

@ -30,6 +30,8 @@ CREATE TABLE IF NOT EXISTS `users` (
`is_admin` TINYINT(1) DEFAULT 0,
`is_active` TINYINT(1) DEFAULT 1,
`microsoft_id` VARCHAR(255) UNIQUE,
`totp_secret` VARCHAR(64) NULL,
`totp_enabled` TINYINT(1) NOT NULL DEFAULT 0,
`last_login` TIMESTAMP NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
@ -53,6 +55,9 @@ CREATE TABLE IF NOT EXISTS `voucher_templates` (
`max_uses` INT NOT NULL DEFAULT 1,
`expire_minutes` INT NOT NULL DEFAULT 480,
`description` VARCHAR(500),
`qos_rate_max_down` INT NULL,
`qos_rate_max_up` INT NULL,
`qos_usage_quota` INT NULL,
`is_active` TINYINT(1) DEFAULT 1,
`created_by` INT,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
@ -60,6 +65,20 @@ CREATE TABLE IF NOT EXISTS `voucher_templates` (
FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `api_keys` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`key_prefix` VARCHAR(16) NOT NULL,
`key_hash` VARCHAR(255) NOT NULL,
`created_by` INT,
`last_used_at` TIMESTAMP NULL,
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON DELETE SET NULL,
INDEX `idx_prefix` (`key_prefix`),
INDEX `idx_active` (`is_active`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `vouchers` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`site_id` INT NOT NULL,