I am trying to create an access control system.
Here is an example of how the table I'm trying to control access to looks like this:
things table: id group_id name 1 1 thing 1 2 1 thing 2 3 1 thing 3 4 1 thing 4 5 2 thing 5
And the access control table looks like this:
access table: user_id type object_id access 1 group 1 50 1 thing 1 10 1 thing 2 100
Access can be granted either by specifying the identifier of the “thing” directly, or granted to the entire group of things by specifying the identifier of the group. In the above example, user 1 was granted access level 50 to group 1, which should be applied if there are no other rules that provide more specific access to a single thing.
I need a query that returns a list of things (ids only in order) along with the access level for a specific user. Therefore, using the example above, I would like something similar for user id 1:
desired result: thing_id access 1 10 2 100 3 50 (things 3 and 4 have no specific access rule, 4 50 so this '50' is from the group rule) 5 (thing 5 has no rules at all, so although I still want it in the output, there no access level for it)
Closest I can come up with the following:
SELECT * FROM things LEFT JOIN access ON user_id = 1 AND ( (access.type = 'group' AND access.object_id = things.group_id) OR (access.type = 'thing' AND access.object_id = things.id) )
But this returns multiple rows when I want only one for each row in the “stuff” table. I’m not sure how to go to one line for each thing, or how to prioritize the rules of the “thing” over the rules of the “group”.
If that helps, the database I'm using is PostgreSQL.
Please feel free to leave a comment if there is any information that I missed.
Thanks in advance!