首页 > 解决方案 > cancancan的多级授权

问题描述

我正面临挑战。一个多级授权系统和一个朋友告诉我 cancancan 可以帮助我。

我阅读了文档,但无法弄清楚。所以我在这里解释一下。我的目标是创建一个系统:

现在,每个用户只能看到自己创建的记录,或者来自低于但不能高于或来自其他部门的用户的记录。

我应该如何从模型和一切开始?

标签: rubyruby-on-rails-5cancancan

解决方案


首先,您需要在数据库级别跟踪此树。为此,您可以添加对将引用创建该特定用户的用户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

根据您的用户树的特征,这个建议在效率方面很快就会变得很差,因为从所有者到根的所有用户都可能从数据库中加载以执行这些检查。如果您开始面临这些问题,这里有一些值得探索的想法:

  1. 对列使用类似数组的类型parent_ids来存储父 ID 的整个列表。我看到这个提议的主要缺点是,如果树中有更改,它会增加一些开销,并且引用完整性约束会丢失(AFAIK 在这种情况下无法添加外键)。
  2. 除了上述建议之外,修改 CanCanCan 功能以直接针对数据库运行查询,而不是在内存中进行检查(执行 ruby​​ 代码)。

推荐阅读