I am designing an access control list feature for my php+mysql web app and trying to make it as automatic as possible.
I think I've got a proof of concept of how the ACL should work, but I'm struggling to optimise my queries
The concept of the automation is to allow for conflicting rules, and then order the rules depending on how important the rules are, then reorder the rules based on information held in the most important rule.
[In this case, a rule weight of 0 is more important that weights with higher numbers...think "inverse weight"]
So what I have so far may return something like this:
This represents a default rule of allow delete, then a user (weight 1) protecting his/her resource group and then an admin (weight 0) allowing a specific resource to be deleted by anyone
Code:
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
|role |policy |weight |limit_type |action|allow_deny |group_name |resource |
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
|General |Global>Resource>User>Resource Group>User Group |0 |Resource |DELETE|ALLOW |NULL |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
|Prevent Delete |Global>Resource Group>User Group>Resource>User |1 |Resource Group |DELETE|DENY |protect mine |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
|General |User>Resource>User Group>Resource Group>Global |9999 |Resource Group |DELETE|ALLOW |company |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
(ordered by weight ASC)
I then want to order the same result set but on the limit_type column and the order should follow the (reverse) order of the policy template. At present I have copied the original query but changed the order by to this
Code:
ORDER BY
CASE
acl.limit_type
WHEN 'User Group' THEN 1
WHEN 'Resource Group' THEN 2
WHEN 'User' THEN 3
WHEN 'Resource' THEN 4
WHEN 'Global' THEN 5
END
This then gives a result set looking like this:
Code:
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
|role |policy |weight |limit_type |action|allow_deny |group_name |resource |
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
|General |User>Resource>User Group>Resource Group>Global |9999 |Resource Group |DELETE|ALLOW |company |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
|Prevent Delete |Global>Resource Group>User Group>Resource>User |1 |Resource Group |DELETE|DENY |protect mine |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
|General |Global>Resource>User>Resource Group>User Group |0 |Resource |DELETE|ALLOW |NULL |7d81aa2e-f385-11e1-8ca6-80c16eeeb2ad |
+---------------+-----------------------------------------------+-------+----------------+------+---------------+---------------+-------------------------------------+
The system then loops over this set setting the action of "delete" to ALLOW or DENY based on the allow_deny column
[the reason this loops and flip flops between states is that the last row may not always contain an explicit action]
So, my question is this: Can I sensibly combine the two queries into one?
[The policy field is just a varchar string and does not have to be separated by ">", so i could reformat this column if necessary]