我的项目中有一个用户模型和许多其他模型,为了创建一个RBAC系统,我实现了角色和权限。用户has_and_belongs_to_many
角色和角色has_and_belongs_to_many
权限。
class Permission
include Mongoid::Document
field :ability, type: String
has_and_belongs_to_many :roles
belongs_to :permission_for, polymorphic: true, dependent: :destroy
index({ability: 1,permission_for_id: 1},unique: true)
end
class Role
include Mongoid::Document
field :name, type: String
has_and_belongs_to_many :permissions
has_and_belongs_to_many :users
belongs_to :role_for, polymorphic: true
index({name: 1,role_for_id: 1},unique: true)
end
在用户模型中,我有:
Class User
include Mongoid::Document
.
.
.
def able?(scope,model,action)
# There must be something to load and check permissions
end
end
在作用域中定义的角色 ( role_for
( 和在角色作用域中的模型(项目是作用域,任务是该作用域中的模型(中定义的权限,permission_for
.
模型中,我需要从数据库中获取数据并检查用户是否能够执行此操作,在大量数据中花费的时间太长。 我实现able?
功能很简单,它只是加载每个用户的角色和每个角色的权限,然后检查权限的能力是否等于操作,然后返回 true 或 false!
有没有 gem 或代码做类似的事情? 如果没有,您能否给我建议,说明如何以这种方式实现角色和权限,同时减少数据库负载?
许许多多的塔恩克
编辑 1
好的,我已经创建了这种关系并设法在我的模型中使用它,正常使用时的性能还可以,但是当我想获取大量数据时,它非常慢。我需要在作用域模型中缓存角色和权限,我该怎么做?有没有轨道插件可以为我做到这一点?
我们的产品接近软启动,我实施了该解决方案,但进行了细微调整:
我是如何做到的 RBAC:
项目<---角色<--->权限--->任务 ^ (能力( | | V 用户(能够?
此架构是最终实现的非常简化的版本,但概念是相同的
如果用户的相关角色女巫与模型相关的所有权限的联合具有能力,则User.able?(model,ability)
返回 true。
权限>>查看编辑删除 V 角色-------------------------------- 1 真假假 2 真真假 3 假真假 -------------------------------- 结果 真 真 假
我的情况是用户具有角色 1,2,3,然后用户可以view
,edit
但不能delete
为了解决性能问题和数据库命中使用俄罗斯娃娃缓存,对于每个角色,我缓存权限的哈希表示:
role.get_permissions
# returns {modelID => ['view'], model2ID => ['view','edit']}
然后为用户合并所有这些哈希值,并再次缓存该新哈希值。
在每次调用用户类able?
方法时,我都会获得该哈希(从缓存中或如果更改,则从数据库中生成新哈希值(和作业完成:)
我们关于此缓存的最严重问题是缓存过期。所以我们决定为我们的ORM(MongoID(添加新功能。
在角色中添加或删除权限将更新角色模型中的属性(不更新其时间戳(
对于添加/删除/编辑角色上的角色用户,我们这样做,也这样做,也为项目角色关系。
但是对于任务权限,我们什么也没做,因为权限永远不会改变(能力和 ID 很重要(。
对于角色权限关系更新不会触发角色update_permission。
希望这对任何人的帮助都能达到这一点。