chore: translate all Spanish comments and log messages to English
This commit is contained in:
@@ -10,11 +10,11 @@ use crate::common::errors::DomainError;
|
||||
use crate::domain::entities::file::File;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
|
||||
/// Composite que envuelve `Arc<dyn FileReadPort>` + `Arc<dyn FileWritePort>`
|
||||
/// y delega cada método al port correspondiente.
|
||||
/// Composite that wraps `Arc<dyn FileReadPort>` + `Arc<dyn FileWritePort>`
|
||||
/// and delegates each method to the corresponding port.
|
||||
///
|
||||
/// Gracias al blanket impl `impl<T: FileReadPort + FileWritePort> FileStoragePort for T {}`
|
||||
/// este tipo obtiene `FileStoragePort` automáticamente.
|
||||
/// Thanks to the blanket impl `impl<T: FileReadPort + FileWritePort> FileStoragePort for T {}`
|
||||
/// this type automatically gets `FileStoragePort`.
|
||||
pub struct CompositeFileRepository {
|
||||
read: Arc<dyn FileReadPort>,
|
||||
write: Arc<dyn FileWritePort>,
|
||||
|
||||
@@ -21,9 +21,9 @@ use crate::infrastructure::services::path_service::PathService;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
use crate::common::config::AppConfig;
|
||||
|
||||
/// Implementación de repositorio para operaciones de **lectura** de archivos.
|
||||
/// Repository implementation for file **read** operations.
|
||||
///
|
||||
/// Implementa `FileReadPort`:
|
||||
/// Implements `FileReadPort`:
|
||||
/// get_file, list_files, get_file_content, get_file_stream,
|
||||
/// get_file_range_stream, get_file_mmap, get_file_path, get_parent_folder_id.
|
||||
pub struct FileFsReadRepository {
|
||||
@@ -37,7 +37,7 @@ pub struct FileFsReadRepository {
|
||||
}
|
||||
|
||||
impl FileFsReadRepository {
|
||||
/// Constructor completo con todas las dependencias de infraestructura.
|
||||
/// Full constructor with all infrastructure dependencies.
|
||||
pub fn new(
|
||||
root_path: PathBuf,
|
||||
storage_mediator: Arc<dyn StorageMediator>,
|
||||
@@ -58,7 +58,7 @@ impl FileFsReadRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/// Stub para pruebas (no realiza I/O real).
|
||||
/// Stub for testing (does not perform real I/O).
|
||||
pub fn default_stub() -> Self {
|
||||
Self {
|
||||
root_path: PathBuf::from("./storage"),
|
||||
@@ -75,7 +75,7 @@ impl FileFsReadRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── helpers internos ────────────────────────────────────
|
||||
// ─── internal helpers ─────────────────────────────────────
|
||||
|
||||
fn resolve_storage_path(&self, storage_path: &StoragePath) -> PathBuf {
|
||||
self.path_service.resolve_path(storage_path)
|
||||
|
||||
@@ -21,9 +21,9 @@ use crate::infrastructure::services::path_service::PathService;
|
||||
use crate::domain::services::path_service::StoragePath;
|
||||
use crate::common::config::AppConfig;
|
||||
|
||||
/// Implementación de repositorio para operaciones de **escritura** de archivos.
|
||||
/// Repository implementation for file **write** operations.
|
||||
///
|
||||
/// Implementa `FileWritePort`:
|
||||
/// Implements `FileWritePort`:
|
||||
/// save_file, save_file_from_stream, move_file, delete_file,
|
||||
/// update_file_content, register_file_deferred.
|
||||
pub struct FileFsWriteRepository {
|
||||
@@ -37,7 +37,7 @@ pub struct FileFsWriteRepository {
|
||||
}
|
||||
|
||||
impl FileFsWriteRepository {
|
||||
/// Constructor completo con todas las dependencias.
|
||||
/// Full constructor with all dependencies.
|
||||
pub fn new(
|
||||
root_path: PathBuf,
|
||||
storage_mediator: Arc<dyn StorageMediator>,
|
||||
@@ -50,7 +50,7 @@ impl FileFsWriteRepository {
|
||||
Self { root_path, storage_mediator, id_mapping_service, path_service, metadata_cache, config, parallel_processor }
|
||||
}
|
||||
|
||||
/// Stub para pruebas (no realiza I/O real).
|
||||
/// Stub for testing (does not perform real I/O).
|
||||
pub fn default_stub() -> Self {
|
||||
Self {
|
||||
root_path: PathBuf::from("./storage"),
|
||||
|
||||
@@ -5,147 +5,147 @@ use tracing::{debug, error};
|
||||
use crate::infrastructure::repositories::repository_errors::FolderRepositoryResult;
|
||||
use crate::infrastructure::repositories::folder_fs_repository::FolderFsRepository;
|
||||
|
||||
// Este archivo contiene la implementación de los métodos relacionados con la papelera
|
||||
// para el repositorio de carpetas FolderFsRepository
|
||||
// This file contains the implementation of trash-related methods
|
||||
// for the FolderFsRepository folder repository
|
||||
|
||||
// Implementación de métodos de papelera para el repositorio de carpetas
|
||||
// Implementation of trash methods for the folder repository
|
||||
impl FolderFsRepository {
|
||||
// Obtiene la ruta completa a la papelera
|
||||
// Gets the full path to the trash directory
|
||||
fn get_trash_dir(&self) -> PathBuf {
|
||||
self.get_root_path().join(".trash").join("folders")
|
||||
}
|
||||
|
||||
// Crea una ruta única en la papelera para la carpeta
|
||||
// Creates a unique path in the trash for the folder
|
||||
async fn create_trash_folder_path(&self, folder_id: &str) -> FolderRepositoryResult<PathBuf> {
|
||||
let trash_dir = self.get_trash_dir();
|
||||
|
||||
// Asegurarse que el directorio de la papelera existe
|
||||
// Ensure the trash directory exists
|
||||
if !trash_dir.exists() {
|
||||
fs::create_dir_all(&trash_dir).await
|
||||
.map_err(|e| FolderRepositoryError::StorageError(e.to_string()))?;
|
||||
}
|
||||
|
||||
// Crear una ruta única para la carpeta en la papelera
|
||||
// Create a unique path for the folder in the trash
|
||||
Ok(trash_dir.join(folder_id))
|
||||
}
|
||||
}
|
||||
|
||||
// Implementación de los métodos públicos del trait FolderRepository relacionados con la papelera
|
||||
// Implementation of public FolderRepository trait methods related to trash
|
||||
// Implementation of internal methods for trash functionality
|
||||
// These will be enabled when the trash feature is re-enabled
|
||||
impl FolderFsRepository {
|
||||
/// Helper method that will be used for trash functionality
|
||||
pub(crate) async fn _trash_move_to_trash(&self, folder_id: &str) -> FolderRepositoryResult<()> {
|
||||
debug!("Moviendo carpeta a la papelera: {}", folder_id);
|
||||
debug!("Moving folder to trash: {}", folder_id);
|
||||
|
||||
// Obtener la ruta física de la carpeta
|
||||
// Get the physical path of the folder
|
||||
let folder_path = match self.get_mapped_folder_path(folder_id).await {
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
error!("Error obteniendo ruta de la carpeta {}: {:?}", folder_id, e);
|
||||
error!("Error getting folder path {}: {:?}", folder_id, e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
let folder_path_buf = PathBuf::from(folder_path.to_string());
|
||||
|
||||
// Verificamos que la carpeta existe
|
||||
// Verify the folder exists
|
||||
if !folder_path_buf.exists() {
|
||||
return Err(FolderRepositoryError::NotFound(format!("Folder not found: {}", folder_id)));
|
||||
}
|
||||
|
||||
// Crear directorio en la papelera
|
||||
// Create directory in the trash
|
||||
let trash_folder_path = self.create_trash_folder_path(folder_id).await?;
|
||||
|
||||
// Mover la carpeta físicamente a la papelera
|
||||
// Physically move the folder to the trash
|
||||
match fs::rename(&folder_path_buf, &trash_folder_path).await {
|
||||
Ok(_) => {
|
||||
debug!("Carpeta movida a papelera: {} -> {}", folder_path_buf.display(), trash_folder_path.display());
|
||||
debug!("Folder moved to trash: {} -> {}", folder_path_buf.display(), trash_folder_path.display());
|
||||
|
||||
// Actualizar el mapeo al nuevo path en la papelera
|
||||
// Update the mapping to the new path in the trash
|
||||
if let Err(e) = self.update_mapped_folder_path(folder_id, &trash_folder_path).await {
|
||||
error!("Error actualizando mapeo de carpeta en papelera: {}", e);
|
||||
error!("Error updating folder mapping in trash: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error moviendo carpeta a papelera: {}", e);
|
||||
error!("Error moving folder to trash: {}", e);
|
||||
Err(FolderRepositoryError::StorageError(e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Restaura una carpeta desde la papelera a su ubicación original
|
||||
/// Restores a folder from the trash to its original location
|
||||
pub(crate) async fn _trash_restore_from_trash(&self, folder_id: &str, original_path: &str) -> FolderRepositoryResult<()> {
|
||||
debug!("Restaurando carpeta {} a {}", folder_id, original_path);
|
||||
debug!("Restoring folder {} to {}", folder_id, original_path);
|
||||
|
||||
// Obtener la ruta actual en la papelera
|
||||
// Get the current path in the trash
|
||||
let current_path = match self.get_mapped_folder_path(folder_id).await {
|
||||
Ok(path) => PathBuf::from(path),
|
||||
Err(e) => {
|
||||
error!("Error obteniendo ruta actual de la carpeta {}: {:?}", folder_id, e);
|
||||
error!("Error getting current folder path {}: {:?}", folder_id, e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Convertir la ruta original a PathBuf
|
||||
// Convert the original path to PathBuf
|
||||
let original_path_buf = PathBuf::from(original_path);
|
||||
|
||||
// Asegurar que el directorio padre de destino existe
|
||||
// Ensure the destination parent directory exists
|
||||
if let Some(parent) = original_path_buf.parent() {
|
||||
if !parent.exists() {
|
||||
fs::create_dir_all(parent).await
|
||||
.map_err(|e| {
|
||||
error!("Error creando directorio padre para restauración: {}", e);
|
||||
error!("Error creating parent directory for restoration: {}", e);
|
||||
FolderRepositoryError::StorageError(e.to_string())
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
// Mover la carpeta de la papelera a su ubicación original
|
||||
// Move the folder from the trash to its original location
|
||||
match fs::rename(¤t_path, &original_path_buf).await {
|
||||
Ok(_) => {
|
||||
debug!("Carpeta restaurada: {} -> {}", current_path.display(), original_path_buf.display());
|
||||
debug!("Folder restored: {} -> {}", current_path.display(), original_path_buf.display());
|
||||
|
||||
// Actualizar el mapeo a la ruta original
|
||||
// Update the mapping to the original path
|
||||
if let Err(e) = self.update_mapped_folder_path(folder_id, &original_path_buf).await {
|
||||
error!("Error actualizando mapeo de carpeta restaurada: {}", e);
|
||||
error!("Error updating restored folder mapping: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error restaurando carpeta: {}", e);
|
||||
error!("Error restoring folder: {}", e);
|
||||
Err(FolderRepositoryError::StorageError(e.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Elimina una carpeta permanentemente (usado por la papelera)
|
||||
/// Permanently deletes a folder (used by the trash)
|
||||
pub(crate) async fn _trash_delete_folder_permanently(&self, folder_id: &str) -> FolderRepositoryResult<()> {
|
||||
debug!("Eliminando carpeta permanentemente: {}", folder_id);
|
||||
debug!("Permanently deleting folder: {}", folder_id);
|
||||
|
||||
// Similar a delete_folder pero sin validaciones adicionales
|
||||
// Similar to delete_folder but without additional validations
|
||||
let folder_path = match self.get_mapped_folder_path(folder_id).await {
|
||||
Ok(path) => PathBuf::from(path),
|
||||
Err(e) => {
|
||||
error!("Error obteniendo ruta de la carpeta {}: {:?}", folder_id, e);
|
||||
error!("Error getting folder path {}: {:?}", folder_id, e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Eliminar la carpeta recursivamente
|
||||
// Delete the folder recursively
|
||||
if folder_path.exists() {
|
||||
match fs::remove_dir_all(&folder_path).await {
|
||||
Ok(_) => {
|
||||
debug!("Carpeta eliminada permanentemente: {}", folder_path.display());
|
||||
debug!("Folder permanently deleted: {}", folder_path.display());
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error eliminando carpeta permanentemente: {}", e);
|
||||
// No reportar error si la carpeta ya no existe
|
||||
error!("Error permanently deleting folder: {}", e);
|
||||
// Don't report error if the folder no longer exists
|
||||
if e.kind() != std::io::ErrorKind::NotFound {
|
||||
return Err(FolderRepositoryError::StorageError(e.to_string()));
|
||||
}
|
||||
@@ -153,16 +153,16 @@ impl FolderFsRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// Eliminar el mapeo
|
||||
// Remove the mapping
|
||||
if let Err(e) = self.remove_mapped_folder_id(folder_id).await {
|
||||
error!("Error eliminando mapeo de la carpeta: {}", e);
|
||||
error!("Error removing folder mapping: {}", e);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
debug!("Carpeta eliminada permanentemente con éxito: {}", folder_id);
|
||||
debug!("Folder permanently deleted successfully: {}", folder_id);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Re-exportaciones necesarias para el compilador
|
||||
// Re-exports needed by the compiler
|
||||
use crate::infrastructure::repositories::repository_errors::FolderRepositoryError;
|
||||
@@ -20,9 +20,9 @@ impl CalendarEventPgRepository {
|
||||
#[async_trait]
|
||||
impl CalendarEventRepository for CalendarEventPgRepository {
|
||||
async fn create_event(&self, event: CalendarEvent) -> CalendarEventRepositoryResult<CalendarEvent> {
|
||||
// Este método necesitaría una implementación completa que construya el CalendarEvent
|
||||
// desde el resultado de la query, utilizando métodos del constructor
|
||||
// Para esta demostración, vamos a retornar el mismo evento
|
||||
// This method would need a full implementation that builds the CalendarEvent
|
||||
// from the query result, using constructor methods
|
||||
// For this demonstration, we return the same event
|
||||
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -50,7 +50,7 @@ impl CalendarEventRepository for CalendarEventPgRepository {
|
||||
.await
|
||||
.map_err(|e| DomainError::database_error(format!("Failed to create calendar event: {}", e)))?;
|
||||
|
||||
// Devolvemos el mismo evento en vez de un resultado
|
||||
// We return the same event instead of a result
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ impl CalendarEventRepository for CalendarEventPgRepository {
|
||||
.await
|
||||
.map_err(|e| DomainError::database_error(format!("Failed to update calendar event: {}", e)))?;
|
||||
|
||||
// En una implementación completa, recuperaríamos el evento actualizado
|
||||
// Por simplicidad, devolvemos el mismo evento que recibimos
|
||||
// In a full implementation, we would retrieve the updated event
|
||||
// For simplicity, we return the same event we received
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
@@ -176,9 +176,9 @@ impl CalendarEventRepository for CalendarEventPgRepository {
|
||||
.map_err(|e| DomainError::database_error(format!("Failed to get calendar event by id: {}", e)))?
|
||||
.ok_or_else(|| DomainError::not_found("Calendar Event", id.to_string()))?;
|
||||
|
||||
// En una implementación real, construiríamos un objeto CalendarEvent completo
|
||||
// Por simplicidad, creamos un objeto con valores predeterminados para
|
||||
// demostrar el enfoque sin macros
|
||||
// In a real implementation, we would build a complete CalendarEvent object
|
||||
// For simplicity, we create an object with default values to
|
||||
// demonstrate the approach without macros
|
||||
|
||||
let event = CalendarEvent::with_id(
|
||||
row.get("id"),
|
||||
|
||||
@@ -32,14 +32,14 @@ impl CalendarRepository for CalendarPgRepository {
|
||||
.bind(calendar.owner_id())
|
||||
.bind(calendar.description())
|
||||
.bind(calendar.color())
|
||||
.bind(false) // is_public no existe como campo
|
||||
.bind(false) // is_public doesn't exist as a field
|
||||
.bind(calendar.created_at())
|
||||
.bind(calendar.updated_at())
|
||||
.fetch_one(&*self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::database_error(format!("Failed to create calendar: {}", e)))?;
|
||||
|
||||
// Construir el objeto Calendar utilizando su constructor with_id
|
||||
// Build the Calendar object using its with_id constructor
|
||||
let result = Calendar::with_id(
|
||||
row.get("id"),
|
||||
row.get("name"),
|
||||
@@ -66,14 +66,14 @@ impl CalendarRepository for CalendarPgRepository {
|
||||
.bind(calendar.name())
|
||||
.bind(calendar.description())
|
||||
.bind(calendar.color())
|
||||
.bind(false) // is_public no existe como campo
|
||||
.bind(false) // is_public doesn't exist as a field
|
||||
.bind(now)
|
||||
.bind(calendar.id())
|
||||
.fetch_one(&*self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::database_error(format!("Failed to update calendar: {}", e)))?;
|
||||
|
||||
// Construir el objeto Calendar utilizando su constructor with_id
|
||||
// Build the Calendar object using its with_id constructor
|
||||
let result = Calendar::with_id(
|
||||
row.get("id"),
|
||||
row.get("name"),
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::application::dtos::favorites_dto::FavoriteItemDto;
|
||||
use crate::application::ports::favorites_ports::FavoritesRepositoryPort;
|
||||
use crate::common::errors::{Result, DomainError, ErrorKind};
|
||||
|
||||
/// Implementación PostgreSQL del puerto de persistencia de favoritos.
|
||||
/// PostgreSQL implementation of the favorites persistence port.
|
||||
pub struct FavoritesPgRepository {
|
||||
db_pool: Arc<PgPool>,
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::application::dtos::recent_dto::RecentItemDto;
|
||||
use crate::application::ports::recent_ports::RecentItemsRepositoryPort;
|
||||
use crate::common::errors::{Result, DomainError, ErrorKind};
|
||||
|
||||
/// Implementación PostgreSQL del puerto de persistencia de elementos recientes.
|
||||
/// PostgreSQL implementation of the recent items persistence port.
|
||||
pub struct RecentItemsPgRepository {
|
||||
db_pool: Arc<PgPool>,
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::application::ports::auth_ports::SessionStoragePort;
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::infrastructure::repositories::pg::transaction_utils::with_transaction;
|
||||
|
||||
// Implementar From<sqlx::Error> para SessionRepositoryError para permitir conversiones automáticas
|
||||
// Implement From<sqlx::Error> for SessionRepositoryError to allow automatic conversions
|
||||
impl From<sqlx::Error> for SessionRepositoryError {
|
||||
fn from(err: sqlx::Error) -> Self {
|
||||
SessionPgRepository::map_sqlx_error(err)
|
||||
@@ -26,14 +26,14 @@ impl SessionPgRepository {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
// Método auxiliar para mapear errores SQL a errores de dominio
|
||||
// Helper method to map SQL errors to domain errors
|
||||
pub fn map_sqlx_error(err: sqlx::Error) -> SessionRepositoryError {
|
||||
match err {
|
||||
sqlx::Error::RowNotFound => {
|
||||
SessionRepositoryError::NotFound("Sesión no encontrada".to_string())
|
||||
SessionRepositoryError::NotFound("Session not found".to_string())
|
||||
},
|
||||
_ => SessionRepositoryError::DatabaseError(
|
||||
format!("Error de base de datos: {}", err)
|
||||
format!("Database error: {}", err)
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -41,9 +41,9 @@ impl SessionPgRepository {
|
||||
|
||||
#[async_trait]
|
||||
impl SessionRepository for SessionPgRepository {
|
||||
/// Crea una nueva sesión utilizando una transacción
|
||||
/// Creates a new session using a transaction
|
||||
async fn create_session(&self, session: Session) -> SessionRepositoryResult<Session> {
|
||||
// Crear una copia de la sesión para el closure
|
||||
// Create a copy of the session for the closure
|
||||
let session_clone = session.clone();
|
||||
|
||||
with_transaction(
|
||||
@@ -51,7 +51,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
"create_session",
|
||||
|tx| {
|
||||
Box::pin(async move {
|
||||
// Insertar la sesión
|
||||
// Insert the session
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO auth.sessions (
|
||||
@@ -74,8 +74,8 @@ impl SessionRepository for SessionPgRepository {
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
|
||||
// Opcionalmente, actualizar el último login del usuario
|
||||
// dentro de la misma transacción
|
||||
// Optionally, update the user's last login
|
||||
// within the same transaction
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.users
|
||||
@@ -87,12 +87,12 @@ impl SessionRepository for SessionPgRepository {
|
||||
.execute(&mut **tx)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
// Convertimos el error pero sin interrumpir la creación
|
||||
// de la sesión si falla la actualización
|
||||
tracing::warn!("No se pudo actualizar last_login_at para usuario {}: {}",
|
||||
// Convert the error but without interrupting session
|
||||
// creation if the update fails
|
||||
tracing::warn!("Could not update last_login_at for user {}: {}",
|
||||
session_clone.user_id(), e);
|
||||
SessionRepositoryError::DatabaseError(format!(
|
||||
"Sesión creada pero no se pudo actualizar last_login_at: {}", e
|
||||
"Session created but could not update last_login_at: {}", e
|
||||
))
|
||||
})?;
|
||||
|
||||
@@ -104,7 +104,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
Ok(session)
|
||||
}
|
||||
|
||||
/// Obtiene una sesión por ID
|
||||
/// Gets a session by ID
|
||||
async fn get_session_by_id(&self, id: &str) -> SessionRepositoryResult<Session> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -132,7 +132,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Obtiene una sesión por token de actualización
|
||||
/// Gets a session by refresh token
|
||||
async fn get_session_by_refresh_token(&self, refresh_token: &str) -> SessionRepositoryResult<Session> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -160,7 +160,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Obtiene todas las sesiones de un usuario
|
||||
/// Gets all sessions for a user
|
||||
async fn get_sessions_by_user_id(&self, user_id: &str) -> SessionRepositoryResult<Vec<Session>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
@@ -195,16 +195,16 @@ impl SessionRepository for SessionPgRepository {
|
||||
Ok(sessions)
|
||||
}
|
||||
|
||||
/// Revoca una sesión específica utilizando una transacción
|
||||
/// Revokes a specific session using a transaction
|
||||
async fn revoke_session(&self, session_id: &str) -> SessionRepositoryResult<()> {
|
||||
let id = session_id.to_string(); // Clone para uso en closure
|
||||
let id = session_id.to_string(); // Clone for use in closure
|
||||
|
||||
with_transaction(
|
||||
&self.pool,
|
||||
"revoke_session",
|
||||
|tx| {
|
||||
Box::pin(async move {
|
||||
// Revocar la sesión
|
||||
// Revoke the session
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.sessions
|
||||
@@ -218,14 +218,14 @@ impl SessionRepository for SessionPgRepository {
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
|
||||
// Si encontramos la sesión, podemos registrar un evento de seguridad
|
||||
// If we found the session, we can log a security event
|
||||
if let Some(row) = result {
|
||||
let user_id: String = row.try_get("user_id").unwrap_or_default();
|
||||
|
||||
// Registrar evento de seguridad (en una tabla de seguridad)
|
||||
// Esto es opcional pero muestra cómo se puede realizar operaciones
|
||||
// adicionales en la misma transacción
|
||||
tracing::info!("Sesión con ID {} del usuario {} revocada", id, user_id);
|
||||
// Log security event (in a security table)
|
||||
// This is optional but shows how additional operations
|
||||
// can be performed in the same transaction
|
||||
tracing::info!("Session with ID {} for user {} revoked", id, user_id);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -234,16 +234,16 @@ impl SessionRepository for SessionPgRepository {
|
||||
).await
|
||||
}
|
||||
|
||||
/// Revoca todas las sesiones de un usuario utilizando una transacción
|
||||
/// Revokes all sessions for a user using a transaction
|
||||
async fn revoke_all_user_sessions(&self, user_id: &str) -> SessionRepositoryResult<u64> {
|
||||
let user_id_clone = user_id.to_string(); // Clone para uso en closure
|
||||
let user_id_clone = user_id.to_string(); // Clone for use in closure
|
||||
|
||||
with_transaction(
|
||||
&self.pool,
|
||||
"revoke_all_user_sessions",
|
||||
|tx| {
|
||||
Box::pin(async move {
|
||||
// Revocar todas las sesiones del usuario
|
||||
// Revoke all sessions for the user
|
||||
let result = sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.sessions
|
||||
@@ -258,9 +258,9 @@ impl SessionRepository for SessionPgRepository {
|
||||
|
||||
let affected = result.rows_affected();
|
||||
|
||||
// Registrar evento de seguridad
|
||||
// Log security event
|
||||
if affected > 0 {
|
||||
tracing::info!("Revocadas {} sesiones del usuario {}", affected, user_id_clone);
|
||||
tracing::info!("Revoked {} sessions for user {}", affected, user_id_clone);
|
||||
}
|
||||
|
||||
Ok(affected)
|
||||
@@ -269,7 +269,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
).await
|
||||
}
|
||||
|
||||
/// Elimina sesiones expiradas
|
||||
/// Deletes expired sessions
|
||||
async fn delete_expired_sessions(&self) -> SessionRepositoryResult<u64> {
|
||||
let now = Utc::now();
|
||||
|
||||
@@ -288,7 +288,7 @@ impl SessionRepository for SessionPgRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// Implementación del puerto de almacenamiento para la capa de aplicación
|
||||
// Implementation of the storage port for the application layer
|
||||
#[async_trait]
|
||||
impl SessionStoragePort for SessionPgRepository {
|
||||
async fn create_session(&self, session: Session) -> Result<Session, DomainError> {
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::application::ports::auth_ports::UserStoragePort;
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::infrastructure::repositories::pg::transaction_utils::with_transaction;
|
||||
|
||||
// Implementar From<sqlx::Error> para UserRepositoryError para permitir conversiones automáticas
|
||||
// Implement From<sqlx::Error> for UserRepositoryError to allow automatic conversions
|
||||
impl From<sqlx::Error> for UserRepositoryError {
|
||||
fn from(err: sqlx::Error) -> Self {
|
||||
UserPgRepository::map_sqlx_error(err)
|
||||
@@ -25,26 +25,26 @@ impl UserPgRepository {
|
||||
Self { pool }
|
||||
}
|
||||
|
||||
// Método auxiliar para mapear errores SQL a errores de dominio
|
||||
// Helper method to map SQL errors to domain errors
|
||||
pub fn map_sqlx_error(err: sqlx::Error) -> UserRepositoryError {
|
||||
match err {
|
||||
sqlx::Error::RowNotFound => {
|
||||
UserRepositoryError::NotFound("Usuario no encontrado".to_string())
|
||||
UserRepositoryError::NotFound("User not found".to_string())
|
||||
},
|
||||
sqlx::Error::Database(db_err) => {
|
||||
if db_err.code().map_or(false, |code| code == "23505") {
|
||||
// Código para violación de unicidad en PostgreSQL
|
||||
// PostgreSQL uniqueness violation code
|
||||
UserRepositoryError::AlreadyExists(
|
||||
"Usuario o email ya existe".to_string()
|
||||
"User or email already exists".to_string()
|
||||
)
|
||||
} else {
|
||||
UserRepositoryError::DatabaseError(
|
||||
format!("Error de base de datos: {}", db_err)
|
||||
format!("Database error: {}", db_err)
|
||||
)
|
||||
}
|
||||
},
|
||||
_ => UserRepositoryError::DatabaseError(
|
||||
format!("Error de base de datos: {}", err)
|
||||
format!("Database error: {}", err)
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ impl UserPgRepository {
|
||||
|
||||
#[async_trait]
|
||||
impl UserRepository for UserPgRepository {
|
||||
/// Crea un nuevo usuario utilizando una transacción
|
||||
/// Creates a new user using a transaction
|
||||
async fn create_user(&self, user: User) -> UserRepositoryResult<User> {
|
||||
// Creamos una copia del usuario para el closure
|
||||
let user_clone = user.clone();
|
||||
@@ -61,14 +61,14 @@ impl UserRepository for UserPgRepository {
|
||||
&self.pool,
|
||||
"create_user",
|
||||
|tx| {
|
||||
// Necesitamos mover el closure a un BoxFuture para devolver dentro
|
||||
// de la llamada with_transaction
|
||||
// We need to move the closure into a BoxFuture to return inside
|
||||
// the with_transaction call
|
||||
Box::pin(async move {
|
||||
// Usamos los getters para extraer los valores
|
||||
// Convertimos user.role() a string para pasarlo como texto plano
|
||||
// Use getters to extract the values
|
||||
// Convert user.role() to string to pass it as plain text
|
||||
let role_str = user_clone.role().to_string();
|
||||
|
||||
// Modificar el SQL para hacer un cast explícito al tipo auth.userrole
|
||||
// Modify the SQL to do an explicit cast to the auth.userrole type
|
||||
let _result = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO auth.users (
|
||||
@@ -87,7 +87,7 @@ impl UserRepository for UserPgRepository {
|
||||
.bind(user_clone.username())
|
||||
.bind(user_clone.email())
|
||||
.bind(user_clone.password_hash())
|
||||
.bind(&role_str) // Convertir a string pero con cast explícito en SQL
|
||||
.bind(&role_str) // Convert to string but with explicit cast in SQL
|
||||
.bind(user_clone.storage_quota_bytes())
|
||||
.bind(user_clone.storage_used_bytes())
|
||||
.bind(user_clone.created_at())
|
||||
@@ -100,18 +100,18 @@ impl UserRepository for UserPgRepository {
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
|
||||
// Podríamos realizar operaciones adicionales aquí,
|
||||
// como configurar permisos, roles, etc.
|
||||
// We could perform additional operations here,
|
||||
// such as configuring permissions, roles, etc.
|
||||
|
||||
Ok(user_clone)
|
||||
}) as BoxFuture<'_, UserRepositoryResult<User>>
|
||||
}
|
||||
).await?;
|
||||
|
||||
Ok(user) // Devolvemos el usuario original por simplicidad
|
||||
Ok(user) // Return the original user for simplicity
|
||||
}
|
||||
|
||||
/// Obtiene un usuario por ID
|
||||
/// Gets a user by ID
|
||||
async fn get_user_by_id(&self, id: &str) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -153,7 +153,7 @@ impl UserRepository for UserPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Obtiene un usuario por nombre de usuario
|
||||
/// Gets a user by username
|
||||
async fn get_user_by_username(&self, username: &str) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -195,7 +195,7 @@ impl UserRepository for UserPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Obtiene un usuario por correo electrónico
|
||||
/// Gets a user by email
|
||||
async fn get_user_by_email(&self, email: &str) -> UserRepositoryResult<User> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -237,9 +237,9 @@ impl UserRepository for UserPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Actualiza un usuario existente utilizando una transacción
|
||||
/// Updates an existing user using a transaction
|
||||
async fn update_user(&self, user: User) -> UserRepositoryResult<User> {
|
||||
// Creamos una copia del usuario para el closure
|
||||
// Create a copy of the user for the closure
|
||||
let user_clone = user.clone();
|
||||
|
||||
with_transaction(
|
||||
@@ -247,7 +247,7 @@ impl UserRepository for UserPgRepository {
|
||||
"update_user",
|
||||
|tx| {
|
||||
Box::pin(async move {
|
||||
// Actualizar el usuario
|
||||
// Update the user
|
||||
sqlx::query(
|
||||
r#"
|
||||
UPDATE auth.users
|
||||
@@ -278,8 +278,8 @@ impl UserRepository for UserPgRepository {
|
||||
.await
|
||||
.map_err(Self::map_sqlx_error)?;
|
||||
|
||||
// Podríamos realizar operaciones adicionales aquí dentro
|
||||
// de la misma transacción, como actualizar permisos, etc.
|
||||
// We could perform additional operations here inside
|
||||
// the same transaction, such as updating permissions, etc.
|
||||
|
||||
Ok(user_clone)
|
||||
}) as BoxFuture<'_, UserRepositoryResult<User>>
|
||||
@@ -289,7 +289,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
/// Actualiza solo el uso de almacenamiento de un usuario
|
||||
/// Updates only the storage usage of a user
|
||||
async fn update_storage_usage(&self, user_id: &str, usage_bytes: i64) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -309,7 +309,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Actualiza la fecha de último inicio de sesión
|
||||
/// Updates the last login date
|
||||
async fn update_last_login(&self, user_id: &str) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -328,7 +328,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lista usuarios con paginación
|
||||
/// Lists users with pagination
|
||||
async fn list_users(&self, limit: i64, offset: i64) -> UserRepositoryResult<Vec<User>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
@@ -378,7 +378,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(users)
|
||||
}
|
||||
|
||||
/// Activa o desactiva un usuario
|
||||
/// Activates or deactivates a user
|
||||
async fn set_user_active_status(&self, user_id: &str, active: bool) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -398,7 +398,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Cambia la contraseña de un usuario
|
||||
/// Changes a user's password
|
||||
async fn change_password(&self, user_id: &str, password_hash: &str) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -418,9 +418,9 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Cambia el rol de un usuario
|
||||
/// Changes a user's role
|
||||
async fn change_role(&self, user_id: &str, role: UserRole) -> UserRepositoryResult<()> {
|
||||
// Convertir el rol a string para el binding
|
||||
// Convert the role to string for the binding
|
||||
let role_str = role.to_string();
|
||||
|
||||
sqlx::query(
|
||||
@@ -441,7 +441,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Lista usuarios por rol
|
||||
/// Lists users by role
|
||||
async fn list_users_by_role(&self, role: &str) -> UserRepositoryResult<Vec<User>> {
|
||||
let rows = sqlx::query(
|
||||
r#"
|
||||
@@ -490,7 +490,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(users)
|
||||
}
|
||||
|
||||
/// Elimina un usuario
|
||||
/// Deletes a user
|
||||
async fn delete_user(&self, user_id: &str) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -548,7 +548,7 @@ impl UserRepository for UserPgRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Actualiza la cuota de almacenamiento de un usuario
|
||||
/// Updates a user's storage quota
|
||||
async fn update_storage_quota(&self, user_id: &str, quota_bytes: i64) -> UserRepositoryResult<()> {
|
||||
sqlx::query(
|
||||
r#"
|
||||
@@ -568,7 +568,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Cuenta el número total de usuarios
|
||||
/// Counts the total number of users
|
||||
async fn count_users(&self) -> UserRepositoryResult<i64> {
|
||||
let row = sqlx::query(
|
||||
"SELECT COUNT(*) as count FROM auth.users"
|
||||
@@ -581,7 +581,7 @@ impl UserRepository for UserPgRepository {
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
/// Obtiene estadísticas de almacenamiento agregadas
|
||||
/// Gets aggregated storage statistics
|
||||
async fn get_storage_stats(&self) -> UserRepositoryResult<StorageStats> {
|
||||
let row = sqlx::query(
|
||||
r#"
|
||||
@@ -610,7 +610,7 @@ impl UserRepository for UserPgRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// Implementación del puerto de almacenamiento para la capa de aplicación
|
||||
// Storage port implementation for the application layer
|
||||
#[async_trait]
|
||||
impl UserStoragePort for UserPgRepository {
|
||||
async fn create_user(&self, user: User) -> Result<User, DomainError> {
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
// Estructura para almacenar en el sistema de archivos
|
||||
// Structure for storing in the file system
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct ShareRecord {
|
||||
id: String,
|
||||
@@ -38,12 +38,12 @@ impl ShareFsRepository {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
/// Obtiene la ruta del archivo JSON donde se almacenan los enlaces compartidos
|
||||
/// Gets the path to the JSON file where shared links are stored
|
||||
fn get_shares_path(&self) -> String {
|
||||
format!("{}/shares.json", self.config.storage_path.display())
|
||||
}
|
||||
|
||||
/// Lee todos los enlaces compartidos del archivo JSON
|
||||
/// Reads all shared links from the JSON file
|
||||
async fn read_shares(&self) -> Result<Vec<ShareRecord>, io::Error> {
|
||||
let path = self.get_shares_path();
|
||||
let path = Path::new(&path);
|
||||
@@ -58,12 +58,12 @@ impl ShareFsRepository {
|
||||
Ok(shares)
|
||||
}
|
||||
|
||||
/// Guarda todos los enlaces compartidos en el archivo JSON
|
||||
/// Saves all shared links to the JSON file
|
||||
async fn write_shares(&self, shares: &[ShareRecord]) -> Result<(), io::Error> {
|
||||
let path = self.get_shares_path();
|
||||
let json = serde_json::to_string_pretty(shares)?;
|
||||
|
||||
// Asegúrate de que el directorio existe
|
||||
// Make sure the directory exists
|
||||
let dir = Path::new(&path).parent().unwrap();
|
||||
if !dir.exists() {
|
||||
fs::create_dir_all(dir).await?
|
||||
@@ -72,7 +72,7 @@ impl ShareFsRepository {
|
||||
fs::write(path, json).await
|
||||
}
|
||||
|
||||
/// Convierte un registro del sistema de archivos a una entidad de dominio
|
||||
/// Converts a file system record to a domain entity
|
||||
fn to_entity(&self, record: &ShareRecord) -> Share {
|
||||
let item_type = ShareItemType::try_from(record.item_type.as_str())
|
||||
.unwrap_or(ShareItemType::File);
|
||||
@@ -97,7 +97,7 @@ impl ShareFsRepository {
|
||||
)
|
||||
}
|
||||
|
||||
/// Convierte una entidad de dominio a un registro para el sistema de archivos
|
||||
/// Converts a domain entity to a file system record
|
||||
fn to_record(&self, share: &Share) -> ShareRecord {
|
||||
ShareRecord {
|
||||
id: share.id().to_string(),
|
||||
@@ -122,16 +122,16 @@ impl ShareStoragePort for ShareFsRepository {
|
||||
let mut shares = self.read_shares().await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
// Verifica si el enlace ya existe
|
||||
// Check if the link already exists
|
||||
let existing_index = shares.iter().position(|s| s.id == share.id());
|
||||
|
||||
let record = self.to_record(share);
|
||||
|
||||
if let Some(index) = existing_index {
|
||||
// Actualización
|
||||
// Update
|
||||
shares[index] = record;
|
||||
} else {
|
||||
// Inserción
|
||||
// Insert
|
||||
shares.push(record);
|
||||
}
|
||||
|
||||
@@ -190,16 +190,16 @@ impl ShareStoragePort for ShareFsRepository {
|
||||
let mut shares = self.read_shares().await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
// Busca el índice del enlace a actualizar
|
||||
// Find the index of the link to update
|
||||
let index = shares.iter().position(|s| s.id == share.id())
|
||||
.ok_or_else(|| {
|
||||
DomainError::not_found("Share", format!("Share with ID {} not found for update", share.id()))
|
||||
})?;
|
||||
|
||||
// Actualiza el registro
|
||||
// Update the record
|
||||
shares[index] = self.to_record(share);
|
||||
|
||||
// Guarda los cambios
|
||||
// Save changes
|
||||
self.write_shares(&shares).await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
@@ -210,16 +210,16 @@ impl ShareStoragePort for ShareFsRepository {
|
||||
let mut shares = self.read_shares().await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
// Encuentra el índice del enlace a eliminar
|
||||
// Find the index of the link to delete
|
||||
let initial_len = shares.len();
|
||||
shares.retain(|s| s.id != id);
|
||||
|
||||
// Si no se eliminó ningún enlace, significa que no existía
|
||||
// If no link was deleted, it means it didn't exist
|
||||
if shares.len() == initial_len {
|
||||
return Err(DomainError::not_found("Share", format!("Share with ID {} not found for deletion", id)));
|
||||
}
|
||||
|
||||
// Guarda los cambios
|
||||
// Save changes
|
||||
self.write_shares(&shares).await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
@@ -230,15 +230,15 @@ impl ShareStoragePort for ShareFsRepository {
|
||||
let shares = self.read_shares().await
|
||||
.map_err(|e| DomainError::internal_error("Share", e.to_string()))?;
|
||||
|
||||
// Filtra los enlaces del usuario
|
||||
// Filter the user's links
|
||||
let user_shares: Vec<ShareRecord> = shares.into_iter()
|
||||
.filter(|s| s.created_by == user_id)
|
||||
.collect();
|
||||
|
||||
// Calcula el total
|
||||
// Calculate the total
|
||||
let total = user_shares.len();
|
||||
|
||||
// Aplica la paginación
|
||||
// Apply pagination
|
||||
let paginated: Vec<Share> = user_shares.iter()
|
||||
.skip(offset)
|
||||
.take(limit)
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::domain::entities::trashed_item::{TrashedItem, TrashedItemType};
|
||||
use crate::domain::repositories::trash_repository::TrashRepository;
|
||||
use crate::application::ports::outbound::IdMappingPort;
|
||||
|
||||
/// Estructura para almacenar elementos en la papelera en formato JSON
|
||||
/// Structure for storing trash items in JSON format
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct TrashedItemEntry {
|
||||
id: String,
|
||||
@@ -25,7 +25,7 @@ struct TrashedItemEntry {
|
||||
deletion_date: String,
|
||||
}
|
||||
|
||||
/// Implementación del repositorio de papelera usando el sistema de archivos
|
||||
/// Trash repository implementation using the file system
|
||||
pub struct TrashFsRepository {
|
||||
trash_dir: PathBuf,
|
||||
trash_index_path: PathBuf,
|
||||
@@ -45,7 +45,7 @@ impl TrashFsRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/// Asegura que existe el directorio de papelera
|
||||
/// Ensures the trash directory exists
|
||||
async fn ensure_trash_dir(&self) -> Result<()> {
|
||||
debug!("Checking if trash directory exists: {}", self.trash_dir.display());
|
||||
if !self.trash_dir.exists() {
|
||||
@@ -105,7 +105,7 @@ impl TrashFsRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Obtiene todas las entradas del índice de papelera
|
||||
/// Gets all entries from the trash index
|
||||
async fn get_trash_entries(&self) -> Result<Vec<TrashedItemEntry>> {
|
||||
self.ensure_trash_dir().await?;
|
||||
|
||||
@@ -134,7 +134,7 @@ impl TrashFsRepository {
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
/// Guarda todas las entradas en el índice de papelera
|
||||
/// Saves all entries to the trash index
|
||||
async fn save_trash_entries(&self, entries: Vec<TrashedItemEntry>) -> Result<()> {
|
||||
self.ensure_trash_dir().await?;
|
||||
|
||||
@@ -155,7 +155,7 @@ impl TrashFsRepository {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convierte una entrada JSON a entidad TrashedItem
|
||||
/// Converts a JSON entry to a TrashedItem entity
|
||||
fn entry_to_trashed_item(&self, entry: TrashedItemEntry) -> Result<TrashedItem> {
|
||||
let item_type = match entry.item_type.as_str() {
|
||||
"file" => TrashedItemType::File,
|
||||
@@ -206,7 +206,7 @@ impl TrashFsRepository {
|
||||
))
|
||||
}
|
||||
|
||||
/// Convierte una entidad TrashedItem a entrada JSON
|
||||
/// Converts a TrashedItem entity to a JSON entry
|
||||
fn trashed_item_to_entry(&self, item: &TrashedItem) -> TrashedItemEntry {
|
||||
TrashedItemEntry {
|
||||
id: item.id().to_string(),
|
||||
@@ -228,9 +228,9 @@ impl TrashFsRepository {
|
||||
impl TrashRepository for TrashFsRepository {
|
||||
#[instrument(skip(self))]
|
||||
async fn add_to_trash(&self, item: &TrashedItem) -> Result<()> {
|
||||
debug!("Añadiendo elemento a la papelera: id={}, user={}", item.id(), item.user_id());
|
||||
debug!("Adding item to trash: id={}, user={}", item.id(), item.user_id());
|
||||
|
||||
// Aseguramos que existe el directorio de la papelera para este usuario
|
||||
// Ensure the trash directory exists for this user
|
||||
let user_trash_dir = self.trash_dir.join("files").join(item.user_id().to_string());
|
||||
debug!("User trash directory path: {}", user_trash_dir.display());
|
||||
|
||||
@@ -268,7 +268,7 @@ impl TrashRepository for TrashFsRepository {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn get_trash_items(&self, user_id: &Uuid) -> Result<Vec<TrashedItem>> {
|
||||
debug!("Obteniendo elementos en papelera para usuario: {}", user_id);
|
||||
debug!("Getting trash items for user: {}", user_id);
|
||||
|
||||
let entries = self.get_trash_entries().await?;
|
||||
|
||||
@@ -290,7 +290,7 @@ impl TrashRepository for TrashFsRepository {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn get_trash_item(&self, id: &Uuid, user_id: &Uuid) -> Result<Option<TrashedItem>> {
|
||||
debug!("Buscando elemento en papelera: id={}, user={}", id, user_id);
|
||||
debug!("Looking for item in trash: id={}, user={}", id, user_id);
|
||||
|
||||
let entries = self.get_trash_entries().await?;
|
||||
|
||||
@@ -311,7 +311,7 @@ impl TrashRepository for TrashFsRepository {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn restore_from_trash(&self, id: &Uuid, user_id: &Uuid) -> Result<()> {
|
||||
debug!("Restaurando elemento de la papelera: id={}, user={}", id, user_id);
|
||||
debug!("Restoring item from trash: id={}, user={}", id, user_id);
|
||||
|
||||
let mut entries = self.get_trash_entries().await?;
|
||||
|
||||
@@ -333,16 +333,16 @@ impl TrashRepository for TrashFsRepository {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn delete_permanently(&self, id: &Uuid, user_id: &Uuid) -> Result<()> {
|
||||
debug!("Eliminando permanentemente elemento de la papelera: id={}, user={}", id, user_id);
|
||||
debug!("Permanently deleting item from trash: id={}, user={}", id, user_id);
|
||||
|
||||
// Simplemente eliminamos la entrada del índice
|
||||
// Los archivos físicos se eliminarán a través del repositorio correspondiente
|
||||
// Simply remove the entry from the index
|
||||
// Physical files will be deleted through the corresponding repository
|
||||
self.restore_from_trash(id, user_id).await
|
||||
}
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn clear_trash(&self, user_id: &Uuid) -> Result<()> {
|
||||
debug!("Limpiando papelera para usuario: {}", user_id);
|
||||
debug!("Clearing trash for user: {}", user_id);
|
||||
|
||||
let mut entries = self.get_trash_entries().await?;
|
||||
let user_id_str = user_id.to_string();
|
||||
@@ -355,7 +355,7 @@ impl TrashRepository for TrashFsRepository {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
async fn get_expired_items(&self) -> Result<Vec<TrashedItem>> {
|
||||
debug!("Buscando elementos de papelera expirados");
|
||||
debug!("Looking for expired trash items");
|
||||
|
||||
let entries = self.get_trash_entries().await?;
|
||||
let now = Utc::now();
|
||||
|
||||
Reference in New Issue
Block a user