acton_htmx/auth/
mod.rs

1//! Authentication and session management
2//!
3//! This module provides session-based authentication with secure HTTP-only cookies.
4
5pub mod extractors;
6pub mod handlers;
7pub mod password;
8pub mod session;
9pub mod user;
10
11pub use extractors::{Authenticated, AuthenticationError, OptionalAuth};
12pub use handlers::{
13    login_form, login_post, logout_post, register_form, register_post, AuthHandlerError,
14    LoginForm, RegisterForm,
15};
16pub use password::{
17    hash_password, verify_password, PasswordError, PasswordHashConfig, PasswordHasher,
18};
19pub use session::{FlashLevel, FlashMessage, SessionData, SessionError, SessionId};
20pub use user::{CreateUser, EmailAddress, User, UserError};
21
22use serde::{Deserialize, Serialize};
23
24/// Session wrapper for handler extractors
25///
26/// Provides access to the current user's session data within request handlers.
27#[derive(Debug, Clone)]
28pub struct Session {
29    id: SessionId,
30    data: SessionData,
31}
32
33impl Session {
34    /// Create a new session wrapper
35    #[must_use]
36    pub const fn new(id: SessionId, data: SessionData) -> Self {
37        Self { id, data }
38    }
39
40    /// Get the session ID
41    #[must_use]
42    pub const fn id(&self) -> &SessionId {
43        &self.id
44    }
45
46    /// Get the session data
47    #[must_use]
48    pub const fn data(&self) -> &SessionData {
49        &self.data
50    }
51
52    /// Get mutable access to session data
53    pub const fn data_mut(&mut self) -> &mut SessionData {
54        &mut self.data
55    }
56
57    /// Get a value from the session
58    #[must_use]
59    pub fn get<T: for<'de> Deserialize<'de>>(&self, key: &str) -> Option<T> {
60        self.data.get(key)
61    }
62
63    /// Set a value in the session
64    ///
65    /// # Errors
66    ///
67    /// Returns error if value cannot be serialized
68    pub fn set<T: Serialize>(&mut self, key: String, value: T) -> Result<(), SessionError> {
69        self.data.set(key, value)
70    }
71
72    /// Remove a value from the session
73    pub fn remove(&mut self, key: &str) -> Option<serde_json::Value> {
74        self.data.remove(key)
75    }
76
77    /// Get the user ID if authenticated
78    #[must_use]
79    pub const fn user_id(&self) -> Option<i64> {
80        self.data.user_id
81    }
82
83    /// Set the user ID (for login)
84    pub const fn set_user_id(&mut self, user_id: Option<i64>) {
85        self.data.user_id = user_id;
86    }
87
88    /// Add a flash message
89    pub fn add_flash(&mut self, message: FlashMessage) {
90        self.data.flash_messages.push(message);
91    }
92
93    /// Take all flash messages (clears them from session)
94    pub fn take_flashes(&mut self) -> Vec<FlashMessage> {
95        std::mem::take(&mut self.data.flash_messages)
96    }
97
98    /// Check if there are any flash messages
99    #[must_use]
100    pub fn has_flashes(&self) -> bool {
101        !self.data.flash_messages.is_empty()
102    }
103}