aboutsummaryrefslogtreecommitdiffstats
path: root/src/api/mod.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 12:28:21 +0000
committertv <tv@krebsco.de>2026-11-09 13:32:07 +0100
commit4dbd83e1c38bb8c2e17884ba3fd5145251b3cc0f (patch)
tree9d0fdded29c02028591025c6ec39ccf5aa481c67 /src/api/mod.rs
parentd12ccc782d8e6eab46eb6e0976b747dca1013b36 (diff)
api: a stream opened with a token ends with it
A token was checked when a request came, and a stream answered to it (the dashboard's events, a subscription's links and messages, the store's streams) then went on for as long as the client kept it open: past the token's expiry, past its user's tokens being revoked, its user disabled or removed, its session ended. Now a middleware inside `login::bearer` (`login::streams_end`) ends a streaming answer (`text/event-stream`, `application/x-ndjson`) to a request with a token at the token's deadline, its expiry, or as soon as the document no longer takes it (`token::still_taken`, the checks `verify` makes of the document, now its own function): looked at when a change touches protocol data (the root, a switch, among it), and when a session ends on the node itself in a swarm without a registry (`AppState::session_ended`). No polling: a timer for the expiry, and the changes as they come. The client reconnects with the token it has then; a refreshed token is a new one, so a stream lasts a token's lifetime at most (12 hours by default). `futures` is a dependency of every build now (for `take_until`), not only of libp2p's and Tor's.
Diffstat (limited to 'src/api/mod.rs')
-rw-r--r--src/api/mod.rs5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/api/mod.rs b/src/api/mod.rs
index 6631bc9..97724ff 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -121,6 +121,11 @@ pub(crate) fn router(state: AppState, auth_state: AuthState, debug_api: bool) ->
))
// Who has a password here (`/auth/keys`: a user's last key goes only then).
.layer(axum::Extension(auth_state))
+ // A stream answered to a token ends with it (expired, revoked, its session ended).
+ .layer(middleware::from_fn_with_state(
+ state.clone(),
+ login::streams_end,
+ ))
// Outside authentication: a token, if the request brings one, names the user.
.layer(middleware::from_fn_with_state(state.clone(), login::bearer))
// Outermost: pages of other origins, and their preflights, which bring no