我尝试定义用户创建的角色,从权限列表中选择权限。 我想要这样的许可:
def initialize(user)
user.projects_users.each do |project_user|
project_user.role.privileges do |privilege|
can :create, ProjectsUser, :project_id => project_user.project_id
end
end
end
但是我试图以这样的方式保存数据库中的权限,以便我可以这样做以获得上述结果
def initialize(user)
user.projects_users.each do |project_user|
project_user.role.privileges do |privilege|
can privilege.action.to_sym, privilege.subject_class.constantize, privilege.conditions
end
end
end
问题出在' privilege.conditions'部分。我无法存储必须仅在Ability.rb文件中执行的条件。如果我试着存储:
{ :project_id => project_user.project_id }
可以说没有名为' project_user'的变量。我可以将它保存为字符串,并在我的Ability文件中执行eval(privilege.condition),但是我只需要对值进行此操作。我试过这样的事情:
def initialize(user)
user.projects_users.each do |project_user|
project_user.role.privileges do |privilege|
can privilege.action.to_sym, privilege.subject_class.constantize, privilege.conditions.each do |subject, id|
subject => eval(id)
end
end
end
end
我得到的错误是语法错误,意外=>,期待关键字_end'对于' subject =>'片。
不确定如何准确地做到这一点......
我使用这一行命令来测试它:
@user_id = 4
@role = Role.create(name: "Tester", project_id: 4)
@priv = Privilege.create(:action => :create, :subject_class => 'ProjectsUser', :conditions => { :project_id => 'project_user.project_id' })
@role.privileges << @priv
@project_user = ProjectsUser.create(:user_id => @user_id, :role_id => @role.id, :project_id => @role.project_id)
@a = Ability.new(User.find(@user_id))
@a.can?(:create, ProjectsUser.new(:user_id => @user_id + 1, :role_id => @role.id, :project_id => @role.project_id))
有什么建议吗?
答案 0 :(得分:2)
好的,所以我找到了一个非常简单的工作。基本上没有正确评估条件的do块。这是工作代码:
user.projects_users.each do |project_user|
project_user.role.privileges.each do |privilege|
can privilege.action.to_sym, privilege.subject_class.constantize, Hash[privilege.conditions.map {|subject, condition| [subject, eval(condition)] }]
end
end
注意Hash[privilege.conditions.map {|subject, condition| [subject, eval(condition)] }]
这样做是将符号作为条件,例如:subject_id并将其映射到已评估的条件,该条件评估为特定的id。
在我的模特中我有
class Privilege < ActiveRecord::Base
has_and_belongs_to_many :roles
serialize :conditions, Hash
end
示例模型是:
Privilege.create(
:action => :create,
:subject_class => 'ProjectsUser',
:conditions => { :project_id => 'project_user.project_id' }
)
<强>更新强>
此方法仅适用于深度为一级的条件。像这样的条件是行不通的。您将得到:TypeError:没有将Hash隐式转换为String
:conditions => {
:project => {
:location_id => 'project_user.project.location_id'
}
}
这不是最佳解决方案,但解决此问题的方法是
:conditions => {
:project => "{
:location_id => eval(\"project_user.project.location_id'\")
}"
}
答案 1 :(得分:1)
我肯定会说你有点倒退了。从数据库记录动态创建一堆auth规则将非常难以测试,因为测试套件中的任何地方都需要大量的设置,而且过于复杂。
而是使用块来声明复杂的关系和角色来存储权限。
使用带有作用域资源的角色Rolify gem的示例:
can :moderate, Forum do |forum|
user.has_role?(:moderator, forum)
end
您还可以使用角色为组分配权限:
if user.has_role? :admin
can :crud, User
# ...
end
我想说如果你真的需要一个复杂的完全动态的解决方案,其中管理员从Web界面创建授权规则,角色定义等,那么你肯定已经超出了CanCan。但你真的需要吗?