230 lines
9.6 KiB
Python
230 lines
9.6 KiB
Python
from functools import wraps
|
|
from flask import render_template, abort, current_app
|
|
from flask_login import current_user
|
|
|
|
def permission_required(min_level):
|
|
"""
|
|
Decorador para verificar nivel de permisos en rutas web.
|
|
|
|
Args:
|
|
min_level (int): Nivel mínimo requerido
|
|
|
|
Returns:
|
|
function: Decorador configurado
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if not current_user.is_authenticated:
|
|
return current_app.login_manager.unauthorized()
|
|
|
|
if not current_user.has_permission(min_level):
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="No tiene permisos suficientes para acceder a esta página."), 403
|
|
|
|
return f(*args, **kwargs)
|
|
return decorated_function
|
|
return decorator
|
|
|
|
def project_access_required(access_type='view'):
|
|
"""
|
|
Decorador para verificar acceso a un proyecto específico.
|
|
|
|
Args:
|
|
access_type (str): Tipo de acceso ('view' o 'edit')
|
|
|
|
Returns:
|
|
function: Decorador configurado
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if not current_user.is_authenticated:
|
|
return current_app.login_manager.unauthorized()
|
|
|
|
# Obtener ID del proyecto de los argumentos
|
|
project_id = kwargs.get('project_id')
|
|
|
|
if not project_id:
|
|
abort(400, description="ID de proyecto no proporcionado")
|
|
|
|
# Verificar permisos específicos del proyecto
|
|
from services.project_service import get_project
|
|
|
|
project = get_project(project_id)
|
|
|
|
if not project:
|
|
abort(404, description="Proyecto no encontrado")
|
|
|
|
# Verificar si el proyecto está activo
|
|
if project.get('estado') != 'activo' and not current_user.has_permission(9000):
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="El proyecto no está activo."), 403
|
|
|
|
# Verificar permisos específicos
|
|
# Administradores siempre tienen acceso
|
|
if current_user.has_permission(9000):
|
|
return f(*args, **kwargs)
|
|
|
|
# Verificar permisos en el archivo de permisos del proyecto
|
|
from utils.file_utils import load_json_file
|
|
import os
|
|
|
|
storage_path = current_app.config['STORAGE_PATH']
|
|
project_dir = os.path.join(storage_path, 'projects', project.get('directory', ''))
|
|
permissions_file = os.path.join(project_dir, 'permissions.json')
|
|
|
|
permissions = load_json_file(permissions_file, {})
|
|
|
|
# Verificar permisos específicos del usuario
|
|
user_permissions = permissions.get(current_user.id, {})
|
|
|
|
if access_type == 'edit' and user_permissions.get('can_edit', False):
|
|
return f(*args, **kwargs)
|
|
|
|
if access_type == 'view' and user_permissions.get('can_view', False):
|
|
return f(*args, **kwargs)
|
|
|
|
# Verificar nivel general requerido según el esquema
|
|
schema_code = project.get('esquema')
|
|
|
|
if not schema_code:
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="No tiene permisos para acceder a este proyecto."), 403
|
|
|
|
from services.schema_service import get_schema
|
|
|
|
schema = get_schema(schema_code)
|
|
|
|
if not schema:
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="Esquema no encontrado."), 403
|
|
|
|
# Nivel mínimo para ver/editar según el esquema
|
|
min_level_view = 0 # Por defecto, cualquier usuario autenticado puede ver
|
|
min_level_edit = 5000 # Por defecto, se requiere nivel de gestor para editar
|
|
|
|
# Si hay configuración específica en el esquema, usarla
|
|
if 'nivel_ver' in schema:
|
|
min_level_view = schema.get('nivel_ver', 0)
|
|
|
|
if 'nivel_editar' in schema:
|
|
min_level_edit = schema.get('nivel_editar', 5000)
|
|
|
|
# Verificar nivel según tipo de acceso
|
|
if access_type == 'edit' and current_user.has_permission(min_level_edit):
|
|
return f(*args, **kwargs)
|
|
|
|
if access_type == 'view' and current_user.has_permission(min_level_view):
|
|
return f(*args, **kwargs)
|
|
|
|
# Si llega aquí, no tiene permisos
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="No tiene permisos para acceder a este proyecto."), 403
|
|
|
|
return decorated_function
|
|
return decorator
|
|
|
|
def document_access_required(access_type='view'):
|
|
"""
|
|
Decorador para verificar acceso a un documento específico.
|
|
|
|
Args:
|
|
access_type (str): Tipo de acceso ('view' o 'edit')
|
|
|
|
Returns:
|
|
function: Decorador configurado
|
|
"""
|
|
def decorator(f):
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if not current_user.is_authenticated:
|
|
return current_app.login_manager.unauthorized()
|
|
|
|
# Obtener IDs de proyecto y documento
|
|
project_id = kwargs.get('project_id')
|
|
document_id = kwargs.get('document_id')
|
|
|
|
if not project_id or not document_id:
|
|
abort(400, description="ID de proyecto o documento no proporcionado")
|
|
|
|
# Verificar permisos del proyecto primero
|
|
from services.project_service import get_project
|
|
|
|
project = get_project(project_id)
|
|
|
|
if not project:
|
|
abort(404, description="Proyecto no encontrado")
|
|
|
|
# Verificar si el proyecto está activo
|
|
if project.get('estado') != 'activo' and not current_user.has_permission(9000):
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="El proyecto no está activo."), 403
|
|
|
|
# Administradores siempre tienen acceso
|
|
if current_user.has_permission(9000):
|
|
return f(*args, **kwargs)
|
|
|
|
# Obtener información del documento
|
|
from services.document_service import get_document
|
|
|
|
document = get_document(project_id, document_id)
|
|
|
|
if not document:
|
|
abort(404, description="Documento no encontrado")
|
|
|
|
# Obtener el esquema del proyecto
|
|
schema_code = project.get('esquema')
|
|
|
|
if not schema_code:
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="No tiene permisos para acceder a este documento."), 403
|
|
|
|
# Cargar el esquema específico del proyecto
|
|
from utils.file_utils import load_json_file
|
|
import os
|
|
|
|
storage_path = current_app.config['STORAGE_PATH']
|
|
project_dir = os.path.join(storage_path, 'projects', project.get('directory', ''))
|
|
project_schema_file = os.path.join(project_dir, 'schema.json')
|
|
|
|
schema = load_json_file(project_schema_file)
|
|
|
|
if not schema:
|
|
# Si no hay esquema específico, usar el general
|
|
from services.schema_service import get_schema
|
|
schema = get_schema(schema_code)
|
|
|
|
if not schema:
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="Esquema no encontrado."), 403
|
|
|
|
# Obtener el tipo de documento
|
|
document_name = document.get('document_id', '').split('_', 1)[1] if '_' in document.get('document_id', '') else ''
|
|
|
|
# Buscar configuración de permisos para este tipo de documento
|
|
for doc_type in schema.get('documentos', []):
|
|
if doc_type.get('nombre', '').lower().replace(' ', '_') == document_name:
|
|
# Verificar nivel según tipo de acceso
|
|
if access_type == 'edit' and current_user.has_permission(doc_type.get('nivel_editar', 5000)):
|
|
return f(*args, **kwargs)
|
|
|
|
if access_type == 'view' and current_user.has_permission(doc_type.get('nivel_ver', 0)):
|
|
return f(*args, **kwargs)
|
|
|
|
# Si no se encontró configuración específica o no tiene permisos
|
|
return render_template('error.html',
|
|
error_code=403,
|
|
error_message="No tiene permisos para acceder a este documento."), 403
|
|
|
|
return decorated_function
|
|
return decorator
|