create table veil.veil_demo_init_fns() inherits (veil.veil_init_fns); insert into veil.veil_demo_init_fns values ('veil.veil_demo_init', 1); create schema hidden; revoke all on schema hidden from public; create table hidden.privileges ( privilege_id integer not null, privilege_name varchar(80) not null ); alter table hidden.privileges add constraint privilege__pk primary key(privilege_id); create table hidden.roles ( role_id integer not null, role_name varchar(80) not null ); alter table hidden.roles add constraint role__pk primary key(role_id); create table hidden.role_privileges ( role_id integer not null, privilege_id integer not null ); alter table hidden.role_privileges add constraint role_privilege__pk primary key(role_id, privilege_id); alter table hidden.role_privileges add constraint role_privilege__role_fk foreign key(role_id) references hidden.roles(role_id); alter table hidden.role_privileges add constraint role_privilege__priv_fk foreign key(privilege_id) references hidden.privileges(privilege_id); create table hidden.role_roles ( role_id integer not null, has_role_id integer not null ); alter table hidden.role_roles add constraint role_role__pk primary key(role_id, has_role_id); alter table hidden.role_roles add constraint role_role__role_fk foreign key(role_id) references hidden.roles(role_id); alter table hidden.role_roles add constraint role_role__has_role_fk foreign key(has_role_id) references hidden.roles(role_id); create sequence person_id_seq; create table hidden.persons ( person_id integer not null, person_name varchar(80) not null ); alter table hidden.persons add constraint person__pk primary key(person_id); create sequence project_id_seq; create table hidden.projects ( project_id integer not null, project_name varchar(80) not null ); alter table hidden.projects add constraint project__pk primary key(project_id); create table hidden.detail_types ( detail_type_id integer not null, required_privilege_id integer not null, detail_type_name varchar(80) not null ); alter table hidden.detail_types add constraint detail_type__pk primary key(detail_type_id); alter table hidden.detail_types add constraint detail_type__priv_fk foreign key(required_privilege_id) references hidden.privileges(privilege_id); create table hidden.assignments ( project_id integer not null, person_id integer not null, role_id integer not null ); alter table hidden.assignments add constraint assignment__pk primary key(project_id, person_id); alter table hidden.assignments add constraint assignment__project_fk foreign key(project_id) references hidden.projects(project_id); alter table hidden.assignments add constraint assignment__person_fk foreign key(person_id) references hidden.persons(person_id); alter table hidden.assignments add constraint assignment__role_fk foreign key(role_id) references hidden.roles(role_id); create table hidden.person_roles ( person_id integer not null, role_id integer not null ); alter table hidden.person_roles add constraint person_role__pk primary key(person_id, role_id); alter table hidden.person_roles add constraint person_role__person_fk foreign key(person_id) references hidden.persons(person_id); alter table hidden.person_roles add constraint person_role__role_fk foreign key(role_id) references hidden.roles(role_id); create table hidden.project_details ( project_id integer not null, detail_type_id integer not null, value text not null ); alter table hidden.project_details add constraint project_detail__pk primary key(project_id, detail_type_id); alter table hidden.project_details add constraint project_detail__project_fk foreign key(project_id) references hidden.projects(project_id); alter table hidden.project_details add constraint project_detail__detail_fk foreign key(detail_type_id) references hidden.detail_types(detail_type_id); create table hidden.person_details ( person_id integer not null, detail_type_id integer not null, value text not null ); alter table hidden.person_details add constraint person_detail__pk primary key(person_id, detail_type_id); alter table hidden.person_details add constraint person_detail__person_fk foreign key(person_id) references hidden.persons(person_id); alter table hidden.person_details add constraint person_detail__detail_fk foreign key(detail_type_id) references hidden.detail_types(detail_type_id); insert into hidden.privileges (privilege_id, privilege_name) values (10001, 'select_privileges'), (10002, 'insert_privileges'), (10003, 'update_privileges'), (10004, 'delete_privileges'), (10005, 'select_roles'), (10006, 'insert_roles'), (10007, 'update_roles'), (10008, 'delete_roles'), (10009, 'select_role_privileges'), (10010, 'insert_role_privileges'), (10011, 'update_role_privileges'), (10012, 'delete_role_privileges'), (10013, 'select_persons'), (10014, 'insert_persons'), (10015, 'update_persons'), (10016, 'delete_persons'), (10017, 'select_projects'), (10018, 'insert_projects'), (10019, 'update_projects'), (10020, 'delete_projects'), (10021, 'select_detail_types'), (10022, 'insert_detail_types'), (10023, 'update_detail_types'), (10024, 'delete_detail_types'), (10025, 'select_assignments'), (10026, 'insert_assignments'), (10027, 'update_assignments'), (10028, 'delete_assignments'), (10029, 'select_person_roles'), (10030, 'insert_person_roles'), (10031, 'update_person_roles'), (10032, 'delete_person_roles'), (10033, 'select_project_details'), (10034, 'insert_project_details'), (10035, 'update_project_details'), (10036, 'delete_project_details'), (10037, 'select_person_details'), (10038, 'insert_person_details'), (10039, 'update_person_details'), (10040, 'delete_person_details'), (10041, 'select_role_roles'), (10042, 'insert_role_roles'), (10043, 'update_role_roles'), (10044, 'delete_role_roles'), (10100, 'can_connect'), (10150, 'view_basic'), (10151, 'view_personal'), (10152, 'view_personal_secure'), (10153, 'view_project_confidential'); insert into hidden.roles (role_id, role_name) values (11001, 'DBA'), (11002, 'Personal Context'), (11003, 'Employee'), (11004, 'Worker'), (11005, 'Project Manager'), (11006, 'Director'), (11007, 'Manager'); -- DBA can do anything (but is not automatically an employee) insert into hidden.role_privileges (role_id, privilege_id) select 11001, privilege_id from hidden.privileges where privilege_id != 10100; -- Personal Context allows update of personal details insert into hidden.role_privileges (role_id, privilege_id) values (11002, 10013), (11002, 10015), (11002, 10025), (11002, 10029), (11002, 10037), (11002, 10038), (11002, 10039), (11002, 10040), (11002, 10150), (11002, 10151), (11002, 10152); -- Basic Access can see lookup data insert into hidden.role_privileges (role_id, privilege_id) select 11003, privilege_id from hidden.privileges where privilege_name in ('select_privileges', 'select_roles', 'select_role_privileges', 'select_detail_types'); insert into hidden.role_privileges (role_id, privilege_id) select 11003, 10100; -- Workers can modify project info insert into hidden.role_privileges (role_id, privilege_id) select 11004, privilege_id from hidden.privileges where privilege_name like '%project%' and privilege_name not like 'delete%' and privilege_name not like '%confidential'; insert into hidden.role_privileges (role_id, privilege_id) select 11004, 10025; insert into hidden.role_privileges (role_id, privilege_id) select 11004, 10150; -- Project Manager can do anything to project info and can see personal info insert into hidden.role_privileges (role_id, privilege_id) select 11005, privilege_id from hidden.privileges where privilege_name like '%project%' or privilege_name like '%assignment%'; insert into hidden.role_privileges (role_id, privilege_id) select 11005, privilege_id from hidden.privileges where privilege_name like 'select_person%'; insert into hidden.role_privileges (role_id, privilege_id) select 11005, 10150; insert into hidden.role_privileges (role_id, privilege_id) select 11005, 10151; -- Director can do anything except modify personal details insert into hidden.role_privileges (role_id, privilege_id) select 11006, privilege_id from hidden.privileges where privilege_name not like '%person%'; insert into hidden.role_privileges (role_id, privilege_id) select 11006, privilege_id from hidden.privileges where privilege_name like 'select_person%'; insert into hidden.role_privileges (role_id, privilege_id) select 11006, 10014; insert into hidden.role_privileges (role_id, privilege_id) select 11006, 10151; insert into hidden.role_privileges (role_id, privilege_id) select 11006, 10152; -- Manager can see personal info insert into hidden.role_privileges (role_id, privilege_id) select 11007, privilege_id from hidden.privileges where privilege_name like 'select_person%'; insert into hidden.role_privileges (role_id, privilege_id) select 11007, 10150; insert into hidden.role_privileges (role_id, privilege_id) select 11007, 10151; insert into hidden.persons (person_id, person_name) values (1, 'Deb (the DBA)'), (2, 'Pat (the PM)'), (3, 'Derick (the director)'), (4, 'Will (the worker)'), (5, 'Wilma (the worker)'), (6, 'Fred (the fired DBA)'); insert into hidden.person_roles (person_id, role_id) values (1, 11001), (1, 11003), (2, 11003), (2, 11007), (3, 11003), (3, 11006), (4, 11003), (5, 11003), (6, 11001); insert into hidden.projects (project_id, project_name) values (101, 'Secret Project'), (102, 'Public project'); insert into hidden.assignments (project_id, person_id, role_id) values (101, 3, 11005), (101, 5, 11004), (102, 2, 11005), (102, 4, 11004), (102, 5, 11004); insert into hidden.detail_types (detail_type_id, required_privilege_id, detail_type_name) values (1001, 10150, 'start_date'), (1002, 10150, 'status'), (1003, 10150, 'join_date'), (1004, 10152, 'salary'), (1005, 10151, 'date of birth'), (1006, 10152, 'sin'), (1007, 10150, 'skills'), (1008, 10153, 'contract value'); insert into hidden.person_details (person_id, detail_type_id, value) values (1, 1003, '20050102'), (2, 1003, '20050103'), (3, 1003, '20050104'), (4, 1003, '20050105'), (5, 1003, '20050106'), (6, 1003, '20050107'), (1, 1002, 'Employee'), (2, 1002, 'Employee'), (3, 1002, 'Employee'), (4, 1002, 'Employee'), (5, 1002, 'Employee'), (6, 1002, 'Terminated'), (1, 1004, '50,000'), (2, 1004, '50,000'), (3, 1004, '80,000'), (4, 1004, '30,000'), (5, 1004, '30,000'), (6, 1004, '40,000'), (1, 1005, '19610102'), (2, 1005, '19600102'), (3, 1005, '19650102'), (4, 1005, '19660102'), (5, 1005, '19670102'), (1, 1006, '123456789'), (2, 1006, '123456789'), (3, 1006, '123456789'), (4, 1006, '123456789'), (5, 1006, '123456789'), (1, 1007, 'Oracle, C, SQL'), (2, 1007, 'Soft peoply-stuff'), (3, 1007, 'None at all'), (4, 1007, 'Subservience'), (5, 1007, 'Subservience'); insert into hidden.project_details (project_id, detail_type_id, value) values (101, 1001, '20050101'), (101, 1002, 'Secretly ongoing'), (101, 1008, '$800,000'), (102, 1001, '20050101'), (102, 1002, 'Ongoing'), (102, 1008, '$100,000'); -- Veil Variables: -- Shared: -- privs_range Range The range of privilege_id in the privileges table -- roles_range Range The range of role_id in the roles table -- role_privs Bitmap Array Array of privilege bitmaps indexed by role_id -- det_types_range Range The range of detail_type_id in detail_types -- det_types_privs Int4Array Mapping of detail_type_id to the privilege -- required to access details of that type -- -- Session: -- person_id Int4 The id of the currently connected person -- global_context Bitmap The global privileges of the connected person -- project_context Bitmap Hash Hash of privilege bitmaps, indexed by -- project_id, giving the connected person's project privileges. -- -- Security Contexts: -- Global -- Privileges are identified in variable global_context -- Personal -- Privileges are identified in role_privs[11002]. -- Project -- A relational context. Privileges are identified in -- project_context[project_id]. -- Replacement for default version of veil_init. -- Initialise and load all shared variables. -- create or replace function veil.veil_demo_init(doing_reset bool) returns bool as ' declare exists_privs_range bool; exists_roles_range bool; exists_role_privs bool; exists_det_types_range bool; exists_det_types_privs bool; init_reqd bool; dummy bool; dummy2 bool; dummyint int4; _count int4; begin -- Declare all shared variables. select into exists_privs_range, exists_roles_range, exists_role_privs, exists_det_types_range, exists_det_types_privs veil.share(''privs_range''), veil.share(''roles_range''), veil.share(''role_privs''), veil.share(''det_types_range''), veil.share(''det_types_privs''); init_reqd = not (exists_privs_range and exists_role_privs and exists_role_privs and exists_det_types_range and exists_det_types_privs); if init_reqd or doing_reset then -- Load ranges for privs and roles. select into dummyint veil.init_range(''roles_range'', min(role_id), max(role_id)) from hidden.roles; select into dummyint veil.init_range(''privs_range'', min(privilege_id), max(privilege_id)) from hidden.privileges; -- Load range for detail_types select into dummyint veil.init_range(''det_types_range'', min(detail_type_id), max(detail_type_id)) from hidden.detail_types; -- Initialise array of required privs for detail_types select into dummy veil.init_int4array(''det_types_privs'', ''det_types_range''); select into _count count(veil.int4array_set(''det_types_privs'', detail_type_id, required_privilege_id)) from hidden.detail_types; -- Initialise role_privs bitmap_array select into dummy veil.init_bitmap_array(''role_privs'', ''roles_range'', ''privs_range''); -- Populate role_privs bitmap_array select into _count count(veil.bitmap_array_setbit(''role_privs'', role_id, privilege_id)) from hidden.role_privileges; end if; -- Declare important session variables, so that we do not -- get odd, undefined variable, error messages. select into dummyint, dummy, dummy2 veil.int4_set(''person_id'', null), veil.init_bitmap(''global_context'', ''privs_range''), veil.init_bitmap_hash(''project_context'', ''privs_range''); return true; end; ' language plpgsql volatile security definer; revoke execute on function veil.veil_demo_init(bool) from public; create or replace function connect_person(_person_id int4) returns bool as ' declare dummy int4; _connect bool; proj_roles record; last_proj int4; first_rec bool; begin -- In reality this function would require some authentication token such -- as a password. This is just a dumb demo version. select into _connect disconnect_person(); -- Test whether provided person exists. This is where we would, in a -- real version, do proper authentication. select into dummy 1 from hidden.persons where person_id = _person_id; if found then -- The person exists and passes authentication -- From the persons roles set the global_context bitmap. select into dummy count(veil.union_from_bitmap_array(''global_context'', ''role_privs'', role_id)) from hidden.person_roles where person_id = _person_id; -- Check that user has can_connect privilege select into _connect veil.bitmap_testbit(''global_context'', 10100); if not _connect then select into _connect disconnect_person(); return false; end if; -- From the persons assignments set the project_context bitmap hash. select into dummy count(veil.union_into_bitmap_hash(''project_context'', project_id::text, veil.bitmap_from_array(''scratch_bitmap'', ''role_privs'', role_id))) from hidden.assignments where person_id = _person_id; -- Finally, record the person_id for the connection. select into dummy veil.int4_set(''person_id'', _person_id); return true; else return false; end if; end; ' language plpgsql volatile security definer; create or replace function disconnect_person() returns bool as ' declare dummy int4; dummy2 bool; dummy3 bool; begin -- Clear session bitmaps, and reset the person_id select into dummy, dummy2, dummy3 veil.int4_set(''person_id'', null), veil.init_bitmap(''global_context'', ''privs_range''), veil.init_bitmap_hash(''project_context'', ''privs_range''); return false; end; ' language plpgsql volatile security definer; create or replace function i_have_global_priv(priv_id int4) returns bool as ' declare connection_id int4; result bool; begin select into connection_id, result veil.int4_get(''person_id''), veil.bitmap_testbit(''global_context'', priv_id); if connection_id is null then return false; else return result; end if; end; ' language plpgsql volatile security definer; create or replace function i_have_personal_priv(priv_id int4, person_id int4) returns bool as ' declare connection_id int4; result bool; begin select into connection_id, result veil.int4_get(''person_id''), veil.bitmap_testbit(''global_context'', priv_id); if connection_id is null then -- No-one is connected return false; else if result then -- We have the required privilege in global context. No need -- to check any further return true; else if person_id = connection_id then -- We are connected as the owner of this record. Check -- whether we have the required privilege in personal -- context. select into result veil.bitmap_array_testbit(''role_privs'', 11002, priv_id); return result; else -- We have no personal context rights to this record return false; end if; end if; end if; end; ' language plpgsql volatile security definer; create or replace function i_have_project_priv(priv_id int4, project_id int4) returns bool as ' declare connection_id int4; result bool; begin select into connection_id, result veil.int4_get(''person_id''), veil.bitmap_testbit(''global_context'', priv_id); if connection_id is null then -- No-one is connected return false; else if result then -- We have the required privilege in global context. No need -- to check any further return true; else select into result veil.bitmap_hash_testbit(''project_context'', project_id::text, priv_id); return result; end if; end if; end; ' language plpgsql volatile security definer; create or replace function i_have_proj_or_pers_priv( priv_id int4, project_id int4, person_id int4) returns bool as ' declare connection_id int4; result bool; begin select into connection_id, result veil.int4_get(''person_id''), veil.bitmap_testbit(''global_context'', priv_id); if connection_id is null then -- No-one is connected return false; else if result then -- We have the required privilege in global context. No need -- to check any further return true; else if person_id = connection_id then -- We are connected as the owner of this record. Check -- whether we have the required privilege in personal -- context. select into result veil.bitmap_array_testbit(''role_privs'', 11002, priv_id); return result; end if; select into result veil.bitmap_hash_testbit(''project_context'', project_id::text, priv_id); return result; -- We have no personal context rights to this record -- so check project context return false; end if; end if; end; ' language plpgsql volatile security definer; create or replace function i_have_project_detail_priv(detail_id int4, proj_id int4) returns bool as ' declare result bool; begin select into result i_have_project_priv(veil.int4array_get(''det_types_privs'', detail_id), proj_id); return result; end; ' language plpgsql volatile security definer; create or replace function i_have_person_detail_priv(detail_id int4, person_id int4) returns bool as ' declare result bool; begin select into result i_have_personal_priv(veil.int4array_get(''det_types_privs'', detail_id), person_id); return result; end; ' language plpgsql volatile security definer; create view privileges( privilege_id, privilege_name) as select privilege_id, privilege_name from hidden.privileges where i_have_global_priv(10001); create rule ii_privileges as on insert to privileges do instead insert into hidden.privileges (privilege_id, privilege_name) select new.privilege_id, new.privilege_name where i_have_global_priv(10002); create rule iu_privileges as on update to privileges do instead update hidden.privileges set privilege_name = new.privilege_name, privilege_id = new.privilege_id where privilege_id = old.privilege_id and i_have_global_priv(10003); create rule id_privileges as on delete to privileges do instead delete from hidden.privileges where privilege_id = old.privilege_id and i_have_global_priv(10004); grant select, insert, update, delete on privileges to public; create view roles( role_id, role_name) as select role_id, role_name from hidden.roles where i_have_global_priv(10005); create rule ii_roles as on insert to roles do instead insert into hidden.roles (role_id, role_name) select new.role_id, new.role_name where i_have_global_priv(10006); create rule iu_roles as on update to roles do instead update hidden.roles set role_name = new.role_name, role_id = new.role_id where role_id = old.role_id and i_have_global_priv(10007); create rule id_roles as on delete to roles do instead delete from hidden.roles where role_id = old.role_id and i_have_global_priv(10008); grant select, insert, update, delete on roles to public; create view role_privileges( role_id, privilege_id) as select role_id, privilege_id from hidden.role_privileges where i_have_global_priv(10009); create rule ii_role_privileges as on insert to role_privileges do instead insert into hidden.role_privileges (role_id, privilege_id) select new.role_id, new.privilege_id where i_have_global_priv(10010); create rule iu_role_privileges as on update to role_privileges do instead update hidden.role_privileges set role_id = new.role_id, privilege_id = new.privilege_id where role_id = old.role_id and privilege_id = old.privilege_id and i_have_global_priv(10011); create rule id_role_privileges as on delete to role_privileges do instead delete from hidden.role_privileges where role_id = old.role_id and i_have_global_priv(10012); grant select, insert, update, delete on role_privileges to public; create view role_roles( role_id, has_role_id) as select role_id, has_role_id from hidden.role_roles where i_have_global_priv(10041); create rule ii_role_roles as on insert to role_roles do instead insert into hidden.role_roles (role_id, has_role_id) select new.role_id, new.has_role_id where i_have_global_priv(10042); create rule iu_role_roles as on update to role_roles do instead update hidden.role_roles set role_id = new.role_id, has_role_id = new.has_role_id where role_id = old.role_id and i_have_global_priv(10043); create rule id_role_roles as on delete to role_roles do instead delete from hidden.role_roles where role_id = old.role_id and i_have_global_priv(10044); grant select, insert, update, delete on role_roles to public; create view persons( person_id, person_name) as select person_id, person_name from hidden.persons where i_have_personal_priv(10013, person_id); create rule ii_persons as on insert to persons do instead insert into hidden.persons (person_id, person_name) select new.person_id, new.person_name where i_have_personal_priv(10014, new.person_id); create rule iu_persons as on update to persons do instead update hidden.persons set person_id = new.person_id, person_name = new.person_name where person_id = old.person_id and i_have_personal_priv(10015, old.person_id); create rule id_persons as on delete to persons do instead delete from hidden.persons where person_id = old.person_id and i_have_personal_priv(10016, old.person_id); grant select, insert, update, delete on persons to public; create view projects( project_id, project_name) as select project_id, project_name from hidden.projects where i_have_project_priv(10017, project_id); create rule ii_projects as on insert to projects do instead insert into hidden.projects (project_id, project_name) select new.project_id, new.project_name where i_have_project_priv(10018, new.project_id); create rule iu_projects as on update to projects do instead update hidden.projects set project_id = new.project_id, project_name = new.project_name where project_id = old.project_id and i_have_project_priv(10019, old.project_id); create rule id_projects as on delete to projects do instead delete from hidden.projects where project_id = old.project_id and i_have_project_priv(10020, old.project_id); grant select, insert, update, delete on projects to public; create view detail_types ( detail_type_id, required_privilege_id, detail_type_name) as select detail_type_id, required_privilege_id, detail_type_name from hidden.detail_types where i_have_global_priv(10021); create rule ii_detail_types as on insert to detail_types do instead insert into hidden.detail_types (detail_type_id, detail_type_name) select new.detail_type_id, new.detail_type_name where i_have_global_priv(10022); create rule iu_detail_types as on update to detail_types do instead update hidden.detail_types set detail_type_id = new.detail_type_id, detail_type_name = new.detail_type_name where detail_type_id = old.detail_type_id and i_have_global_priv(10023); create rule id_detail_types as on delete to detail_types do instead delete from hidden.detail_types where detail_type_id = old.detail_type_id and i_have_global_priv(10024); grant select, insert, update, delete on detail_types to public; create view assignments ( project_id, person_id, role_id) as select project_id, person_id, role_id from hidden.assignments where i_have_proj_or_pers_priv(10025, project_id, person_id); create rule ii_assignments as on insert to assignments do instead insert into hidden.assignments (project_id, person_id, role_id) select new.project_id, new.person_id, new.role_id where i_have_proj_or_pers_priv(10026, new.project_id, new.person_id); create rule iu_assignments as on update to assignments do instead update hidden.assignments set project_id = new.project_id, person_id = new.person_id, role_id = new.person_id where project_id = old.project_id and person_id = old.person_id and i_have_proj_or_pers_priv(10027, old.project_id, old.person_id); create rule id_assignments as on delete to assignments do instead delete from hidden.assignments where project_id = old.project_id and person_id = old.person_id and i_have_proj_or_pers_priv(10028, old.project_id, old.person_id); grant select, insert, update, delete on assignments to public; create view person_roles ( person_id, role_id) as select person_id, role_id from hidden.person_roles where i_have_personal_priv(10029, person_id); create rule ii_person_roles as on insert to person_roles do instead insert into hidden.person_roles (person_id, role_id) select new.person_id, new.role_id where i_have_personal_priv(10030, new.person_id); create rule iu_person_roles as on update to person_roles do instead update hidden.person_roles set person_id = new.person_id, role_id = new.role_id where person_id = old.person_id and role_id = old.role_id and i_have_personal_priv(10031, old.person_id); create rule id_person_roles as on delete to person_roles do instead delete from hidden.person_roles where person_id = old.person_id and role_id = old.role_id and i_have_personal_priv(10032, old.person_id); grant select, insert, update, delete on person_roles to public; create view project_details ( project_id, detail_type_id, value) as select project_id, detail_type_id, value from hidden.project_details where i_have_project_priv(10033, project_id) and i_have_project_detail_priv(detail_type_id, project_id); create rule ii_project_details as on insert to project_details do instead insert into hidden.project_details (project_id, detail_type_id, value) select new.project_id, new.detail_type_id, new.value where i_have_project_priv(10034, new.project_id) and i_have_project_detail_priv(new.detail_type_id, new.project_id); create rule iu_project_details as on update to project_details do instead update hidden.project_details set project_id = new.project_id, detail_type_id = new.detail_type_id, value = new.value where project_id = old.project_id and detail_type_id = old.detail_type_id and i_have_project_priv(10035, old.project_id) and i_have_project_detail_priv(old.detail_type_id, old.project_id); create rule id_project_details as on delete to project_details do instead delete from hidden.project_details where project_id = old.project_id and detail_type_id = old.detail_type_id and i_have_project_priv(10036, old.project_id) and i_have_project_detail_priv(old.detail_type_id, old.project_id); grant select, insert, update, delete on project_details to public; create view person_details ( person_id, detail_type_id, value) as select person_id, detail_type_id, value from hidden.person_details where i_have_personal_priv(10037, person_id) and i_have_person_detail_priv(detail_type_id, person_id); create rule ii_person_details as on insert to person_details do instead insert into hidden.person_details (person_id, detail_type_id, value) select new.person_id, new.detail_type_id, new.value where i_have_personal_priv(10038, new.person_id) and i_have_person_detail_priv(new.detail_type_id, new.person_id); create rule iu_person_details as on update to person_details do instead update hidden.person_details set person_id = new.person_id, detail_type_id = new.detail_type_id, value = new.value where person_id = old.person_id and detail_type_id = old.detail_type_id and i_have_personal_priv(10039, old.person_id) and i_have_person_detail_priv(old.detail_type_id, old.person_id); create rule id_person_details as on delete to person_details do instead delete from hidden.person_details where person_id = old.person_id and detail_type_id = old.detail_type_id and i_have_personal_priv(10040, old.person_id) and i_have_person_detail_priv(old.detail_type_id, old.person_id); grant select, insert, update, delete on person_details to public; create or replace function global_privs_qry() returns setof int4 as ' select * from veil.bitmap_bits(''global_context''); ' language sql stable security definer; create or replace view my_global_privs ( privilege_id) as select * from global_privs_qry(); grant select on my_global_privs to public; create or replace function personal_privs_qry() returns setof int4 as ' select * from veil.bitmap_array_bits(''role_privs'', 11002); ' language sql stable security definer; create or replace view my_personal_privs ( privilege_id) as select * from personal_privs_qry(); grant select on my_personal_privs to public; create or replace function projects_qry() returns setof varchar as ' select * from veil.bitmap_hash_entries(''project_context''); ' language sql stable security definer; create or replace view my_projects ( project_id) as select * from projects_qry(); grant select on my_projects to public; create type hidden.proj_privs as ( project_id int4, privilege_id int4 ); create or replace function project_privs() returns setof hidden.proj_privs as ' declare _project record; _priv record; _result hidden.proj_privs; begin for _project in select * from veil.bitmap_hash_entries(''project_context'') loop _result.project_id = _project.veil_bitmap_hash_entries; for _priv in select * from veil.bitmap_hash_bits(''project_context'', _result.project_id) loop _result.privilege_id = _priv.veil_bitmap_hash_bits; return next _result; end loop; end loop; return; end; ' language plpgsql stable security definer; grant execute on function project_privs() to public; create or replace view my_project_privs ( project_id, privilege_id) as select * from project_privs(); grant select on my_project_privs to public; create or replace view my_privs ( context, project, privilege_id, privilege_name) as select a.context, a.project, a.id, p.privilege_name from ( select 'Project' as context, project_id as project, privilege_id as id, 3 as seq from my_project_privs union all select 'Global', null, privilege_id, 1 from my_global_privs union all select 'Personal', null, privilege_id, 2 from my_personal_privs ) a, privileges p where p.privilege_id = a.id order by a.seq, a.context, a.project, a.id; grant select on my_privs to public;