chore: translate all Spanish comments and log messages to English
This commit is contained in:
@@ -15,7 +15,7 @@ use crate::application::dtos::user_dto::{
|
||||
use crate::interfaces::errors::AppError;
|
||||
|
||||
pub fn auth_routes() -> Router<Arc<AppState>> {
|
||||
// Rutas que NO requieren autenticación
|
||||
// Routes that do NOT require authentication
|
||||
let public_routes = Router::new()
|
||||
.route("/register", post(register))
|
||||
.route("/login", post(login))
|
||||
@@ -27,14 +27,14 @@ pub fn auth_routes() -> Router<Arc<AppState>> {
|
||||
.route("/oidc/callback", get(oidc_callback))
|
||||
.route("/oidc/exchange", post(oidc_exchange));
|
||||
|
||||
// Rutas que SÍ requieren autenticación - usamos route_layer para aplicar middleware
|
||||
// El middleware usará el state que se pase con .with_state() desde main.rs
|
||||
// Routes that DO require authentication - we use route_layer to apply middleware
|
||||
// The middleware will use the state passed with .with_state() from main.rs
|
||||
let protected_routes = Router::new()
|
||||
.route("/me", get(get_current_user))
|
||||
.route("/change-password", put(change_password))
|
||||
.route("/logout", post(logout));
|
||||
|
||||
// Combinar rutas públicas y protegidas
|
||||
// Combine public and protected routes
|
||||
public_routes.merge(protected_routes)
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ async fn register(
|
||||
},
|
||||
None => {
|
||||
tracing::error!("Auth service not configured");
|
||||
return Err(AppError::internal_error("Servicio de autenticación no configurado"));
|
||||
return Err(AppError::internal_error("Authentication service not configured"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -153,7 +153,7 @@ async fn login(
|
||||
},
|
||||
None => {
|
||||
tracing::error!("Auth service not configured");
|
||||
return Err(AppError::internal_error("Servicio de autenticación no configurado"));
|
||||
return Err(AppError::internal_error("Authentication service not configured"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,7 +174,7 @@ async fn login(
|
||||
// Ensure the response has the expected fields
|
||||
if auth_response.access_token.is_empty() || auth_response.refresh_token.is_empty() {
|
||||
tracing::error!("Login response contains empty tokens for user: {}", dto.username);
|
||||
return Err(AppError::internal_error("Error generando tokens de autenticación"));
|
||||
return Err(AppError::internal_error("Error generating authentication tokens"));
|
||||
}
|
||||
|
||||
Ok((StatusCode::OK, Json(auth_response)))
|
||||
@@ -198,7 +198,7 @@ async fn refresh_token(
|
||||
|
||||
// Normal process for real tokens
|
||||
let auth_service = state.auth_service.as_ref()
|
||||
.ok_or_else(|| AppError::internal_error("Servicio de autenticación no configurado"))?;
|
||||
.ok_or_else(|| AppError::internal_error("Authentication service not configured"))?;
|
||||
|
||||
let auth_response = auth_service.auth_application_service.refresh_token(dto).await?;
|
||||
|
||||
@@ -214,37 +214,37 @@ async fn get_current_user(
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
// Normal process for all users
|
||||
let auth_service = state.auth_service.as_ref()
|
||||
.ok_or_else(|| AppError::internal_error("Servicio de autenticación no configurado"))?;
|
||||
.ok_or_else(|| AppError::internal_error("Authentication service not configured"))?;
|
||||
|
||||
// Extraer y validar el token directamente
|
||||
// Extract and validate the token directly
|
||||
let token = headers
|
||||
.get(header::AUTHORIZATION)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.and_then(|value| value.strip_prefix("Bearer "))
|
||||
.ok_or_else(|| AppError::unauthorized("Token de autorización no encontrado"))?;
|
||||
.ok_or_else(|| AppError::unauthorized("Authorization token not found"))?;
|
||||
|
||||
// Validar el token y obtener claims
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Token inválido: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
|
||||
let user_id = claims.sub;
|
||||
|
||||
// Primero, actualizar las estadísticas de uso de almacenamiento
|
||||
// IMPORTANTE: Esperamos el cálculo para devolver datos actualizados
|
||||
// First, update the storage usage statistics
|
||||
// IMPORTANT: We await the calculation to return updated data
|
||||
if let Some(storage_usage_service) = state.storage_usage_service.as_ref() {
|
||||
// Calcular storage de forma síncrona (esperamos el resultado)
|
||||
// Calculate storage synchronously (we await the result)
|
||||
match storage_usage_service.update_user_storage_usage(&user_id).await {
|
||||
Ok(usage) => {
|
||||
tracing::info!("Updated storage usage for user {}: {} bytes", user_id, usage);
|
||||
},
|
||||
Err(e) => {
|
||||
// Solo log de warning, no fallar la petición completa
|
||||
// Only log a warning, don't fail the entire request
|
||||
tracing::warn!("Failed to update storage usage for user {}: {}", user_id, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ahora obtener los datos del usuario CON el almacenamiento actualizado
|
||||
// Now get the user data WITH the updated storage
|
||||
let user = auth_service.auth_application_service.get_user_by_id(&user_id).await?;
|
||||
|
||||
Ok((StatusCode::OK, Json(user)))
|
||||
@@ -256,18 +256,18 @@ async fn change_password(
|
||||
Json(dto): Json<ChangePasswordDto>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let auth_service = state.auth_service.as_ref()
|
||||
.ok_or_else(|| AppError::internal_error("Servicio de autenticación no configurado"))?;
|
||||
.ok_or_else(|| AppError::internal_error("Authentication service not configured"))?;
|
||||
|
||||
// Extraer y validar el token directamente
|
||||
// Extract and validate the token directly
|
||||
let token = headers
|
||||
.get(header::AUTHORIZATION)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.and_then(|value| value.strip_prefix("Bearer "))
|
||||
.ok_or_else(|| AppError::unauthorized("Token de autorización no encontrado"))?;
|
||||
.ok_or_else(|| AppError::unauthorized("Authorization token not found"))?;
|
||||
|
||||
// Validar el token y obtener claims
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Token inválido: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
|
||||
auth_service.auth_application_service.change_password(&claims.sub, dto).await?;
|
||||
|
||||
@@ -279,18 +279,18 @@ async fn logout(
|
||||
headers: HeaderMap,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let auth_service = state.auth_service.as_ref()
|
||||
.ok_or_else(|| AppError::internal_error("Servicio de autenticación no configurado"))?;
|
||||
.ok_or_else(|| AppError::internal_error("Authentication service not configured"))?;
|
||||
|
||||
// Extraer y validar el token directamente
|
||||
// Extract and validate the token directly
|
||||
let token = headers
|
||||
.get(header::AUTHORIZATION)
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.and_then(|value| value.strip_prefix("Bearer "))
|
||||
.ok_or_else(|| AppError::unauthorized("Token de autorización no encontrado"))?;
|
||||
.ok_or_else(|| AppError::unauthorized("Authorization token not found"))?;
|
||||
|
||||
// Validar el token y obtener claims
|
||||
// Validate the token and get claims
|
||||
let claims = auth_service.token_service.validate_token(token)
|
||||
.map_err(|e| AppError::unauthorized(&format!("Token inválido: {}", e)))?;
|
||||
.map_err(|e| AppError::unauthorized(&format!("Invalid token: {}", e)))?;
|
||||
|
||||
// Use access token for logout (we don't have refresh token in headers)
|
||||
auth_service.auth_application_service.logout(&claims.sub, token).await?;
|
||||
@@ -314,7 +314,7 @@ async fn get_system_status(
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> Result<impl IntoResponse, AppError> {
|
||||
let auth_service = state.auth_service.as_ref()
|
||||
.ok_or_else(|| AppError::internal_error("Servicio de autenticación no configurado"))?;
|
||||
.ok_or_else(|| AppError::internal_error("Authentication service not configured"))?;
|
||||
|
||||
// Count admin users to determine if system is initialized
|
||||
let admin_count = auth_service.auth_application_service.count_admin_users().await
|
||||
|
||||
@@ -13,86 +13,86 @@ use crate::application::dtos::file_dto::FileDto;
|
||||
use crate::application::dtos::folder_dto::FolderDto;
|
||||
use crate::interfaces::api::handlers::ApiResult;
|
||||
|
||||
/// Estado compartido para el handler de batch
|
||||
/// Shared state for the batch handler
|
||||
#[derive(Clone)]
|
||||
pub struct BatchHandlerState {
|
||||
pub batch_service: Arc<BatchOperationService>,
|
||||
}
|
||||
|
||||
/// DTO para las solicitudes de operaciones en lote de archivos
|
||||
/// DTO for batch file operation requests
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BatchFileOperationRequest {
|
||||
/// IDs de los archivos a procesar
|
||||
/// IDs of the files to process
|
||||
pub file_ids: Vec<String>,
|
||||
/// ID de la carpeta destino (opcional)
|
||||
/// Target folder ID (optional)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub target_folder_id: Option<String>,
|
||||
}
|
||||
|
||||
/// DTO para las solicitudes de operaciones en lote de carpetas
|
||||
/// DTO for batch folder operation requests
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BatchFolderOperationRequest {
|
||||
/// IDs de las carpetas a procesar
|
||||
/// IDs of the folders to process
|
||||
pub folder_ids: Vec<String>,
|
||||
/// Si la operación debe ser recursiva
|
||||
/// Whether the operation should be recursive
|
||||
#[serde(default)]
|
||||
pub recursive: bool,
|
||||
/// ID de la carpeta destino (opcional)
|
||||
/// Target folder ID (optional)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub target_folder_id: Option<String>,
|
||||
}
|
||||
|
||||
/// DTO para las solicitudes de creación en lote de carpetas
|
||||
/// DTO for batch folder creation requests
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BatchCreateFoldersRequest {
|
||||
/// Detalles de las carpetas a crear
|
||||
/// Details of the folders to create
|
||||
pub folders: Vec<CreateFolderDetail>,
|
||||
}
|
||||
|
||||
/// Detalle para creación de una carpeta
|
||||
/// Detail for folder creation
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CreateFolderDetail {
|
||||
/// Nombre de la carpeta
|
||||
/// Folder name
|
||||
pub name: String,
|
||||
/// ID de la carpeta padre (opcional)
|
||||
/// Parent folder ID (optional)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parent_id: Option<String>,
|
||||
}
|
||||
|
||||
/// DTO para los resultados de operaciones en lote
|
||||
/// DTO for batch operation results
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct BatchOperationResponse<T> {
|
||||
/// Entidades procesadas exitosamente
|
||||
/// Successfully processed entities
|
||||
pub successful: Vec<T>,
|
||||
/// Operaciones fallidas con sus mensajes de error
|
||||
/// Failed operations with their error messages
|
||||
pub failed: Vec<FailedOperation>,
|
||||
/// Estadísticas de la operación
|
||||
/// Operation statistics
|
||||
pub stats: BatchOperationStats,
|
||||
}
|
||||
|
||||
/// Operación fallida en un lote
|
||||
/// Failed operation in a batch
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct FailedOperation {
|
||||
/// Identificador de la entidad que falló
|
||||
/// Identifier of the entity that failed
|
||||
pub id: String,
|
||||
/// Mensaje de error
|
||||
/// Error message
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
/// Estadísticas de una operación por lotes
|
||||
/// Statistics for a batch operation
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct BatchOperationStats {
|
||||
/// Número total de operaciones
|
||||
/// Total number of operations
|
||||
pub total: usize,
|
||||
/// Número de operaciones exitosas
|
||||
/// Number of successful operations
|
||||
pub successful: usize,
|
||||
/// Número de operaciones fallidas
|
||||
/// Number of failed operations
|
||||
pub failed: usize,
|
||||
/// Tiempo total de ejecución en milisegundos
|
||||
/// Total execution time in milliseconds
|
||||
pub execution_time_ms: u128,
|
||||
}
|
||||
|
||||
/// Convierte BatchStats del dominio a DTO
|
||||
/// Converts domain BatchStats to DTO
|
||||
impl From<BatchStats> for BatchOperationStats {
|
||||
fn from(stats: BatchStats) -> Self {
|
||||
Self {
|
||||
@@ -104,7 +104,7 @@ impl From<BatchStats> for BatchOperationStats {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convierte BatchResult<T> del dominio a DTO
|
||||
/// Converts domain BatchResult<T> to DTO
|
||||
impl<T, U> From<BatchResult<T>> for BatchOperationResponse<U>
|
||||
where
|
||||
U: From<T>,
|
||||
@@ -124,12 +124,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Handler para mover múltiples archivos en lote
|
||||
/// Handler for moving multiple files in batch
|
||||
pub async fn move_files_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFileOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay archivos para procesar
|
||||
// Verify there are files to process
|
||||
if request.file_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -139,35 +139,35 @@ pub async fn move_files_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.move_files(request.file_ids, request.target_folder_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Convertir resultado a DTO
|
||||
// Convert result to DTO
|
||||
let response: BatchOperationResponse<FileDto> = result.into();
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para copiar múltiples archivos en lote
|
||||
/// Handler for copying multiple files in batch
|
||||
pub async fn copy_files_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFileOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay archivos para procesar
|
||||
// Verify there are files to process
|
||||
if request.file_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -177,35 +177,35 @@ pub async fn copy_files_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.copy_files(request.file_ids, request.target_folder_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Convertir resultado a DTO
|
||||
// Convert result to DTO
|
||||
let response: BatchOperationResponse<FileDto> = result.into();
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para eliminar múltiples archivos en lote
|
||||
/// Handler for deleting multiple files in batch
|
||||
pub async fn delete_files_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFileOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay archivos para procesar
|
||||
// Verify there are files to process
|
||||
if request.file_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -215,13 +215,13 @@ pub async fn delete_files_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.delete_files(request.file_ids)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Crear respuesta personalizada para IDs de string
|
||||
// Create custom response for string IDs
|
||||
let response = BatchOperationResponse {
|
||||
successful: result.successful,
|
||||
failed: result.failed.into_iter()
|
||||
@@ -230,26 +230,26 @@ pub async fn delete_files_batch(
|
||||
stats: result.stats.into(),
|
||||
};
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para eliminar múltiples carpetas en lote
|
||||
/// Handler for deleting multiple folders in batch
|
||||
pub async fn delete_folders_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFolderOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay carpetas para procesar
|
||||
// Verify there are folders to process
|
||||
if request.folder_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -259,13 +259,13 @@ pub async fn delete_folders_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.delete_folders(request.folder_ids, request.recursive)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Crear respuesta personalizada para IDs de string
|
||||
// Create custom response for string IDs
|
||||
let response = BatchOperationResponse {
|
||||
successful: result.successful,
|
||||
failed: result.failed.into_iter()
|
||||
@@ -274,26 +274,26 @@ pub async fn delete_folders_batch(
|
||||
stats: result.stats.into(),
|
||||
};
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para crear múltiples carpetas en lote
|
||||
/// Handler for creating multiple folders in batch
|
||||
pub async fn create_folders_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchCreateFoldersRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay carpetas para procesar
|
||||
// Verify there are folders to process
|
||||
if request.folders.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -303,41 +303,41 @@ pub async fn create_folders_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Transformar el formato para el servicio
|
||||
// Transform the format for the service
|
||||
let folders = request.folders
|
||||
.into_iter()
|
||||
.map(|detail| (detail.name, detail.parent_id))
|
||||
.collect();
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.create_folders(folders)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Convertir resultado a DTO
|
||||
// Convert result to DTO
|
||||
let response: BatchOperationResponse<FolderDto> = result.into();
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::CREATED // Todas exitosas
|
||||
StatusCode::CREATED // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para obtener múltiples archivos en lote
|
||||
/// Handler for getting multiple files in batch
|
||||
pub async fn get_files_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFileOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay archivos para procesar
|
||||
// Verify there are files to process
|
||||
if request.file_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -347,35 +347,35 @@ pub async fn get_files_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.get_multiple_files(request.file_ids)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Convertir resultado a DTO
|
||||
// Convert result to DTO
|
||||
let response: BatchOperationResponse<FileDto> = result.into();
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
}
|
||||
|
||||
/// Handler para obtener múltiples carpetas en lote
|
||||
/// Handler for getting multiple folders in batch
|
||||
pub async fn get_folders_batch(
|
||||
State(state): State<BatchHandlerState>,
|
||||
Json(request): Json<BatchFolderOperationRequest>,
|
||||
) -> ApiResult<impl IntoResponse> {
|
||||
// Verificar que hay carpetas para procesar
|
||||
// Verify there are folders to process
|
||||
if request.folder_ids.is_empty() {
|
||||
return Ok((
|
||||
StatusCode::BAD_REQUEST,
|
||||
@@ -385,24 +385,24 @@ pub async fn get_folders_batch(
|
||||
).into_response());
|
||||
}
|
||||
|
||||
// Ejecutar operación de lote
|
||||
// Execute batch operation
|
||||
let result = state.batch_service
|
||||
.get_multiple_folders(request.folder_ids)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Convertir resultado a DTO
|
||||
// Convert result to DTO
|
||||
let response: BatchOperationResponse<FolderDto> = result.into();
|
||||
|
||||
// Determinar código de estado basado en los resultados
|
||||
// Determine status code based on results
|
||||
let status_code = if response.stats.failed > 0 {
|
||||
if response.stats.successful > 0 {
|
||||
StatusCode::PARTIAL_CONTENT // Algunas operaciones exitosas, otras fallidas
|
||||
StatusCode::PARTIAL_CONTENT // Some operations successful, others failed
|
||||
} else {
|
||||
StatusCode::BAD_REQUEST // Todas fallaron
|
||||
StatusCode::BAD_REQUEST // All failed
|
||||
}
|
||||
} else {
|
||||
StatusCode::OK // Todas exitosas
|
||||
StatusCode::OK // All successful
|
||||
};
|
||||
|
||||
Ok((status_code, Json(response)).into_response())
|
||||
|
||||
@@ -11,14 +11,14 @@ use tracing::{error, info};
|
||||
use crate::application::ports::recent_ports::RecentItemsUseCase;
|
||||
use crate::interfaces::middleware::auth::AuthUser;
|
||||
|
||||
/// Parámetros de consulta para obtener elementos recientes
|
||||
/// Query parameters for getting recent items
|
||||
#[derive(Deserialize)]
|
||||
pub struct GetRecentParams {
|
||||
#[serde(default)]
|
||||
limit: Option<i32>,
|
||||
}
|
||||
|
||||
/// Obtener elementos recientes del usuario
|
||||
/// Get user's recent items
|
||||
pub async fn get_recent_items(
|
||||
State(recent_service): State<Arc<dyn RecentItemsUseCase>>,
|
||||
auth_user: AuthUser,
|
||||
@@ -28,22 +28,22 @@ pub async fn get_recent_items(
|
||||
|
||||
match recent_service.get_recent_items(user_id, params.limit).await {
|
||||
Ok(items) => {
|
||||
info!("Recuperados {} elementos recientes para usuario", items.len());
|
||||
info!("Retrieved {} recent items for user", items.len());
|
||||
(StatusCode::OK, Json(items)).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error al recuperar elementos recientes: {}", err);
|
||||
error!("Error retrieving recent items: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!({
|
||||
"error": format!("Fallo al recuperar elementos recientes: {}", err)
|
||||
"error": format!("Failed to retrieve recent items: {}", err)
|
||||
}))
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Registrar acceso a un elemento
|
||||
/// Record access to an item
|
||||
pub async fn record_item_access(
|
||||
State(recent_service): State<Arc<dyn RecentItemsUseCase>>,
|
||||
auth_user: AuthUser,
|
||||
@@ -51,39 +51,39 @@ pub async fn record_item_access(
|
||||
) -> impl IntoResponse {
|
||||
let user_id = &auth_user.id;
|
||||
|
||||
// Validar tipo de elemento
|
||||
// Validate item type
|
||||
if item_type != "file" && item_type != "folder" {
|
||||
return (
|
||||
StatusCode::BAD_REQUEST,
|
||||
Json(serde_json::json!({
|
||||
"error": "El tipo de elemento debe ser 'file' o 'folder'"
|
||||
"error": "Item type must be 'file' or 'folder'"
|
||||
}))
|
||||
).into_response();
|
||||
}
|
||||
|
||||
match recent_service.record_item_access(user_id, &item_id, &item_type).await {
|
||||
Ok(_) => {
|
||||
info!("Registrado acceso a {} '{}' en recientes", item_type, item_id);
|
||||
info!("Recorded access to {} '{}' in recents", item_type, item_id);
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(serde_json::json!({
|
||||
"message": "Acceso registrado correctamente"
|
||||
"message": "Access recorded successfully"
|
||||
}))
|
||||
).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error al registrar acceso en recientes: {}", err);
|
||||
error!("Error recording access in recents: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!({
|
||||
"error": format!("Fallo al registrar acceso: {}", err)
|
||||
"error": format!("Failed to record access: {}", err)
|
||||
}))
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Eliminar un elemento de recientes
|
||||
/// Remove an item from recents
|
||||
pub async fn remove_from_recent(
|
||||
State(recent_service): State<Arc<dyn RecentItemsUseCase>>,
|
||||
auth_user: AuthUser,
|
||||
@@ -94,36 +94,36 @@ pub async fn remove_from_recent(
|
||||
match recent_service.remove_from_recent(user_id, &item_id, &item_type).await {
|
||||
Ok(removed) => {
|
||||
if removed {
|
||||
info!("Eliminado {} '{}' de recientes", item_type, item_id);
|
||||
info!("Removed {} '{}' from recents", item_type, item_id);
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(serde_json::json!({
|
||||
"message": "Elemento eliminado de recientes"
|
||||
"message": "Item removed from recents"
|
||||
}))
|
||||
).into_response()
|
||||
} else {
|
||||
info!("Elemento {} '{}' no estaba en recientes", item_type, item_id);
|
||||
info!("Item {} '{}' was not in recents", item_type, item_id);
|
||||
(
|
||||
StatusCode::NOT_FOUND,
|
||||
Json(serde_json::json!({
|
||||
"message": "Elemento no estaba en recientes"
|
||||
"message": "Item was not in recents"
|
||||
}))
|
||||
).into_response()
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error al eliminar de recientes: {}", err);
|
||||
error!("Error removing from recents: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!({
|
||||
"error": format!("Fallo al eliminar de recientes: {}", err)
|
||||
"error": format!("Failed to remove from recents: {}", err)
|
||||
}))
|
||||
).into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Limpiar todos los elementos recientes
|
||||
/// Clear all recent items
|
||||
pub async fn clear_recent_items(
|
||||
State(recent_service): State<Arc<dyn RecentItemsUseCase>>,
|
||||
auth_user: AuthUser,
|
||||
@@ -132,20 +132,20 @@ pub async fn clear_recent_items(
|
||||
|
||||
match recent_service.clear_recent_items(user_id).await {
|
||||
Ok(_) => {
|
||||
info!("Limpiados todos los elementos recientes para usuario");
|
||||
info!("Cleared all recent items for user");
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(serde_json::json!({
|
||||
"message": "Elementos recientes limpiados correctamente"
|
||||
"message": "Recent items cleared successfully"
|
||||
}))
|
||||
).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error al limpiar elementos recientes: {}", err);
|
||||
error!("Error clearing recent items: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(serde_json::json!({
|
||||
"error": format!("Fallo al limpiar elementos recientes: {}", err)
|
||||
"error": format!("Failed to clear recent items: {}", err)
|
||||
}))
|
||||
).into_response()
|
||||
}
|
||||
|
||||
@@ -10,34 +10,34 @@ use crate::application::dtos::search_dto::SearchCriteriaDto;
|
||||
use crate::common::di::AppState;
|
||||
|
||||
/**
|
||||
* Manejador para las operaciones de búsqueda a través de la API.
|
||||
* Handler for search operations through the API.
|
||||
*
|
||||
* Este manejador expone endpoints relacionados con la funcionalidad de búsqueda,
|
||||
* permitiendo a los usuarios buscar archivos y carpetas usando diversos criterios.
|
||||
* This handler exposes endpoints related to search functionality,
|
||||
* allowing users to search for files and folders using various criteria.
|
||||
*/
|
||||
pub struct SearchHandler;
|
||||
|
||||
impl SearchHandler {
|
||||
/**
|
||||
* Realiza una búsqueda basada en los criterios proporcionados como parámetros de consulta.
|
||||
* Performs a search based on the criteria provided as query parameters.
|
||||
*
|
||||
* Este endpoint permite búsquedas simples directamente con parámetros URL.
|
||||
* This endpoint allows simple searches directly with URL parameters.
|
||||
*
|
||||
* @param state Estado de la aplicación con servicios
|
||||
* @param query_params Parámetros de búsqueda como query string
|
||||
* @return Respuesta HTTP con los resultados de la búsqueda
|
||||
* @param state Application state with services
|
||||
* @param query_params Search parameters as query string
|
||||
* @return HTTP response with the search results
|
||||
*/
|
||||
pub async fn search_files_get(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<SearchParams>,
|
||||
) -> impl IntoResponse {
|
||||
info!("API: Búsqueda de archivos con parámetros: {:?}", params);
|
||||
info!("API: File search with parameters: {:?}", params);
|
||||
|
||||
// Extraer el servicio de búsqueda o devolver error si no está disponible
|
||||
// Extract the search service or return error if not available
|
||||
let search_service = match &state.applications.search_service {
|
||||
Some(service) => service,
|
||||
None => {
|
||||
error!("Servicio de búsqueda no disponible");
|
||||
error!("Search service not available");
|
||||
return (
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
Json(json!({
|
||||
@@ -47,7 +47,7 @@ impl SearchHandler {
|
||||
}
|
||||
};
|
||||
|
||||
// Convertir parámetros de búsqueda a DTO
|
||||
// Convert search parameters to DTO
|
||||
let search_criteria = SearchCriteriaDto {
|
||||
name_contains: params.query,
|
||||
file_types: params.type_filter.map(|t| t.split(',').map(|s| s.trim().to_string()).collect()),
|
||||
@@ -63,15 +63,15 @@ impl SearchHandler {
|
||||
offset: params.offset.unwrap_or(0),
|
||||
};
|
||||
|
||||
// Realizar la búsqueda
|
||||
// Perform the search
|
||||
match search_service.search(search_criteria).await {
|
||||
Ok(results) => {
|
||||
info!("Búsqueda completada, {} archivos y {} carpetas encontrados",
|
||||
info!("Search completed, {} files and {} folders found",
|
||||
results.files.len(), results.folders.len());
|
||||
(StatusCode::OK, Json(results)).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error en búsqueda: {}", err);
|
||||
error!("Search error: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(json!({
|
||||
@@ -83,26 +83,26 @@ impl SearchHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Realiza una búsqueda avanzada basada en un objeto de criterios JSON completo.
|
||||
* Performs an advanced search based on a complete JSON criteria object.
|
||||
*
|
||||
* Este endpoint permite búsquedas más complejas con todos los criterios posibles
|
||||
* proporcionados en el cuerpo de la solicitud.
|
||||
* This endpoint allows more complex searches with all possible criteria
|
||||
* provided in the request body.
|
||||
*
|
||||
* @param state Estado de la aplicación con servicios
|
||||
* @param criteria Criterios de búsqueda completos
|
||||
* @return Respuesta HTTP con los resultados de la búsqueda
|
||||
* @param state Application state with services
|
||||
* @param criteria Complete search criteria
|
||||
* @return HTTP response with the search results
|
||||
*/
|
||||
pub async fn search_files_post(
|
||||
State(state): State<AppState>,
|
||||
Json(criteria): Json<SearchCriteriaDto>,
|
||||
) -> impl IntoResponse {
|
||||
info!("API: Búsqueda avanzada de archivos");
|
||||
info!("API: Advanced file search");
|
||||
|
||||
// Extraer el servicio de búsqueda o devolver error si no está disponible
|
||||
// Extract the search service or return error if not available
|
||||
let search_service = match &state.applications.search_service {
|
||||
Some(service) => service,
|
||||
None => {
|
||||
error!("Servicio de búsqueda no disponible");
|
||||
error!("Search service not available");
|
||||
return (
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
Json(json!({
|
||||
@@ -112,15 +112,15 @@ impl SearchHandler {
|
||||
}
|
||||
};
|
||||
|
||||
// Realizar la búsqueda
|
||||
// Perform the search
|
||||
match search_service.search(criteria).await {
|
||||
Ok(results) => {
|
||||
info!("Búsqueda completada, {} archivos y {} carpetas encontrados",
|
||||
info!("Search completed, {} files and {} folders found",
|
||||
results.files.len(), results.folders.len());
|
||||
(StatusCode::OK, Json(results)).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error en búsqueda: {}", err);
|
||||
error!("Search error: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(json!({
|
||||
@@ -132,24 +132,24 @@ impl SearchHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Limpia la caché de resultados de búsqueda.
|
||||
* Clears the search results cache.
|
||||
*
|
||||
* Este endpoint es útil para forzar búsquedas frescas después de cambios
|
||||
* significativos en el sistema de archivos.
|
||||
* This endpoint is useful for forcing fresh searches after significant
|
||||
* changes in the file system.
|
||||
*
|
||||
* @param state Estado de la aplicación con servicios
|
||||
* @return Respuesta HTTP indicando éxito o error
|
||||
* @param state Application state with services
|
||||
* @return HTTP response indicating success or error
|
||||
*/
|
||||
pub async fn clear_search_cache(
|
||||
State(state): State<AppState>,
|
||||
) -> impl IntoResponse {
|
||||
info!("API: Limpiando caché de búsqueda");
|
||||
info!("API: Clearing search cache");
|
||||
|
||||
// Extraer el servicio de búsqueda o devolver error si no está disponible
|
||||
// Extract the search service or return error if not available
|
||||
let search_service = match &state.applications.search_service {
|
||||
Some(service) => service,
|
||||
None => {
|
||||
error!("Servicio de búsqueda no disponible");
|
||||
error!("Search service not available");
|
||||
return (
|
||||
StatusCode::SERVICE_UNAVAILABLE,
|
||||
Json(json!({
|
||||
@@ -159,10 +159,10 @@ impl SearchHandler {
|
||||
}
|
||||
};
|
||||
|
||||
// Limpiar la caché
|
||||
// Clear the cache
|
||||
match search_service.clear_search_cache().await {
|
||||
Ok(_) => {
|
||||
info!("Caché de búsqueda limpiada correctamente");
|
||||
info!("Search cache cleared successfully");
|
||||
(
|
||||
StatusCode::OK,
|
||||
Json(json!({
|
||||
@@ -171,7 +171,7 @@ impl SearchHandler {
|
||||
).into_response()
|
||||
},
|
||||
Err(err) => {
|
||||
error!("Error al limpiar caché de búsqueda: {}", err);
|
||||
error!("Error clearing search cache: {}", err);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Json(json!({
|
||||
@@ -183,43 +183,43 @@ impl SearchHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parámetros de búsqueda para el endpoint GET
|
||||
/// Search parameters for the GET endpoint
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct SearchParams {
|
||||
/// Texto a buscar en nombres de archivos y carpetas
|
||||
/// Text to search for in file and folder names
|
||||
pub query: Option<String>,
|
||||
|
||||
/// Filtro por tipos de archivo (extensiones separadas por comas)
|
||||
/// Filter by file types (comma-separated extensions)
|
||||
#[serde(rename = "type")]
|
||||
pub type_filter: Option<String>,
|
||||
|
||||
/// Filtrar elementos creados después de esta fecha (timestamp)
|
||||
/// Filter items created after this date (timestamp)
|
||||
pub created_after: Option<u64>,
|
||||
|
||||
/// Filtrar elementos creados antes de esta fecha (timestamp)
|
||||
/// Filter items created before this date (timestamp)
|
||||
pub created_before: Option<u64>,
|
||||
|
||||
/// Filtrar elementos modificados después de esta fecha (timestamp)
|
||||
/// Filter items modified after this date (timestamp)
|
||||
pub modified_after: Option<u64>,
|
||||
|
||||
/// Filtrar elementos modificados antes de esta fecha (timestamp)
|
||||
/// Filter items modified before this date (timestamp)
|
||||
pub modified_before: Option<u64>,
|
||||
|
||||
/// Tamaño mínimo en bytes
|
||||
/// Minimum size in bytes
|
||||
pub min_size: Option<u64>,
|
||||
|
||||
/// Tamaño máximo en bytes
|
||||
/// Maximum size in bytes
|
||||
pub max_size: Option<u64>,
|
||||
|
||||
/// ID de carpeta para limitar la búsqueda
|
||||
/// Folder ID to limit the search scope
|
||||
pub folder_id: Option<String>,
|
||||
|
||||
/// Búsqueda recursiva en subcarpetas
|
||||
/// Recursive search in subfolders
|
||||
pub recursive: Option<bool>,
|
||||
|
||||
/// Límite de resultados para paginación
|
||||
/// Result limit for pagination
|
||||
pub limit: Option<usize>,
|
||||
|
||||
/// Desplazamiento para paginación
|
||||
/// Offset for pagination
|
||||
pub offset: Option<usize>,
|
||||
}
|
||||
@@ -8,7 +8,7 @@ use tracing::{debug, error, warn, instrument};
|
||||
use crate::common::di::AppState;
|
||||
use crate::interfaces::middleware::auth::AuthUser;
|
||||
|
||||
/// Obtiene todos los elementos en la papelera para el usuario actual
|
||||
/// Gets all items in the trash for the current user
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_trash_items(
|
||||
State(state): State<AppState>,
|
||||
@@ -19,7 +19,7 @@ pub async fn get_trash_items(
|
||||
// privilege escalation attacks.
|
||||
let effective_user = auth_user.id.clone();
|
||||
|
||||
debug!("Solicitud para listar elementos en papelera para usuario {}", effective_user);
|
||||
debug!("Request to list trash items for user {}", effective_user);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
Some(service) => service,
|
||||
@@ -34,11 +34,11 @@ pub async fn get_trash_items(
|
||||
|
||||
match result {
|
||||
Ok(items) => {
|
||||
debug!("Encontrados {} elementos en la papelera", items.len());
|
||||
debug!("Found {} items in trash", items.len());
|
||||
(StatusCode::OK, Json(json!(items)))
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error al obtener elementos de la papelera: {:?}", e);
|
||||
error!("Error retrieving trash items: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error retrieving trash items: {}", e)
|
||||
})))
|
||||
@@ -46,14 +46,14 @@ pub async fn get_trash_items(
|
||||
}
|
||||
}
|
||||
|
||||
/// Mueve un elemento (archivo o carpeta) a la papelera (función genérica, no usada directamente en rutas)
|
||||
/// Moves an item (file or folder) to the trash (generic function, not used directly in routes)
|
||||
#[instrument(skip_all)]
|
||||
pub async fn move_to_trash(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
Path((item_type, item_id)): Path<(String, String)>,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para mover a papelera: tipo={}, id={}, usuario={}",
|
||||
debug!("Request to move to trash: type={}, id={}, user={}",
|
||||
item_type, item_id, auth_user.id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
@@ -68,14 +68,14 @@ pub async fn move_to_trash(
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Elemento movido a papelera con éxito");
|
||||
debug!("Item moved to trash successfully");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "Item moved to trash successfully"
|
||||
})))
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error al mover elemento a papelera: {:?}", e);
|
||||
error!("Error moving item to trash: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error moving item to trash: {}", e)
|
||||
})))
|
||||
@@ -83,14 +83,14 @@ pub async fn move_to_trash(
|
||||
}
|
||||
}
|
||||
|
||||
/// Mueve un archivo a la papelera
|
||||
/// Moves a file to the trash
|
||||
#[instrument(skip_all)]
|
||||
pub async fn move_file_to_trash(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
Path(item_id): Path<String>,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para mover archivo a papelera: id={}, usuario={}",
|
||||
debug!("Request to move file to trash: id={}, user={}",
|
||||
item_id, auth_user.id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
@@ -102,19 +102,19 @@ pub async fn move_file_to_trash(
|
||||
}
|
||||
};
|
||||
|
||||
// Especificar que es un archivo
|
||||
// Specify that it is a file
|
||||
let result = trash_service.move_to_trash(&item_id, "file", &auth_user.id).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Archivo movido a papelera con éxito");
|
||||
debug!("File moved to trash successfully");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "File moved to trash successfully"
|
||||
})))
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error al mover archivo a papelera: {:?}", e);
|
||||
error!("Error moving file to trash: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error moving file to trash: {}", e)
|
||||
})))
|
||||
@@ -122,14 +122,14 @@ pub async fn move_file_to_trash(
|
||||
}
|
||||
}
|
||||
|
||||
/// Mueve una carpeta a la papelera
|
||||
/// Moves a folder to the trash
|
||||
#[instrument(skip_all)]
|
||||
pub async fn move_folder_to_trash(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
Path(item_id): Path<String>,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para mover carpeta a papelera: id={}, usuario={}",
|
||||
debug!("Request to move folder to trash: id={}, user={}",
|
||||
item_id, auth_user.id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
@@ -141,19 +141,19 @@ pub async fn move_folder_to_trash(
|
||||
}
|
||||
};
|
||||
|
||||
// Especificar que es una carpeta
|
||||
// Specify that it is a folder
|
||||
let result = trash_service.move_to_trash(&item_id, "folder", &auth_user.id).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Carpeta movida a papelera con éxito");
|
||||
debug!("Folder moved to trash successfully");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "Folder moved to trash successfully"
|
||||
})))
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error al mover carpeta a papelera: {:?}", e);
|
||||
error!("Error moving folder to trash: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error moving folder to trash: {}", e)
|
||||
})))
|
||||
@@ -161,14 +161,14 @@ pub async fn move_folder_to_trash(
|
||||
}
|
||||
}
|
||||
|
||||
/// Restaura un elemento desde la papelera a su ubicación original
|
||||
/// Restores an item from the trash to its original location
|
||||
#[instrument(skip_all)]
|
||||
pub async fn restore_from_trash(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
Path(trash_id): Path<String>,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para restaurar elemento {} de papelera", trash_id);
|
||||
debug!("Request to restore item {} from trash", trash_id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
Some(service) => service,
|
||||
@@ -182,7 +182,7 @@ pub async fn restore_from_trash(
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Elemento restaurado con éxito");
|
||||
debug!("Item restored successfully");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "Item restored successfully"
|
||||
@@ -199,7 +199,7 @@ pub async fn restore_from_trash(
|
||||
})));
|
||||
}
|
||||
|
||||
error!("Error al restaurar elemento de papelera: {:?}", e);
|
||||
error!("Error restoring item from trash: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error restoring item from trash: {}", e)
|
||||
})))
|
||||
@@ -207,14 +207,14 @@ pub async fn restore_from_trash(
|
||||
}
|
||||
}
|
||||
|
||||
/// Elimina permanentemente un elemento de la papelera
|
||||
/// Permanently deletes an item from the trash
|
||||
#[instrument(skip_all)]
|
||||
pub async fn delete_permanently(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
Path(trash_id): Path<String>,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para eliminar permanentemente elemento {}", trash_id);
|
||||
debug!("Request to permanently delete item {}", trash_id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
Some(service) => service,
|
||||
@@ -228,7 +228,7 @@ pub async fn delete_permanently(
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Elemento eliminado permanentemente");
|
||||
debug!("Item permanently deleted");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "Item deleted permanently"
|
||||
@@ -245,7 +245,7 @@ pub async fn delete_permanently(
|
||||
})));
|
||||
}
|
||||
|
||||
error!("Error al eliminar permanentemente elemento: {:?}", e);
|
||||
error!("Error permanently deleting item: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error deleting item permanently: {}", e)
|
||||
})))
|
||||
@@ -253,13 +253,13 @@ pub async fn delete_permanently(
|
||||
}
|
||||
}
|
||||
|
||||
/// Vacía la papelera completamente para el usuario actual
|
||||
/// Empties the trash completely for the current user
|
||||
#[instrument(skip_all)]
|
||||
pub async fn empty_trash(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
) -> (StatusCode, Json<serde_json::Value>) {
|
||||
debug!("Solicitud para vaciar papelera del usuario {}", auth_user.id);
|
||||
debug!("Request to empty trash for user {}", auth_user.id);
|
||||
|
||||
let trash_service = match state.trash_service.as_ref() {
|
||||
Some(service) => service,
|
||||
@@ -273,14 +273,14 @@ pub async fn empty_trash(
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
debug!("Papelera vaciada con éxito");
|
||||
debug!("Trash emptied successfully");
|
||||
(StatusCode::OK, Json(json!({
|
||||
"success": true,
|
||||
"message": "Trash emptied successfully"
|
||||
})))
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Error al vaciar papelera: {:?}", e);
|
||||
error!("Error emptying trash: {:?}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({
|
||||
"error": format!("Error emptying trash: {}", e)
|
||||
})))
|
||||
|
||||
@@ -90,14 +90,14 @@ pub fn create_api_routes(app_state: &AppState) -> Router<AppState> {
|
||||
let favorites_service = app_state.favorites_service.clone();
|
||||
let recent_service = app_state.recent_service.clone();
|
||||
|
||||
// Inicializar el servicio de operaciones por lotes
|
||||
// Initialize the batch operations service
|
||||
let batch_service = Arc::new(BatchOperationService::default(
|
||||
file_retrieval_service.clone(),
|
||||
file_management_service.clone(),
|
||||
folder_service.clone()
|
||||
));
|
||||
|
||||
// Crear estado para el manejador de operaciones por lotes
|
||||
// Create state for the batch operations handler
|
||||
let batch_handler_state = BatchHandlerState {
|
||||
batch_service: batch_service.clone(),
|
||||
};
|
||||
@@ -154,14 +154,14 @@ pub fn create_api_routes(app_state: &AppState) -> Router<AppState> {
|
||||
// Merge the routers
|
||||
let files_router = basic_file_router.merge(file_operations_router);
|
||||
|
||||
// Crear rutas para operaciones por lotes
|
||||
// Create routes for batch operations
|
||||
let batch_router = Router::new()
|
||||
// Operaciones de archivos
|
||||
// File operations
|
||||
.route("/files/move", post(batch_handler::move_files_batch))
|
||||
.route("/files/copy", post(batch_handler::copy_files_batch))
|
||||
.route("/files/delete", post(batch_handler::delete_files_batch))
|
||||
.route("/files/get", post(batch_handler::get_files_batch))
|
||||
// Operaciones de carpetas
|
||||
// Folder operations
|
||||
.route("/folders/delete", post(batch_handler::delete_folders_batch))
|
||||
.route("/folders/create", post(batch_handler::create_folders_batch))
|
||||
.route("/folders/get", post(batch_handler::get_folders_batch))
|
||||
@@ -183,7 +183,7 @@ pub fn create_api_routes(app_state: &AppState) -> Router<AppState> {
|
||||
Router::new()
|
||||
};
|
||||
|
||||
// Implementaciones directas de handlers para compartir, sin depender de ShareHandler
|
||||
// Direct handler implementations for sharing, without depending on ShareHandler
|
||||
|
||||
// Create routes for shared resources management (requires auth)
|
||||
let share_router = if let Some(share_service) = share_service.clone() {
|
||||
|
||||
Reference in New Issue
Block a user