我的项目中有一个用户模型和许多其他模型,用于创建我实施角色和权限的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?
函数很简单,它只是加载每个用户的角色和每个角色的权限,然后检查权限的能力是否等于action,然后返回true或false!
有没有宝石或代码做那样的事情?如果没有,你能否给我建议如何以这种方式实现角色和权限,以及更少的数据库负载?
很多很多人
修改1
好的,我已经创建了这个关系并设法在我的模型中使用它,正常使用中的性能是可以的,但是当我想获得大量数据时它非常慢。我需要在范围模型中缓存角色和权限,我该怎么做呢?有没有rails的插件可以帮我吗?
答案 0 :(得分:1)
我们的产品接近软启动,我实施了该解决方案,但稍作调整:
Project <--- Role <---> Permissions ---> Task ^ (ability) | | V User (able?)
这个模式是最终实现的非常简化的版本,但概念是相同的
如果与模型相关的用户相关角色的所有权限的联合具有权限,则 User.able?(model,ability)
返回true。
permission >> View Edit Delete V Role -------------------------------- 1 true false false 2 true true false 3 false true false -------------------------------- result true true false
我的情况是用户有角色1,2,3然后用户可以view
,edit
但不能delete
解决性能问题和数据库命中使用俄语玩偶缓存,为每个角色我缓存哈希表示权限:
role.get_permissions
# returns {modelID => ['view'], model2ID => ['view','edit']}
然后为用户合并所有这些哈希值,并再次缓存新哈希值。
在用户类的able?
方法的每次调用中,我获得该哈希(来自缓存或如果更改,则从数据库生成新的)和作业完成:)
我们关于此缓存的最严重问题是缓存过期。所以我们决定为ORM(MongoID)
添加新功能在角色中添加或删除权限将更新角色模型中的属性(不更新其时间戳)
对于添加/删除/编辑角色的角色用户,我们这样做,也用于项目角色关系。
但是对于任务许可我们什么也没做,因为权限永远不会改变(能力和ID很重要)。
对于角色权限关系更新,不会触发角色的update_permission。
希望这对任何人都有帮助。