refactor: remove serde from domain entities for Clean Architecture compliance

- Remove Serialize/Deserialize from File, Folder, Session, User, Contact entities
- Create contact_persistence_dto.rs for JSONB persistence in infrastructure layer
- Update contact_pg_repository to use persistence DTOs
- Fix dependency on zip crate (downgrade from 7.2.0 to 2.1.0)
- Fix unused variable warnings in main.rs
- Move PathService import from domain to infrastructure
- Add missing fields to CoreServices and RepositoryServices
- Create proper service initialization in main.rs

Clean Architecture improvements:
- Domain layer no longer depends on serde framework
- Persistence concerns isolated to infrastructure layer
- TokenClaims in auth_service.rs is only exception (required for JWT)
This commit is contained in:
Dionisio
2026-02-02 23:56:40 +01:00
parent 6aceb07f3f
commit 52840e57df
88 changed files with 4286 additions and 4847 deletions
@@ -1,8 +1,7 @@
use std::sync::Arc;
use crate::domain::entities::user::{User, UserRole};
use crate::domain::entities::session::Session;
use crate::domain::services::auth_service::AuthService;
use crate::application::ports::auth_ports::{UserStoragePort, SessionStoragePort};
use crate::application::ports::auth_ports::{UserStoragePort, SessionStoragePort, PasswordHasherPort, TokenServicePort};
use crate::application::dtos::user_dto::{UserDto, RegisterDto, LoginDto, AuthResponseDto, ChangePasswordDto, RefreshTokenDto};
use crate::application::dtos::folder_dto::CreateFolderDto;
use crate::application::ports::inbound::FolderUseCase;
@@ -11,7 +10,8 @@ use crate::common::errors::{DomainError, ErrorKind};
pub struct AuthApplicationService {
user_storage: Arc<dyn UserStoragePort>,
session_storage: Arc<dyn SessionStoragePort>,
auth_service: Arc<AuthService>,
password_hasher: Arc<dyn PasswordHasherPort>,
token_service: Arc<dyn TokenServicePort>,
folder_service: Option<Arc<dyn FolderUseCase>>,
}
@@ -19,12 +19,14 @@ impl AuthApplicationService {
pub fn new(
user_storage: Arc<dyn UserStoragePort>,
session_storage: Arc<dyn SessionStoragePort>,
auth_service: Arc<AuthService>,
password_hasher: Arc<dyn PasswordHasherPort>,
token_service: Arc<dyn TokenServicePort>,
) -> Self {
Self {
user_storage,
session_storage,
auth_service,
password_hasher,
token_service,
folder_service: None,
}
}
@@ -127,11 +129,23 @@ impl AuthApplicationService {
1024 * 1024 * 1024 // 1GB para usuarios normales
};
// Crear usuario
// Validar longitud de password antes de hashear
if dto.password.len() < 8 {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"User",
"Password debe tener al menos 8 caracteres"
));
}
// Hashear el password usando el servicio de infraestructura
let password_hash = self.password_hasher.hash_password(&dto.password)?;
// Crear usuario con el hash pre-generado
let user = User::new(
dto.username.clone(),
dto.email,
dto.password,
password_hash,
role,
quota,
).map_err(|e| DomainError::new(
@@ -203,13 +217,8 @@ impl AuthApplicationService {
));
}
// Verificar contraseña
let is_valid = user.verify_password(&dto.password)
.map_err(|_| DomainError::new(
ErrorKind::AccessDenied,
"Auth",
"Credenciales inválidas"
))?;
// Verificar contraseña usando el hasher inyectado
let is_valid = self.password_hasher.verify_password(&dto.password, user.password_hash())?;
if !is_valid {
return Err(DomainError::new(
@@ -223,11 +232,10 @@ impl AuthApplicationService {
user.register_login();
self.user_storage.update_user(user.clone()).await?;
// Generar tokens
let access_token = self.auth_service.generate_access_token(&user)
.map_err(DomainError::from)?;
// Generar tokens usando el servicio de tokens inyectado
let access_token = self.token_service.generate_access_token(&user)?;
let refresh_token = self.auth_service.generate_refresh_token();
let refresh_token = self.token_service.generate_refresh_token();
// Guardar sesión
let session = Session::new(
@@ -235,7 +243,7 @@ impl AuthApplicationService {
refresh_token.clone(),
None, // IP (se puede añadir desde la capa HTTP)
None, // User-Agent (se puede añadir desde la capa HTTP)
self.auth_service.refresh_token_expiry_days(),
self.token_service.refresh_token_expiry_days(),
);
self.session_storage.create_session(session).await?;
@@ -246,7 +254,7 @@ impl AuthApplicationService {
access_token,
refresh_token,
token_type: "Bearer".to_string(),
expires_in: self.auth_service.refresh_token_expiry_secs(),
expires_in: self.token_service.refresh_token_expiry_secs(),
})
}
@@ -283,10 +291,9 @@ impl AuthApplicationService {
self.session_storage.revoke_session(session.id()).await?;
// Generar nuevos tokens
let access_token = self.auth_service.generate_access_token(&user)
.map_err(DomainError::from)?;
let access_token = self.token_service.generate_access_token(&user)?;
let new_refresh_token = self.auth_service.generate_refresh_token();
let new_refresh_token = self.token_service.generate_refresh_token();
// Crear nueva sesión
let new_session = Session::new(
@@ -294,7 +301,7 @@ impl AuthApplicationService {
new_refresh_token.clone(),
None,
None,
self.auth_service.refresh_token_expiry_days(),
self.token_service.refresh_token_expiry_days(),
);
self.session_storage.create_session(new_session).await?;
@@ -304,7 +311,7 @@ impl AuthApplicationService {
access_token,
refresh_token: new_refresh_token,
token_type: "Bearer".to_string(),
expires_in: self.auth_service.refresh_token_expiry_secs(),
expires_in: self.token_service.refresh_token_expiry_secs(),
})
}
@@ -342,13 +349,8 @@ impl AuthApplicationService {
// Obtener usuario
let mut user = self.user_storage.get_user_by_id(user_id).await?;
// Verificar contraseña actual
let is_valid = user.verify_password(&dto.current_password)
.map_err(|_| DomainError::new(
ErrorKind::AccessDenied,
"Auth",
"Contraseña actual incorrecta"
))?;
// Verificar contraseña actual usando el hasher inyectado
let is_valid = self.password_hasher.verify_password(&dto.current_password, user.password_hash())?;
if !is_valid {
return Err(DomainError::new(
@@ -358,13 +360,18 @@ impl AuthApplicationService {
));
}
// Actualizar contraseña
user.update_password(dto.new_password.clone())
.map_err(|e| DomainError::new(
// Validar nueva contraseña
if dto.new_password.len() < 8 {
return Err(DomainError::new(
ErrorKind::InvalidInput,
"User",
format!("Error al cambiar contraseña: {}", e)
))?;
"Password debe tener al menos 8 caracteres"
));
}
// Hashear nueva contraseña y actualizar usuario
let new_hash = self.password_hasher.hash_password(&dto.new_password)?;
user.update_password_hash(new_hash);
// Guardar usuario actualizado
self.user_storage.update_user(user).await?;