feat: habilitar acceso automático al Hub por dominio
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
-- ============================================================================
|
||||
-- GLM HUB — MIGRACIÓN: ACCESO AUTOMÁTICO POR DOMINIO
|
||||
-- ============================================================================
|
||||
-- Ejecutar una sola vez sobre la base existente.
|
||||
-- Resultado:
|
||||
-- * Todo correo @gomezleemarketing.com entra automáticamente como Usuario.
|
||||
-- * glm_hub_authorized_users conserva solo administradores y bloqueos.
|
||||
-- * Los permisos internos de cada aplicación continúan fuera del Hub.
|
||||
-- ============================================================================
|
||||
|
||||
begin;
|
||||
|
||||
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.';
|
||||
|
||||
-- Permite que cada persona consulte únicamente su propia excepción, incluyendo
|
||||
-- un posible bloqueo con is_active = false.
|
||||
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'), ''))
|
||||
);
|
||||
|
||||
-- Garantiza los cinco administradores definidos.
|
||||
insert into public.glm_hub_authorized_users (email, full_name, role, is_active)
|
||||
values
|
||||
('jgomez@gomezleemarketing.com', 'José Leopoldo Gómez', 'admin', true),
|
||||
('iaracena@gomezleemarketing.com', 'Isaac Aracena', 'admin', true),
|
||||
('ethen@gomezleemarketing.com', 'Eidan Then', 'admin', true),
|
||||
('mgomez@gomezleemarketing.com', 'Máximo Gomez', 'admin', true),
|
||||
('lmatos@gomezleemarketing.com', 'Luis Matos', 'admin', true)
|
||||
on conflict (email) do update
|
||||
set
|
||||
full_name = excluded.full_name,
|
||||
role = excluded.role,
|
||||
is_active = true,
|
||||
updated_at = now();
|
||||
|
||||
-- Los usuarios normales ya no requieren una fila. Se conservan administradores
|
||||
-- y bloqueos (member con is_active = false).
|
||||
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 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;
|
||||
$$;
|
||||
|
||||
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;
|
||||
|
||||
-- Actualiza la solicitud de acceso para que un usuario corporativo no necesite
|
||||
-- existir previamente en glm_hub_authorized_users.
|
||||
create or replace function public.glm_hub_prepare_access_request(p_app_id uuid)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
volatile
|
||||
security definer
|
||||
set search_path = ''
|
||||
as $$
|
||||
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;
|
||||
begin
|
||||
v_user_id := auth.uid();
|
||||
v_email := lower(coalesce(auth.jwt() ->> 'email', ''));
|
||||
|
||||
if v_user_id is null or v_email = '' then
|
||||
return jsonb_build_object('ok', false, 'error', 'Tu sesión no es válida. Cierra sesión e inicia nuevamente.');
|
||||
end if;
|
||||
|
||||
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
|
||||
limit 1;
|
||||
|
||||
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 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
|
||||
where app.id = p_app_id
|
||||
and app.visibility = 'published'
|
||||
limit 1;
|
||||
|
||||
if not found then
|
||||
return jsonb_build_object('ok', false, 'error', 'La aplicación seleccionada ya no está publicada.');
|
||||
end if;
|
||||
|
||||
if exists (
|
||||
select 1
|
||||
from public.glm_hub_access_requests as request
|
||||
where request.requester_email = v_email
|
||||
and request.app_id = p_app_id
|
||||
and request.status = 'pending'
|
||||
) then
|
||||
return jsonb_build_object(
|
||||
'ok', false,
|
||||
'code', 'PENDING_EXISTS',
|
||||
'error', 'Ya existe una solicitud pendiente para esta aplicación.'
|
||||
);
|
||||
end if;
|
||||
|
||||
insert into public.glm_hub_access_requests (
|
||||
requester_user_id,
|
||||
requester_name,
|
||||
requester_email,
|
||||
app_id,
|
||||
app_name,
|
||||
app_category
|
||||
)
|
||||
values (
|
||||
v_user_id,
|
||||
v_name,
|
||||
v_email,
|
||||
p_app_id,
|
||||
v_app_name,
|
||||
v_app_category
|
||||
)
|
||||
returning id into v_request_id;
|
||||
|
||||
return jsonb_build_object(
|
||||
'ok', true,
|
||||
'requestId', v_request_id,
|
||||
'requesterName', v_name,
|
||||
'requesterEmail', v_email,
|
||||
'appName', v_app_name,
|
||||
'appCategory', v_app_category
|
||||
);
|
||||
end;
|
||||
$$;
|
||||
|
||||
alter function public.glm_hub_prepare_access_request(uuid) owner to postgres;
|
||||
revoke all on function public.glm_hub_prepare_access_request(uuid) from public, anon;
|
||||
grant execute on function public.glm_hub_prepare_access_request(uuid) to authenticated;
|
||||
grant execute on function public.glm_hub_prepare_access_request(uuid) to service_role;
|
||||
|
||||
notify pgrst, 'reload schema';
|
||||
|
||||
commit;
|
||||
|
||||
-- ==========================================================================
|
||||
-- OPERACIONES FUTURAS
|
||||
-- ==========================================================================
|
||||
|
||||
-- HACER ADMINISTRADOR:
|
||||
-- insert into public.glm_hub_authorized_users (email, full_name, role, is_active)
|
||||
-- values ('usuario@gomezleemarketing.com', 'Nombre del usuario', 'admin', true)
|
||||
-- on conflict (email) do update
|
||||
-- set full_name = excluded.full_name, role = 'admin', is_active = true, updated_at = now();
|
||||
|
||||
-- DEVOLVER A USUARIO NORMAL:
|
||||
-- delete from public.glm_hub_authorized_users
|
||||
-- where email = 'usuario@gomezleemarketing.com';
|
||||
|
||||
-- BLOQUEAR USUARIO:
|
||||
-- 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 USUARIO:
|
||||
-- delete from public.glm_hub_authorized_users
|
||||
-- where email = 'usuario@gomezleemarketing.com'
|
||||
-- and role = 'member';
|
||||
Reference in New Issue
Block a user