From 3d1e00646ac068756ffa81646d908121393ca495 Mon Sep 17 00:00:00 2001 From: "Hermes (Server)" Date: Thu, 20 Aug 2026 09:52:07 +0200 Subject: [PATCH] =?UTF-8?q?Fix:=20Navidrome-Login=20=E2=80=94=20Passwort-S?= =?UTF-8?q?ichtbarkeit=20+=20Trim=20(Login=20fehlgeschlagen)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Systematische Diagnose bewies: App-Code, Server, User 'Baka' und Passwort sind korrekt (1:1-Nachbau des App-Requests inkl. Salt/Token -> Navidrome status:ok). Der Fehler lag im auf dem Gerät verwendeten Credential-Wert: - der alte Build (Ping-Fehlalarm) persistierte ungültige Zugangsdaten, - verdeckte Tippfehler im obscureText-Passwortfeld blieben unsichtbar. Fix: - Passwort-Anzeigen-Umschalter (Auge-Icon) im Login-Dialog. - URL + Passwort werden getrimmt (Autofill/Tastatur-Leerzeichen). Ein erfolgreicher Login ueberschreibt die alten gespeicherten Credentials; der Ping-Fix stellt sicher, dass nur gueltige gespeichert werden. 84/84 Tests gruen, analyze sauber. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Tr2UwurtxyJUpWpBSeVmBm --- CHANGELOG.md | 16 ++++++++++++++++ lib/settings/settings_screen.dart | 29 +++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c11f729..dc879a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,22 @@ Format angelehnt an [Keep a Changelog](https://keepachangelog.com/de/1.0.0/). ## [Unreleased] +### 🔎 Login-Diagnose: Passwort-Sichtbarkeit + Trim (2026-08-20) +- 🐛 **„Login fehlgeschlagen" trotz korrekter Zugangsdaten:** Systematische + Analyse (App-Code, App-Logs, Caddy/Navidrome-Logs, 1:1-Nachbau des + App-Requests inkl. Salt/Token) hat bewiesen: **App-Code, Server, User „Baka" + und Passwort sind korrekt** — der Fehler lag im auf dem Gerät verwendeten + Credential-Wert (der ältere Build mit dem Ping-Fehlalarm persistierte + ungültige Zugangsdaten; verdeckte Tippfehler im Passwortfeld blieben + unsichtbar). +- 🔧 **Passwort-Anzeigen-Umschalter** (Auge-Icon) im Navidrome-Login — Tippfehler + werden sichtbar. +- 🔧 **URL + Passwort werden getrimmt** (randständige Leerzeichen aus Autofill / + Tastatur entfernt). +- ℹ️ Ein erfolgreicher Login überschreibt die alten (ungültigen) gespeicherten + Zugangsdaten — der Ping-Fix aus dieser Version stellt sicher, dass künftig + nur noch gültige Credentials gespeichert werden. + ### 🔒 Datenschutz: Log-Bereinigung vor Server-Upload (2026-08-20) - ✅ **Was:** Diagnose-Logs werden jetzt zentral bereinigt, bevor sie an `logs.baka-net.de` gehen. Der lokale `debugPrint` bleibt vollständig. diff --git a/lib/settings/settings_screen.dart b/lib/settings/settings_screen.dart index 774823e..a6d4f17 100644 --- a/lib/settings/settings_screen.dart +++ b/lib/settings/settings_screen.dart @@ -160,6 +160,7 @@ class _SettingsScreenState extends State { final passCtrl = TextEditingController(); String selectedUser = 'Dustin'; bool verbindet = false; + bool obscure = true; String? fehler; showDialog( @@ -228,11 +229,20 @@ class _SettingsScreenState extends State { TextField( controller: passCtrl, style: const TextStyle(color: Colors.white), - obscureText: true, - decoration: const InputDecoration( + obscureText: obscure, + decoration: InputDecoration( labelText: 'Passwort', - labelStyle: TextStyle(color: Colors.grey), - border: OutlineInputBorder(), + labelStyle: const TextStyle(color: Colors.grey), + border: const OutlineInputBorder(), + // Anzeigen-Umschalter: verdeckte Tippfehler im Passwort + // sichtbar machen (häufigste Login-Fehlerquelle). + suffixIcon: IconButton( + icon: Icon( + obscure ? Icons.visibility_off : Icons.visibility, + color: Colors.grey, + ), + onPressed: () => setDialogState(() => obscure = !obscure), + ), ), ), if (fehler != null) ...[ @@ -262,16 +272,19 @@ class _SettingsScreenState extends State { ? null : () async { setDialogState(() => verbindet = true); + // Randständige Leerzeichen entfernen (verdeckte + // Fehlerquelle im obscureText-Feld / bei Autofill). + final url = urlCtrl.text.trim(); + final pass = passCtrl.text.trim(); logger.info( - 'Navidrome Login-Versuch (pwLeer=${passCtrl.text.isEmpty})'); - _navidrome.setCredentials( - urlCtrl.text, selectedUser, passCtrl.text); + 'Navidrome Login-Versuch (pwLeer=${pass.isEmpty})'); + _navidrome.setCredentials(url, selectedUser, pass); final ok = await _navidrome.ping(); setDialogState(() => verbindet = false); if (ok && ctx.mounted) { logger.info('Navidrome Login erfolgreich'); await _navidrome.speichereZugangsdaten( - urlCtrl.text, selectedUser, passCtrl.text); + url, selectedUser, pass); if (ctx.mounted) Navigator.pop(ctx); if (mounted) setState(() {}); } else if (ctx.mounted) {