【发布时间】:2019-08-08 11:41:30
【问题描述】:
我有一个包含应用程序功能的自引用树结构。通过另外两个多对多表,我想知道用户可以访问哪些功能。
app_user (id, name, is_superuser)
feature (id, parent_id, name)
job (id, name)
job_feature_relationship (job_id, feature_id, deny)
job_user_relationship (job_id, user_id)
总结:用户可以有多个工作。作业包含一组功能,可以选择拒绝。这对于在树结构中管理权限很有用,例如:
有以下特点:
sales
sales/product
sales/product/createProduct
sales/product/deleteProduct
sales/product/listProducts
sales/customer
sales/customer/createCustomer
sales/customer/deleteCustomer
sales/customer/listCustomers
只有叶节点(createProduct、deleteProduct、listProducts、createCustomer、deleteCustomer、listCustomers)是实际操作。
如果工作看起来像这样:
(sales)
用户应该能够执行销售下的所有操作,因此在此示例中所有操作。
但是,如果工作看起来像这样:
(sales/customer)
(sales/customer/deleteCustomer, deny)
用户应该只能listCustomers 和createCustomer,因为sales/customer 将允许子树中的所有内容,但deleteCustomer 被拒绝。
最后一个补充,与此问题不完全相关,但superuser 用户可以访问所有功能,这意味着如果 if_superuser bool 标志设置为 true,则无论作业如何,所有功能都应该可以访问。
我离解决方案只有一步之遥。
with recursive
feature_tree(parent, child, name, level) as (
select id, id, feature, 1
from feature
union all
select parent, id, feature.feature, feature_tree.level + 1
from feature_tree
join feature on (
feature_tree.child = feature.parent_id
)
)
select
feature_tree.name
, feature_tree.level
, deny
from feature
join feature_tree on (
feature_tree.parent = feature.id
)
left join job_feature_relationship on (
job_feature_relationship.feature_id = feature.id
)
left join job_user_relationship on (
job_user_relationship.job_id = job_feature_relationship.job_id
)
join app_user on (
-- app_user.id = 1
app_user.id = 2
-- app_user.id = 3
-- app_user.id = 4
)
where (
-- this condition is responsible for only returning leafs
not exists(select 1 from feature descendant where descendant.parent_id = feature_tree.child)
and (
app_user.is_superuser
or job_user_relationship.user_id = app_user.id
)
)
order by feature_tree.level desc;
我想要的可以很容易地依次描述,python示例代码:
features = set()
for feature in features:
if feature.deny:
features = features.difference(feature.tree)
else:
features = features.union(feature.tree)
由于排序,添加和删除一组特征将具有正确的最终结果。 提前感谢您的帮助。
【问题讨论】:
-
请给我们一组我们可以使用的样本数据。这非常复杂,而且很难生成自己的测试数据。
-
感谢您的宝贵时间,我用更合理的示例数据和 sql fiddle 更新了我的问题。
标签: postgresql aggregate