问题
I am trying to write an application where there are files and users. The permissions for the files should be as in unix: read/write/execute. Each file belongs to a owner and a group, and for each file there are "other" users (based on who is owner, and who belongs to a group). The schema looks like this:
create table s_file(
file_id INTEGER PRIMARY KEY,
parent_id INTEGER default NULL,
name,
content BLOB DEFAULT NULL,
owner_id INTEGER NOT NULL,
group_id INTEGER NOT NULL,
read_owner BOOLEAN not null default 1,
write_owner BOOLEAN not null default 1,
execute_owner BOOLEAN not null default 1,
read_group BOOLEAN not null default 1,
write_group BOOLEAN not null default 0,
execute_group BOOLEAN not null default 1,
read_other BOOLEAN not null default 1,
write_other BOOLEAN not null default 0,
execute_other BOOLEAN not null default 1
);
create table s_user( uid INTEGER PRIMARY KEY,
name NOT NULL, password NOT NULL);
create table s_group( gid INTEGER PRIMARY KEY, name NOT NULL);
create table s_user_in_group ( uid INTEGER NOT NULL,
gid INTEGER NOT NULL);
insert into s_user(uid,name,password) values (1,'root','pw');
insert into s_user(uid,name,password) values (2,'gauss', 'pw');
insert into s_user(uid,name,password) values (3,'conway', 'pw');
insert into s_group(gid,name) values (1,'root');
insert into s_group(gid,name) values (2,'producer');
insert into s_group(gid,name) values (3,'gauss');
insert into s_group(gid,name) values (4,'conway');
insert into s_user_in_group(uid,gid) values (2,2),(2,3),(3,4);
insert into s_file(file_id,name,owner_id,group_id) values (1,'galois',1,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (2,1,'home',1,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group) values (3,1,'models',1,2,1);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (4,2,'gauss',2,3);
insert into s_file(file_id,parent_id,name,owner_id,group_id) values (5,2,'conway',3,4);
insert into s_file(file_id,parent_id,name,owner_id,group_id,content) values (6,4,'boston.pfa',2,3,'cB');
insert into s_file(file_id,parent_id,name,owner_id,group_id,content) values (7,5,'iris.pfa',3,4,'cI');
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group,content) values (8,3,'boston.pfa',2,2,1,'CB');
insert into s_file(file_id,parent_id,name,owner_id,group_id,write_group,content) values (9,3,'iris.pfa',2,2,1,'CI');
Here are some example data: File Tree:
galois
|-- home
| |-- gauss
| | +-- boston.pfa
| +-- conway
| +-- iris.pfa
+-- models
|-- boston.pfa
+-- iris.pfa
I would like to write a query, if it is possible in sqlite, otherwise with python, to see for example, if the user conway, can write /galois/models/boston.pfa According to my example data, which you can find below, it should not be possible, since conway is not the owner nor in the group producers and others are not allowed to write. So what I am trying to do, if it is possible in sql, is the following table / entry:
file_id, user_id, can_write/can_execute/can_read
Please find below some example data:
sqlite> select file_id, parent_id, name, owner_id, group_id, write_owner, write_group,write_other from s_file;
1||galois|1|1|1|0|0
2|1|home|1|1|1|0|0
3|1|models|1|2|1|1|0
4|2|gauss|2|3|1|0|0
5|2|conway|3|4|1|0|0
6|4|boston.pfa|2|3|1|0|0
7|5|iris.pfa|3|4|1|0|0
8|3|boston.pfa|2|2|1|1|0
9|3|iris.pfa|2|2|1|1|0
sqlite> select uid,name from s_user;
1|root
2|gauss
3|conway
sqlite> select gid,name from s_group;
1|root
2|producer
3|gauss
4|conway
sqlite> select uid,gid from s_user_in_group;
2|2
2|3
3|4
Any suggestions?
Thanks for your help!
Edit: On suggestion of @Mike I would proceed as follows: 1. Create a view
file_id, user_id, can_read, can_write, can_execute
with "local" permissions
- Use CTEs to decide if user can access (a la unix) a specific file: for this the user must have rights to execute each direcotory above the file until the root directory.
My problem is to decide, if the first step can be done solely in sql (that would be great), or if I have to mix it with python [In this case I would also implement step 2. in python]
Or maybe you have a better idea on how to structure (schema) the data to achieve this goal?
Thank you again for you help!
回答1:
I found a solution:
create view if not exists user_rights as
select u.uid,f.file_id,
case
when f.owner_id = u.uid then f.read_owner
when u.uid = uig.uid then max(f.read_group) else max(f.read_other) end as can_read,
case
when f.owner_id = u.uid then f.write_owner
when u.uid = uig.uid then max(f.write_group) else max(f.write_other) end as can_write,
case
when f.owner_id = u.uid then f.execute_owner
when u.uid = uig.uid then max(f.execute_group) else max(f.execute_other) end as can_execute
from s_user u,s_file f left join s_user_in_group uig on f.group_id = uig.gid group by u.uid,file_id;
The complete solution may be found here:
https://github.com/orgesleka/unix-acl-sql
来源:https://stackoverflow.com/questions/53078903/how-to-determine-in-sql-if-a-user-can-read-write-execute-a-file-a-la-unix-permis