Agrego carpeta del source sql de la Base de Datos
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
-- ============================================================================
|
||||
-- internal.clean_expired_sessions
|
||||
-- ============================================================================
|
||||
-- PROPÓSITO
|
||||
-- Elimina todas las sesiones cuya fecha de expiración ya pasó. Pensada
|
||||
-- para ejecutarse periódicamente por cron.
|
||||
--
|
||||
-- El job de cron que la dispara (ten_day_session_cleanup_job, días
|
||||
-- 1, 11 y 21 de cada mes a las 00:00) se versiona en
|
||||
-- cron/auth/ten_day_session_cleanup_job.sql.
|
||||
--
|
||||
-- PARÁMETROS
|
||||
-- Ninguno.
|
||||
--
|
||||
-- AUTORIZACIÓN
|
||||
-- No aplica (función interna invocada por cron).
|
||||
--
|
||||
-- ERRORES (RAISE EXCEPTION)
|
||||
-- Ninguno.
|
||||
--
|
||||
-- RETORNA
|
||||
-- void.
|
||||
--
|
||||
-- EFECTOS SECUNDARIOS
|
||||
-- DELETE en internal.sesiones de las filas con expires_at < NOW().
|
||||
-- ============================================================================
|
||||
|
||||
create OR REPLACE function internal.clean_expired_sessions() returns void
|
||||
security definer
|
||||
SET search_path = internal, pg_catalog
|
||||
language plpgsql
|
||||
as
|
||||
$$
|
||||
BEGIN
|
||||
-- Elimina todas las sesiones cuya fecha de expiración es anterior a la actual.
|
||||
DELETE FROM internal.sesiones
|
||||
WHERE expires_at < NOW();
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,44 @@
|
||||
-- ============================================================================
|
||||
-- internal.clean_old_sessions_on_new_login
|
||||
-- ============================================================================
|
||||
-- PROPÓSITO
|
||||
-- Trigger function: al insertar una nueva sesión, elimina cualquier otra
|
||||
-- sesión previa del mismo usuario. Garantiza que cada usuario tiene a lo
|
||||
-- sumo una sesión activa.
|
||||
--
|
||||
-- El trigger que la invoca (trg_clean_old_sessions, BEFORE INSERT on
|
||||
-- internal.sesiones) se versiona en
|
||||
-- triggers/auth/trg_clean_old_sessions.sql.
|
||||
--
|
||||
-- PARÁMETROS
|
||||
-- Implícitos del trigger (NEW.usuario_id, NEW.token).
|
||||
--
|
||||
-- AUTORIZACIÓN
|
||||
-- No aplica (es trigger).
|
||||
--
|
||||
-- ERRORES (RAISE EXCEPTION)
|
||||
-- Ninguno.
|
||||
--
|
||||
-- RETORNA
|
||||
-- trigger (la fila NEW para continuar el INSERT).
|
||||
--
|
||||
-- EFECTOS SECUNDARIOS
|
||||
-- DELETE en internal.sesiones de cualquier sesión del mismo usuario con
|
||||
-- token distinto al recién insertado.
|
||||
-- ============================================================================
|
||||
|
||||
create OR REPLACE function internal.clean_old_sessions_on_new_login() returns trigger
|
||||
security definer
|
||||
set search_path = internal, pg_catalog
|
||||
language plpgsql
|
||||
as
|
||||
$$
|
||||
BEGIN
|
||||
-- Esto asegura que solo la sesión actual (la que se está creando) permanezca.
|
||||
DELETE FROM internal.sesiones
|
||||
WHERE usuario_id = NEW.usuario_id
|
||||
AND token IS DISTINCT FROM NEW.token;
|
||||
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,39 @@
|
||||
-- ============================================================================
|
||||
-- internal.create_password_hash
|
||||
-- ============================================================================
|
||||
-- PROPÓSITO
|
||||
-- Devuelve el hash bcrypt de una contraseña en texto plano. Usa
|
||||
-- crypt() + gen_salt('bf') del módulo pgcrypto, que vive en el schema
|
||||
-- extensions.
|
||||
--
|
||||
-- Helper interno usado por internal.fc_insertar_usuario (vía
|
||||
-- public.fc_insertar_usuario) y por funciones futuras de cambio de
|
||||
-- contraseña.
|
||||
--
|
||||
-- PARÁMETROS
|
||||
-- p_password_plain TEXT contraseña en claro.
|
||||
--
|
||||
-- AUTORIZACIÓN
|
||||
-- Función interna, sin validación propia. Pensada para ser llamada por
|
||||
-- otras funciones server-side, no por el cliente directamente.
|
||||
--
|
||||
-- ERRORES (RAISE EXCEPTION)
|
||||
-- Ninguno propio.
|
||||
--
|
||||
-- RETORNA
|
||||
-- TEXT con el hash bcrypt.
|
||||
--
|
||||
-- EFECTOS SECUNDARIOS
|
||||
-- Ninguno.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION internal.create_password_hash(p_password_plain TEXT)
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = extensions, public
|
||||
AS $$
|
||||
BEGIN
|
||||
RETURN crypt(p_password_plain, gen_salt('bf'::text));
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,45 @@
|
||||
-- ============================================================================
|
||||
-- internal.validar_token
|
||||
-- ============================================================================
|
||||
-- PROPÓSITO
|
||||
-- Dado un token de sesión, devuelve el rol del usuario asociado si la
|
||||
-- sesión está vigente. Si el token no existe o ya expiró, devuelve NULL.
|
||||
-- Helper interno usado por internal.validate_permission y por funciones
|
||||
-- públicas que necesitan saber el rol del actor.
|
||||
--
|
||||
-- PARÁMETROS
|
||||
-- p_token UUID token de sesión.
|
||||
--
|
||||
-- AUTORIZACIÓN
|
||||
-- Función interna, sin validación propia.
|
||||
--
|
||||
-- ERRORES (RAISE EXCEPTION)
|
||||
-- Ninguno.
|
||||
--
|
||||
-- RETORNA
|
||||
-- TEXT con el rol del usuario, o NULL si el token es inválido o expiró.
|
||||
--
|
||||
-- EFECTOS SECUNDARIOS
|
||||
-- Ninguno (STABLE).
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION internal.validar_token(p_token uuid)
|
||||
RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
STABLE SECURITY DEFINER
|
||||
SET search_path TO 'public'
|
||||
AS $function$
|
||||
DECLARE
|
||||
v_rol TEXT;
|
||||
BEGIN
|
||||
SELECT u.rol
|
||||
FROM public.usuarios u
|
||||
JOIN internal.sesiones s ON s.usuario_id = u.id
|
||||
AND s.token = p_token
|
||||
AND s.expires_at > NOW()
|
||||
INTO v_rol;
|
||||
-- Retorna el rol si el token es válido, de lo contrario, retorna NULL
|
||||
RETURN v_rol;
|
||||
END;
|
||||
$function$
|
||||
;
|
||||
@@ -0,0 +1,62 @@
|
||||
-- ============================================================================
|
||||
-- internal.validate_permission
|
||||
-- ============================================================================
|
||||
-- PROPÓSITO
|
||||
-- Valida que el portador del token tenga permiso para ejecutar una acción
|
||||
-- dada. Rebota con excepción si el token es inválido, si la acción no
|
||||
-- está registrada, o si el rol del usuario no está autorizado.
|
||||
--
|
||||
-- Es la pieza central del control de acceso: toda función pública (fc_*)
|
||||
-- la invoca al inicio.
|
||||
--
|
||||
-- PARÁMETROS
|
||||
-- p_token UUID token de sesión del actor.
|
||||
-- p_accion TEXT nombre de la acción a validar (clave en internal.permisos).
|
||||
--
|
||||
-- AUTORIZACIÓN
|
||||
-- Función interna; ella misma es el validador de autorización.
|
||||
--
|
||||
-- ERRORES (RAISE EXCEPTION)
|
||||
-- - 'Token de sesión inválido o expirado'
|
||||
-- - 'Error interno: acción no reconocida: X'
|
||||
-- - 'No tienes internal.permisos para realizar esta acción'
|
||||
-- (NOTA: el texto del error contiene "internal.permisos" por un error
|
||||
-- histórico de redacción; se refiere a permisos en general.)
|
||||
--
|
||||
-- RETORNA
|
||||
-- void si el actor tiene permiso. Si no, rebota antes de retornar.
|
||||
--
|
||||
-- EFECTOS SECUNDARIOS
|
||||
-- Ninguno (STABLE).
|
||||
-- ============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION internal.validate_permission(p_token UUID, p_accion TEXT)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
STABLE
|
||||
SECURITY DEFINER
|
||||
SET search_path TO public
|
||||
AS $$
|
||||
DECLARE
|
||||
v_rol TEXT;
|
||||
v_roles_permitidos TEXT[];
|
||||
BEGIN
|
||||
SELECT internal.validar_token(p_token) INTO v_rol;
|
||||
|
||||
IF v_rol IS NULL THEN
|
||||
RAISE EXCEPTION 'Token de sesión inválido o expirado';
|
||||
END IF;
|
||||
|
||||
SELECT roles_permitidos INTO v_roles_permitidos
|
||||
FROM internal.permisos
|
||||
WHERE accion = p_accion;
|
||||
|
||||
IF v_roles_permitidos IS NULL THEN
|
||||
RAISE EXCEPTION 'Error interno: acción no reconocida: %', p_accion;
|
||||
END IF;
|
||||
|
||||
IF v_rol <> ALL(v_roles_permitidos) THEN
|
||||
RAISE EXCEPTION 'No tienes internal.permisos para realizar esta acción';
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
Reference in New Issue
Block a user