fix: corregir acceso automático al Hub por dominio
This commit is contained in:
@@ -25,3 +25,9 @@ No es necesario modificar los workflows de n8n.
|
||||
| `role = member`, `is_active = false` | Usuario bloqueado |
|
||||
|
||||
Los registros `member` activos se eliminan durante la migración porque ya no son necesarios.
|
||||
|
||||
## Corrección de compatibilidad con Supabase self-hosted
|
||||
|
||||
La validación del perfil consulta `glm_hub_authorized_users` como una lista limitada a una fila. Cuando no existe una fila, el resultado vacío se interpreta como **Usuario normal**, evitando que algunas versiones self-hosted de PostgREST rechacen el inicio de sesión al solicitar un objeto único sin coincidencias.
|
||||
|
||||
Para instalaciones que todavía conserven la función anterior de autorización, ejecuta `SUPABASE-GLM-HUB-HOTFIX-ACCESO-POR-DOMINIO.sql` una sola vez.
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
-- ============================================================================
|
||||
-- GLM HUB — HOTFIX DE ACCESO AUTOMÁTICO POR DOMINIO
|
||||
-- ============================================================================
|
||||
-- Ejecutar una sola vez en Supabase Studio > SQL Editor.
|
||||
--
|
||||
-- Resultado esperado:
|
||||
-- * Todo usuario autenticado con @gomezleemarketing.com entra como Usuario.
|
||||
-- * La ausencia de una fila en glm_hub_authorized_users NO bloquea el acceso.
|
||||
-- * La tabla queda reservada para administradores y bloqueos excepcionales.
|
||||
-- ============================================================================
|
||||
|
||||
begin;
|
||||
|
||||
comment on table public.glm_hub_authorized_users is
|
||||
'Excepciones del GLM Hub: administradores activos y usuarios bloqueados. Los usuarios corporativos normales no requieren registro.';
|
||||
|
||||
-- Cada usuario puede consultar únicamente su propia excepción. Una respuesta
|
||||
-- vacía significa que es un Usuario normal del dominio corporativo.
|
||||
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 their own control record"
|
||||
on public.glm_hub_authorized_users
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
email = lower(coalesce((select auth.jwt() ->> 'email'), ''))
|
||||
);
|
||||
|
||||
-- La ausencia de registro significa acceso normal como Usuario.
|
||||
create or replace function public.glm_hub_is_active_user()
|
||||
returns boolean
|
||||
language plpgsql
|
||||
stable
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
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;
|
||||
$$;
|
||||
|
||||
-- Solo una fila activa con role = admin concede funciones administrativas.
|
||||
create or replace function public.glm_hub_is_admin()
|
||||
returns boolean
|
||||
language plpgsql
|
||||
stable
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
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;
|
||||
|
||||
revoke all on function public.glm_hub_is_active_user() from public, anon;
|
||||
revoke all on function public.glm_hub_is_admin() from public, anon;
|
||||
grant execute on function public.glm_hub_is_active_user() to authenticated;
|
||||
grant execute on function public.glm_hub_is_admin() to authenticated;
|
||||
grant execute on function public.glm_hub_is_active_user() to service_role;
|
||||
grant execute on function public.glm_hub_is_admin() to service_role;
|
||||
|
||||
-- Limpia registros normales antiguos. Se conservan administradores y bloqueos.
|
||||
delete from public.glm_hub_authorized_users
|
||||
where role = 'member'
|
||||
and is_active = true;
|
||||
|
||||
notify pgrst, 'reload schema';
|
||||
|
||||
commit;
|
||||
|
||||
-- VERIFICACIÓN OPCIONAL:
|
||||
-- select public.glm_hub_is_active_user() as puede_entrar,
|
||||
-- public.glm_hub_is_admin() as es_administrador;
|
||||
+11
-11
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -9,7 +9,7 @@
|
||||
<link rel="shortcut icon" type="image/png" href="https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM.png?v=glm-hub-20260722-v3" />
|
||||
<link rel="apple-touch-icon" href="https://dbit.digitalcompass.agency/storage/v1/object/public/public-assets/GLM.png?v=glm-hub-20260722-v3" />
|
||||
<title>GLM Hub — GomezLee Marketing</title>
|
||||
<script type="module" crossorigin src="/assets/index-_vT1KbDN.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-Kd6NFVcJ.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-9ByAKvcq.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
+8
-2
@@ -139,12 +139,18 @@ async function authorizeSupabaseSession(authSession: SupabaseAuthSession): Promi
|
||||
|
||||
// Todos los correos corporativos entran como Usuario por defecto.
|
||||
// La tabla solo conserva administradores y bloqueos excepcionales.
|
||||
// Se consulta como una lista limitada a una fila en lugar de usar
|
||||
// `maybeSingle()`. En algunas instalaciones self-hosted de PostgREST, una
|
||||
// consulta sin coincidencias puede responder como error al solicitar un
|
||||
// objeto único. Una lista vacía, en cambio, representa correctamente a un
|
||||
// usuario corporativo normal que no necesita registro en la tabla.
|
||||
const { data, error } = await supabase
|
||||
.from("glm_hub_authorized_users")
|
||||
.select("email, full_name, role, is_active")
|
||||
.eq("email", email)
|
||||
.maybeSingle();
|
||||
const access = data as AuthorizedUserRow | null;
|
||||
.limit(1);
|
||||
const accessRows = (data ?? []) as AuthorizedUserRow[];
|
||||
const access = accessRows[0] ?? null;
|
||||
|
||||
if (error) {
|
||||
console.error("No se pudo validar el perfil de acceso:", error);
|
||||
|
||||
Reference in New Issue
Block a user