Forráskód Böngészése

Taak 128-A klaar: resource live en end-to-end getest op productie

subscribe.json geeft status 1 zonder bevestigingsmail, de rolfilter werkt
en de index klopt. Restjes: unsubscribe nog niet aangeroepen en een
tikfout in de omschrijving van tid 36676 die letterlijk in de app komt.

Belangrijk voor de app-kant: POST vereist een X-CSRF-Token, anders komt
er ['CSRF validation failed'] terug. Mijn eerdere inschatting dat de
token niet afgedwongen werd was fout. De app is er al op ingericht
(drupalLogin schrijft userToken, drupalRequest zet de header), maar wie
het 5e argument vergeet krijgt stil een lege lijst terug -- drupalRequest
slikt elke non-2xx zonder melding.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bob 18 órája
szülő
commit
7351df6f17
1 módosított fájl, 37 hozzáadás és 55 törlés
  1. 37 55
      TASKS.md

+ 37 - 55
TASKS.md

@@ -33,7 +33,7 @@ Google Play en één doorloop die alleen Bob kan doen.
 
 
 | **114** | Opruimen na de filterbalk-ombouw | **Eigenaar: Bob.** Restjes van taak 113 (afgerond 2026-09-20): (a) component-parameter **`parameter1`** op `FilterBalkComponent` ontstond automatisch bij *Convert to Component* en wordt nergens gelezen — mag weg, en daarmee ook de meegegeven waarde op Home en `PUitgaanPage`; (b) **page state `zoekOpen` op Home** is overbodig (de App State-versie stuurt alles); (c) App State **`zoekActief`** (Boolean) bestond al vóór deze taak en heeft **0 gebruikers**; (d) wegwerp: componenten **`FilterBalkKanweg`** en **`FilterBalkComponentCopy`** + pagina's **`homeCopy`** en **`PUitgaanPageCopy`**. Geen van alle blokkeert iets — `dart analyze` geeft 0 errors |
-| **128-B/C/D** | Nieuwsbrieven-blok op `mijnProfiel` | **Wacht op 128-A (Drupal).** Plan is af en doorgemeten — blok, waarschuwing bij 0 gevolgde gemeenten, vertalingen. Eigen blok hieronder |
+| **128-B/C/D** | Nieuwsbrieven-blok op `mijnProfiel` | **Backend staat live en is getest; klaar om te bouwen** zodra de lopende FlutterFlow-sessie klaar is (Bob meldt dat). Blok + waarschuwing bij 0 gevolgde gemeenten + vertalingen. ⚠️ CSRF-token meegeven, zie het blok hieronder |
 
 ## 👤 BOB — OPEN, in volgorde van wat de livegang blokkeert
 
@@ -55,7 +55,7 @@ Google Play en één doorloop die alleen Bob kan doen.
 | **123** | `mijn_stadsrechten` uitbreiden met de keten | **Code staat klaar en is op productie getest.** Vervang regels 316-372 van `custom.evenementen_aanmaken.inc` + `cc all`. Blokkeert 124 |
 | **124-126** | Stadsrechten-cascade op `stadsactiviteitAanmaken` | Voorvullen van provincie/gemeente/plaats (124), een **crash** bij een lege plaatsenlijst (125) en een stille verkeerde plaats bij het wisselen van gemeente (126). Eigen blok hieronder |
 | **127** | **Kopie-knop op `MijnAanmeldingen`** (clonen) | Wens Bob 2026-09-20, **vóór de livegang**. Backend bestaat al; Drupal-patch voor 3 gaten staat klaar en is getest (127-A). App-deel in stappen B t/m F; het activiteitendeel (127-E) deelt de cascade met 124. Eigen blok hieronder |
-| **128-A** | **Nieuwsbrieven: Drupal-resource** | Wens Bob 2026-09-21. Plan + code-opzet staan klaar en zijn doorgemeten; alleen bouwen, deployen en de resource **plus de 3 operaties** aanvinken in het endpoint. Blokkeert 128-B/C/D. Eigen blok hieronder |
+| **128-A** | ✅ **KLAAR** — nieuwsbrieven-resource staat live | Gedeployd en getest op productie 2026-09-21. Rest: één tikfout in de omschrijving van tid 36676 (*verstuurt* → verstuurd), zie het blok hieronder |
 
 ---
 #
@@ -176,59 +176,41 @@ een eigen kijkje waard, geen taak.
 
 ### 128-A · Drupal: resource `nieuwsbrieven` · Eigenaar: Bob
 
