que tienen un esquema de tablas cuyos contenidos básicamente se reducen a:el uso de vistas para el control de acceso en PostgreSQL
- Un conjunto de usuarios
- Un conjunto de grupos de objetos
- una lista de control de acceso (ACL) indicando qué usuarios tienen acceso a qué grupos
- Un conjunto de objetos, cada uno de los cuales pertenece exactamente a un grupo.
Quiero crear una aplicación simple que admita el control de acceso. Estoy pensando que las vistas serían un buen enfoque aquí.
Supongamos que tengo la siguiente inicialización de la base de datos:
/* Database definition */
BEGIN;
CREATE SCHEMA foo;
CREATE TABLE foo.users (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE foo.groups (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE foo.acl (
user_ INT REFERENCES foo.users,
group_ INT REFERENCES foo.groups
);
CREATE TABLE foo.objects (
id SERIAL PRIMARY KEY,
group_ INT REFERENCES foo.groups,
name TEXT,
data TEXT
);
/* Sample data */
-- Create groups A and B
INSERT INTO foo.groups VALUES (1, 'A');
INSERT INTO foo.groups VALUES (2, 'B');
-- Create objects belonging to group A
INSERT INTO foo.objects VALUES (1, 1, 'object in A', 'apples');
INSERT INTO foo.objects VALUES (2, 1, 'another object in A', 'asparagus');
-- Create objects belonging to group B
INSERT INTO foo.objects VALUES (3, 2, 'object in B', 'bananas');
INSERT INTO foo.objects VALUES (4, 2, 'object in B', 'blueberries');
-- Create users
INSERT INTO foo.users VALUES (1, 'alice');
INSERT INTO foo.users VALUES (2, 'amy');
INSERT INTO foo.users VALUES (3, 'billy');
INSERT INTO foo.users VALUES (4, 'bob');
INSERT INTO foo.users VALUES (5, 'caitlin');
INSERT INTO foo.users VALUES (6, 'charlie');
-- alice and amy can access group A
INSERT INTO foo.acl VALUES (1, 1);
INSERT INTO foo.acl VALUES (2, 1);
-- billy and bob can access group B
INSERT INTO foo.acl VALUES (3, 2);
INSERT INTO foo.acl VALUES (4, 2);
-- caitlin and charlie can access groups A and B
INSERT INTO foo.acl VALUES (5, 1);
INSERT INTO foo.acl VALUES (5, 2);
INSERT INTO foo.acl VALUES (6, 1);
INSERT INTO foo.acl VALUES (6, 2);
COMMIT;
Mi idea es utilizar puntos de vista que reflejan la base de datos, pero restringir el contenido a sólo lo que el usuario actual (comprobado por mi script PHP) pueden acceder (aquí solo usaré el usuario 'bob'). Supongamos que yo corro esto al comienzo de cada sesión de PostgreSQL (es decir, cada vez que alguien accede a una página en mi sitio):
BEGIN;
CREATE TEMPORARY VIEW users AS
SELECT * FROM foo.users
WHERE name='bob';
CREATE TEMPORARY VIEW acl AS
SELECT acl.* FROM foo.acl, users
WHERE acl.user_=users.id;
CREATE TEMPORARY VIEW groups AS
SELECT groups.* FROM foo.groups, acl
WHERE groups.id=acl.group_;
CREATE TEMPORARY VIEW objects AS
SELECT objects.* FROM foo.objects, groups
WHERE objects.group_=groups.id;
COMMIT;
Mi pregunta es, ¿es un buen enfoque? ¿Estas declaraciones CREATE TEMPORARY VIEW producen una sobrecarga significativa, especialmente en comparación con un par de consultas simples?
Además, ¿hay alguna manera de hacer que estas vistas sean permanentes en la definición de mi base de datos, y luego vincular un valor al nombre de usuario por sesión? De esta forma, no tiene que crear todas estas vistas cada vez que un usuario carga una página.
En la comprobación de una actualización/eliminar, si me refiero al usuario por ID en lugar del nombre, no puedo renunciar CREATE VIEW AllowedUserGroup y acl de referencia directamente para esa parte? –
Claro, eso funcionará bien. También puedes usar AllowedUserGroup para SELECT, pero pensé que AllowedObjects sería un poco más útil. También podría hacer que AllowedObjects simplemente uniera 'objects' al AllowedUserGroup para que toda la lógica de ACL/Grupo/Usuario esté contenida en la vista AllowedUserGroup ... la ruta de ejecución debería ser la misma en ambos sentidos. – richardtallent