adding webdav features
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
//! Adapters module for translating between external protocols and internal models
|
||||
|
||||
pub mod webdav_adapter;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,5 +2,6 @@ pub mod dtos;
|
||||
pub mod ports;
|
||||
pub mod services;
|
||||
pub mod transactions;
|
||||
pub mod adapters;
|
||||
|
||||
// Re-exportaciones para facilitar el acceso a los principales puertos
|
||||
// Re-exportaciones para facilitar el acceso a los principales puertos
|
||||
@@ -23,6 +23,15 @@ pub trait FileUseCase: Send + Sync + 'static {
|
||||
/// Obtiene un archivo por su ID
|
||||
async fn get_file(&self, id: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
/// Obtiene un archivo por su ruta (para WebDAV)
|
||||
async fn get_file_by_path(&self, path: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
/// Crea un nuevo archivo en la ruta especificada (para WebDAV)
|
||||
async fn create_file(&self, parent_path: &str, filename: &str, content: &[u8], content_type: &str) -> Result<FileDto, DomainError>;
|
||||
|
||||
/// Actualiza el contenido de un archivo existente (para WebDAV)
|
||||
async fn update_file(&self, path: &str, content: &[u8]) -> Result<(), DomainError>;
|
||||
|
||||
/// Lista archivos en una carpeta
|
||||
async fn list_files(&self, folder_id: Option<&str>) -> Result<Vec<FileDto>, DomainError>;
|
||||
|
||||
|
||||
@@ -56,6 +56,12 @@ pub trait FileStoragePort: Send + Sync + 'static {
|
||||
|
||||
/// Obtiene la ruta de almacenamiento de un archivo
|
||||
async fn get_file_path(&self, id: &str) -> Result<StoragePath, DomainError>;
|
||||
|
||||
/// Obtiene el ID de la carpeta padre para una ruta dada (necesario para WebDAV)
|
||||
async fn get_parent_folder_id(&self, path: &str) -> Result<String, DomainError>;
|
||||
|
||||
/// Actualiza el contenido de un archivo existente
|
||||
async fn update_file_content(&self, file_id: &str, content: Vec<u8>) -> Result<(), DomainError>;
|
||||
}
|
||||
|
||||
/// Puerto secundario para persistencia de carpetas
|
||||
|
||||
@@ -140,6 +140,18 @@ impl FileService {
|
||||
Ok(FileDto::empty())
|
||||
}
|
||||
|
||||
async fn get_file_by_path(&self, _path: &str) -> Result<FileDto, DomainError> {
|
||||
Ok(FileDto::empty())
|
||||
}
|
||||
|
||||
async fn create_file(&self, _parent_path: &str, _filename: &str, _content: &[u8], _content_type: &str) -> Result<FileDto, DomainError> {
|
||||
Ok(FileDto::empty())
|
||||
}
|
||||
|
||||
async fn update_file(&self, _path: &str, _content: &[u8]) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn list_files(&self, _folder_id: Option<&str>) -> Result<Vec<FileDto>, DomainError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
@@ -186,6 +198,76 @@ impl FileService {
|
||||
Ok(FileDto::from(file))
|
||||
}
|
||||
|
||||
/// Gets a file by path (needed for WebDAV)
|
||||
pub async fn get_file_by_path(&self, path: &str) -> FileServiceResult<FileDto> {
|
||||
// This is a simple implementation for WebDAV support
|
||||
// First, normalize the path (remove leading/trailing slashes)
|
||||
let path = path.trim_start_matches('/').trim_end_matches('/');
|
||||
|
||||
// List all files and find the one with matching path
|
||||
let all_files = self.list_files(None).await?;
|
||||
|
||||
for file in all_files {
|
||||
let file_path = file.path.trim_start_matches('/').trim_end_matches('/');
|
||||
if file_path == path || file_path.ends_with(&format!("/{}", path)) || path.ends_with(&format!("/{}", file_path)) {
|
||||
return Ok(file);
|
||||
}
|
||||
}
|
||||
|
||||
// If no file found, return an error
|
||||
Err(FileServiceError::NotFound(format!("File not found at path: {}", path)))
|
||||
}
|
||||
|
||||
/// Creates or updates a file at a specific path (needed for WebDAV)
|
||||
pub async fn create_file(&self, parent_path: &str, filename: &str, content: &[u8], content_type: &str) -> FileServiceResult<FileDto> {
|
||||
// Get parent folder ID if parent path is not empty
|
||||
let parent_id = if !parent_path.is_empty() {
|
||||
match self.file_repository.get_parent_folder_id(parent_path).await {
|
||||
Ok(id) => Some(id),
|
||||
Err(_) => None // If parent doesn't exist, use root
|
||||
}
|
||||
} else {
|
||||
None // Root folder
|
||||
};
|
||||
|
||||
// Save the file with the provided filename and parent folder
|
||||
let file = self.file_repository.save_file(
|
||||
filename.to_string(),
|
||||
parent_id,
|
||||
content_type.to_string(),
|
||||
content.to_vec()
|
||||
).await.map_err(FileServiceError::from)?;
|
||||
|
||||
Ok(FileDto::from(file))
|
||||
}
|
||||
|
||||
/// Updates an existing file (needed for WebDAV)
|
||||
pub async fn update_file(&self, path: &str, content: &[u8]) -> FileServiceResult<()> {
|
||||
// First, try to get the file by path
|
||||
match self.get_file_by_path(path).await {
|
||||
Ok(file) => {
|
||||
// Update the file content
|
||||
self.file_repository.update_file_content(&file.id, content.to_vec())
|
||||
.await
|
||||
.map_err(FileServiceError::from)
|
||||
},
|
||||
Err(_) => {
|
||||
// If file doesn't exist, extract filename and parent path and create it
|
||||
let path = path.trim_start_matches('/').trim_end_matches('/');
|
||||
let (parent_path, filename) = if let Some(idx) = path.rfind('/') {
|
||||
(&path[..idx], &path[idx+1..])
|
||||
} else {
|
||||
("", path)
|
||||
};
|
||||
|
||||
// Create new file
|
||||
self.create_file(parent_path, filename, content, "application/octet-stream").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists files in a folder
|
||||
pub async fn list_files(&self, folder_id: Option<&str>) -> FileServiceResult<Vec<FileDto>> {
|
||||
let files = self.file_repository.list_files(folder_id).await
|
||||
@@ -247,6 +329,21 @@ impl FileUseCase for FileService {
|
||||
.map_err(DomainError::from)
|
||||
}
|
||||
|
||||
async fn get_file_by_path(&self, path: &str) -> Result<FileDto, DomainError> {
|
||||
FileService::get_file_by_path(self, path).await
|
||||
.map_err(DomainError::from)
|
||||
}
|
||||
|
||||
async fn create_file(&self, parent_path: &str, filename: &str, content: &[u8], content_type: &str) -> Result<FileDto, DomainError> {
|
||||
FileService::create_file(self, parent_path, filename, content, content_type).await
|
||||
.map_err(DomainError::from)
|
||||
}
|
||||
|
||||
async fn update_file(&self, path: &str, content: &[u8]) -> Result<(), DomainError> {
|
||||
FileService::update_file(self, path, content).await
|
||||
.map_err(DomainError::from)
|
||||
}
|
||||
|
||||
async fn list_files(&self, folder_id: Option<&str>) -> Result<Vec<FileDto>, DomainError> {
|
||||
FileService::list_files(self, folder_id).await
|
||||
.map_err(DomainError::from)
|
||||
|
||||
Reference in New Issue
Block a user