Row Security- Integridad referencial

From: Victor Hugo Roumieu <vhr273(at)gmail(dot)com>
To: POSTGRES <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Row Security- Integridad referencial
Date: 2016-11-03 15:18:12
Message-ID: CAPrQUT7NjbBYv4qkFCOCuBzVVXqPoXHsw=5-4B1cSDg3PTY58Q@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Muy buenos dias a todos.
Me pude dar un tiempo y me dedique a investigar el tema de referencia (Row
Security) llevo en ello ya dos días y pido disculpas si lo que pregunto es
muy obvio.

No encuentro como propagar la seguridad en integridad referencial.

Esto es: Si defino una regla de seguridad a nivel registro, quiero que los
detalles en otras tablas que hacen referencia, tambien hereden la
visibilidad definida en la regla.

Asi como logré hacerlo andar debo en todas las tablas definir las reglas, y
si en un detalle que apunta a una cabecera no lo hiciera, el usuario
logeado veria el detalle que tiene un ID en el campo del FK que apunta a
una tupla que para él no existe.

Esta es la prueba y como pude lograr lo que queria, aun cuando no es lo
automático que pretendo:

create schema aux;

create table aux.empresas (
id serial not null primary key,
descripcion text
);

create table aux.cabeceras (
id serial not null primary key,
descripcion text
);

create table aux.detalles (
id serial not null primary key,
cabera integer references aux.cabeceras(id),
descripcion text
)

create table aux.empresas_usos_datos (
esquema text,
tabla text,
id integer,
empresa integer references aux.empresas(id),
primary key (esquema, tabla, id, empresa)
)

create table aux.empresas_usuarios (
empresa integer references aux.empresas(id),
usuario text,
primary key (empresa,usuario)
)

grant all on aux.empresas_usos_datos to administracion;
grant all on aux.empresas_usuarios to administracion;

insert into aux.empresas (descripcion) values ('Empresa 1');
insert into aux.empresas (descripcion) values ('Empresa 2');

insert into aux.empresas_usuarios (empresa,usuario) values (1,'vhr');
insert into aux.empresas_usuarios (empresa,usuario) values (2,'sofy');

CREATE OR REPLACE FUNCTION aux.vinculo_tupla_con_empresa()
RETURNS trigger AS
$BODY$
declare

v_old_data TEXT;
v_new_data TEXT;
v_c integer;
r_cursor record;
id1 integer;

BEGIN
BEGIN
v_c := NEW.ID;
EXCEPTION
WHEN OTHERS THEN
BEGIN
v_c := NEW.GID;
EXCEPTION
WHEN OTHERS THEN
v_c := -1;
END;
END;

IF (TG_OP = 'DELETE') THEN
for id1 in (select distinct u1.empresa from aux.empresas_usuarios
u1 where u1.usuario = session_user::TEXT ) loop
RAISE NOTICE 'Ejecutado borrado % % % % % %',id1,
v_c,session_user, TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT, now();
delete from aux.empresas_usos_datos where
esquema=TG_TABLE_SCHEMA::TEXT and tabla=TG_TABLE_NAME::TEXT and id=v_c and
empresa= id1;
end loop;
RETURN NEW;
ELSIF (TG_OP = 'INSERT') THEN
for id1 in (select distinct u1.empresa from aux.empresas_usuarios
u1 where u1.usuario = session_user::TEXT ) loop
RAISE NOTICE 'Ejecutado % % % % % %',id1,
v_c,user,session_user, current_user, now();
insert into aux.empresas_usos_datos (empresa,esquema,tabla,id )
values (id1, TG_TABLE_SCHEMA::TEXT,TG_TABLE_NAME::TEXT,v_c);
end loop;
RETURN NEW;
END IF;

EXCEPTION
WHEN data_exception THEN
RAISE WARNING '[aux.vinculo_tupla_con_empresa] - ERROR [DATA
EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN unique_violation THEN
RAISE WARNING '[aux.vinculo_tupla_con_empresa] - ERROR [UNIQUE] -
SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN OTHERS THEN
RAISE WARNING '[aux.vinculo_tupla_con_empresa] - ERROR [OTHER] -
SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;

CREATE OR REPLACE FUNCTION aux.verifico_tupla_con_empresa(esquema_r
text,tabla_r text, id_r integer)
RETURNS boolean AS
$BODY$
declare

v_c integer;
r_cursor record;
id1 integer;

BEGIN
--RAISE NOTICE 'Ejecutado % % % %
%',id_r,esquema_r,tabla_r,session_user, now();
select 1 from aux.empresas_usos_datos u1 into id1
where u1.id = id_r and u1.esquema = esquema_r and u1.tabla =
tabla_r and exists (select 1 from aux.empresas_usuarios eu where eu.usuario
= session_user and eu.empresa = u1.empresa);
if (id1 = 1) then
return true;
else
return false;
end if;

