Files
cdc-project-management/supabase_tablero_cdc_team_hours_permission.sql
T

176 lines
5.3 KiB
PL/PgSQL

-- ============================================================================
-- TABLERO CDC — PERMISO INDIVIDUAL PARA "HORAS DEL EQUIPO"
-- Migración aditiva y segura.
--
-- Objetivo:
-- 1) Agregar tablero_cdc_allowed_users.can_view_team_hours.
-- 2) Mantener el acceso actual de los usuarios activos existentes la primera vez.
-- 3) Dejar nuevos usuarios SIN este permiso por defecto.
-- 4) Proteger los RPC usados por el módulo Horas del equipo.
--
-- No modifica proyectos, horas, histórico, métricas, tarifarios, listas ni briefs.
-- ============================================================================
begin;
-- Se ejecuta de forma idempotente. Solo en la PRIMERA instalación del permiso
-- se conserva el comportamiento actual dando acceso a los usuarios activos existentes.
do $$
declare
permission_was_missing boolean;
begin
select not exists (
select 1
from information_schema.columns
where table_schema = 'public'
and table_name = 'tablero_cdc_allowed_users'
and column_name = 'can_view_team_hours'
) into permission_was_missing;
if permission_was_missing then
alter table public.tablero_cdc_allowed_users
add column can_view_team_hours boolean not null default false;
update public.tablero_cdc_allowed_users
set can_view_team_hours = true,
updated_at = now()
where is_active = true;
end if;
end
$$;
comment on column public.tablero_cdc_allowed_users.can_view_team_hours is
'Controla si el usuario puede ver y consultar el módulo Horas del equipo. Los usuarios nuevos quedan sin acceso hasta que se les habilite explícitamente.';
-- Función central de permiso. Se usa desde el frontend y desde los RPC de datos.
create or replace function public.tablero_cdc_current_user_can_view_team_hours()
returns boolean
language sql
stable
security definer
set search_path = public
as $$
select exists (
select 1
from public.tablero_cdc_allowed_users u
where lower(trim(u.email)) = lower(trim(coalesce(auth.jwt() ->> 'email', '')))
and u.is_active = true
and u.can_view_team_hours = true
);
$$;
revoke all on function public.tablero_cdc_current_user_can_view_team_hours() from public;
grant execute on function public.tablero_cdc_current_user_can_view_team_hours() to authenticated;
-- Roster de equipo: solo usuarios con el permiso pueden consultarlo.
create or replace function public.tablero_cdc_get_team_hours_roster()
returns table (
email text,
full_name text
)
language plpgsql
stable
security definer
set search_path = public
as $$
begin
if not public.tablero_cdc_current_user_can_view_team_hours() then
raise exception 'No autorizado';
end if;
return query
select
lower(trim(u.email)) as email,
coalesce(nullif(trim(u.full_name), ''), lower(trim(u.email))) as full_name
from public.tablero_cdc_allowed_users u
where u.is_active = true
order by coalesce(nullif(trim(u.full_name), ''), lower(trim(u.email)));
end;
$$;
revoke all on function public.tablero_cdc_get_team_hours_roster() from public;
grant execute on function public.tablero_cdc_get_team_hours_roster() to authenticated;
-- Lectura paginada de horas actuales + histórico. El acceso se valida en servidor,
-- de modo que ocultar el botón no sea el único control del módulo.
create or replace function public.tablero_cdc_get_team_hours_records(
p_from date default null,
p_to date default null,
p_limit integer default 1000,
p_offset integer default 0
)
returns table (
id uuid,
record_source text,
source_key text,
work_date date,
project_name text,
client text,
country text,
worked_by_name text,
worked_by_email text,
task_name text,
duration_minutes integer,
notes text
)
language plpgsql
stable
security definer
set search_path = public
as $$
begin
if not public.tablero_cdc_current_user_can_view_team_hours() then
raise exception 'No autorizado';
end if;
return query
select
c.id,
c.record_source,
c.source_key,
c.work_date,
c.project_name,
c.client,
c.country,
c.worked_by_name,
c.worked_by_email,
c.task_name,
c.duration_minutes,
c.notes
from public.tablero_cdc_time_combined c
where (p_from is null or c.work_date >= p_from)
and (p_to is null or c.work_date <= p_to)
order by c.work_date desc, c.id asc
limit least(greatest(coalesce(p_limit, 1000), 1), 1000)
offset greatest(coalesce(p_offset, 0), 0);
end;
$$;
revoke all on function public.tablero_cdc_get_team_hours_records(date, date, integer, integer) from public;
grant execute on function public.tablero_cdc_get_team_hours_records(date, date, integer, integer) to authenticated;
commit;
-- ============================================================================
-- ADMINISTRACIÓN DEL PERMISO
-- ============================================================================
-- Dar acceso:
-- update public.tablero_cdc_allowed_users
-- set can_view_team_hours = true, updated_at = now()
-- where lower(email) = lower('correo@gomezleemarketing.com');
--
-- Quitar acceso:
-- update public.tablero_cdc_allowed_users
-- set can_view_team_hours = false, updated_at = now()
-- where lower(email) = lower('correo@gomezleemarketing.com');
--
-- Ver estado actual:
select
email,
full_name,
role,
is_active,
can_view_team_hours
from public.tablero_cdc_allowed_users
order by full_name nulls last, email;