-**✅ GEDEPLOYD OP DEVBOB ÉN PRODUCTIE 2026-09-21 door Bob.** Alle drie de
-operaties staan op beide omgevingen aan en `nieuwsbrieven.json` levert de juiste
-lijst: een gebruiker zonder de rol `Horeca-owner` ziet 2 van de 3, en de status
-beweegt mee met een abonnement. **Nog niet getest: de twee POST-endpoints** —
-Bobs tests liepen via de website-pagina (`source = website`). Op productie staat
-`source = app` nog op 0 treffers; dat is meteen de manier om te zien of de
-eerste app-aanmelding door de nieuwe route is gekomen.
-
-⚠️ **Nazorg op beide omgevingen:** het gedeployde `custom.nieuwsbrieven.inc`
-bevat nog de eerste versie, met `variable_get('custom_nieuwsbrieven_confirm',
-TRUE)` — die zou een ingelogde app-gebruiker wél een bevestigingsmail sturen.
-Vervang die regels door de versie in het snippet (die roept
-`simplenews_require_double_opt_in()` aan) en draai `cc all`. Wie niet wil
-redeployen: `drush @<alias> vset custom_nieuwsbrieven_confirm 0` doet het ook,
-maar dan staat er een knop die niemand later nog begrijpt.
-
-**✅ Code is af en staat klaar in `snippets/nieuwsbrieven-drupal.inc.txt`** (compleet bestand `custom.nieuwsbrieven.inc` + het blok voor `custom_services_resources()` + de deploy- en controlestappen). PHP-syntax gecontroleerd op de server en de index-logica read-only drooggedraaid op productie voor een Horeca-owner, een gewone gebruiker met abonnement en een zonder: rolfilter en statussen kloppen.
-
-Zelfde vorm als het bestaande `favorieten` (flag/unflag/is_flagged):
-
-```
-GET  /nl/flutterdrup/nieuwsbrieven.json               -> lijst + status
-POST /nl/flutterdrup/nieuwsbrieven/subscribe.json     -> {"tid": 36676}
-POST /nl/flutterdrup/nieuwsbrieven/unsubscribe.json   -> {"tid": 36676}
-```
-
-Index-respons (alle waarden als string/int, `status` als int):
-
-```json
-[{"tid":"36676","naam":"...","omschrijving":"...","status":1}]
-```
-
-Kern van de index-callback:
-
-```php
-function _custom_nieuwsbrieven_index() {
-  global $user;
-  if (empty($user->uid)) return services_error('Niet ingelogd', 401);
-  $out = array();
-  foreach (_custom_nieuwsbrieven_zichtbaar() as $tid => $c) {
-    $sub = simplenews_subscriber_load_by_mail($user->mail);
-    $st  = ($sub && isset($sub->newsletter_subscription[$tid]))
-         ? (int) $sub->newsletter_subscription[$tid]->status : 0;
-    $out[] = array(
-      'tid' => (string) $tid,
-      'naam' => $c->name,
-      'omschrijving' => trim(strip_tags($c->description)),
-      'status' => $st,
-    );
-  }
-  return $out;
-}
-```
+**✅ 128-A IS KLAAR — gedeployd en end-to-end getest op productie (Bob,
+2026-09-21).** `nieuwsbrieven.json` levert de juiste lijst (zonder de rol
+`Horeca-owner` zie je 2 van de 3), en `subscribe.json` gaf
+`{"tid":"36667",…,"status":1,"geabonneerd":true}` — direct actief, geen
+bevestigingsmail, precies zoals bedoeld. `custom_nieuwsbrieven_confirm` staat op
+FALSE.
+
+### ⚠️ CSRF-token is VERPLICHT bij POST — cruciaal voor 128-B
+
+Zonder `X-CSRF-Token` antwoordt het endpoint met `["CSRF validation failed"]`
+(gemeten 2026-09-21; mijn eerdere inschatting dat de token niet afgedwongen werd,
+was fout). Met de token erbij werkt het meteen.
+
+**De app is hier al op ingericht, mits je het bestaande patroon volgt:**
+`drupalRequest` zet de header zodra het 5e argument gevuld is, en
+`drupalLogin` schrijft de token bij het inloggen naar `FFAppState().userToken`
+(`lib/custom_code/actions/drupal_login.dart:45`). Geef bij de subscribe- en
+unsubscribe-actie dus **exact dezelfde vijf argumenten mee als het
+favorieten-hartje** op `HorecagelegenheidCurrent`:
+`userSessionname`, `userSessionid`, **`userToken`**, plus de body.
+
+**Vergeet je die token, dan faalt het STIL.** `drupalRequest` geeft bij elke
+non-2xx gewoon `[]` terug (regel 143), dus er komt geen foutmelding: de switch
+lijkt te werken en er gebeurt niets. Controleer een nieuwe actie daarom met
+`adb logcat | grep "I flutter"` — die action print `STATUS` en de body.
+
+### Kleine restjes op 128-A
+
+- `unsubscribe.json` is nog niet één keer aangeroepen. Zelfde route als
+  subscribe, dus laag risico; de app-test dekt het vanzelf af.
+- **Tikfout in de omschrijving van tid 36676**, die letterlijk in de app komt:
+  *"Deze wordt donderdagavond **verstuurt**"* → *verstuurd*. Te wijzigen op
+  `/admin/config/services/simplenews` (Description van de nieuwsbrief).
+- Alles met `source = app` in `{simplenews_subscription}` is voortaan via de
+  app binnengekomen — gratis telling, stond op 0 vóór de eerste test.
 
 **`_custom_nieuwsbrieven_zichtbaar()` is de spil** en wordt door alle drie de
 callbacks gebruikt: hij geeft `simplenews_category_get_visible()` terug (dat