EXCEPTION
WHEN data_exception THEN
RAISE WARNING '[aux.verifico_tupla_con_empresa] - ERROR [DATA
EXCEPTION] - SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN unique_violation THEN
RAISE WARNING '[aux.verifico_tupla_con_empresa] - ERROR [UNIQUE] -
SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
WHEN OTHERS THEN
RAISE WARNING '[aux.verifico_tupla_con_empresa] - ERROR [OTHER] -
SQLSTATE: %, SQLERRM: %',SQLSTATE,SQLERRM;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;

grant all on aux.verifico_tupla_con_empresa(

CREATE TRIGGER cabeceras_trg
after INSERT OR DELETE
ON aux.cabeceras
FOR EACH ROW
EXECUTE PROCEDURE aux.vinculo_tupla_con_empresa();

CREATE TRIGGER detalles_trg
after INSERT OR DELETE
ON aux.detalles
FOR EACH ROW
EXECUTE PROCEDURE aux.vinculo_tupla_con_empresa();

GRANT ALL ON SCHEMA aux TO administracion;
grant all on aux.cabeceras to administracion;
GRANT ALL ON aux.cabeceras_id_seq TO administracion;
grant all on aux.detalles to administracion;
GRANT ALL ON aux.detalles_id_seq TO administracion;

ALTER TABLE aux.cabeceras ENABLE ROW LEVEL SECURITY;

DROP POLICY cabeceras_administracion ON aux.cabeceras;

CREATE POLICY cabeceras_administracion ON aux.cabeceras TO administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','cabeceras', id)
);

drop POLICY cabeceras_select_administracion ON aux.cabeceras;

CREATE POLICY cabeceras_select_administracion ON aux.cabeceras for select
TO administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','cabeceras', id)
);

drop POLICY cabeceras_insert_administracion ON aux.cabeceras;
CREATE POLICY cabeceras_insert_administracion ON aux.cabeceras for INSERT
TO administracion
WITH CHECK (true);

DROP POLICY cabeceras_update_administracion ON aux.cabeceras
CREATE POLICY cabeceras_update_administracion ON aux.cabeceras for update
TO administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','cabeceras', id)
);

ALTER TABLE aux.detalles ENABLE ROW LEVEL SECURITY;

DROP POLICY detalles_administracion ON aux.detalles;

CREATE POLICY detalles_administracion ON aux.detalles TO administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','detalles', id)
);

drop POLICY detalles_select_administracion ON aux.detalles;

CREATE POLICY detalles_select_administracion ON aux.detalles for select TO
administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','detalles', id)
);

drop POLICY detalles_insert_administracion ON aux.detalles;
CREATE POLICY detalles_insert_administracion ON aux.detalles for INSERT TO
administracion
WITH CHECK (true);

DROP POLICY detalles_update_administracion ON aux.detalles
CREATE POLICY detalles_update_administracion ON aux.detalles for update TO
administracion
USING ( aux.verifico_tupla_con_empresa( 'aux','detalles', id)
);

select * from aux.detalles

delete from aux.empresas_usos_datos
where id < 19

table aux.empresas_usos_datos
table aux.empresas_usuarios

delete from aux.cabeceras
where id > 0

SET SESSION AUTHORIZATION vhr;

insert into aux.cabeceras(descripcion) values ('Intento con usuario:
'||session_user||' '||now()::text);
insert into aux.detalles (cabera,descripcion) select b.id,'renglon 1 de
'||b.descripcion from aux.cabeceras b

select * from aux.cabeceras
select * from aux.detalles

SET SESSION AUTHORIZATION sofy;

select * from aux.cabeceras
select * from aux.detalles

insert into aux.cabeceras(descripcion) values ('Intento con usuario:
'||session_user||' '||now()::text);
insert into aux.detalles (cabera,descripcion) select b.id,'renglon 1 de
'||b.descripcion from aux.cabeceras b

La pregunta hay algo automático que resuleva este problema?
O La integridad dependerá de mi prolijidad al definir las reglas de
seguridad?

Desde ya muchas gracias por la ayuda que pudieran darme y nuevamente
disculpas si lo que pregunto es trivial.
Fuerte Abrazo a todos

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Marcelo Diaz 2016-11-03 15:54:16 Re: [pgsql-es-ayuda] Guía para configuración óptima de Postrgesql
Previous Message Francisco Olarte 2016-11-03 11:46:53 Re: Cambio en tipo de columna de varchar por text