another fix - once more
This commit is contained in:
@@ -21,17 +21,40 @@ class CreateReport:
|
|||||||
ubicacion: Optional[str] = None) -> Dict[str, Any]:
|
ubicacion: Optional[str] = None) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Sends a create report message to RabbitMQ.
|
Sends a create report message to RabbitMQ.
|
||||||
The actual database save will be done by the consumer.
|
Valida previamente:
|
||||||
|
- Usuario existe
|
||||||
|
- Descripción no está vacía
|
||||||
|
- Tipo de reporte válido
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
# Verify user exists (we still need to check this before queuing)
|
# Validación: descripción requerida
|
||||||
user = self.user_repo.find_by_id(id_usuario)
|
if not descripcion or not descripcion.strip():
|
||||||
if not user:
|
|
||||||
return {
|
return {
|
||||||
"status": "error",
|
"status": "error",
|
||||||
"message": f"Usuario con ID {id_usuario} no existe"
|
"message": "La descripción del reporte es requerida"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validación: tipo de reporte válido (1-5)
|
||||||
|
if tipo_reporte < 1 or tipo_reporte > 5:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "El tipo de reporte debe estar entre 1 y 5"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validación: usuario existe (CRÍTICO)
|
||||||
|
try:
|
||||||
|
user = self.user_repo.find_by_id(id_usuario)
|
||||||
|
if not user:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Usuario con ID {id_usuario} no existe"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al validar usuario: {str(e)}"
|
||||||
}
|
}
|
||||||
|
|
||||||
id_reporte = str(uuid4())
|
id_reporte = str(uuid4())
|
||||||
@@ -43,7 +66,7 @@ class CreateReport:
|
|||||||
id_reporte=id_reporte,
|
id_reporte=id_reporte,
|
||||||
id_usuario=id_usuario,
|
id_usuario=id_usuario,
|
||||||
tipo_reporte=tipo_reporte,
|
tipo_reporte=tipo_reporte,
|
||||||
descripcion=descripcion,
|
descripcion=descripcion.strip(),
|
||||||
ubicacion=ubicacion,
|
ubicacion=ubicacion,
|
||||||
visibilidad=50.0, # Visibilidad inicial neutral
|
visibilidad=50.0, # Visibilidad inicial neutral
|
||||||
fecha_creacion=fecha_creacion.isoformat()
|
fecha_creacion=fecha_creacion.isoformat()
|
||||||
@@ -105,11 +128,27 @@ class UpdateReportVisibility:
|
|||||||
def execute(self, report_id: str, new_visibility: float, penalize_author: bool = False) -> Dict[str, Any]:
|
def execute(self, report_id: str, new_visibility: float, penalize_author: bool = False) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Sends an update report visibility message to RabbitMQ.
|
Sends an update report visibility message to RabbitMQ.
|
||||||
The actual database update will be done by the consumer.
|
Valida previamente:
|
||||||
|
- Reporte existe
|
||||||
|
- Visibilidad en rango válido (0-100)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
|
# Validación: reporte existe
|
||||||
|
try:
|
||||||
|
report = self.repo.find_by_id(report_id)
|
||||||
|
if not report:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Reporte con ID {report_id} no existe"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al buscar reporte: {str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
# Validar rango de visibilidad
|
# Validar rango de visibilidad
|
||||||
if new_visibility < 0 or new_visibility > 100:
|
if new_visibility < 0 or new_visibility > 100:
|
||||||
return {
|
return {
|
||||||
@@ -161,11 +200,26 @@ class DeleteReport:
|
|||||||
def execute(self, report_id: str) -> Dict[str, Any]:
|
def execute(self, report_id: str) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Sends a delete report message to RabbitMQ.
|
Sends a delete report message to RabbitMQ.
|
||||||
The actual database deletion will be done by the consumer.
|
Valida previamente:
|
||||||
|
- Reporte existe
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
|
# Validación: reporte existe
|
||||||
|
try:
|
||||||
|
report = self.repo.find_by_id(report_id)
|
||||||
|
if not report:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Reporte con ID {report_id} no existe"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al buscar reporte: {str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
# Create message object
|
# Create message object
|
||||||
message = ReportMessage(
|
message = ReportMessage(
|
||||||
event_type=ReportEventType.DELETE,
|
event_type=ReportEventType.DELETE,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from infrastructure.adapters.rabbitmq.sender import send_to_queue
|
|||||||
from infrastructure.adapters.rabbitmq.messages import UserMessage, UserEventType
|
from infrastructure.adapters.rabbitmq.messages import UserMessage, UserEventType
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List, Optional, Dict, Any
|
from typing import List, Optional, Dict, Any
|
||||||
|
import re
|
||||||
|
|
||||||
class CreateUser:
|
class CreateUser:
|
||||||
"""Use case para crear un nuevo usuario - envía mensaje a RabbitMQ"""
|
"""Use case para crear un nuevo usuario - envía mensaje a RabbitMQ"""
|
||||||
@@ -19,17 +20,61 @@ class CreateUser:
|
|||||||
Sends a create user message to RabbitMQ.
|
Sends a create user message to RabbitMQ.
|
||||||
The actual database save will be done by the consumer.
|
The actual database save will be done by the consumer.
|
||||||
|
|
||||||
|
Valida previamente:
|
||||||
|
- Email válido
|
||||||
|
- Email no duplicado
|
||||||
|
- Campos no vacíos
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
|
# Validación de campos requeridos
|
||||||
|
if not nombre or not nombre.strip():
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "El nombre es requerido"
|
||||||
|
}
|
||||||
|
if not apellido or not apellido.strip():
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "El apellido es requerido"
|
||||||
|
}
|
||||||
|
if not email or not email.strip():
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "El email es requerido"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validación de formato email
|
||||||
|
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||||
|
if not re.match(email_pattern, email):
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "El email no tiene un formato válido"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validación de email duplicado (CRÍTICO)
|
||||||
|
try:
|
||||||
|
existing_user = self.repo.find_by_email(email)
|
||||||
|
if existing_user:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"El email '{email}' ya está registrado"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al validar email: {str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
fecha_creacion = datetime.now()
|
fecha_creacion = datetime.now()
|
||||||
|
|
||||||
# Create message object
|
# Create message object
|
||||||
message = UserMessage(
|
message = UserMessage(
|
||||||
event_type=UserEventType.CREATE,
|
event_type=UserEventType.CREATE,
|
||||||
nombre=nombre,
|
nombre=nombre.strip(),
|
||||||
apellido=apellido,
|
apellido=apellido.strip(),
|
||||||
email=email,
|
email=email.strip(),
|
||||||
fecha_nacimiento=fecha_nacimiento.isoformat(),
|
fecha_nacimiento=fecha_nacimiento.isoformat(),
|
||||||
fecha_creacion=fecha_creacion.isoformat(),
|
fecha_creacion=fecha_creacion.isoformat(),
|
||||||
calificacion=50.0,
|
calificacion=50.0,
|
||||||
@@ -94,17 +139,40 @@ class UpdateUser:
|
|||||||
url_foto_perfil: str = None, biografia: str = None) -> Dict[str, Any]:
|
url_foto_perfil: str = None, biografia: str = None) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Sends an update user message to RabbitMQ.
|
Sends an update user message to RabbitMQ.
|
||||||
The actual database update will be done by the consumer.
|
|
||||||
|
Valida previamente:
|
||||||
|
- Usuario existe
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
|
# Validación: usuario existe
|
||||||
|
try:
|
||||||
|
user = self.repo.find_by_id(user_id)
|
||||||
|
if not user:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Usuario con ID {user_id} no existe"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al buscar usuario: {str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validación: al menos un campo para actualizar
|
||||||
|
if not any([nombre, apellido, url_foto_perfil, biografia]):
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": "Se requiere al menos un campo para actualizar"
|
||||||
|
}
|
||||||
|
|
||||||
# Create message object with only the fields to update
|
# Create message object with only the fields to update
|
||||||
message = UserMessage(
|
message = UserMessage(
|
||||||
event_type=UserEventType.UPDATE,
|
event_type=UserEventType.UPDATE,
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
nombre=nombre,
|
nombre=nombre.strip() if nombre else None,
|
||||||
apellido=apellido,
|
apellido=apellido.strip() if apellido else None,
|
||||||
url_foto_perfil=url_foto_perfil,
|
url_foto_perfil=url_foto_perfil,
|
||||||
biografia=biografia
|
biografia=biografia
|
||||||
)
|
)
|
||||||
@@ -134,11 +202,27 @@ class DeleteUser:
|
|||||||
def execute(self, user_id: int) -> Dict[str, Any]:
|
def execute(self, user_id: int) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Sends a delete user message to RabbitMQ.
|
Sends a delete user message to RabbitMQ.
|
||||||
The actual database deletion will be done by the consumer.
|
|
||||||
|
Valida previamente:
|
||||||
|
- Usuario existe
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dictionary with status and message
|
Dictionary with status and message
|
||||||
"""
|
"""
|
||||||
|
# Validación: usuario existe
|
||||||
|
try:
|
||||||
|
user = self.repo.find_by_id(user_id)
|
||||||
|
if not user:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Usuario con ID {user_id} no existe"
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
"status": "error",
|
||||||
|
"message": f"Error al buscar usuario: {str(e)}"
|
||||||
|
}
|
||||||
|
|
||||||
# Create message object
|
# Create message object
|
||||||
message = UserMessage(
|
message = UserMessage(
|
||||||
event_type=UserEventType.DELETE,
|
event_type=UserEventType.DELETE,
|
||||||
|
|||||||
@@ -6,14 +6,16 @@ from application.services.report_services import (
|
|||||||
)
|
)
|
||||||
from infrastructure.adapters.persistence.report_repository_mongo import ReportRepositoryMongo
|
from infrastructure.adapters.persistence.report_repository_mongo import ReportRepositoryMongo
|
||||||
from infrastructure.adapters.persistence.user_repository_sql import UserRepositorySQL
|
from infrastructure.adapters.persistence.user_repository_sql import UserRepositorySQL
|
||||||
|
import logging
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
report_repo = ReportRepositoryMongo()
|
report_repo = ReportRepositoryMongo()
|
||||||
user_repo = UserRepositorySQL()
|
user_repo = UserRepositorySQL()
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@router.post("/", status_code=status.HTTP_202_ACCEPTED)
|
@router.post("/", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def create_report(report_data: ReportCreateRequest):
|
async def create_report(report_data: ReportCreateRequest):
|
||||||
"""Crea un nuevo reporte - envía a cola de procesamiento"""
|
"""Crea un nuevo reporte - envía a cola de procesamiento con validaciones previas"""
|
||||||
try:
|
try:
|
||||||
create_use_case = CreateReport(report_repo, user_repo)
|
create_use_case = CreateReport(report_repo, user_repo)
|
||||||
result = create_use_case.execute(
|
result = create_use_case.execute(
|
||||||
@@ -22,54 +24,98 @@ async def create_report(report_data: ReportCreateRequest):
|
|||||||
descripcion=report_data.descripcion,
|
descripcion=report_data.descripcion,
|
||||||
ubicacion=report_data.ubicacion
|
ubicacion=report_data.ubicacion
|
||||||
)
|
)
|
||||||
|
|
||||||
if result["status"] == "error":
|
if result["status"] == "error":
|
||||||
raise HTTPException(
|
message = result["message"]
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
if "no existe" in message:
|
||||||
detail=result["message"]
|
# 404 Not Found: usuario no existe
|
||||||
)
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.error(f"Error inesperado en create_report: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Error al crear reporte: {str(e)}"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@router.get("/{report_id}", response_model=ReportResponse)
|
@router.get("/{report_id}", response_model=ReportResponse)
|
||||||
async def get_report(report_id: str):
|
async def get_report(report_id: str):
|
||||||
"""Obtiene un reporte por ID"""
|
"""Obtiene un reporte por ID"""
|
||||||
get_use_case = GetReportById(report_repo)
|
try:
|
||||||
report = get_use_case.execute(report_id)
|
get_use_case = GetReportById(report_repo)
|
||||||
if not report:
|
report = get_use_case.execute(report_id)
|
||||||
|
if not report:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"Reporte con ID {report_id} no encontrado"
|
||||||
|
)
|
||||||
|
return report
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener reporte {report_id}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Reporte con ID {report_id} no encontrado"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return report
|
|
||||||
|
|
||||||
@router.get("/user/{user_id}", response_model=list[ReportResponse])
|
@router.get("/user/{user_id}")
|
||||||
async def get_user_reports(user_id: int):
|
async def get_user_reports(user_id: int):
|
||||||
"""Obtiene todos los reportes de un usuario"""
|
"""Obtiene todos los reportes de un usuario - retorna lista vacía si no hay reportes"""
|
||||||
get_use_case = GetReportsByUser(report_repo)
|
try:
|
||||||
reports = get_use_case.execute(user_id)
|
get_use_case = GetReportsByUser(report_repo)
|
||||||
return reports
|
reports = get_use_case.execute(user_id)
|
||||||
|
return reports
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener reportes del usuario {user_id}: {e}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Error interno del servidor"
|
||||||
|
)
|
||||||
|
|
||||||
@router.get("/", response_model=list[ReportResponse])
|
@router.get("/")
|
||||||
async def list_reports():
|
async def list_reports():
|
||||||
"""Obtiene todos los reportes"""
|
"""Obtiene todos los reportes - retorna lista vacía si no hay reportes"""
|
||||||
list_use_case = ListAllReports(report_repo)
|
try:
|
||||||
return list_use_case.execute()
|
list_use_case = ListAllReports(report_repo)
|
||||||
|
return list_use_case.execute()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al listar reportes: {e}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Error interno del servidor"
|
||||||
|
)
|
||||||
|
|
||||||
@router.get("/shadowbanned/list", response_model=list[ReportResponse])
|
@router.get("/shadowbanned/list")
|
||||||
async def get_shadowbanned_reports(threshold: float = 20):
|
async def get_shadowbanned_reports(threshold: float = 20):
|
||||||
"""Obtiene reportes shadowbaneados (baja visibilidad)"""
|
"""Obtiene reportes shadowbaneados (baja visibilidad) - retorna lista vacía si no hay"""
|
||||||
get_use_case = GetShadowbannedReports(report_repo)
|
try:
|
||||||
return get_use_case.execute(threshold)
|
get_use_case = GetShadowbannedReports(report_repo)
|
||||||
|
return get_use_case.execute(threshold)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener reportes shadowbaneados: {e}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Error interno del servidor"
|
||||||
|
)
|
||||||
|
|
||||||
@router.put("/{report_id}/visibility", status_code=status.HTTP_202_ACCEPTED)
|
@router.put("/{report_id}/visibility", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def update_report_visibility(report_id: str, visibility_data: ReportUpdateVisibilityRequest):
|
async def update_report_visibility(report_id: str, visibility_data: ReportUpdateVisibilityRequest):
|
||||||
"""Actualiza la visibilidad de un reporte - envía a cola de procesamiento"""
|
"""Actualiza la visibilidad de un reporte - envía a cola de procesamiento con validaciones previas"""
|
||||||
try:
|
try:
|
||||||
update_use_case = UpdateReportVisibility(report_repo, user_repo)
|
update_use_case = UpdateReportVisibility(report_repo, user_repo)
|
||||||
result = update_use_case.execute(
|
result = update_use_case.execute(
|
||||||
@@ -77,28 +123,64 @@ async def update_report_visibility(report_id: str, visibility_data: ReportUpdate
|
|||||||
new_visibility=visibility_data.new_visibility,
|
new_visibility=visibility_data.new_visibility,
|
||||||
penalize_author=visibility_data.penalize_author
|
penalize_author=visibility_data.penalize_author
|
||||||
)
|
)
|
||||||
|
|
||||||
if result["status"] == "error":
|
if result["status"] == "error":
|
||||||
raise HTTPException(
|
message = result["message"]
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
if "no existe" in message:
|
||||||
detail=result["message"]
|
# 404 Not Found: reporte no existe
|
||||||
)
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.error(f"Error al actualizar visibilidad del reporte {report_id}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Error al actualizar visibilidad: {str(e)}"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@router.delete("/{report_id}", status_code=status.HTTP_202_ACCEPTED)
|
@router.delete("/{report_id}", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def delete_report(report_id: str):
|
async def delete_report(report_id: str):
|
||||||
"""Elimina un reporte - envía a cola de procesamiento"""
|
"""Elimina un reporte - envía a cola de procesamiento con validaciones previas"""
|
||||||
delete_use_case = DeleteReport(report_repo)
|
try:
|
||||||
result = delete_use_case.execute(report_id)
|
delete_use_case = DeleteReport(report_repo)
|
||||||
if result["status"] == "error":
|
result = delete_use_case.execute(report_id)
|
||||||
|
|
||||||
|
if result["status"] == "error":
|
||||||
|
message = result["message"]
|
||||||
|
if "no existe" in message:
|
||||||
|
# 404 Not Found: reporte no existe
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
|
return result
|
||||||
|
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al eliminar reporte {report_id}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=result["message"]
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return result
|
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ from application.services.user_services import (
|
|||||||
CreateUser, GetUserById, GetUserByEmail, ListAllUsers, UpdateUser, DeleteUser
|
CreateUser, GetUserById, GetUserByEmail, ListAllUsers, UpdateUser, DeleteUser
|
||||||
)
|
)
|
||||||
from infrastructure.adapters.persistence.user_repository_sql import UserRepositorySQL
|
from infrastructure.adapters.persistence.user_repository_sql import UserRepositorySQL
|
||||||
|
import logging
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
user_repo = UserRepositorySQL()
|
user_repo = UserRepositorySQL()
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@router.post("/", status_code=status.HTTP_202_ACCEPTED)
|
@router.post("/", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def create_user(user_data: UserCreateRequest):
|
async def create_user(user_data: UserCreateRequest):
|
||||||
"""Crea un nuevo usuario - envía a cola de procesamiento"""
|
"""Crea un nuevo usuario - envía a cola de procesamiento con validaciones previas"""
|
||||||
try:
|
try:
|
||||||
create_use_case = CreateUser(user_repo)
|
create_use_case = CreateUser(user_repo)
|
||||||
result = create_use_case.execute(
|
result = create_use_case.execute(
|
||||||
@@ -21,76 +23,160 @@ async def create_user(user_data: UserCreateRequest):
|
|||||||
url_foto_perfil=user_data.url_foto_perfil,
|
url_foto_perfil=user_data.url_foto_perfil,
|
||||||
biografia=user_data.biografia
|
biografia=user_data.biografia
|
||||||
)
|
)
|
||||||
|
|
||||||
if result["status"] == "error":
|
if result["status"] == "error":
|
||||||
raise HTTPException(
|
# Detectar tipo de error para código HTTP apropiado
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
message = result["message"]
|
||||||
detail=result["message"]
|
if "ya está registrado" in message:
|
||||||
)
|
# 409 Conflict: email duplicado
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_409_CONFLICT,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
return result
|
return result
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logger.error(f"Error inesperado en create_user: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Error al crear usuario: {str(e)}"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
|
|
||||||
@router.get("/{user_id}", response_model=UserResponse)
|
@router.get("/{user_id}", response_model=UserResponse)
|
||||||
async def get_user(user_id: int):
|
async def get_user(user_id: int):
|
||||||
"""Obtiene un usuario por ID"""
|
"""Obtiene un usuario por ID"""
|
||||||
get_use_case = GetUserById(user_repo)
|
try:
|
||||||
user = get_use_case.execute(user_id)
|
get_use_case = GetUserById(user_repo)
|
||||||
if not user:
|
user = get_use_case.execute(user_id)
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"Usuario con ID {user_id} no encontrado"
|
||||||
|
)
|
||||||
|
return user
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener usuario {user_id}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Usuario con ID {user_id} no encontrado"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return user
|
|
||||||
|
|
||||||
@router.get("/email/{email}", response_model=UserResponse)
|
@router.get("/email/{email}", response_model=UserResponse)
|
||||||
async def get_user_by_email(email: str):
|
async def get_user_by_email(email: str):
|
||||||
"""Obtiene un usuario por email"""
|
"""Obtiene un usuario por email"""
|
||||||
get_use_case = GetUserByEmail(user_repo)
|
try:
|
||||||
user = get_use_case.execute(email)
|
get_use_case = GetUserByEmail(user_repo)
|
||||||
if not user:
|
user = get_use_case.execute(email)
|
||||||
|
if not user:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=f"Usuario con email {email} no encontrado"
|
||||||
|
)
|
||||||
|
return user
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al obtener usuario por email {email}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_404_NOT_FOUND,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=f"Usuario con email {email} no encontrado"
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return user
|
|
||||||
|
|
||||||
@router.get("/", response_model=list[UserResponse])
|
@router.get("/")
|
||||||
async def list_users():
|
async def list_users():
|
||||||
"""Obtiene todos los usuarios"""
|
"""Obtiene todos los usuarios - retorna lista vacía si no hay registros"""
|
||||||
list_use_case = ListAllUsers(user_repo)
|
try:
|
||||||
return list_use_case.execute()
|
list_use_case = ListAllUsers(user_repo)
|
||||||
|
return list_use_case.execute()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al listar usuarios: {e}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Error interno del servidor"
|
||||||
|
)
|
||||||
|
|
||||||
@router.put("/{user_id}", status_code=status.HTTP_202_ACCEPTED)
|
@router.put("/{user_id}", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def update_user(user_id: int, user_data: UserUpdateRequest):
|
async def update_user(user_id: int, user_data: UserUpdateRequest):
|
||||||
"""Actualiza un usuario - envía a cola de procesamiento"""
|
"""Actualiza un usuario - envía a cola de procesamiento con validaciones previas"""
|
||||||
update_use_case = UpdateUser(user_repo)
|
try:
|
||||||
result = update_use_case.execute(
|
update_use_case = UpdateUser(user_repo)
|
||||||
user_id=user_id,
|
result = update_use_case.execute(
|
||||||
nombre=user_data.nombre,
|
user_id=user_id,
|
||||||
apellido=user_data.apellido,
|
nombre=user_data.nombre,
|
||||||
url_foto_perfil=user_data.url_foto_perfil,
|
apellido=user_data.apellido,
|
||||||
biografia=user_data.biografia
|
url_foto_perfil=user_data.url_foto_perfil,
|
||||||
)
|
biografia=user_data.biografia
|
||||||
if result["status"] == "error":
|
)
|
||||||
raise HTTPException(
|
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
if result["status"] == "error":
|
||||||
detail=result["message"]
|
message = result["message"]
|
||||||
|
if "no existe" in message:
|
||||||
|
# 404 Not Found: usuario no existe
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
|
return result
|
||||||
|
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al actualizar usuario {user_id}: {e}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return result
|
|
||||||
|
|
||||||
@router.delete("/{user_id}", status_code=status.HTTP_202_ACCEPTED)
|
@router.delete("/{user_id}", status_code=status.HTTP_202_ACCEPTED)
|
||||||
async def delete_user(user_id: int):
|
async def delete_user(user_id: int):
|
||||||
"""Elimina un usuario - envía a cola de procesamiento"""
|
"""Elimina un usuario - envía a cola de procesamiento con validaciones previas"""
|
||||||
delete_use_case = DeleteUser(user_repo)
|
try:
|
||||||
result = delete_use_case.execute(user_id)
|
delete_use_case = DeleteUser(user_repo)
|
||||||
if result["status"] == "error":
|
result = delete_use_case.execute(user_id)
|
||||||
|
|
||||||
|
if result["status"] == "error":
|
||||||
|
message = result["message"]
|
||||||
|
if "no existe" in message:
|
||||||
|
# 404 Not Found: usuario no existe
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# 400 Bad Request: error de validación
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail=message
|
||||||
|
)
|
||||||
|
|
||||||
|
# 202 Accepted: enviado a la cola correctamente
|
||||||
|
return result
|
||||||
|
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error al eliminar usuario {user_id}: {e}", exc_info=True)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail=result["message"]
|
detail="Error interno del servidor"
|
||||||
)
|
)
|
||||||
return result
|
|
||||||
|
|||||||
Reference in New Issue
Block a user