Commit graph

35 commits

Author SHA1 Message Date
Claude
46c03d53b8
Batch-CSV-Import: admin/import.php (Name,MaxGeräte,Minuten; max 200 Zeilen) 2026-06-06 05:43:09 +00:00
Claude
ce75215498
CAPTCHA für öffentlichen Modus (Rechenaufgabe oder hCaptcha)
- includes/Captcha.php (math self-contained / hcaptcha via siteverify)
- index.php: Verifikation bei anonymer Erstellung + Anzeige in beiden Formularen
- Settings in admin/integrations.php (Modus, Site-Key, Secret)
2026-06-06 05:42:06 +00:00
Claude
546accc185
Konsolidierung: Security-Härtung + .gitignore
- TOTP-Secret wird verschlüsselt-at-rest gespeichert (Crypto, Klartext-Fallback)
- forgot_password.php: Throttle (3/15min je Session) gegen Reset-Spam
- .gitignore für vendor/, composer.lock, phpunit-Cache, Updater-Laufzeitdaten
- Verifiziert: PHPUnit 15/15 grün, PHPStan ohne Fehler
2026-06-06 05:38:40 +00:00
Claude
c63c5e78f0
README: Maturity-Features dokumentieren (2FA-Recovery, API-Scopes, Reporting, Health, Tests), v2.3.0 + CI-Badge 2026-06-05 20:57:04 +00:00
Claude
997cda01a8
E-Mail-Retry, Voucher-Resend, Tageslimit, Docker-Politur
- Mailer::send mit Retry (2 Versuche); SMTP-Test & Templates waren bereits da
- admin/vouchers.php: Code per E-Mail (erneut) versenden (ajax_resend)
- Tageslimit Voucher pro Nicht-Admin-Benutzer (Setting + Durchsetzung in index)
- Docker: HEALTHCHECK (health.php) + curl; GHCR-Publish-Workflow
- Setting user_daily_voucher_limit + enforce in integrations.php
2026-06-05 20:56:26 +00:00
Claude
2e0f36d6c1
Reporting: admin/reports.php mit Charts, CSV-Export (täglich/Site/Nutzer) & Druck/PDF 2026-06-05 20:50:18 +00:00
Claude
0b1d4ec3b8
Webhook-Events & Health-Endpoint
- Notifier: controllerUnreachable, loginNewIp, updateAvailable
- Login von neuer IP -> Webhook (Abgleich gegen audit_log)
- cron_sync meldet nicht erreichbare Controller; cron_cleanup prüft täglich
  optional auf Updates und meldet Verfügbarkeit
- health.php: Status-Endpoint (DB; optional Controller per ?deep=1&token=)
2026-06-05 20:49:06 +00:00
Claude
c7f9b7d39c
API-Reife: Scopes (read/write), Rate-Limit pro Key, OpenAPI-Spec
- ApiKey::hasScope + checkRateLimit (Fixed-Window/min via api_key_hits)
- bootstrap erzwingt Rate-Limit (429) und api_require_scope() in Endpunkten
- admin/api_keys.php: Scope-Auswahl + Limit beim Erstellen, Anzeige in Tabelle
- api/openapi.php: OpenAPI-3.0-Spec (Import in Postman/Swagger)
- Schema 0003 (api_keys.scope, api_keys.rate_limit, Tabelle api_key_hits)
2026-06-05 20:47:26 +00:00
Claude
ba121d60e6
2FA-Reife: Recovery-Codes, Enforce-Policy für Admins, Admin-Reset
- Recovery-/Backup-Codes (8x, einmalig nutzbar) bei Aktivierung + Regenerieren;
  Login akzeptiert TOTP ODER Recovery-Code
- Setting enforce_2fa_admins: Admins ohne 2FA werden zur Einrichtung geleitet
- Admin kann 2FA eines Nutzers zurücksetzen (admin/users.php)
- Schema 0003 (users.totp_backup_codes); security.php zeigt Codes & Restanzahl
2026-06-05 20:45:28 +00:00
Claude
dce10a8a08
Screenshots vereinheitlicht (1200px/2×) + neue Seiten (API-Keys, 2FA, Integration)
Alle Screenshots im einheitlichen Format neu gerendert; Admin-Mockups mit
vollständiger, konsistenter Sidebar. Neue README-Sektion mit API-Keys-,
Integration-&-Wartung- und 2FA-Screenshot.
2026-06-05 20:19:55 +00:00
Claude
0cc4d3a047
README: neue Features dokumentieren (REST-API, 2FA, Webhooks, Docker), v2.2.0 2026-06-05 19:46:14 +00:00
Claude
9463486225
Erweiterte Features (2/2): Cleanup/DSGVO, Webhooks, REST-API, Backup, CI, Docker
- Auto-Cleanup/DSGVO: cron_cleanup.php (token-geschützt) löscht abgelaufene
  Voucher, Audit-Log, Login-Versuche und Reset-Tokens nach konfigurierbaren
  Fristen
