diff --git a/CHANGELOG.md b/CHANGELOG.md index af12d9a..132f464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,29 @@ Format angelehnt an [Keep a Changelog](https://keepachangelog.com/de/1.0.0/). ## [Unreleased] +### 🔑 Baka-Konto-Dialog trimmte das Passwort nicht — Autofill-Leerzeichen ließ korrekte Logins scheitern (2026-08-29) + +- 🐛 **Im "Baka-Konto"-Anmelde-Dialog (`_AnmeldeDialogState._anmelden()` in + `downloads_screen.dart`) wurde der Benutzername vor dem Absenden getrimmt + (`_benutzer.text.trim()`), das Passwort aber nicht** (`_passwort.text` + roh, an beiden Stellen: beim `BakaAuth.anmelden(...)`-Aufruf UND beim + anschließenden `NavidromeService.speichereZugangsdaten(...)`). Ein durch + Autofill/Tastatur-Vorschläge im `obscureText`-Passwortfeld eingefügtes + unsichtbares Leerzeichen landete dadurch im gesendeten UND dauerhaft + gespeicherten Passwort — der Login schlug fehl, obwohl der Nutzer sein + Passwort korrekt kannte. +- 🔧 **Fix:** `_passwort.text.trim()` an beiden Stellen, mit demselben + Kommentar wie beim strukturell identischen, bereits behobenen Fall im + Navidrome-Login-Dialog (`settings_screen.dart`, Commit `3d1e00646ac`) — + das war schon einmal exakt dasselbe Symptom in einem zweiten + Passwort-Dialog. Falls das Muster ein drittes Mal auftaucht: derselbe + Trim-Fix, derselbe Kommentar. +- ✅ **Getestet (RED→GREEN):** neuer Widget-Test in `online_screen_test.dart` + gibt im Passwortfeld `'geheim '` (mit Leerzeichen) ein und bestätigt, dass + sowohl der gesendete `POST /auth/login`-Body als auch + `nav.passwort` das getrimmte `'geheim'` enthalten. Volle Suite (605 Tests) + grün, `flutter analyze` ohne Befund. + ### ✨ Staggered List-Enter-Animation: Listen faden beim ersten Erscheinen gestaffelt ein (2026-08-29) - ✅ **Teil 1 einer Animations-Serie** (inspiriert von Xiaomis HyperOS- diff --git a/lib/downloads/downloads_screen.dart b/lib/downloads/downloads_screen.dart index 8fbdce1..d2ee725 100644 --- a/lib/downloads/downloads_screen.dart +++ b/lib/downloads/downloads_screen.dart @@ -900,7 +900,10 @@ class _AnmeldeDialogState extends State<_AnmeldeDialog> { _fehler = null; }); final auth = context.read(); - final fehler = await auth.anmelden(_benutzer.text.trim(), _passwort.text); + // Randständige Leerzeichen entfernen (verdeckte + // Fehlerquelle im obscureText-Feld / bei Autofill). + final passwort = _passwort.text.trim(); + final fehler = await auth.anmelden(_benutzer.text.trim(), passwort); if (!mounted) return; if (fehler == null) { // Navidrome- und Baka-Konto teilen sich die Zugangsdaten (siehe @@ -909,7 +912,7 @@ class _AnmeldeDialogState extends State<_AnmeldeDialog> { // Passwort scheitern. final nav = context.read().navidrome; await nav.speichereZugangsdaten( - nav.serverUrl, _benutzer.text.trim(), _passwort.text); + nav.serverUrl, _benutzer.text.trim(), passwort); if (!mounted) return; Navigator.pop(context); return; diff --git a/test/downloads/online_screen_test.dart b/test/downloads/online_screen_test.dart index 607104b..f0facf7 100644 --- a/test/downloads/online_screen_test.dart +++ b/test/downloads/online_screen_test.dart @@ -301,6 +301,40 @@ void main() { expect(auth.istAngemeldet, isTrue); }); + testWidgets( + 'Anmelden trimmt das Passwort — ein unsichtbares Leerzeichen durch ' + 'Autofill im obscureText-Feld darf den Login nicht scheitern lassen ' + '(wie im Navidrome-Dialog, settings_screen.dart)', (tester) async { + late String gesendetesPasswort; + final auth = BakaAuth( + client: MockClient((request) async { + final body = jsonDecode(request.body) as Map; + gesendetesPasswort = body['password'] as String; + if (body['password'] == 'geheim') { + return http.Response(jsonEncode({'token': 'jwt-neu'}), 200); + } + return http.Response('', 500); + }), + speicher: _MemorySpeicher(), + ); + final nav = NavidromeService() + ..setCredentials('https://musik.baka-net.de', 'Tinker', 'altesPasswort'); + + await tester.pumpWidget(_wrap(auth, + db: db, categories: categories, navidrome: nav)); + await tester.pumpAndSettle(); + + await tester.tap(find.text('Beim Baka-Konto anmelden')); + await tester.pumpAndSettle(); + + await tester.enterText(find.byType(TextField).last, 'geheim '); + await tester.tap(find.text('Anmelden')); + await tester.pumpAndSettle(); + + expect(gesendetesPasswort, 'geheim'); + expect(nav.passwort, 'geheim'); + }); + testWidgets( 'Server-User meldet sich im Hintergrund mit denselben Zugangsdaten ' 'beim Baka-Konto an', (tester) async {