1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! [`SessionAuthExt`]: ergonomic login/logout helpers on [`SessionData`].
//!
//! Collapses the four-step "rotate id → write user id → delete old store
//! entry → save new store entry" sequence that every server-function login
//! handler has had to spell out by hand. Symmetrically wraps the logout
//! sequence so callers cannot forget to rotate the id before clearing the
//! user reference. See issue #4446.
use Result;
use Serialize;
use ;
use SessionStoreRef;
/// Login/logout helpers for [`SessionData`].
///
/// Both methods perform the session-fixation prevention rotation that is a
/// required step on authentication state transitions: each call regenerates
/// the session id, removes the old store entry referenced by the previous
/// id, and persists the updated [`SessionData`] under the new id.
///
/// The trait is provided as an extension so existing call sites can opt
/// in by adding a single `use` and replacing their inline blocks; the
/// implementation lives in `reinhardt-middleware` because that is the
/// crate that owns [`SessionData`] and [`SessionStoreRef`]. `BaseUser` is
/// deliberately *not* a bound on `login` — taking `impl Serialize` keeps
/// the helper usable with any primary-key shape (`i64`, `Uuid`, a tenant
/// composite key, …) and avoids the otherwise-circular auth ↔ middleware
/// coupling.
///
/// # Usage
///
/// ```rust,ignore
/// use reinhardt::middleware::session::{
/// SessionAuthExt, SessionData, SessionStoreRef,
/// };
///
/// #[server_fn]
/// pub async fn login(
/// username: String,
/// password: String,
/// #[inject] mut session: SessionData,
/// #[inject] store: SessionStoreRef,
/// ) -> Result<(), ServerFnError> {
/// // … authenticate `user` …
/// session.login(&store, user.id())
/// .map_err(|e| ServerFnError::application(e.to_string()))?;
/// Ok(())
/// }
/// ```