feat: habilitar acceso automático al Hub por dominio
This commit is contained in:
+104
-44
@@ -2,7 +2,7 @@
|
||||
-- GLM HUB — ESQUEMA COMPLETO DE SUPABASE
|
||||
-- ============================================================================
|
||||
-- Incluye:
|
||||
-- 1) Usuarios autorizados y roles.
|
||||
-- 1) Acceso automático por dominio, administradores y bloqueos excepcionales.
|
||||
-- 2) Catálogo compartido para todos los usuarios del Hub.
|
||||
-- 3) Favoritos y accesos recientes por usuario.
|
||||
-- 4) Bucket público para los íconos.
|
||||
@@ -20,8 +20,13 @@ begin;
|
||||
create extension if not exists pgcrypto with schema extensions;
|
||||
|
||||
-- --------------------------------------------------------------------------
|
||||
-- 1. USUARIOS AUTORIZADOS
|
||||
-- 1. ACCESO POR DOMINIO, ADMINISTRADORES Y BLOQUEOS
|
||||
-- --------------------------------------------------------------------------
|
||||
-- Regla vigente:
|
||||
-- * Todo usuario autenticado con @gomezleemarketing.com entra como member.
|
||||
-- * Un registro activo con role = 'admin' concede funciones administrativas.
|
||||
-- * Un registro con is_active = false bloquea excepcionalmente ese correo.
|
||||
-- * Los usuarios normales no necesitan una fila en esta tabla.
|
||||
|
||||
create table if not exists public.glm_hub_authorized_users (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
@@ -54,6 +59,9 @@ create table if not exists public.glm_hub_authorized_users (
|
||||
)
|
||||
);
|
||||
|
||||
comment on table public.glm_hub_authorized_users is
|
||||
'Excepciones de acceso del GLM Hub: administradores activos y usuarios bloqueados. Los usuarios corporativos normales no requieren registro.';
|
||||
|
||||
create or replace function public.glm_hub_normalize_authorized_user()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
@@ -85,14 +93,17 @@ grant all on table public.glm_hub_authorized_users to service_role;
|
||||
|
||||
drop policy if exists "GLM Hub users can read only their active access"
|
||||
on public.glm_hub_authorized_users;
|
||||
drop policy if exists "GLM Hub users can read their own control record"
|
||||
on public.glm_hub_authorized_users;
|
||||
|
||||
create policy "GLM Hub users can read only their active access"
|
||||
-- Cada persona solo puede consultar su propia excepción. Esto permite que el
|
||||
-- frontend detecte también un bloqueo (is_active = false) sin exponer a otros.
|
||||
create policy "GLM Hub users can read their own control record"
|
||||
on public.glm_hub_authorized_users
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
is_active = true
|
||||
and email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||
email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||
);
|
||||
|
||||
insert into public.glm_hub_authorized_users (email, full_name, role, is_active)
|
||||
@@ -109,41 +120,64 @@ set
|
||||
is_active = true,
|
||||
updated_at = now();
|
||||
|
||||
-- Estas funciones se ejecutan con los permisos/RLS del usuario autenticado.
|
||||
-- Los registros member activos ya no son necesarios: la ausencia de fila
|
||||
-- significa Usuario normal. Se conservan únicamente admins y bloqueos.
|
||||
delete from public.glm_hub_authorized_users
|
||||
where role = 'member'
|
||||
and is_active = true;
|
||||
|
||||
create or replace function public.glm_hub_is_active_user()
|
||||
returns boolean
|
||||
language sql
|
||||
language plpgsql
|
||||
stable
|
||||
security invoker
|
||||
set search_path = public, auth
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from public.glm_hub_authorized_users as access
|
||||
where access.is_active = true
|
||||
and access.email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||
);
|
||||
declare
|
||||
v_email text;
|
||||
begin
|
||||
v_email := lower(coalesce(auth.jwt() ->> 'email', ''));
|
||||
|
||||
return
|
||||
auth.uid() is not null
|
||||
and v_email ~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@gomezleemarketing\.com$'
|
||||
and not exists (
|
||||
select 1
|
||||
from public.glm_hub_authorized_users as access
|
||||
where access.email = v_email
|
||||
and access.is_active = false
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
create or replace function public.glm_hub_is_admin()
|
||||
returns boolean
|
||||
language sql
|
||||
language plpgsql
|
||||
stable
|
||||
security invoker
|
||||
set search_path = public, auth
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from public.glm_hub_authorized_users as access
|
||||
where access.is_active = true
|
||||
and access.role = 'admin'
|
||||
and access.email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||
);
|
||||
declare
|
||||
v_email text;
|
||||
begin
|
||||
v_email := lower(coalesce(auth.jwt() ->> 'email', ''));
|
||||
|
||||
return
|
||||
auth.uid() is not null
|
||||
and exists (
|
||||
select 1
|
||||
from public.glm_hub_authorized_users as access
|
||||
where access.email = v_email
|
||||
and access.role = 'admin'
|
||||
and access.is_active = true
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
alter function public.glm_hub_is_active_user() owner to postgres;
|
||||
alter function public.glm_hub_is_admin() owner to postgres;
|
||||
|
||||
-- n8n llama esta función usando el JWT recibido desde el frontend.
|
||||
-- SECURITY DEFINER permite consultar la tabla interna sin quedar bloqueado por RLS,
|
||||
-- pero el correo y el usuario siempre se toman del JWT real de Supabase.
|
||||
create or replace function public.glm_hub_icon_generation_access()
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
@@ -162,7 +196,7 @@ begin
|
||||
select exists (
|
||||
select 1
|
||||
from public.glm_hub_authorized_users as access
|
||||
where lower(access.email) = v_email
|
||||
where access.email = v_email
|
||||
and access.role = 'admin'
|
||||
and access.is_active = true
|
||||
)
|
||||
@@ -564,7 +598,9 @@ declare
|
||||
v_user_id uuid;
|
||||
v_email text;
|
||||
v_name text;
|
||||
v_control_name text;
|
||||
v_role text;
|
||||
v_is_active boolean;
|
||||
v_app_name text;
|
||||
v_app_category text;
|
||||
v_request_id uuid;
|
||||
@@ -576,21 +612,31 @@ begin
|
||||
return jsonb_build_object('ok', false, 'error', 'Tu sesión no es válida. Cierra sesión e inicia nuevamente.');
|
||||
end if;
|
||||
|
||||
select coalesce(nullif(btrim(access.full_name), ''), split_part(v_email, '@', 1)), access.role
|
||||
into v_name, v_role
|
||||
if v_email !~ '^[a-z0-9.!#$%&''*+/=?^_`{|}~-]+@gomezleemarketing\.com$' then
|
||||
return jsonb_build_object('ok', false, 'error', 'Debes utilizar una cuenta corporativa de GomezLee Marketing.');
|
||||
end if;
|
||||
|
||||
select access.full_name, access.role, access.is_active
|
||||
into v_control_name, v_role, v_is_active
|
||||
from public.glm_hub_authorized_users as access
|
||||
where access.email = v_email
|
||||
and access.is_active = true
|
||||
limit 1;
|
||||
|
||||
if not found then
|
||||
return jsonb_build_object('ok', false, 'error', 'El usuario no está autorizado en GLM Hub.');
|
||||
if found and v_is_active = false then
|
||||
return jsonb_build_object('ok', false, 'error', 'Tu acceso al GLM Hub está deshabilitado. Contacta a IT Support.');
|
||||
end if;
|
||||
|
||||
if v_role = 'admin' then
|
||||
if coalesce(v_role, 'member') = 'admin' then
|
||||
return jsonb_build_object('ok', false, 'error', 'Los administradores no necesitan solicitar acceso desde el Hub.');
|
||||
end if;
|
||||
|
||||
v_name := coalesce(
|
||||
nullif(btrim(v_control_name), ''),
|
||||
nullif(btrim(auth.jwt() -> 'user_metadata' ->> 'full_name'), ''),
|
||||
nullif(btrim(auth.jwt() -> 'user_metadata' ->> 'name'), ''),
|
||||
split_part(v_email, '@', 1)
|
||||
);
|
||||
|
||||
select app.name, app.category
|
||||
into v_app_name, v_app_category
|
||||
from public.glm_hub_apps as app
|
||||
@@ -867,21 +913,35 @@ commit;
|
||||
-- OPERACIONES DE ADMINISTRACIÓN (EJECUTAR DESDE SQL EDITOR)
|
||||
-- ============================================================================
|
||||
|
||||
-- DAR ACCESO A UN USUARIO NORMAL:
|
||||
-- IMPORTANTE:
|
||||
-- Todo correo @gomezleemarketing.com entra automáticamente como Usuario.
|
||||
-- La tabla glm_hub_authorized_users se usa solo para administradores y bloqueos.
|
||||
|
||||
-- CONVERTIR UN USUARIO EN ADMINISTRADOR:
|
||||
-- insert into public.glm_hub_authorized_users (email, full_name, role, is_active)
|
||||
-- values ('usuario@gomezleemarketing.com', 'Nombre del usuario', 'member', true)
|
||||
-- values ('usuario@gomezleemarketing.com', 'Nombre del usuario', 'admin', true)
|
||||
-- on conflict (email) do update
|
||||
-- set full_name = excluded.full_name, role = 'member', is_active = true;
|
||||
-- set full_name = excluded.full_name, role = 'admin', is_active = true, updated_at = now();
|
||||
|
||||
-- QUITAR ACCESO SIN BORRAR EL REGISTRO:
|
||||
-- update public.glm_hub_authorized_users
|
||||
-- set is_active = false
|
||||
-- DEVOLVER UN ADMINISTRADOR A USUARIO NORMAL:
|
||||
-- delete from public.glm_hub_authorized_users
|
||||
-- where email = 'usuario@gomezleemarketing.com';
|
||||
|
||||
-- REACTIVAR ACCESO:
|
||||
-- update public.glm_hub_authorized_users
|
||||
-- set is_active = true
|
||||
-- where email = 'usuario@gomezleemarketing.com';
|
||||
-- BLOQUEAR EXCEPCIONALMENTE A UN USUARIO DEL DOMINIO:
|
||||
-- insert into public.glm_hub_authorized_users (email, full_name, role, is_active)
|
||||
-- values ('usuario@gomezleemarketing.com', 'Nombre del usuario', 'member', false)
|
||||
-- on conflict (email) do update
|
||||
-- set full_name = excluded.full_name, role = 'member', is_active = false, updated_at = now();
|
||||
|
||||
-- DESBLOQUEAR A UN USUARIO NORMAL:
|
||||
-- delete from public.glm_hub_authorized_users
|
||||
-- where email = 'usuario@gomezleemarketing.com'
|
||||
-- and role = 'member';
|
||||
|
||||
-- VER ADMINISTRADORES Y BLOQUEOS:
|
||||
-- select email, full_name, role, is_active, updated_at
|
||||
-- from public.glm_hub_authorized_users
|
||||
-- order by role, email;
|
||||
|
||||
-- VER SOLICITUDES DE ACCESO:
|
||||
-- select requester_name, requester_email, app_name, status, decided_by_name, decided_by_email, created_at, decided_at
|
||||
|
||||
Reference in New Issue
Block a user