fix
All checks were successful
DEPLOY_MULTI_BRACH/pipeline/head This commit looks good

This commit is contained in:
minguezsanzjuanjose
2026-04-14 01:00:37 +02:00
parent 3da81a9495
commit 9dd97b34f2
16 changed files with 339 additions and 137 deletions

View File

@@ -1,13 +1,34 @@
from django.contrib.auth import authenticate
from rest_framework.authtoken.models import Token
from rest_framework_simplejwt.tokens import RefreshToken
class Admin:
def get_status_action(self):
# Tu lógica de status que ya tenías
return {"status": "ok", "service": "Admin Infrastructure"}
def obtener_token_action(self, params):
"""
Lógica para comprobar la salud del sistema.
Devuelve el estado básico del entorno.
Capa Action: Valida credenciales y genera un par de tokens JWT.
"""
# En el futuro, podrías usar get_parameterized aquí si quisieras
# consultar estados en la base de datos.
return {
"status": "ok",
"message": "V-Encore API System is active",
"environment": "dev" # Esto podría venir de una variable de entorno
}
username = params.get('username')
password = params.get('password')
# 1. Autenticación
user = authenticate(username=username, password=password)
if user is not None:
# 2. Generación de JWT (Access & Refresh)
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
'user': user.username,
'status': 'success'
}
return None

View File

@@ -0,0 +1,25 @@
from django.db import models
from django.utils import timezone
class Log(models.Model):
# Usamos BigAutoField para el BIGINT id de tu tabla
id = models.BigAutoField(primary_key=True)
user_id = models.IntegerField(default=0)
user = models.CharField(max_length=255, default='anonimo')
app_id = models.IntegerField(default=0)
# GenericIPAddressField para el tipo INET de Postgres
remote_address = models.GenericIPAddressField(null=True, blank=True)
request = models.JSONField(null=True, blank=True) # Para JSONB
response = models.JSONField(null=True, blank=True) # Para JSONB
status_code = models.CharField(max_length=10, default='0')
path = models.CharField(max_length=255)
method = models.CharField(max_length=10)
createdAt = models.DateTimeField(default=timezone.now)
updatedAt = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'audit_logs'
managed = False # Al estar la tabla ya creada, Django no intentará modificarla
def __str__(self):
return f"{self.method} {self.path} ({self.status_code})"

View File

@@ -1,6 +1,12 @@
from django.http import JsonResponse
from .actions import Admin
import logging
import json
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from .models import Log
logger = logging.getLogger(__name__)
@@ -25,4 +31,65 @@ def status_view(request):
# BLOQUE 4: Log de cierre y retorno
logger.info(f"FIN - Health Check completado. Status: {status_code}")
return JsonResponse(response_data, status=status_code)
return JsonResponse(response_data, status=status_code)
@csrf_exempt
@staticmethod
def api_token(request):
"""
Endpoint: api/token/
Patrón: 4 bloques con persistencia en Log DB.
"""
# --- BLOQUE 1: LOG INITIATION ---
logger.info("INICIO - Petición de JWT (api/token/)")
# Iniciamos el registro en la base de datos (Estándar compañeros)
log_entry = Log.objects.create(
user='anonimo',
path='api/token/',
method='POST',
createdAt=timezone.now(),
status_code='0'
)
try:
if request.method == 'POST':
# --- BLOQUE 2: DATA CLEANING ---
body_data = json.loads(request.body)
log_entry.request = body_data # Guardamos lo que entró
log_entry.save()
params = {
'username': body_data.get('username'),
'password': body_data.get('password')
}
# --- BLOQUE 3: ACTION CALL ---
admin_logic = Admin()
resultado = admin_logic.obtener_token_action(params)
# --- BLOQUE 4: LOG CLOSURE & RESPONSE ---
if resultado:
status = 200
log_entry.user = resultado['user']
log_entry.response = resultado
log_entry.status_code = str(status)
log_entry.updatedAt = timezone.now()
log_entry.save()
logger.info(f"FIN - JWT generado para: {log_entry.user}")
return JsonResponse(resultado, status=status)
else:
status = 401
response_error = {"error": "Credenciales inválidas"}
log_entry.status_code = str(status)
log_entry.response = response_error
log_entry.save()
return JsonResponse(response_error, status=status)
except Exception as e:
logger.error(f"ERROR CRÍTICO en api_token: {str(e)}")
log_entry.status_code = '500'
log_entry.response = {'error': str(e)}
log_entry.save()
return JsonResponse({'error': 'Error interno'}, status=500)

