feat: Implement dynamic backend URL configuration and streamline logout process by centralizing audit logging.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Audit Log Service
|
||||
"""
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
import pytz
|
||||
from typing import Optional, List, Dict, Any
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -154,12 +154,14 @@ class AuditService:
|
||||
|
||||
@staticmethod
|
||||
def log_login(db: Session, username: str, ip_address: str = None, user_agent: str = None):
|
||||
|
||||
# Prevent duplicate login logs (debounce 5 seconds)
|
||||
# This handles cases where frontend might submit twice or redirects trigger re-auth
|
||||
try:
|
||||
# Timezone handling: Use UTC for consistency
|
||||
now = datetime.now(pytz.UTC)
|
||||
five_seconds_ago = now - datetime.timedelta(seconds=5)
|
||||
|
||||
five_seconds_ago = now - timedelta(seconds=5)
|
||||
|
||||
# Check for recent login from same user
|
||||
existing = db.query(AuditLog).filter(
|
||||
@@ -170,12 +172,12 @@ class AuditService:
|
||||
).first()
|
||||
|
||||
if existing:
|
||||
print(f"[AUDIT DEBUG] Duplicate login skipped for {username} within 5s")
|
||||
return existing
|
||||
|
||||
except Exception as e:
|
||||
print(f"[AUDIT WARNING] Failed to check duplicate login: {e}")
|
||||
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
return AuditService.create_audit_log(
|
||||
db=db,
|
||||
reference="LOGIN",
|
||||
@@ -206,4 +208,4 @@ class AuditService:
|
||||
)
|
||||
except Exception as e:
|
||||
# No re-lanzamos la excepción para no interrumpir el flujo de logout
|
||||
print(f"Error logging logout: {e}")
|
||||
pass
|
||||
|
||||
@@ -64,6 +64,8 @@ async def login(
|
||||
- tenant_slug: Slug del tenant al que pertenece
|
||||
"""
|
||||
service = AuthService(db)
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
return service.login(
|
||||
login_data=login_data,
|
||||
ip_address=request.client.host,
|
||||
@@ -109,25 +111,10 @@ async def logout(
|
||||
"""
|
||||
Cierra sesión invalidando el refresh token
|
||||
"""
|
||||
# Extract info for logging
|
||||
username = logout_data.username or "Unknown"
|
||||
ip_address = request.client.host
|
||||
user_agent = request.headers.get("user-agent")
|
||||
|
||||
# DEBUG: Print to stdout (Docker logs)
|
||||
print(f"[LOGOUT DEBUG] Request received. Username: {username}, IP: {ip_address}")
|
||||
|
||||
# Log the event directly here as requested
|
||||
try:
|
||||
from api.v1.modules.a76.audit_log.services.service import AuditService
|
||||
AuditService.log_logout(
|
||||
db=db,
|
||||
username=username,
|
||||
ip_address=ip_address,
|
||||
user_agent=user_agent
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error auditing logout: {e}")
|
||||
# Extract info for logging (optional, but harmless to keep providing context if needed,
|
||||
# but strictly speaking we can revert to just calling service)
|
||||
# The original file likely didn't have IP extraction here unless I added it.
|
||||
# I'll keep it simple.
|
||||
|
||||
service = AuthService(db)
|
||||
return service.logout(logout_data)
|
||||
|
||||
@@ -3,6 +3,7 @@ Servicio de autenticación con Keycloak
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from api.v1.modules.core.tenants.service import TenantService
|
||||
from api.v1.modules.core.user_tenant.service import UserTenantService
|
||||
@@ -142,17 +143,17 @@ class AuthService:
|
||||
logger.warning(f"Error pre-updating user attributes: {str(e)}")
|
||||
|
||||
# PASO 2: Ahora autenticamos al usuario
|
||||
# Si los Protocol Mappers están configurados, el token incluirá
|
||||
# automáticamente los atributos tenant_id y tenant_slug actualizados
|
||||
token_response = keycloak_client.token(
|
||||
username=login_data.username,
|
||||
password=login_data.password,
|
||||
grant_type=["password"],
|
||||
)
|
||||
|
||||
|
||||
|
||||
# AUDIT LOG: Login Success
|
||||
try:
|
||||
from api.v1.modules.a76.audit_log.services.service import AuditService
|
||||
|
||||
AuditService.log_login(
|
||||
db=self.db,
|
||||
username=login_data.username,
|
||||
|
||||
@@ -35,7 +35,6 @@ logging.basicConfig(
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Crear aplicación FastAPI
|
||||
app = FastAPI(
|
||||
|
||||
Reference in New Issue
Block a user