2015-11-28 40 views
1

值我有一個數據庫來管理用戶及其權限。每個用戶都被分配給一個具有權限的組(讀寫布爾值),但僅限於特定的文件。並且每個用戶都可以擁有多個具有更高優先級的特殊權限,並且只爲特定用戶提供額外的權限。加入表和覆蓋PostgreSQL的

我正在尋找一個查詢在那裏我可以指定用戶,並取回他們可以訪問所有文件和權利。因此,如果用戶user1是組standard具有讀取權限可以說file1.txt他們有兩個特殊的權限,以附加寫入文件file1.txt並命名hello2.txt另一個文件。在組standard任何其他用戶應當僅能夠讀取file1.txt例如user2其也分配到組的標準。

我的數據庫的摘要形式:

CREATE TABLE files(
    fid INTEGER PRIMARY KEY, 
    fname VARCHAR(200) UNIQUE 
); 

CREATE TABLE permissions(
    pid INTEGER PRIMARY KEY, 
    pread BOOLEAN DEFAULT FALSE, 
    pwrite BOOLEAN DEFAULT FALSE, 
    pfid INTEGER REFERENCES files(fid) 
); 

CREATE TABLE groups(
    gid INTEGER PRIMARY KEY, 
    gname VARCHAR(50) 
); 

CREATE TABLE users (
    uid INTEGER PRIMARY KEY, 
    uname VARCHAR(10), 
    ugroup INTEGER REFERENCES groups(gid) 
); 

CREATE TABLE specialpermissions(
    sppid INTEGER REFERENCES permissions(pid), 
    spuid INTEGER REFERENCES users(uid), 
    PRIMARY KEY (sppid, spuid) 
); 

CREATE TABLE grouppermissions(
    gpgid INTEGER REFERENCES groups(gid), 
    gppid INTEGER REFERENCES permissions(pid), 
    PRIMARY KEY (gpgid, gppid) 
); 
--Create a group 
INSERT INTO groups (gid, gname) VALUES (1, 'standard'); 
--Crate users and assign them to the group standard 
INSERT INTO users (uid, uname, ugroup) VALUES (1, 'user1', 1), (2, 'user2' ,1); 
--Create tow files name file1.txt and file2.txt 
INSERT INTO files (fid, fname) VALUES (1, 'file1.txt'), (2, 'file2.txt'); 
--Create a permission to read file1, to write file1 and to write file2 
INSERT INTO permissions (pid, pread, pwrite, pfid) VALUES (1, TRUE, FALSE, 1), (2, TRUE, TRUE, 1), (3, FALSE, TRUE, 2); 
--Assign the read permission for file1 to group standard 
INSERT INTO grouppermissions (gpgid, gppid) VALUES (1, 1); 
--Assign write permission for file1 and write permission to file2 
INSERT INTO specialpermissions (sppid, spuid) VALUES (2, 1), (3, 1); 

我設法創建一個查詢來獲取與該組分配的權限,但我不知道我怎麼能超越他們,如果有一個特殊的權限授予給用戶或如何加入兩個表的其他權利在一起,同時還具有簡單的結果是這樣的:

SELECT 
    u.uname, 
    g.gname, 
    p.pread, 
    p.pwrite, 
    f.fname 
FROM users u 
    INNER JOIN groups g ON g.gid = u.ugroup 
    INNER JOIN grouppermissions gp ON gp.gpgid = g.gid 
    INNER JOIN permissions p ON p.pid = gp.gppid 
    INNER JOIN files f ON f.fid = p.pfid 
ORDER BY u.uname; 

結果:

uname | gname | pread | pwrite | fname 
-------+----------+-------+--------+----------- 
user1 | standard | t  | f  | file1.txt 
user2 | standard | t  | f  | file1.txt 

期望的結果:

uname | gname | pread | pwrite | fname 
-------+----------+-------+--------+----------- 
user1 | standard | t  | t  | file1.txt 
user1 | standard | f  | t  | file2.txt 
user2 | standard | t  | f  | file1.txt 
+0

榮譽一個極好說明問題,包括DDL和測試數據! – wildplasser

回答

0
SELECT 
    u.uname, 
    ug.gname, 
    exists(select * from permissions p left join grouppermissions gp on (gp.gppid = p.pid) 
            left join groups g on (gp.gpgid = g.gid) 
            left join specialpermissions sp on (sp.sppid = p.pid) 
            where p.pread = true and p.pfid = f.fid and (u.ugroup = g.gid or u.uid = sp.spuid)) as pread, 

    exists(select * from permissions p left join grouppermissions gp on (gp.gppid = p.pid) 
            left join groups g on (gp.gpgid = g.gid) 
            left join specialpermissions sp on (sp.sppid = p.pid) 
            where p.pwrite = true and p.pfid = f.fid and (u.ugroup = g.gid or u.uid = sp.spuid)) as pwrite, 
    f.fname 
FROM users u 
INNER JOIN files f ON 1=1 
INNER JOIN groups ug ON (ug.gid = u.ugroup) 
ORDER BY u.uname; 

請注意,我選擇這種類型的查詢,因爲它會很容易地擴展到用戶和組之間的關係是多對多的情況下(通過降低加盟在主查詢中添加組成員的最終左連接到子查詢)。

此外,該查詢不會返回在上爲用戶文件的權限是「F」,「F」的情況。如果您不想要,可以過濾此查詢的結果以將其刪除。

+0

謝謝,這對我來說非常適合! – scsere