Refactor and clean up code across multiple modules
- 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.
This commit is contained in:
@@ -1,10 +1,3 @@
|
||||
#![allow(
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::cast_precision_loss,
|
||||
clippy::cast_possible_wrap
|
||||
)]
|
||||
|
||||
use std::io::{self, Write};
|
||||
|
||||
/// Write `text` to the terminal's clipboard using the OSC-52 escape sequence.
|
||||
@@ -15,6 +8,10 @@ use std::io::{self, Write};
|
||||
///
|
||||
/// The `output` parameter should be a writable handle to the terminal (e.g.
|
||||
/// `io::stdout()` or `io::stderr()`).
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `io::Error` if writing to `output` or flushing fails.
|
||||
pub fn write_osc52(output: &mut impl Write, text: &str) -> io::Result<()> {
|
||||
use base64::Engine as _;
|
||||
|
||||
@@ -37,13 +34,22 @@ mod tests {
|
||||
let output = String::from_utf8(buf).unwrap();
|
||||
|
||||
// Should start with OSC sequence
|
||||
assert!(output.starts_with("\x1b]52;c;"), "should start with OSC52 prefix");
|
||||
assert!(
|
||||
output.starts_with("\x1b]52;c;"),
|
||||
"should start with OSC52 prefix"
|
||||
);
|
||||
|
||||
// Should have base64 payload
|
||||
assert!(output.contains("aGVsbG8="), "should contain base64 of 'hello'");
|
||||
assert!(
|
||||
output.contains("aGVsbG8="),
|
||||
"should contain base64 of 'hello'"
|
||||
);
|
||||
|
||||
// Should end with ST
|
||||
assert!(output.ends_with("\x1b\\"), "should end with string terminator");
|
||||
assert!(
|
||||
output.ends_with("\x1b\\"),
|
||||
"should end with string terminator"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
#![allow(
|
||||
clippy::cast_possible_truncation,
|
||||
clippy::cast_sign_loss,
|
||||
clippy::cast_precision_loss,
|
||||
clippy::cast_possible_wrap
|
||||
)]
|
||||
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
@@ -19,17 +12,16 @@ struct LogFileWriter {
|
||||
|
||||
impl std::io::Write for LogFileWriter {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
match OpenOptions::new()
|
||||
if let Ok(mut file) = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open(&self.path)
|
||||
{
|
||||
Ok(mut file) => file.write(buf),
|
||||
Err(_) => {
|
||||
// fallback: write to /dev/null
|
||||
let mut null = fs::OpenOptions::new().write(true).open("/dev/null")?;
|
||||
null.write(buf)
|
||||
}
|
||||
file.write(buf)
|
||||
} else {
|
||||
// fallback: write to /dev/null
|
||||
let mut null = fs::OpenOptions::new().write(true).open("/dev/null")?;
|
||||
null.write(buf)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,11 +53,15 @@ impl<'a> MakeWriter<'a> for LogFileWriter {
|
||||
/// never panics at startup.
|
||||
///
|
||||
/// The subscriber uses `RUST_LOG` / `ZESDEX_LOG` env-filtering.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if creating the log directory or initializing the tracing
|
||||
/// subscriber fails unexpectedly.
|
||||
pub fn init_logging() -> Result<(), anyhow::Error> {
|
||||
// ── determine log directory ──────────────────────────────────────
|
||||
let data_dir = dirs::data_dir()
|
||||
.map(|p| p.join("zesdex"))
|
||||
.unwrap_or_else(|| PathBuf::from("/tmp/zesdex"));
|
||||
let data_dir =
|
||||
dirs::data_dir().map_or_else(|| PathBuf::from("/tmp/zesdex"), |p| p.join("zesdex"));
|
||||
|
||||
let log_dir = data_dir.join("logs");
|
||||
|
||||
@@ -73,7 +69,10 @@ pub fn init_logging() -> Result<(), anyhow::Error> {
|
||||
if let Err(e) = fs::create_dir_all(&log_dir) {
|
||||
// If we can't create the directory, log via eprintln and continue
|
||||
// with a /dev/null fallback.
|
||||
eprintln!("[zesdex-utils::logger] failed to create log dir {log_dir:?}: {e}");
|
||||
eprintln!(
|
||||
"[zesdex-utils::logger] failed to create log dir {}: {e}",
|
||||
log_dir.display()
|
||||
);
|
||||
}
|
||||
|
||||
// ── build log file path ──────────────────────────────────────────
|
||||
|
||||
@@ -22,6 +22,7 @@ pub struct Paginated<T> {
|
||||
|
||||
impl<T> Paginated<T> {
|
||||
/// The total number of pages.
|
||||
#[must_use]
|
||||
pub fn total_pages(&self) -> usize {
|
||||
if self.total == 0 {
|
||||
return 0;
|
||||
@@ -30,11 +31,13 @@ impl<T> Paginated<T> {
|
||||
}
|
||||
|
||||
/// Whether there is a next page.
|
||||
#[must_use]
|
||||
pub fn has_next(&self) -> bool {
|
||||
self.page < self.total_pages()
|
||||
}
|
||||
|
||||
/// Whether there is a previous page.
|
||||
#[must_use]
|
||||
pub fn has_prev(&self) -> bool {
|
||||
self.page > 1
|
||||
}
|
||||
@@ -46,6 +49,7 @@ impl<T> Paginated<T> {
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `page == 0` or `page_size == 0`.
|
||||
#[must_use]
|
||||
pub fn paginate<T>(items: Vec<T>, page: usize, page_size: usize) -> Paginated<T> {
|
||||
assert!(page > 0, "page must be 1-based");
|
||||
assert!(page_size > 0, "page_size must be > 0");
|
||||
@@ -70,6 +74,7 @@ pub fn paginate<T>(items: Vec<T>, page: usize, page_size: usize) -> Paginated<T>
|
||||
/// Compute the SQL offset/limit from 1-based page params.
|
||||
///
|
||||
/// Returns `(offset, limit)`.
|
||||
#[must_use]
|
||||
pub fn page_params(page: usize, page_size: usize) -> (usize, usize) {
|
||||
let offset = page.saturating_sub(1) * page_size;
|
||||
(offset, page_size)
|
||||
|
||||
@@ -8,15 +8,16 @@
|
||||
/// Characters that are invalid in filenames on most operating systems.
|
||||
const INVALID_FILENAME_CHARS: &[char] = &[
|
||||
'/', '\0', '<', '>', ':', '"', '\\', '|', '?', '*', '\x01', '\x02', '\x03', '\x04', '\x05',
|
||||
'\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10',
|
||||
'\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b',
|
||||
'\x1c', '\x1d', '\x1e', '\x1f', '\x7f',
|
||||
'\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11',
|
||||
'\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d',
|
||||
'\x1e', '\x1f', '\x7f',
|
||||
];
|
||||
|
||||
/// Replace characters that are invalid in filenames with `_`.
|
||||
///
|
||||
/// Also strips leading/trailing whitespace and dots, because those can be
|
||||
/// problematic on some filesystems.
|
||||
#[must_use]
|
||||
pub fn sanitize_filename(s: &str) -> String {
|
||||
let sanitized: String = s
|
||||
.chars()
|
||||
@@ -43,6 +44,7 @@ pub fn sanitize_filename(s: &str) -> String {
|
||||
///
|
||||
/// Replaces `..` path components with `_`, collapses repeated separators,
|
||||
/// and strips any leading `/` to keep the result relative.
|
||||
#[must_use]
|
||||
pub fn sanitize_path(path: &str) -> String {
|
||||
let mut cleaned = String::new();
|
||||
|
||||
@@ -71,6 +73,7 @@ pub fn sanitize_path(path: &str) -> String {
|
||||
|
||||
/// Escape HTML special characters so the string can be safely embedded in
|
||||
/// HTML or XML content.
|
||||
#[must_use]
|
||||
pub fn sanitize_html(s: &str) -> String {
|
||||
let mut escaped = String::with_capacity(s.len());
|
||||
|
||||
@@ -93,6 +96,7 @@ pub fn sanitize_html(s: &str) -> String {
|
||||
///
|
||||
/// If `max_chars` is 0, returns an empty string. If the string is already
|
||||
/// short enough, returns it unchanged.
|
||||
#[must_use]
|
||||
pub fn truncate(s: &str, max_chars: usize) -> String {
|
||||
if max_chars == 0 {
|
||||
return String::new();
|
||||
@@ -110,6 +114,7 @@ pub fn truncate(s: &str, max_chars: usize) -> String {
|
||||
|
||||
/// Validate that a session ID contains only alphanumeric characters, dashes,
|
||||
/// and underscores, and is non-empty.
|
||||
#[must_use]
|
||||
pub fn is_valid_session_id(id: &str) -> bool {
|
||||
if id.is_empty() {
|
||||
return false;
|
||||
@@ -140,10 +145,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_sanitize_path_removes_dotdot() {
|
||||
assert_eq!(
|
||||
sanitize_path("foo/../../bar"),
|
||||
"foo/_/_/bar"
|
||||
);
|
||||
assert_eq!(sanitize_path("foo/../../bar"), "foo/_/_/bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -20,6 +20,7 @@ const MAX_SLUG_LENGTH: usize = 80;
|
||||
/// 5. Truncate to 80 characters, breaking at the last full word if possible.
|
||||
///
|
||||
/// Returns `None` if the slug would be completely empty.
|
||||
#[must_use]
|
||||
pub fn slugify(s: &str) -> Option<String> {
|
||||
if s.is_empty() {
|
||||
return None;
|
||||
@@ -74,6 +75,7 @@ pub fn slugify(s: &str) -> Option<String> {
|
||||
/// Join `base` with a slugified version of `name`.
|
||||
///
|
||||
/// If `slugify(name)` returns `None`, the name is used as-is (lowercased).
|
||||
#[must_use]
|
||||
pub fn slug_path(base: &Path, name: &str) -> PathBuf {
|
||||
match slugify(name) {
|
||||
Some(slug) => base.join(slug),
|
||||
@@ -131,6 +133,9 @@ mod tests {
|
||||
#[test]
|
||||
fn test_slug_path() {
|
||||
let base = Path::new("/tmp");
|
||||
assert_eq!(slug_path(base, "Hello World"), Path::new("/tmp/hello-world"));
|
||||
assert_eq!(
|
||||
slug_path(base, "Hello World"),
|
||||
Path::new("/tmp/hello-world")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user