From 0dc1b6c3a741f487c81d19310d8e47dc5c912d16 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Fri, 22 May 2026 12:19:16 +0200 Subject: [PATCH] Fix: FinTS-Konto-Auswahl speichern + Bearbeiten-Dialog mit Checkboxen Session-Lock im SSE-Stream blockierte den parallelen POST der Konto-Auswahl bis zum Timeout. session_write_close() im Run-Endpoint behebt das. Bearbeiten-Dialog zeigt gespeicherte Konto-Identifier jetzt als Checkboxen; Abhaken entfernt aus account_filter, alles abgehakt = Reset. --- Changes.md | 9 +++ src/Controllers/BankController.php | 15 ++++- src/Models/BankSource.php | 43 ++++++++++++++ src/Views/bank/fints.php | 51 ++++++++++++++--- tests/38_BankSourceFilterFromPostTest.php | 69 +++++++++++++++++++++++ 5 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 tests/38_BankSourceFilterFromPostTest.php diff --git a/Changes.md b/Changes.md index d56b75f..438e5ed 100644 --- a/Changes.md +++ b/Changes.md @@ -2,6 +2,15 @@ --- +## 2026-05-22 – Fix: FinTS-Konto-Auswahl wird jetzt gespeichert + Bearbeiten-Dialog mit Checkboxen + +- **Bug:** Beim ersten Abruf erschien das Konto-Auswahl-Modal, das Speichern blieb aber hängen. Ursache war PHP-Session-Locking: der SSE-Stream `/bank/direkt/{id}/run` hielt die Session-Datei während des `awaitAccountSelection()`-Polling-Loops gesperrt, der parallele POST `/bank/direkt/{id}/accounts` blockierte beim `session_start()` → Deadlock bis Timeout +- **Fix:** Im SSE-Endpoint `session_write_close()` direkt nach dem Auth-Check; entstört zugleich die analog gelagerte TAN-Eingabe +- **UI:** Im Bearbeiten-Dialog einer FinTS-Verbindung erscheinen die gespeicherten Konten jetzt als Checkbox-Liste (statt nur als Text). Abhaken entfernt den Identifier beim Speichern aus `account_filter`; alle abgehakt verhält sich wie der Reset-Toggle +- Filter-Berechnung als `BankSource::computeFilterFromPost()` extrahiert, neuer Test `38_BankSourceFilterFromPostTest` deckt Reset, Teilauswahl, leere Auswahl und Schutz gegen Unterschieben fremder Identifier ab + +--- + ## 2026-05-22 – Feature: APP_KEY Status & Generator in den Einstellungen - Neuer Settings-Bereich unter dem Betriebsmodus zeigt Status des Verschlüsselungsschlüssels (`APP_KEY`): **Gesetzt** (grün, 64 Hex-Zeichen valide), **Ungültig** (falsches Format) oder **Fehlt** (leer) diff --git a/src/Controllers/BankController.php b/src/Controllers/BankController.php index e35d2c3..00b518e 100644 --- a/src/Controllers/BankController.php +++ b/src/Controllers/BankController.php @@ -462,6 +462,12 @@ class BankController extends BaseController ob_end_clean(); } + // Session-Lock freigeben, damit parallele POSTs (TAN-/Konto-Auswahl) + // während des Pollings nicht blockieren. + if (session_status() === PHP_SESSION_ACTIVE) { + session_write_close(); + } + $send = function (string $event, string $data): void { foreach (explode("\n", $data) as $line) { echo 'event: ' . $event . "\n"; @@ -537,9 +543,12 @@ class BankController extends BaseController 'benutzerkennung' => trim($_POST['benutzerkennung'] ?? '') ?: null, 'pin' => $newPin !== '' ? $newPin : $source['pin'], ]; - // Reset-Button: Konto-Filter explizit löschen → beim nächsten Abruf neu auswählen - if (isset($_POST['reset_account_filter'])) { - $data['account_filter'] = null; + $filterUpdate = BankSource::computeFilterFromPost( + $source['account_filter'] ?? null, + $_POST + ); + if ($filterUpdate['update']) { + $data['account_filter'] = $filterUpdate['value']; } } diff --git a/src/Models/BankSource.php b/src/Models/BankSource.php index 675ca35..0d029c9 100644 --- a/src/Models/BankSource.php +++ b/src/Models/BankSource.php @@ -90,6 +90,49 @@ class BankSource Database::execute('UPDATE bank_sources SET last_fetched_at = NOW() WHERE id = ?', [$id]); } + /** + * Berechnet einen neuen account_filter aus dem bisherigen Filter und einem + * POST-Payload des Bearbeiten-Dialogs. + * + * Rückgabe: + * ['update' => true, 'value' => null] – Filter löschen (Reset) + * ['update' => true, 'value' => '[...]'] – neuen JSON-Filter setzen + * ['update' => false, 'value' => null] – Filter unverändert lassen + * + * Nur Identifier, die bereits im bisherigen Filter standen, werden übernommen + * (kein Unterschieben fremder Konten via POST). + */ + public static function computeFilterFromPost(?string $currentJson, array $post): array + { + if (isset($post['reset_account_filter'])) { + return ['update' => true, 'value' => null]; + } + if (!array_key_exists('active_accounts', $post)) { + return ['update' => false, 'value' => null]; + } + + $known = []; + if ($currentJson !== null && $currentJson !== '') { + $decoded = json_decode($currentJson, true); + if (is_array($decoded)) { + $known = array_values(array_map('strval', $decoded)); + } + } + + $postedRaw = is_array($post['active_accounts']) ? $post['active_accounts'] : []; + $posted = array_map('strval', $postedRaw); + $kept = array_values(array_intersect($known, $posted)); + + if ($kept === [] && $known !== []) { + // Alle abgehakt → wie Reset behandeln (beim nächsten Abruf neu fragen) + return ['update' => true, 'value' => null]; + } + if ($kept !== []) { + return ['update' => true, 'value' => json_encode($kept, JSON_UNESCAPED_UNICODE)]; + } + return ['update' => false, 'value' => null]; + } + /** Aktualisiert sort_order anhand der übergebenen ID-Reihenfolge (Position 0..N). */ public static function updateOrder(array $orderedIds): void { diff --git a/src/Views/bank/fints.php b/src/Views/bank/fints.php index 165d5d6..1439a43 100644 --- a/src/Views/bank/fints.php +++ b/src/Views/bank/fints.php @@ -274,7 +274,10 @@ $connectionsJson = json_encode(array_map(fn($c) => [
-
–
+
+