Arch/services/user_service.py

192 lines
5.5 KiB
Python
Raw Normal View History

2025-03-03 17:50:11 -03:00
import os
import json
import uuid
from datetime import datetime
from flask import current_app
from flask_login import UserMixin
from app import bcrypt
from utils.file_utils import load_json_file, save_json_file
2025-03-03 15:35:24 -03:00
from services.auth_service import (
2025-03-03 17:50:11 -03:00
get_user_by_username,
get_user_by_id,
get_all_users,
create_user,
update_user,
delete_user,
2025-03-03 15:35:24 -03:00
)
2025-03-03 17:50:11 -03:00
class User(UserMixin):
"""Clase de usuario para Flask-Login."""
def __init__(self, user_id, user_data):
self.id = user_id
self.username = user_data.get("username", "")
self.nombre = user_data.get("nombre", "")
self.email = user_data.get("email", "")
self.nivel = user_data.get("nivel", 0)
self.idioma = user_data.get("idioma", "es")
self.fecha_caducidad = user_data.get("fecha_caducidad")
self.empresa = user_data.get("empresa", "")
self.estado = user_data.get("estado", "activo")
self.ultimo_acceso = user_data.get("ultimo_acceso")
def has_permission(self, required_level):
"""Verificar si el usuario tiene el nivel de permiso requerido."""
return self.nivel >= required_level and self.estado == "activo"
def to_dict(self):
"""Convertir el usuario a un diccionario para almacenamiento."""
return {
"username": self.username,
"nombre": self.nombre,
"email": self.email,
"nivel": self.nivel,
"idioma": self.idioma,
"fecha_caducidad": self.fecha_caducidad,
"empresa": self.empresa,
"estado": self.estado,
"ultimo_acceso": self.ultimo_acceso,
}
def get_users_file_path():
"""Obtener la ruta al archivo de usuarios."""
storage_path = current_app.config["STORAGE_PATH"]
return os.path.join(storage_path, "users", "users.json")
def get_all_users():
"""Obtener todos los usuarios del sistema."""
users_data = load_json_file(get_users_file_path(), {})
return users_data
def get_user_by_id(user_id):
"""Obtener un usuario por su ID."""
if not user_id:
return None
users_data = load_json_file(get_users_file_path(), {})
if user_id in users_data:
return User(user_id, users_data[user_id])
return None
2025-03-03 15:35:24 -03:00
# Este archivo importa funcionalidades de auth_service.py para mantener
# consistencia en la estructura del proyecto, y agrega funcionalidades específicas
# de gestión de usuarios que no están relacionadas con la autenticación.
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
def filter_users(filter_params):
"""
Filtrar usuarios según los parámetros proporcionados.
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
Args:
filter_params (dict): Diccionario con parámetros de filtrado
- empresa: Nombre de empresa
- estado: Estado del usuario ('activo', 'inactivo')
- nivel_min: Nivel mínimo de permiso
- nivel_max: Nivel máximo de permiso
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
Returns:
list: Lista de objetos User que cumplen los criterios
"""
users = get_all_users()
filtered_users = []
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
for user in users:
# Filtrar por empresa
2025-03-03 17:50:11 -03:00
if "empresa" in filter_params and filter_params["empresa"]:
if user.empresa != filter_params["empresa"]:
2025-03-03 15:35:24 -03:00
continue
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Filtrar por estado
2025-03-03 17:50:11 -03:00
if "estado" in filter_params and filter_params["estado"]:
if user.estado != filter_params["estado"]:
2025-03-03 15:35:24 -03:00
continue
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Filtrar por nivel mínimo
2025-03-03 17:50:11 -03:00
if "nivel_min" in filter_params and filter_params["nivel_min"] is not None:
if user.nivel < int(filter_params["nivel_min"]):
2025-03-03 15:35:24 -03:00
continue
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Filtrar por nivel máximo
2025-03-03 17:50:11 -03:00
if "nivel_max" in filter_params and filter_params["nivel_max"] is not None:
if user.nivel > int(filter_params["nivel_max"]):
2025-03-03 15:35:24 -03:00
continue
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Si pasó todos los filtros, agregar a la lista
filtered_users.append(user)
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
return filtered_users
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
def get_user_stats():
"""
Obtener estadísticas sobre los usuarios.
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
Returns:
dict: Diccionario con estadísticas
"""
users = get_all_users()
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Inicializar estadísticas
stats = {
2025-03-03 17:50:11 -03:00
"total": len(users),
"activos": 0,
"inactivos": 0,
"expirados": 0,
"por_empresa": {},
"por_nivel": {
"admin": 0, # Nivel 9000+
"gestor": 0, # Nivel 5000-8999
"editor": 0, # Nivel 1000-4999
"lector": 0, # Nivel 0-999
},
2025-03-03 15:35:24 -03:00
}
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
# Calcular estadísticas
for user in users:
# Estado
2025-03-03 17:50:11 -03:00
if user.estado == "activo":
stats["activos"] += 1
2025-03-03 15:35:24 -03:00
else:
2025-03-03 17:50:11 -03:00
stats["inactivos"] += 1
2025-03-03 15:35:24 -03:00
# Expirados
if user.is_expired():
2025-03-03 17:50:11 -03:00
stats["expirados"] += 1
2025-03-03 15:35:24 -03:00
# Por empresa
2025-03-03 17:50:11 -03:00
empresa = user.empresa or "Sin empresa"
stats["por_empresa"][empresa] = stats["por_empresa"].get(empresa, 0) + 1
2025-03-03 15:35:24 -03:00
# Por nivel
if user.nivel >= 9000:
2025-03-03 17:50:11 -03:00
stats["por_nivel"]["admin"] += 1
2025-03-03 15:35:24 -03:00
elif user.nivel >= 5000:
2025-03-03 17:50:11 -03:00
stats["por_nivel"]["gestor"] += 1
2025-03-03 15:35:24 -03:00
elif user.nivel >= 1000:
2025-03-03 17:50:11 -03:00
stats["por_nivel"]["editor"] += 1
2025-03-03 15:35:24 -03:00
else:
2025-03-03 17:50:11 -03:00
stats["por_nivel"]["lector"] += 1
2025-03-03 15:35:24 -03:00
return stats
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
def check_username_availability(username):
"""
Verificar si un nombre de usuario está disponible.
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
Args:
username (str): Nombre de usuario a verificar
2025-03-03 17:50:11 -03:00
2025-03-03 15:35:24 -03:00
Returns:
bool: True si está disponible, False si ya existe
"""
user = get_user_by_username(username)
2025-03-03 17:50:11 -03:00
return user is None