我使用Devise进行身份验证,使用Rolify进行角色管理,使用CanCan 2.0进行授权。
我正在尝试允许:admin角色更改用户的角色,但禁止所有其他用户访问。
以下是我尝试过但不起作用的内容:
#ability.rb
class Ability
include CanCan::Ability
def initialize(user)
if user.has_role? :admin
can :access, :all
elsif user.has_role? :moderator
can [:index, :read, :update, :destroy], :users, :user_id => user.id
cannot :access, :users, [:role_ids]
end
end
#application_controller.rb
...
rescue_from CanCan::Unauthorized do |exception|
redirect_to root_url, :alert => exception.message
end
我故意以用户身份离开了该协会:
#_form.html.erb
<%= simple_form_for @user do |f| %>
<%= f.association :roles, as: :check_boxes %>
<%#= f.association :roles, as: :check_boxes if can? :update, @user, :roles %>
<%= f.button :submit %>
<% end %>
控制器
#users_controller.rb
class UsersController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource
def index
@users = User.accessible_by(current_ability)
end
def new
@user = User.new
end
def create
@user = User.new(params[:user])
end
def show
@user = User.find(params[:id])
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find(params[:id])
@user.update_without_password(params[:user])
if successfully_updated
redirect_to @user
else
render :action => "edit"
end
end
end
和模型:
#user.rb
class User < ActiveRecord::Base
rolify
attr_accessible :role_ids
...
现在,如果角色为:moderator的用户尝试更改其他用户(或他自己的)角色,则会发生以下情况:
我很困惑。如果发生异常,为什么还要进行更改?我可能做错了什么:)
我试过根据users_controller.rb中的用户角色来操作查询参数如果我在def更新后立即放置一个日志语句,这是我的输出:
2013-04-24 12:42:21 [4161] DEBUG (0.1ms) BEGIN
2013-04-24 12:42:21 [4161] DEBUG (0.3ms) INSERT INTO "users_roles" ("user_id", "role_id") VALUES (5, 1)
2013-04-24 12:42:21 [4161] DEBUG (0.4ms) COMMIT
2013-04-24 12:42:21 [4161] DEBUG User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", "5"]]
2013-04-24 12:42:21 [4161] DEBUG {"username"=>"Blabla", "email"=>"bla@bla.com", "password"=>"", "password_confirmation"=>"", "approved"=>"1", "role_ids"=>["1", "2", ""]}
我必须忽略一些事情......
答案 0 :(得分:1)
首先,你可能想要清理自己的能力,因为目前似乎有些困惑。忽略其他所有内容,为清晰起见,指定修改密码的自定义操作可能是个好主意。例如:
# ability.rb
def initialize(user)
...
cannot :manage_roles, :user
if user.has_role? :admin
can :manage_roles, :user
else
end
(你准备用其他规则来实现什么目前?目前看来你是否让主持人只阅读,编辑和删除,这是你想要的吗?)
您可能希望隐藏或停用表单中的角色部分,以供任何无法对其执行任何操作的人:
#_form.html.erb
<%= simple_form_for @user do |f| %>
<%= f.association :roles, as: :check_boxes if can? :manage_roles, @user %>
<%= f.button :submit %>
<% end %>
(注意can?
只接受两个参数,即动作和对象/类。)
如果您想要更加安全,还可以在控制器中使用以下检查:
# users_controller.rb
def update
@user = User.find(params[:id])
user_params = params[:user]
if cannot? :manage_roles, @user
user_params.delete_if { |k, v| k.to_sym == :role_ids }
end
if @user.update_without_password(user_params)
redirect_to @user
else
render :action => "edit"
end
end
(你需要仔细检查从params散列中删除的正确密钥是什么,我根据你的:role_ids
假设attr_accessible
,但我不知道#39;我真的非常了解simple_form。)
答案 1 :(得分:0)
将角色包含在users/_form.html.erb
文件中:
用简单的形式:
<% if can? :manage, User %>
<%= f.association :roles, as: :check_boxes %>
<% end %>
没有简单的形式:
<% if can? :manage, User %>
<div class="control-group">
<%= f.label :roles, class: "control-label" %>
<div class="controls">
<% Role.all.each do |role| %>
<%= check_box_tag "user[role_ids][]", role.id, @user.role_ids.include?(role.id) %>
<%= role.name %><br />
<% end %>
</div>
</div>
<% end %>
答案 2 :(得分:0)
我不确定我是否理解你希望主持人做什么,但这里是我使用的基本配置。我尽可能地适应你的情景。如果主持人不需要个人权利,只需删除内部条款。
class Ability
include CanCan::Ability
def initialize(user)
# Create guest user aka. anonymous (not logged-in) when user is nil.
user ||= User.new
if user.has_role? :admin
can :manage, :all
elsif user.has_role? :moderator
can :manage, User, user_id: user.id
can :create, User
can :read, :all
else
# Guest user aka. anonymous
can :read, :all
end
end
end
答案 3 :(得分:0)
我最终使用了before_filter,如下所示:
before_filter :prevent_unauthorized_role_setting, :only => [ :create, :update ]
def prevent_unauthorized_role_setting
if cannot? :manage_roles, current_user
params[:user].delete_if { |k, v| k.to_sym == :role_ids }
end
end
同时遵循Zaid在ability.rb中的建议:
cannot :manage_roles, :users
if user.has_role? :admin
can :manage_roles, :users
end
此外,我放弃了Rolify并自行管理角色。