82 lines
2.7 KiB
Rust
82 lines
2.7 KiB
Rust
pub mod crypto;
|
|
pub mod database;
|
|
pub mod redis_store;
|
|
|
|
use async_trait::async_trait;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use crate::config::AppConfig;
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
pub struct SessionPersistenceDiagnostics {
|
|
pub backend: String,
|
|
pub status: String,
|
|
pub active_sessions: usize,
|
|
pub unique_users: usize,
|
|
pub unique_browsers: usize,
|
|
pub latest_accessed_unix: Option<u64>,
|
|
pub truncated: bool,
|
|
pub engine_version: Option<String>,
|
|
pub connected_clients: Option<u64>,
|
|
pub blocked_clients: Option<u64>,
|
|
pub used_memory_bytes: Option<u64>,
|
|
pub server_uptime_secs: Option<u64>,
|
|
pub role: Option<String>,
|
|
pub master_link_status: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct PersistedSession {
|
|
pub token: String,
|
|
pub account_id: String,
|
|
pub browser_id: String,
|
|
pub email: String,
|
|
pub password_ciphertext: String,
|
|
pub user_hash: String,
|
|
pub imap_host: String,
|
|
pub imap_port: u16,
|
|
pub imap_tls: bool,
|
|
pub imap_tls_verify: bool,
|
|
pub smtp_host: String,
|
|
pub smtp_port: u16,
|
|
pub smtp_tls: bool,
|
|
pub smtp_tls_verify: bool,
|
|
pub timeout_secs: u64,
|
|
pub created_at_unix: u64,
|
|
pub last_accessed_unix: u64,
|
|
pub user_agent: String,
|
|
}
|
|
|
|
impl PersistedSession {
|
|
pub fn expired_at(&self, now_unix: u64) -> bool {
|
|
now_unix.saturating_sub(self.last_accessed_unix) > self.timeout_secs
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
pub trait SessionPersistence: Send + Sync {
|
|
async fn save(&self, session: &PersistedSession) -> Result<(), String>;
|
|
async fn load_token(&self, token: &str) -> Result<Option<PersistedSession>, String>;
|
|
async fn load_browser(&self, browser_id: &str) -> Result<Vec<PersistedSession>, String>;
|
|
async fn load_user(&self, user_hash: &str) -> Result<Vec<PersistedSession>, String>;
|
|
async fn browser_exists(&self, browser_id: &str) -> Result<bool, String>;
|
|
async fn delete_account(&self, account_id: &str) -> Result<bool, String>;
|
|
async fn delete_browser(&self, browser_id: &str) -> Result<(), String>;
|
|
async fn purge_expired(&self, now_unix: u64) -> Result<u64, String>;
|
|
async fn diagnostics(&self, now_unix: u64) -> Result<SessionPersistenceDiagnostics, String>;
|
|
}
|
|
|
|
pub async fn from_config(
|
|
config: &AppConfig,
|
|
) -> Result<std::sync::Arc<dyn SessionPersistence>, String> {
|
|
match config.session_backend.as_str() {
|
|
"database" => Ok(std::sync::Arc::new(
|
|
database::DatabaseSessionStore::connect(config).await?,
|
|
)),
|
|
"redis" => Ok(std::sync::Arc::new(
|
|
redis_store::RedisSessionStore::connect(config).await?,
|
|
)),
|
|
other => Err(format!("unsupported session backend: {other}")),
|
|
}
|
|
}
|