- Webhooks: includes/Notifier.php (Slack/Teams/generisch), Auslösung bei
  Voucher-Erstellung (Web + API)
- REST-API: includes/ApiKey.php (SHA-256, Präfix-Lookup), api/bootstrap.php,
  api/vouchers.php (GET/POST), api/sites.php; admin/api_keys.php zur Verwaltung
- Config-Backup/Restore: admin/backup.php (JSON Export/Import, Cron-Token
  geschützt)
- admin/integrations.php: Trusted-Proxy, Webhook, Cleanup-Fristen
- CI: .github/workflows/ci.yml (php -l auf 7.4 & 8.2, lang-Validierung)
- Docker: Dockerfile, docker-compose.yml (MariaDB), entrypoint (config aus ENV),
  .dockerignore
- Nav + i18n (DE/EN) für alle neuen Admin-Seiten
2026-06-05 19:45:28 +00:00
Claude
eec28f77b8
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
2026-06-05 19:39:28 +00:00
Claude
51485810b4
Updater-Migration für Feature-Tabellen + README um neue Features erweitern
- updater/migrations/0001_feature_ui_tables.sql: legt voucher_templates und
  password_reset_tokens idempotent an (CREATE TABLE IF NOT EXISTS), damit
  bestehende Installationen die neuen Tabellen per System-Update erhalten
- Updater-UI: Button "Ausstehende Migrationen ausführen" + run_migrations-Action
  (CSRF-geschützt) im Migrations-Tab
- README: Features (Bulk, Templates, Dark Mode, i18n, Audit-Log, Passwort-Reset),
  zwei neue Screenshots (Bulk-Erstellung, Dashboard Dark Mode), Roadmap & Updater-
  Abschnitt aktualisiert
2026-06-05 19:16:55 +00:00
Claude
526c43e8ee
Merge: UI/UX-Feature-Branch integrieren + Security-Patches re-applien
Integriert die Feature-Branch (Dark Mode, i18n DE/EN, mobile Admin-Layout,
shared admin_nav, Toasts, Voucher-Templates, Bulk-Erstellung, konfigurierbare
Defaults, Password-Reset, Audit-Log-UI + Audit-Logging) mit der bestehenden
Security-/Updater-Arbeit.

