Adding ACL notion to existing tables

From: Bruno Baguette <bruno(dot)baguette(at)gmail(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: Adding ACL notion to existing tables
Date: 2009-08-08 00:13:47
Message-ID: 4A7CC33B.9080102@gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hello !

I would like known your appreciation, and to get some advices and tips
about a design issue about adding ACL notion.

I have several *existing* tables that manages some user's items which
are quite different (postal adresses, photos, climbing_skills,...).
Please note that "Users" are not PostgreSQL users, they are records in a
"member" table.

####################################
-- USER table
CREATE SEQUENCE seq_member_id;
CREATE TABLE members
(
pk_member_id INT8 NOT NULL DEFAULT NEXTVAL('seq_member_id');
... (some user related fields)...
);

-- ITEMS tables
CREATE SEQUENCE seq_item_type_a_id;
CREATE TABLE item_type_a
(
pk_item_id INT8 NOT NULL DEFAULT NEXTVAL('seq_item_type_a_id'),
fk_member_id INT8 NOT NULL,
... (some specific fields) ...
CONSTRAINT fkey_member_id FOREIGN KEY (fk_member_id) REFERENCES
members(pk_member_id)
);

CREATE SEQUENCE seq_item_type_b_id;
CREATE TABLE item_type_b
(
pk_item_id INT8 NOT NULL DEFAULT NEXTVAL('seq_item_type_b_id'),
fk_member_id INT8 NOT NULL,
... (some other specific fields) ...
CONSTRAINT fkey_member_id FOREIGN KEY (fk_member_id) REFERENCES
members(pk_member_id)
);
####################################

Several years laters, there's a need for theses users to be able to
define ACE (Access Control Entries) for their items. So, I have to add
an ACL (Access Control List) notion.

I thought of two solution :
- Solution A
- Solution B

# SOLUTION A.
####################################

CREATE TABLE acl_ace_item
(
item_type VARCHAR(40) NOT NULL,
item_id INT8 NOT NULL,
ace_label VARCHAR(100) NOT NULL,
CONSTRAINT PRIMARY KEY (item_type, item_id),
CONSTRAINT chk_item_type CHECK item_type IN ('item_type_a',
'item_type_b'),
CONSTRAINT chk_acl_uniqueness UNIQUE (item_type, item_id)
);

NOTA : The 'item_type' field will indicates which table need to be
JOINed. I don't known if I can put a JOIN in a CASE structure, but I
have to give a try or find another way.

PRO : Avoid any changes to the existing 'item_type_XXX' tables.

CONS : a) If the user delete a 'item_type_a', 'item_type_b' record, I
will have orphan record in the acl_ace_item table.
b) No way to have a FOREIGN KEY CONSTRAINT on 'item_id' field
since it can be an id from 'item_type_a', 'item_type_b'.

####################################

# SOLUTION B.
####################################

CREATE SEQUENCE seq_acl_item_id;
CREATE TABLE acl_item
(
pk_acl_id INT8 NOT NULL DEFAULT NEXTVAL('seq_acl_item_id'),
CONSTRAINT pkey_acl_item PRIMARY KEY(pk_acl_id)
);

CREATE TABLE acl_ace_item
(
fk_acl_id INT8 NOT NULL,
ace_label VARCHAR(100) NOT NULL,
CONSTRAINT chk_ace_uniqueness UNIQUE (fk_acl_id, ace_label),
CONSTRAINT fkey_acl_id FOREIGN KEY (fk_acl_id) REFERENCES
acl_item(pk_acl_id);
);

ALTER TABLE item_type_a ADD COLUMN fk_acl_id INT8;
ALTER TABLE item_type_a ADD CONSTRAINT fkey_acl_id FOREIGN KEY
(fk_acl_id) REFERENCES acl_item(pk_acl_id);
ALTER TABLE item_type_a ADD CONSTRAINT chk_uniqueness_acl_id UNIQUE
(fk_acl_id);
ALTER TABLE item_type_b ADD COLUMN fk_acl_id INT8;
ALTER TABLE item_type_b ADD CONSTRAINT fkey_acl_id FOREIGN KEY
(fk_acl_id) REFERENCES acl_item(pk_acl_id);
ALTER TABLE item_type_b ADD CONSTRAINT chk_uniqueness_acl_id UNIQUE
(fk_acl_id);

NOTA : - The 'acl_item' table could appears to be useless, but it
enables me to avoid orphan records in the 'acl_ace_item' items.
- A NULL 'fk_acl_id' value in 'item_type_XXX' tables would means
NO defined ACL, and so free access.
- No records in the 'acl_ace_item' table for an existing acl_id
would also means NO defined ACL, and so free access.

PRO : a) JOIN between 'item_type_XXX' tables and acl_ace_item could be
faster than SOLUTION A.

CONS : a) If the user delete a 'item_type_a', 'item_type_b' record, I
will have orphan record in the acl_ace_item table.
b) No way to have a UNIQUE CONSTRAINT that would cover existing
'item_type_XXX', so it is possible to have a same fk_acl_id value in the
'item_type_a' and the 'item_type_b' table. Which is a situation I would
avoid.

####################################

As you can see, I'm not really convinced for SOLUTION A or SOLUTION B as
they have both some CONS. And they will both require some stored
procedures to check references integrity. Solution B seems to be less
weird to me.

What would you do in that kind of situation ? Which solution would you
take ? Would you uses another design to solve that problem ?

Feel free to leave your appreciation about that problem. Your advices,
tips or some interesting URLs are welcome also !

Thanks in advance !

Kind regards,

--
Bruno Baguette - bruno(dot)baguette(at)gmail(dot)com

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Tom Lane 2009-08-08 00:35:57 Re: Make check fails on 8.3.7
Previous Message Greg Stark 2009-08-07 23:44:36 Re: smart or dumb partition?