ruby - cancancan的多级授权
问题描述
我正面临挑战。一个多级授权系统和一个朋友告诉我 cancancan 可以帮助我。
我阅读了文档,但无法弄清楚。所以我在这里解释一下。我的目标是创建一个系统:
- South 部门的用户“John”创建 Jane
- 用户 Jane 创建了 June 和 Paul
- 用户 June 和 Paul 创建 Bob、Nat 和 Emily
还
- 北方部门的用户 Peter 创建了 Rita
- 用户 Rita 创建 Becca 和 Lisa
- 用户 Becca 和 Lisa 创建了 Clara、Lory 和 Alexa
现在,每个用户只能看到自己创建的记录,或者来自低于但不能高于或来自其他部门的用户的记录。
我应该如何从模型和一切开始?
解决方案
首先,您需要在数据库级别跟踪此树。为此,您可以添加对将引用创建该特定用户的用户parent_id
的表的引用。users
对于不是由任何人创建的用户,此列将为空,id
否则将保留父用户的。我强烈建议也使用外键,以保证参照完整性。
然后,您将需要以正确遍历此树结构的方式定义您的 CanCanCan 能力。您可以将这个源自文档的示例作为参考:
class Ability
def initialize(user)
can :read, Photo, Book do |resource|
resource.creator.descendant_of? user
end
end
end
我假设User
模型有一个descendant_of?
方法可以从当前用户遍历树到根检查给定用户是否是资源创建者的父级。一个可能的实现可能如下所示:
# app/models/user.rb
def descendant_of?(target_user)
parent_id == target_user.id || parent&.descendant_of?(target_user)
end
根据您的用户树的特征,这个建议在效率方面很快就会变得很差,因为从所有者到根的所有用户都可能从数据库中加载以执行这些检查。如果您开始面临这些问题,这里有一些值得探索的想法:
- 对列使用类似数组的类型
parent_ids
来存储父 ID 的整个列表。我看到这个提议的主要缺点是,如果树中有更改,它会增加一些开销,并且引用完整性约束会丢失(AFAIK 在这种情况下无法添加外键)。 - 除了上述建议之外,修改 CanCanCan 功能以直接针对数据库运行查询,而不是在内存中进行检查(执行 ruby 代码)。
推荐阅读
- kotlin - 如何在密封类的成员上调用 .value
- json - 更改 json 文件时重新加载 webpack 开发服务器
- python - 一行python中的多个输入
- python - 哪个聚类距离度量可以找到最相关的项目组
- python - 在pandas df中提取+后包含空格的子字符串的行
- php - 如何保存和获取特定页面的评论 meta_key 和 meta_value
- c++ - 如何初始化数组指针对象
- javascript - 如何根据滑块输入更改链接?
- mysql - mysql 插入错误:ER_PARSE_ERROR:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册
- javascript - 如何有效地构造 js 包中的代码以停止导入所有内容