开发者

Grant access to subset of table to user on PostgreSQL

开发者 https://www.devze.com 2023-03-05 18:20 出处:网络
I know that I can use views to grant access to a subset of attributes in a table. But how can I grant access to particular tuples only? Say I have a table of registered students, a use开发者_Python百科

I know that I can use views to grant access to a subset of attributes in a table. But how can I grant access to particular tuples only? Say I have a table of registered students, a use开发者_Python百科rname attribute and then some other like degree_status, how do I grant access so that user A can only select from the table a tuple corresponding to username A ? I have a database exam and I'm studying some past papers and I came across this question but I don't know how to answer it and I cant find how to do it from my book "Dtabase System: A practical Approach to Database Design, Implementation and Management'

Thanks any help is much appreciated!

Matt


Say that you got :

Table items (item_id, ...)
Table users (user_id, ...)
Table users_permissions( user_id, item_id, perm_type )

You could create a VIEW like this :

SELECT i.*, p.perm_type 
FROM items JOIN users_permissions USING (item_id) 
WHERE user_id = get_current_user_id();

Users can select from this view but not remove the WHERE and JOIN restricting the permissions.

The get_current_user_id() function is likely to be the major problem ;)


Along the lines of peufeu's answer, in Postgresql the current user name is available through the function current_user. So a view

CREATE VIEW available_bigtable AS
SELECT * FROM bigtable
WHERE username = current_user;

looks like it does what you need. Grant SELECT to everyone on the view, but to no one (except admins) on the underlying bigtable.


The Veil project provides a framework for row-level access control in PostgreSQL.


How about creating a function that takes the user id and returns the subset of rows he has access to?

CREATE FUNCTION user_items(integer) RETURNS SETOF items AS $$
    SELECT * FROM items WHERE user_id = $1
$$ LANGUAGE SQL;

SELECT * FROM user_items(55); # 55 being the user id

edit Thinking about it more, this could cause quite a performance hit, as the user_id condition would be applied to the whole data set, prior to any other "user-land" conditions.

For example, SELECT * FROM user_items(55) WHERE id=45 would first filter the entire table for user items, and only than find the ID on that subset.

With views, the query planner can decide on the optimal order to evaluate the conditions (where he'll probably filter for the ID first, than for user id). When using a function like I suggested, postgres can't do that.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号