- Simplified token type assignment in OAuth service. - Removed unused session_lock module and re-exported Session from zesdex_entities. - Cleaned up session entity by removing unnecessary comments and code. - Consolidated session handling in HTTP handlers for better readability. - Improved formatting and readability in OAuth repository tests. - Enhanced session lock repository with clearer match statements. - Streamlined session repository error handling. - Refined RNG tests for better clarity. - Adjusted module visibility and organization in lib.rs. - Updated IPC client and connection code for better error handling and clarity. - Improved frame handling in IPC for better readability. - Organized module imports and added test utilities for IPC. - Enhanced database connection error handling. - Simplified JWT token creation error handling. - Improved password verification error handling. - Cleaned up state management code for better readability. - Refactored middleware for session authentication and rate limiting. - Simplified clipboard utility for better error handling. - Enhanced logging initialization for better error reporting. - Improved pagination utility with clearer method annotations. - Cleaned up sanitization functions for filenames and paths. - Enhanced slug generation functions for better clarity and usability.
89 lines
3.1 KiB
Rust
89 lines
3.1 KiB
Rust
#![allow(
|
|
clippy::cast_possible_truncation,
|
|
clippy::cast_sign_loss,
|
|
clippy::cast_precision_loss,
|
|
clippy::cast_possible_wrap
|
|
)]
|
|
//! Filesystem-backed `SessionRepository` implementation.
|
|
//!
|
|
//! Each session is stored as `<base_dir>/sessions/<id>/session.json`.
|
|
//! Writes use a write-then-rename + fsync pattern for crash safety.
|
|
use std::path::Path;
|
|
|
|
use crate::domain::repository::SessionRepository;
|
|
use crate::domain::session::Session;
|
|
|
|
/// Concrete filesystem session repository.
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct FileSystemSessionRepository;
|
|
|
|
impl FileSystemSessionRepository {
|
|
/// Create a new filesystem session repository.
|
|
pub fn new() -> Self {
|
|
FileSystemSessionRepository
|
|
}
|
|
}
|
|
|
|
impl SessionRepository for FileSystemSessionRepository {
|
|
fn list_sessions(&self, base_dir: &Path) -> anyhow::Result<Vec<Session>> {
|
|
let sessions_dir = base_dir.join("sessions");
|
|
let Ok(entries) = std::fs::read_dir(&sessions_dir) else {
|
|
return Ok(Vec::new());
|
|
};
|
|
let mut sessions = Vec::new();
|
|
for entry in entries.flatten() {
|
|
if !entry.path().is_dir() {
|
|
continue;
|
|
}
|
|
let id = entry.file_name().to_string_lossy().to_string();
|
|
if let Ok(session) = self.load_session(base_dir, &id) {
|
|
sessions.push(session);
|
|
}
|
|
}
|
|
Ok(sessions)
|
|
}
|
|
|
|
fn load_session(&self, base_dir: &Path, id: &str) -> anyhow::Result<Session> {
|
|
// Directory-traversal prevention.
|
|
if id.contains('/') || id.contains('\\') || id.contains("..") {
|
|
anyhow::bail!("invalid session id '{id}': must not contain path separators");
|
|
}
|
|
let path = base_dir.join("sessions").join(id).join("session.json");
|
|
if !path.exists() {
|
|
anyhow::bail!("session not found: {id}");
|
|
}
|
|
let data = std::fs::read_to_string(&path)?;
|
|
let session: Session = serde_json::from_str(&data)?;
|
|
Ok(session)
|
|
}
|
|
|
|
fn save_session(&self, base_dir: &Path, session: &Session) -> anyhow::Result<()> {
|
|
let dir = session.session_dir(base_dir);
|
|
std::fs::create_dir_all(&dir)?;
|
|
let path = dir.join("session.json");
|
|
let data = serde_json::to_string_pretty(session)?;
|
|
let tmp = dir.join("session.json.tmp");
|
|
std::fs::write(&tmp, data)?;
|
|
// fsync before rename ensures the data is on disk.
|
|
let f = std::fs::File::open(&tmp)?;
|
|
f.sync_all()?;
|
|
std::fs::rename(&tmp, path)?;
|
|
// fsync the parent directory so the rename survives a crash.
|
|
if let Some(parent) = dir.parent() {
|
|
let _ = std::fs::File::open(parent).and_then(|d| d.sync_all());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn delete_session(&self, base_dir: &Path, id: &str) -> anyhow::Result<()> {
|
|
if id.contains('/') || id.contains('\\') || id.contains("..") {
|
|
anyhow::bail!("invalid session id '{id}': must not contain path separators");
|
|
}
|
|
let dir = base_dir.join("sessions").join(id);
|
|
if dir.exists() {
|
|
std::fs::remove_dir_all(&dir)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|