fix: Actualizar con branding de GLM y restringir acceso con Supabase.
This commit is contained in:
@@ -1,14 +1,243 @@
|
||||
-- =========================================================
|
||||
-- TABLERO CDC - Visibilidad del Total Tarifado
|
||||
-- Ejecutar en Supabase SQL Editor antes de desplegar esta versión.
|
||||
-- TABLERO CDC - Acceso autorizado por Supabase
|
||||
-- Ejecutar en Supabase SQL Editor ANTES de desplegar el ZIP.
|
||||
--
|
||||
-- Objetivo:
|
||||
-- - Por defecto, el Total Tarifado solo lo ven:
|
||||
-- * gmarrero@gomezleemarketing.com
|
||||
-- * jgomez@gomezleemarketing.com
|
||||
-- * iaracena@gomezleemarketing.com
|
||||
-- - Ellos pueden activar/desactivar un botón para mostrarlo temporalmente a todos.
|
||||
-- - No expone montos internos por proyecto; solo habilita/oculta el resumen global/filtrado.
|
||||
-- - El acceso a la app ya no depende de una lista fija en código.
|
||||
-- - Los usuarios permitidos viven en public.tablero_cdc_allowed_users.
|
||||
-- - Para agregar/quitar acceso luego, se actualiza esta tabla en Supabase.
|
||||
-- - También centraliza permisos especiales usados por la app:
|
||||
-- * can_manage_internal_pricing
|
||||
-- * can_delete_projects
|
||||
-- * can_control_pricing_summary
|
||||
-- =========================================================
|
||||
|
||||
begin;
|
||||
|
||||
create table if not exists public.tablero_cdc_allowed_users (
|
||||
email text primary key,
|
||||
full_name text,
|
||||
role text not null default 'user',
|
||||
is_active boolean not null default true,
|
||||
can_delete_projects boolean not null default false,
|
||||
can_manage_internal_pricing boolean not null default false,
|
||||
can_control_pricing_summary boolean not null default false,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
comment on table public.tablero_cdc_allowed_users is
|
||||
'Lista central de usuarios autorizados para entrar al Tablero CDC.';
|
||||
|
||||
comment on column public.tablero_cdc_allowed_users.role is
|
||||
'Rol lógico de la app. director_creativo habilita comportamiento especial de Director Creativo.';
|
||||
|
||||
create or replace function public.set_tablero_cdc_allowed_users_updated_at()
|
||||
returns trigger
|
||||
language plpgsql
|
||||
as $$
|
||||
begin
|
||||
new.email = lower(trim(new.email));
|
||||
new.updated_at = now();
|
||||
return new;
|
||||
end;
|
||||
$$;
|
||||
|
||||
drop trigger if exists trg_tablero_cdc_allowed_users_updated_at on public.tablero_cdc_allowed_users;
|
||||
|
||||
create trigger trg_tablero_cdc_allowed_users_updated_at
|
||||
before insert or update on public.tablero_cdc_allowed_users
|
||||
for each row
|
||||
execute function public.set_tablero_cdc_allowed_users_updated_at();
|
||||
|
||||
-- Usuarios autorizados iniciales.
|
||||
-- Nota: Re-ejecutar este SQL mantiene estos usuarios activos y actualiza sus permisos base.
|
||||
insert into public.tablero_cdc_allowed_users (
|
||||
email,
|
||||
full_name,
|
||||
role,
|
||||
is_active,
|
||||
can_delete_projects,
|
||||
can_manage_internal_pricing,
|
||||
can_control_pricing_summary
|
||||
)
|
||||
values
|
||||
(
|
||||
'iaracena@gomezleemarketing.com',
|
||||
'Isaac Daniel Aracena Toribio',
|
||||
'admin_it',
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
),
|
||||
(
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'José Leopoldo Gomez',
|
||||
'leadership',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
),
|
||||
(
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'Gerardo Marrero',
|
||||
'director_creativo',
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
),
|
||||
(
|
||||
'areyes@gomezleemarketing.com',
|
||||
'Alicia Thaía Reyes',
|
||||
'user',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'boliva@gomezleemarketing.com',
|
||||
'Bonnie Oliva',
|
||||
'user',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'obrisceno@gomezleemarketing.com',
|
||||
'Oscar Brisceño',
|
||||
'user',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'lavila01@gomezlee.marketing',
|
||||
'Lady Avila Faura',
|
||||
'user',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'rmarcano@gomezleemarketing.com',
|
||||
'Ramon Marcano',
|
||||
'user',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'lmatos@gomezleemarketing.com',
|
||||
'Luis Matos',
|
||||
'it',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
),
|
||||
(
|
||||
'mgomez@gomezleemarketing.com',
|
||||
'Máximo Gomez',
|
||||
'leadership',
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
)
|
||||
on conflict (email)
|
||||
do update set
|
||||
full_name = excluded.full_name,
|
||||
role = excluded.role,
|
||||
is_active = excluded.is_active,
|
||||
can_delete_projects = excluded.can_delete_projects,
|
||||
can_manage_internal_pricing = excluded.can_manage_internal_pricing,
|
||||
can_control_pricing_summary = excluded.can_control_pricing_summary,
|
||||
updated_at = now();
|
||||
|
||||
alter table public.tablero_cdc_allowed_users enable row level security;
|
||||
|
||||
drop policy if exists "tablero_cdc_allowed_users_select_own_active" on public.tablero_cdc_allowed_users;
|
||||
drop policy if exists "tablero_cdc_allowed_users_no_insert_from_app" on public.tablero_cdc_allowed_users;
|
||||
drop policy if exists "tablero_cdc_allowed_users_no_update_from_app" on public.tablero_cdc_allowed_users;
|
||||
drop policy if exists "tablero_cdc_allowed_users_no_delete_from_app" on public.tablero_cdc_allowed_users;
|
||||
|
||||
-- La app solo puede leer la fila activa del usuario autenticado.
|
||||
-- La administración real se hace desde Supabase SQL Editor.
|
||||
create policy "tablero_cdc_allowed_users_select_own_active"
|
||||
on public.tablero_cdc_allowed_users
|
||||
for select
|
||||
to authenticated
|
||||
using (
|
||||
is_active = true
|
||||
and lower(email) = lower(coalesce(auth.jwt() ->> 'email', ''))
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_allowed_users_no_insert_from_app"
|
||||
on public.tablero_cdc_allowed_users
|
||||
for insert
|
||||
to authenticated
|
||||
with check (false);
|
||||
|
||||
create policy "tablero_cdc_allowed_users_no_update_from_app"
|
||||
on public.tablero_cdc_allowed_users
|
||||
for update
|
||||
to authenticated
|
||||
using (false)
|
||||
with check (false);
|
||||
|
||||
create policy "tablero_cdc_allowed_users_no_delete_from_app"
|
||||
on public.tablero_cdc_allowed_users
|
||||
for delete
|
||||
to authenticated
|
||||
using (false);
|
||||
|
||||
grant select on public.tablero_cdc_allowed_users to authenticated;
|
||||
|
||||
-- Funciones auxiliares para políticas/RPC.
|
||||
create or replace function public.tablero_cdc_current_user_is_allowed()
|
||||
returns boolean
|
||||
language sql
|
||||
stable
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where u.email = lower(coalesce(auth.jwt() ->> 'email', ''))
|
||||
and u.is_active = true
|
||||
);
|
||||
$$;
|
||||
|
||||
create or replace function public.tablero_cdc_current_user_can_control_pricing_summary()
|
||||
returns boolean
|
||||
language sql
|
||||
stable
|
||||
security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
select exists (
|
||||
select 1
|
||||
from public.tablero_cdc_allowed_users u
|
||||
where u.email = lower(coalesce(auth.jwt() ->> 'email', ''))
|
||||
and u.is_active = true
|
||||
and u.can_control_pricing_summary = true
|
||||
);
|
||||
$$;
|
||||
|
||||
grant execute on function public.tablero_cdc_current_user_is_allowed() to authenticated;
|
||||
grant execute on function public.tablero_cdc_current_user_can_control_pricing_summary() to authenticated;
|
||||
|
||||
-- =========================================================
|
||||
-- Total Tarifado: configuración pública/privada usando tabla de accesos
|
||||
-- =========================================================
|
||||
|
||||
create table if not exists public.tablero_cdc_app_settings (
|
||||
@@ -25,15 +254,16 @@ on conflict (key) do nothing;
|
||||
alter table public.tablero_cdc_app_settings enable row level security;
|
||||
|
||||
drop policy if exists "tablero_cdc_app_settings_select_authenticated" on public.tablero_cdc_app_settings;
|
||||
drop policy if exists "tablero_cdc_app_settings_select_allowed_users" on public.tablero_cdc_app_settings;
|
||||
drop policy if exists "tablero_cdc_app_settings_insert_summary_controllers" on public.tablero_cdc_app_settings;
|
||||
drop policy if exists "tablero_cdc_app_settings_update_summary_controllers" on public.tablero_cdc_app_settings;
|
||||
drop policy if exists "tablero_cdc_app_settings_delete_none" on public.tablero_cdc_app_settings;
|
||||
|
||||
create policy "tablero_cdc_app_settings_select_authenticated"
|
||||
create policy "tablero_cdc_app_settings_select_allowed_users"
|
||||
on public.tablero_cdc_app_settings
|
||||
for select
|
||||
to authenticated
|
||||
using (true);
|
||||
using (public.tablero_cdc_current_user_is_allowed());
|
||||
|
||||
create policy "tablero_cdc_app_settings_insert_summary_controllers"
|
||||
on public.tablero_cdc_app_settings
|
||||
@@ -41,11 +271,7 @@ create policy "tablero_cdc_app_settings_insert_summary_controllers"
|
||||
to authenticated
|
||||
with check (
|
||||
key = 'pricing_summary_public'
|
||||
and lower(coalesce(auth.jwt() ->> 'email', '')) in (
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'iaracena@gomezleemarketing.com'
|
||||
)
|
||||
and public.tablero_cdc_current_user_can_control_pricing_summary()
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_app_settings_update_summary_controllers"
|
||||
@@ -54,19 +280,11 @@ create policy "tablero_cdc_app_settings_update_summary_controllers"
|
||||
to authenticated
|
||||
using (
|
||||
key = 'pricing_summary_public'
|
||||
and lower(coalesce(auth.jwt() ->> 'email', '')) in (
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'iaracena@gomezleemarketing.com'
|
||||
)
|
||||
and public.tablero_cdc_current_user_can_control_pricing_summary()
|
||||
)
|
||||
with check (
|
||||
key = 'pricing_summary_public'
|
||||
and lower(coalesce(auth.jwt() ->> 'email', '')) in (
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'iaracena@gomezleemarketing.com'
|
||||
)
|
||||
and public.tablero_cdc_current_user_can_control_pricing_summary()
|
||||
);
|
||||
|
||||
create policy "tablero_cdc_app_settings_delete_none"
|
||||
@@ -93,6 +311,8 @@ before insert or update on public.tablero_cdc_app_settings
|
||||
for each row
|
||||
execute function public.set_tablero_cdc_app_settings_updated_at();
|
||||
|
||||
grant select on public.tablero_cdc_app_settings to authenticated;
|
||||
|
||||
create or replace function public.tablero_cdc_set_pricing_summary_public(p_enabled boolean)
|
||||
returns jsonb
|
||||
language plpgsql
|
||||
@@ -100,14 +320,9 @@ security definer
|
||||
set search_path = public
|
||||
as $$
|
||||
declare
|
||||
v_email text := lower(coalesce(auth.jwt() ->> 'email', ''));
|
||||
v_enabled boolean := coalesce(p_enabled, false);
|
||||
begin
|
||||
if v_email not in (
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'iaracena@gomezleemarketing.com'
|
||||
) then
|
||||
if not public.tablero_cdc_current_user_can_control_pricing_summary() then
|
||||
raise exception 'No tienes permiso para cambiar la visibilidad del total tarifado.';
|
||||
end if;
|
||||
|
||||
@@ -128,10 +343,11 @@ begin
|
||||
end;
|
||||
$$;
|
||||
|
||||
grant select on public.tablero_cdc_app_settings to authenticated;
|
||||
grant execute on function public.tablero_cdc_set_pricing_summary_public(boolean) to authenticated;
|
||||
|
||||
-- Reemplaza la RPC de resumen para respetar visibilidad pública temporal.
|
||||
-- Reemplaza la RPC de resumen para respetar:
|
||||
-- 1) que el usuario esté autorizado para la app;
|
||||
-- 2) que sea controlador del Total Tarifado o que el total esté público.
|
||||
create or replace function public.tablero_cdc_get_pricing_summary(
|
||||
p_tab text default 'todos',
|
||||
p_search text default '',
|
||||
@@ -153,12 +369,11 @@ as $$
|
||||
),
|
||||
allowed as (
|
||||
select
|
||||
lower(coalesce(auth.jwt() ->> 'email', '')) in (
|
||||
'gmarrero@gomezleemarketing.com',
|
||||
'jgomez@gomezleemarketing.com',
|
||||
'iaracena@gomezleemarketing.com'
|
||||
)
|
||||
or coalesce((select is_public from visibility), false) as can_view_pricing
|
||||
public.tablero_cdc_current_user_is_allowed()
|
||||
and (
|
||||
public.tablero_cdc_current_user_can_control_pricing_summary()
|
||||
or coalesce((select is_public from visibility), false)
|
||||
) as can_view_pricing
|
||||
),
|
||||
params as (
|
||||
select
|
||||
@@ -234,7 +449,6 @@ $$;
|
||||
grant execute on function public.tablero_cdc_get_pricing_summary(text, text, text, text, text, text) to authenticated;
|
||||
|
||||
-- Intenta habilitar realtime para que el cambio de visible/oculto se refleje sin recargar.
|
||||
-- Si la publicación ya existe o la tabla ya está agregada, no hace nada.
|
||||
do $$
|
||||
begin
|
||||
alter publication supabase_realtime add table public.tablero_cdc_app_settings;
|
||||
@@ -243,6 +457,12 @@ exception
|
||||
when undefined_object then null;
|
||||
end $$;
|
||||
|
||||
commit;
|
||||
|
||||
select
|
||||
'Visibilidad del Total Tarifado lista' as status,
|
||||
(select value from public.tablero_cdc_app_settings where key = 'pricing_summary_public') as pricing_summary_public;
|
||||
'Acceso Tablero CDC listo' as status,
|
||||
count(*) filter (where is_active) as usuarios_activos,
|
||||
count(*) filter (where can_control_pricing_summary and is_active) as controlan_total_tarifado,
|
||||
count(*) filter (where can_manage_internal_pricing and is_active) as ven_interno_cargado,
|
||||
count(*) filter (where can_delete_projects and is_active) as pueden_eliminar
|
||||
from public.tablero_cdc_allowed_users;
|
||||
|
||||
Reference in New Issue
Block a user