Author SHA1 Message Date
Hermes (Server) 824f6364e2 Baka-Konto-Dialog: Passwort wird jetzt auch getrimmt (wie im Navidrome-Dialog)
Das Passwortfeld im Baka-Konto-Anmelde-Dialog wurde vor dem Absenden und
vor dem Speichern nicht getrimmt — ein durch Autofill eingefügtes
Leerzeichen ließ korrekte Logins scheitern. Gleicher Fix wie bereits in
settings_screen.dart (Commit 3d1e00646a) für denselben Symptom-Typ.
2026-08-29 18:08:19 +02:00
3 changed files with 62 additions and 2 deletions
+23
View File
@@ -5,6 +5,29 @@ Format angelehnt an [Keep a Changelog](https://keepachangelog.com/de/1.0.0/).
## [Unreleased] ## [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) ### ✨ Staggered List-Enter-Animation: Listen faden beim ersten Erscheinen gestaffelt ein (2026-08-29)
-**Teil 1 einer Animations-Serie** (inspiriert von Xiaomis HyperOS- -**Teil 1 einer Animations-Serie** (inspiriert von Xiaomis HyperOS-
+5 -2
View File
@@ -900,7 +900,10 @@ class _AnmeldeDialogState extends State<_AnmeldeDialog> {
_fehler = null; _fehler = null;
}); });
final auth = context.read<BakaAuth>(); final auth = context.read<BakaAuth>();
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 (!mounted) return;
if (fehler == null) { if (fehler == null) {
// Navidrome- und Baka-Konto teilen sich die Zugangsdaten (siehe // Navidrome- und Baka-Konto teilen sich die Zugangsdaten (siehe
@@ -909,7 +912,7 @@ class _AnmeldeDialogState extends State<_AnmeldeDialog> {
// Passwort scheitern. // Passwort scheitern.
final nav = context.read<DownloadService>().navidrome; final nav = context.read<DownloadService>().navidrome;
await nav.speichereZugangsdaten( await nav.speichereZugangsdaten(
nav.serverUrl, _benutzer.text.trim(), _passwort.text); nav.serverUrl, _benutzer.text.trim(), passwort);
if (!mounted) return; if (!mounted) return;
Navigator.pop(context); Navigator.pop(context);
return; return;
+34
View File
@@ -301,6 +301,40 @@ void main() {
expect(auth.istAngemeldet, isTrue); 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<String, dynamic>;
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( testWidgets(
'Server-User meldet sich im Hintergrund mit denselben Zugangsdaten ' 'Server-User meldet sich im Hintergrund mit denselben Zugangsdaten '
'beim Baka-Konto an', (tester) async { 'beim Baka-Konto an', (tester) async {