fix: el botón de borrar notificaciones fallaba con un 403 de CSRF #17

Closed
HBB wants to merge 0 commits from HBB/rocinante_android:fix/clear-notifications-csrf into main
First-time contributor

El borrado de notificaciones nunca llegaba a ejecutarse en el servidor y la app
informaba de éxito igualmente, así que el fallo pasaba desapercibido.

Tres causas encadenadas:

  1. NotificationsViewModel era el único punto de la app que hacía un POST con el
    BookWyrmApi inyectado por Hilt. Ese cliente no tiene CookieJar (fija la cabecera
    Cookie manualmente e ignora los Set-Cookie), por lo que enviaba una cookie
    csrftoken obsoleta y Django rechazaba el formulario con un 403. Ahora el POST usa
    el cliente de sesión de NetworkClient —el mismo que ya usan la respuesta a
    publicaciones y la actualización de progreso—, que la pestaña ya recibía como
    parámetro pero no utilizaba.

  2. Se enviaba como csrfmiddlewaretoken el token enmascarado extraído del HTML en
    lugar del valor de la cookie csrftoken. Se aplica el mismo criterio que en la
    actualización de progreso: se usa la cookie y el token del HTML queda de respaldo.

  3. Aun con el POST correcto, response.isSuccessful daba falso: la vista de BookWyrm
    borra y termina con redirect("/notifications"), y el cliente de sesión no sigue
    redirecciones, así que la respuesta normal es un 302. Se acepta cualquier 3xx.

Además, clearAllNotifications invocaba el mismo callback tanto al acabar bien como al
fallar, de modo que siempre se mostraba «Notificaciones borradas». Ahora devuelve un
ClearResult y la interfaz muestra el error real. Se añaden trazas de logcat
(RocinanteNotif) solo en caso de fallo; no se registra ningún token.

Verificado en un dispositivo real contra bookwyrm.social.

El borrado de notificaciones nunca llegaba a ejecutarse en el servidor y la app informaba de éxito igualmente, así que el fallo pasaba desapercibido. Tres causas encadenadas: 1. `NotificationsViewModel` era el único punto de la app que hacía un POST con el `BookWyrmApi` inyectado por Hilt. Ese cliente no tiene CookieJar (fija la cabecera `Cookie` manualmente e ignora los `Set-Cookie`), por lo que enviaba una cookie `csrftoken` obsoleta y Django rechazaba el formulario con un 403. Ahora el POST usa el cliente de sesión de `NetworkClient` —el mismo que ya usan la respuesta a publicaciones y la actualización de progreso—, que la pestaña ya recibía como parámetro pero no utilizaba. 2. Se enviaba como `csrfmiddlewaretoken` el token enmascarado extraído del HTML en lugar del valor de la cookie `csrftoken`. Se aplica el mismo criterio que en la actualización de progreso: se usa la cookie y el token del HTML queda de respaldo. 3. Aun con el POST correcto, `response.isSuccessful` daba falso: la vista de BookWyrm borra y termina con `redirect("/notifications")`, y el cliente de sesión no sigue redirecciones, así que la respuesta normal es un 302. Se acepta cualquier 3xx. Además, `clearAllNotifications` invocaba el mismo callback tanto al acabar bien como al fallar, de modo que siempre se mostraba «Notificaciones borradas». Ahora devuelve un `ClearResult` y la interfaz muestra el error real. Se añaden trazas de logcat (`RocinanteNotif`) solo en caso de fallo; no se registra ningún token. Verificado en un dispositivo real contra bookwyrm.social.
El borrado de notificaciones nunca llegaba a ejecutarse en el servidor y la app
informaba de éxito igualmente, así que el fallo pasaba desapercibido.

Tres causas encadenadas:

1. `NotificationsViewModel` era el único punto de la app que hacía un POST con el
   `BookWyrmApi` inyectado por Hilt. Ese cliente no tiene CookieJar (fija la cabecera
   `Cookie` manualmente e ignora los `Set-Cookie`), por lo que enviaba una cookie
   `csrftoken` obsoleta y Django rechazaba el formulario con un 403. Ahora el POST usa
   el cliente de sesión de `NetworkClient` —el mismo que ya usan la respuesta a
   publicaciones y la actualización de progreso—, que la pestaña ya recibía como
   parámetro pero no utilizaba.

2. Se enviaba como `csrfmiddlewaretoken` el token enmascarado extraído del HTML en
   lugar del valor de la cookie `csrftoken`. Se aplica el mismo criterio que en la
   actualización de progreso: se usa la cookie y el token del HTML queda de respaldo.

3. Aun con el POST correcto, `response.isSuccessful` daba falso: la vista de BookWyrm
   borra y termina con `redirect("/notifications")`, y el cliente de sesión no sigue
   redirecciones, así que la respuesta normal es un 302. Se acepta cualquier 3xx.

Además, `clearAllNotifications` invocaba el mismo callback tanto al acabar bien como al
fallar, de modo que siempre se mostraba «Notificaciones borradas». Ahora devuelve un
`ClearResult` y la interfaz muestra el error real. Se añaden trazas de logcat
(`RocinanteNotif`) solo en caso de fallo; no se registra ningún token.

Verificado en un dispositivo real contra bookwyrm.social.
Owner

Muchas gracias. Tenía esto pendiente y me has quitado un buen peso de encima.

Muchas gracias. Tenía esto pendiente y me has quitado un buen peso de encima.
ferlagod closed this pull request 2026-07-25 15:21:11 +00:00

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ferlagod/rocinante_android!17
No description provided.