Konfliktauflösung (6 Dateien: index.php + admin/*): Feature-Version als Basis,
darauf die Security-Patches re-appliziert:
- display_errors=0 + log_errors in allen neuen/gemergten Entry-Points
- Crypto::encrypt/decrypt an allen Site-Passwort-Pfaden (sites/index/vouchers/
  dashboard-Sync, inkl. doCreateVoucher + Bulk)
- CSRF-Prüfung für ALLE Voucher-Erstellungen (auch anonym/öffentlich), Token
  unbedingt im Formular; Session-Throttle gegen Spam
- Updater-Maintenance-Hook am Anfang von index.php wiederhergestellt

Auto-Merge verifiziert: Auth.php enthält Session-Timeout UND writeAuditLog;
login.php behält display_errors=0 + OAuth-state. Updater-Link in shared
admin_nav.php (i18n-Key nav_update DE/EN). Alle PHP-Dateien linten sauber.
2026-06-05 19:10:18 +00:00
Claude
63f1e07681
Neue README mit Screenshots + Updater-Dokumentation
- Überarbeitete, bebilderte Readme.md (Features, Installation, Auto-Updater,
  Sicherheit, Troubleshooting, API)
- 7 gerenderte Screenshots unter docs/screenshots/ (Login, Voucher-Erstellung,
  Voucher-Ergebnis, Dashboard, Updater, Wartungsmodus)
2026-06-05 19:00:36 +00:00
Claude
471c5b49ca
Admin-Sidebar: Link zu System-Update ergänzen
Auf allen 5 Admin-Seiten (Dashboard, Sites, Benutzer, Vouchers,
Einstellungen) einen Navigationspunkt zur Updater-Seite hinzugefügt.
2026-06-05 18:55:34 +00:00
Claude
43149074c9
Updater-System (OpenNIT-Modell) im isolierten updater/-Ordner
Zieht Quellcode + DB-Migrationen über einen HTTP-Update-Proxy nach.
Vollständig isoliert: eigener Namespace Updater\, eigener Autoloader,
eigene Settings (updater/storage/updater-settings.json), eigenes
Migrations-System (_updater_migrations), eigener AuditLogger.

Komponenten (alle in updater/):
- UpdateManager: Version/.version, Maintenance, Progress, checkForUpdates,
  installUpdate (Staging + PROTECTED_PATHS + Migrationen + opcache + finally)
- MigrationRunner: MySQL-Tracking, string-/kommentar-bewusster SQL-Splitter,
  isIgnorableSqlError, 60s-Lockfile-Cache
- UpdateController + admin/update.php (dünner Entry-Shim), Inline-Admin-UI
  mit Channel-Selector, Update-Check, Progress-Bar, Migrations-Tab
- UpdaterFactory (zentraler Channel-Fallback), AuditLogger (audit_log)
- Templates: maintenance.html, update.php; routes.php (Doku)
- README.md mit vollständiger Rückbau-Anleitung

Einzige Bestandscode-Änderung: 4-Zeilen-Maintenance-Hook in index.php
(markiert mit "// Updater maintenance hook").

Proxy: update.loheide.eu/openvouchertool[-development]
2026-06-05 18:51:51 +00:00
Claude
3483da274f
Security: OAuth-state, Verschlüsselung, Session-Timeout & weitere Härtung
- m365_callback.php: OAuth-state-Validierung gegen Login-CSRF
- includes/Crypto.php: Verschlüsselung-at-rest für UniFi-Passwörter
  (AES-256-GCM/libsodium) mit Klartext-Fallback für Bestandsinstallationen
- install.php: APP_KEY-Generierung + Reinstall nur mit Admin-Session
- Auth.php: absolutes Session-Timeout (SESSION_LIFETIME) durchsetzen
- index.php: CSRF + Throttle auch für anonyme öffentliche Voucher-Erstellung
- UniFiController.php: createVoucher liefert nicht mehr den falschen Code
  bei parallelen Erstellungen (note-Match statt blindes reset())
- display_errors in allen Entry-Points deaktiviert, log_errors aktiviert
- test.php & m365_debug.php hinter requireAdmin() (Info-Leak)
- m365_debug.php: abgeschnittene/kaputte Datei vervollständigt
2026-06-05 18:45:47 +00:00
Claude
a1021a0f84
feat: comprehensive UI/UX and feature improvements
- Dark mode: CSS custom properties (global.css) + toggle button, persisted in localStorage
- i18n: German/English language switcher (lang/de.php, lang/en.php, includes/I18n.php)
- Mobile-responsive admin layout: hamburger menu, sidebar overlay (global.js + global.css)
- Shared admin navigation include (includes/admin_nav.php) used across all admin pages
- Toast notifications system globally available via global.js
- Voucher templates/profiles: CRUD UI at admin/templates.php with voucher_templates DB table
- Bulk voucher creation: create 1-20 vouchers at once with multi-print layout on index.php
- Configurable voucher defaults: expire time, device limit, max limit in admin settings
- Template quick-select on voucher form: auto-fills max_uses and expire_minutes
- Password reset flow: forgot_password.php + reset_password.php with token-based reset
- Audit log UI: admin/audit_log.php with filter, pagination, audit_log DB table
- Audit logging on login, user create/edit/delete, site create/edit/delete
- Admin pages updated: index, vouchers, users, sites all use admin_nav.php + dark mode + i18n
- Voucher admin: live search input added alongside existing status filter + pagination
- Users admin: password-reset-link button per user row (when SMTP enabled)
- Login page: i18n, dark mode, language switcher, forgot password link

https://claude.ai/code/session_01YN6Bcm1VSi8mpDeyKpyrdJ
2026-05-08 17:59:17 +00:00
friloo
bf3e55a967
Merge pull request #5 from friloo/claude/unifi-api-migration-dbNMa
Claude/unifi api migration db n ma
2026-04-22 09:24:08 +02:00
Claude
e0a999b27b
Login only once per UniFiController instance to avoid rate limiting
createVoucher() calls apiRequest() twice (cmd/hotspot + stat/voucher),
which previously triggered two separate login requests in rapid succession.
The UniFi controller was rate-limiting the second attempt with 403.

Fix: $loggedIn flag ensures login() is a no-op after the first successful
authentication, reusing the existing session cookie for all API calls.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:52:45 +00:00
Claude
897392041a
Fix session cookie not persisting due to Partitioned attribute
The TOKEN cookie set by UniFi OS includes the 'Partitioned' attribute
(CHIPS), which some libcurl versions do not write to the Netscape cookie
jar file. This caused every API request to go out unauthenticated,
resulting in 401/403 errors even after a successful login.

Fix: extract the TOKEN value directly from the Set-Cookie response
header in login() and pass it via CURLOPT_COOKIE in apiRequest(),
bypassing the broken file-based cookie jar. Cookie file remains as
fallback for environments where extraction fails.

Also update test.php section 8 to validate this fix and show the
extracted cookie value.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:41:42 +00:00
Claude
e705458af3
Add UniFi API diagnostic section to test.php
Shows raw login HTTP code, all response headers, X-CSRF-Token extraction
(header + cookie file fallback), login response body, cookie file contents,
and a follow-up stat/voucher GET to verify the full auth+API flow.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:35:15 +00:00
Claude
dbce0299d6
Add response body detail to login error messages for debugging
https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:31:04 +00:00
Claude
78a2b41329
Fix HTTP 403 on login: add Origin and Referer headers
UniFi OS enforces CSRF protection on the login endpoint itself and
returns 403 if Origin/Referer headers are absent, regardless of whether
the credentials are correct. Required headers:
  Origin: https://controller:port
  Referer: https://controller:port/login

Documented in Art-of-WiFi UniFi-API-client reference implementation.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:28:17 +00:00
friloo
d3e2e669a7
Merge pull request #4 from friloo/claude/unifi-api-migration-dbNMa
Fix sites modal save: disabled button doesn't submit name attribute
2026-04-22 07:23:59 +02:00
Claude
7fdf156f5f
Fix sites modal save: disabled button doesn't submit name attribute
Move form action identifiers to hidden inputs (add_site, edit_site) so
the server-side isset() check always succeeds regardless of button state.
Pattern matches index.php (create_voucher hidden input).
Update JS loading-state selectors to match new button IDs.

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-22 05:20:53 +00:00
friloo
c418f8c5b5
Merge pull request #3 from friloo/claude/unifi-api-migration-dbNMa
Fix UniFi OS API login validation and HTTP method handling
2026-04-21 20:34:22 +02:00
Claude
2874ca0839
Fix UniFi OS API login validation and HTTP method handling
- Login: replace fragile unique_id/email check with proper HTTP 200 trust +
  explicit meta.rc=error detection (matches Art-of-WiFi reference impl)
- Login: add TOKEN cookie fallback for CSRF token extraction in case
  the X-CSRF-Token response header is absent (some firmware versions)
- getVouchers(): pass explicit 'GET' method instead of relying on cURL default
- apiRequest(): use CURLOPT_HTTPGET for GET requests; send CURLOPT_POSTFIELDS
  as empty object for POST with no data; CSRF header only on non-GET requests
- Remove array_filter() header construction, replace with clean conditional append

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-21 18:29:50 +00:00
friloo
b86746fef3
Merge pull request #2 from friloo/claude/unifi-api-migration-dbNMa
Fix sites freeze bug, add features and shorten README
2026-04-21 20:27:56 +02:00
Claude
73967caefa
Fix sites freeze bug, add features and shorten README
Bug fixes:
- UniFiController: add CURLOPT_TIMEOUT (10s) and CURLOPT_CONNECTTIMEOUT (5s)
  to login() and apiRequest() — prevents page freeze when controller unreachable
- UniFiController: fix login response validation for UniFi OS API which returns
  a user object instead of meta.rc=ok
- admin/sites.php: add JS loading state on form submit to give visual feedback
- login.php: handle new 'rate_limited' return value from Auth::login()

New features:
- Database: in-memory settings cache eliminates redundant DB queries per request
- Auth: login rate limiting (10 attempts per 10 min per IP/email) via login_attempts table
- admin/vouchers.php: CSV export with UTF-8 BOM for Excel compatibility
- admin/vouchers.php: client-side pagination (50 per page)
- index.php: QR code display after voucher creation (qrcodejs CDN)
- Mailer: sendTestEmail() method
- admin/settings.php: SMTP test button with AJAX handler
- database.sql: add login_attempts and audit_log tables

Readme: condensed from ~420 to ~220 lines, removed duplicated sections,
M365 Azure Portal walkthrough, contribution guidelines, update/migration section

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-21 16:08:08 +00:00
friloo
a667b65180
Merge pull request #1 from friloo/claude/unifi-api-migration-dbNMa
Migrate to UniFi OS API (port 11443)
2026-04-21 17:55:33 +02:00
Claude
3fd9b2190a
Migrate to UniFi OS API (port 11443)
- Update login endpoint: /api/login → /api/auth/login
- Add X-CSRF-Token extraction via CURLOPT_HEADERFUNCTION in login()
- Inject X-CSRF-Token header into all POST requests in apiRequest()
- Prefix all API paths with /proxy/network (createVoucher, getVouchers, deleteVoucher)
- Update admin/sites.php placeholder and help text to reflect port 11443
- Update Readme.md: fix GitHub clone URL, update port references, rewrite
  API documentation section for UniFi OS, add UniFi OS troubleshooting entry,
  bump version to 2.1.0

https://claude.ai/code/session_01UsuvFAmmeagtQa14QA4iaq
2026-04-21 15:54:56 +00:00
friloo
dbdc237fa1
Initial Upload 2026-04-21 17:45:58 +02:00