How to determine in sql if a user can read/write/execute a file a la unix permissions system?

穿精又带淫゛_ 提交于 2019-12-25 03:18:09

问题


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

  1. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!