view image files

This commit is contained in:
2025-07-23 13:47:42 +02:00
parent b3e68deb38
commit 7f8726c225
23 changed files with 553 additions and 45 deletions

View File

@@ -1,40 +1,65 @@
use std::os::unix::fs::MetadataExt;
use anyhow::{Context, anyhow, bail};
use rustix::fs::statx;
use tokio::{
fs,
io::{self, AsyncWriteExt as _},
};
use tokio_util::io::ReaderStream;
use crate::domain::warren::{
models::file::{
AbsoluteFilePath, CreateDirectoryError, CreateDirectoryRequest, CreateFileError,
CreateFileRequest, DeleteDirectoryError, DeleteDirectoryRequest, DeleteFileError,
DeleteFileRequest, File, FileMimeType, FileName, FilePath, FileType, ListFilesError,
ListFilesRequest, RenameEntryError, RenameEntryRequest,
use crate::{
config::Config,
domain::warren::{
models::file::{
AbsoluteFilePath, CreateDirectoryError, CreateDirectoryRequest, CreateFileError,
CreateFileRequest, DeleteDirectoryError, DeleteDirectoryRequest, DeleteFileError,
DeleteFileRequest, FetchFileError, FetchFileRequest, File, FileMimeType, FileName,
FilePath, FileStream, FileType, ListFilesError, ListFilesRequest, RenameEntryError,
RenameEntryRequest,
},
ports::FileSystemRepository,
},
ports::FileSystemRepository,
};
const MAX_FILE_FETCH_BYTES: &str = "MAX_FILE_FETCH_BYTES";
#[derive(Debug, Clone)]
pub struct FileSystemConfig {
base_directory: String,
max_file_fetch_bytes: u64,
}
impl FileSystemConfig {
pub fn new(base_directory: String) -> Self {
Self { base_directory }
pub fn new(base_directory: String, max_file_fetch_bytes: u64) -> Self {
Self {
base_directory,
max_file_fetch_bytes,
}
}
pub fn from_env(serve_dir: String) -> anyhow::Result<Self> {
// 268435456 bytes = 0.25GB
let max_file_fetch_bytes: u64 = match Config::load_env(MAX_FILE_FETCH_BYTES) {
Ok(value) => value.parse()?,
Err(_) => 268435456,
};
Ok(Self::new(serve_dir, max_file_fetch_bytes))
}
}
#[derive(Debug, Clone)]
pub struct FileSystem {
base_directory: FilePath,
max_file_fetch_bytes: u64,
}
impl FileSystem {
pub fn new(config: FileSystemConfig) -> anyhow::Result<Self> {
let file_system = Self {
base_directory: FilePath::new(&config.base_directory)?,
max_file_fetch_bytes: config.max_file_fetch_bytes,
};
Ok(file_system)
@@ -146,6 +171,27 @@ impl FileSystem {
Ok(path)
}
async fn fetch_file(&self, path: &AbsoluteFilePath) -> anyhow::Result<FileStream> {
let path = self.get_target_path(path);
let file = fs::OpenOptions::new()
.create(false)
.write(false)
.read(true)
.open(&path)
.await?;
let file_size = file.metadata().await?.size();
if file_size > self.max_file_fetch_bytes {
bail!("File size exceeds configured limit");
}
let stream = FileStream::new(ReaderStream::new(file));
Ok(stream)
}
/// Actually removes a file from the underlying file system
///
/// * `path`: The file's absolute path (absolute not in relation to the root file system but `self.base_directory`)
@@ -237,6 +283,15 @@ impl FileSystemRepository for FileSystem {
Ok(file_path)
}
async fn fetch_file(&self, request: FetchFileRequest) -> Result<FileStream, FetchFileError> {
let contents = self
.fetch_file(request.path())
.await
.map_err(|e| anyhow!("Failed to fetch file {}: {e:?}", request.path()))?;
Ok(contents)
}
async fn delete_file(&self, request: DeleteFileRequest) -> Result<FilePath, DeleteFileError> {
let deleted_path = self
.remove_file(request.path())