View File

@@ -1,5 +1,6 @@
# apps/common/apps.py
from django.apps import AppConfig
class CommonConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.common'
name = 'apps.common' # <--- ESTO ES LO QUE DEBE PONER

View File

@@ -1,8 +1,6 @@
from django.urls import path
from .views import get_promocion_view, status_view
from .views import PromocionObtener
urlpatterns = [
# Capa 1: Definición del endpoint
path('obtener/', get_promocion_view, name='get_promocion'),
path('obtener/', PromocionObtener.as_view(), name='obtener_promocion'),
]

View File

@@ -1,73 +1,46 @@
import logging
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.http import JsonResponse
from apps.backend_admin.models import Log
from .actions import getData
from django.utils import timezone # Esta es la forma correcta
class PromocionObtener(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
from django.http import JsonResponse
from .actions import get_status_action
def post(self, request):
# --- BLOQUE 1: LOG INITIATION ---
log_entry = Log.objects.create(
user=request.user.username,
path='promociones/obtener/',
method='POST',
status_code='0'
)
print('llega a despues de log entry')
# Configuración del logger para rastrear la ejecución
logger = logging.getLogger(__name__)
try:
# --- BLOQUE 2: DATA CLEANING ---
data = request.data
log_entry.request = data
log_entry.save()
def get_promocion_view(request):
"""
Vista estandarizada para la obtención de una promoción.
"""
# ---------------------------------------------------------
# BLOQUE 1: Log de iniciación
# ---------------------------------------------------------
logger.info("[START] Iniciando ejecución de get_promocion_view")
params = {'id': data.get('id'), 'activo': data.get('activo')}
try:
# ---------------------------------------------------------
# BLOQUE 2: Limpieza de datos (Data Cleaning)
# ---------------------------------------------------------
# Extraemos los parámetros del request y preparamos el diccionario
raw_data = request.GET.dict()
# Aquí es donde ella aplicaría validaciones adicionales si fuera necesario
clean_params = {
'id': raw_data.get('id'),
'activo': raw_data.get('activo', True) # Valor por defecto
}
# --- BLOQUE 3: ACTION CALL ---
# Aquí ya recibimos las fechas como strings gracias al paso 1
resultado = getData(params)
# ---------------------------------------------------------
# BLOQUE 3: Llamada a la Action (Execution)
# ---------------------------------------------------------
# La lógica de SQL y parametrización vive dentro de esta llamada
resultado_db = getData(clean_params)
# --- BLOQUE 4: LOG CLOSURE & RESPONSE ---
log_entry.response = {"count": len(resultado)} # No guardes todo el JSON si es muy grande
log_entry.status_code = '200'
log_entry.save()
# ---------------------------------------------------------
# BLOQUE 4: Log de cierre y respuesta (Closure)
# ---------------------------------------------------------
logger.info(f"[SUCCESS] get_promocion_view finalizada. Registros encontrados: {len(resultado_db)}")
return JsonResponse({
'status': 'success',
'data': resultado_db
}, status=200)
return JsonResponse(resultado, safe=False, status=200)
except Exception as e:
# Log de error detallado en caso de fallo
logger.error(f"[ERROR] Fallo crítico en get_promocion_view: {str(e)}")
return JsonResponse({
'status': 'error',
'message': 'Error interno del servidor'
}, status=500)
# En views.py
def status_view(request):
# BLOQUE 1: Log de iniciación
logger.info("Iniciando petición de status...")
# BLOQUE 2: Limpieza y validación de datos (En este caso no hay datos de entrada)
data_cleaned = {}
# BLOQUE 3: Llamada a la acción
response_data = get_status_action()
# BLOQUE 4: Log de cierre y retorno
logger.info("Status enviado correctamente.")
return JsonResponse(response_data, status=200)
except Exception as e:
log_entry.status_code = '500'
log_entry.response = {'error': str(e)}
log_entry.save()
return JsonResponse({'error': str(e)}, status=500)