Skip to main content

anvil_core/
session.rs

1//! Session subsystem. Thin wrapper around tower-sessions.
2
3pub use tower_sessions::cookie::SameSite;
4pub use tower_sessions::{MemoryStore, Session, SessionManagerLayer};
5
6use crate::config::SessionConfig;
7
8pub fn build_layer(config: &SessionConfig) -> SessionManagerLayer<MemoryStore> {
9    let store = MemoryStore::default();
10    SessionManagerLayer::new(store)
11        .with_name(config.cookie_name.clone())
12        .with_secure(config.secure)
13        .with_same_site(match config.same_site.as_str() {
14            "strict" => SameSite::Strict,
15            "none" => SameSite::None,
16            _ => SameSite::Lax,
17        })
18        .with_expiry(tower_sessions::Expiry::OnInactivity(
19            tower_sessions::cookie::time::Duration::seconds(config.lifetime_minutes * 60),
20        ))
21}
22
23pub const FLASH_KEY: &str = "_flash";
24pub const ERRORS_KEY: &str = "_errors";
25
26/// Insert a flash message — read by the next request, then cleared.
27pub async fn flash(
28    session: &Session,
29    key: &str,
30    value: serde_json::Value,
31) -> Result<(), crate::Error> {
32    let mut flashes: std::collections::HashMap<String, serde_json::Value> = session
33        .get(FLASH_KEY)
34        .await
35        .map_err(|e| crate::Error::Internal(e.to_string()))?
36        .unwrap_or_default();
37    flashes.insert(key.to_string(), value);
38    session
39        .insert(FLASH_KEY, flashes)
40        .await
41        .map_err(|e| crate::Error::Internal(e.to_string()))?;
42    Ok(())
43}
44
45pub async fn take_flash(
46    session: &Session,
47    key: &str,
48) -> Result<Option<serde_json::Value>, crate::Error> {
49    let mut flashes: std::collections::HashMap<String, serde_json::Value> = session
50        .get(FLASH_KEY)
51        .await
52        .map_err(|e| crate::Error::Internal(e.to_string()))?
53        .unwrap_or_default();
54    let value = flashes.remove(key);
55    session
56        .insert(FLASH_KEY, flashes)
57        .await
58        .map_err(|e| crate::Error::Internal(e.to_string()))?;
59    Ok(value)
60}