Rails授权CanCanCan
Rails authorization CanCanCan
我正在尝试使用 CanCanCan 对路由实施一些授权 gem 但对于某些路由,它不起作用,它要么始终授权,要么根本不授权。
我只希望角色 ID 为 5 (admin) 的用户访问价格控制器的更新操作,这是我的 ability.rb 代码:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
# Define abilities for the passed in user here. For example:
if user.present?
can :show, User
if user.role.id == 5
can [:index, :update, :create], User
end
can :update, PricesController if user.role.id == 3
#
# The first argument to `can` is the action you are giving the user
# permission to do.
# If you pass :manage it will apply to every action. Other common actions
# here are :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on.
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
# class of the resource.
#
# The third argument is an optional hash of conditions to further filter the
# objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
end
end
end
索引等的第一个动作工作正常,第二个动作,我调试了角色 ID 也被正确找到。所以故障必须在我的控制器中,这是我的代码:
def update
authorize! :update, current_user
if @prices.where(description: params[:description]).update(price_params)
respond_to do |format|
format.html { redirect_to prices_path }
format.json { render json: @prices }
end
end
end
如果我使用 current_user
来检查授权方法,每个人都可以更改值,如果我使用 @prices
的实例变量,那么没有人可以执行控制器操作。
我也在处理异常:
rescue_from CanCan::AccessDenied do |e|
respond_to do |format|
format.html { redirect_to current_user, flash: { alert: "Sie besitzen dafür keine Berechtigung!" } }
format.json { render json: { success: false }, status: 401 }
end
end
看了一遍又一遍的文档,还是想不出我的错在哪里。
一些不同的评论:
在你的 ability.rb 我会说使用
if user.role.name == 'admin'
而不是
if user.role.id == 5
因为除非您手动设置您的 ID,否则您可能必须更改它以用于生产。
还有
can :update, PricesController if user.role.id == 3
应该是
can :update, Price if user.role.id == 3
并在您的控制器中替换
authorize! :update, current_user
与
authorize! :update, Price
通常在 rails 更新操作中,您将只更新一个对象,并使用以下方式授权它:
authorize! :update, @price
但在你的情况下,我猜想通过模型授权是你的最佳途径。
能力定义应该是:
can :update, Price if user.role.id == 3
您授权模型 - 而不是控制器。
当调用授权时,你应该传递你正在更新的资源实例或者 class 如果没有实例:
authorize! :read, @thing
authorize! :index, Thing
但是控制器本身以一种与 CanCanCan 无关的方式从根本上被破坏了。这就是一切分崩离析的地方:
@prices.where(description: params[:description]).update(price_params)
where
returns 一组记录 - #update
是一种在 单个记录 上调用的方法。我不知道这是否是一次非常幼稚且失败的大规模更新尝试,或者您是否正在尝试做类似 slug 列(漂亮的 url)的事情。但是你可能应该坚持 rails 约定,直到你知道自己在做什么:
def update
@price = Price.find(params[:id])
authorize!(:update, @price)
if @price.update
# ...
else
# ...
end
end
在这种情况下您也可以只使用load_and_authorize_resource
而不是手动查找和授权。
我正在尝试使用 CanCanCan 对路由实施一些授权 gem 但对于某些路由,它不起作用,它要么始终授权,要么根本不授权。
我只希望角色 ID 为 5 (admin) 的用户访问价格控制器的更新操作,这是我的 ability.rb 代码:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
# Define abilities for the passed in user here. For example:
if user.present?
can :show, User
if user.role.id == 5
can [:index, :update, :create], User
end
can :update, PricesController if user.role.id == 3
#
# The first argument to `can` is the action you are giving the user
# permission to do.
# If you pass :manage it will apply to every action. Other common actions
# here are :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on.
# If you pass :all it will apply to every resource. Otherwise pass a Ruby
# class of the resource.
#
# The third argument is an optional hash of conditions to further filter the
# objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
end
end
end
索引等的第一个动作工作正常,第二个动作,我调试了角色 ID 也被正确找到。所以故障必须在我的控制器中,这是我的代码:
def update
authorize! :update, current_user
if @prices.where(description: params[:description]).update(price_params)
respond_to do |format|
format.html { redirect_to prices_path }
format.json { render json: @prices }
end
end
end
如果我使用 current_user
来检查授权方法,每个人都可以更改值,如果我使用 @prices
的实例变量,那么没有人可以执行控制器操作。
我也在处理异常:
rescue_from CanCan::AccessDenied do |e|
respond_to do |format|
format.html { redirect_to current_user, flash: { alert: "Sie besitzen dafür keine Berechtigung!" } }
format.json { render json: { success: false }, status: 401 }
end
end
看了一遍又一遍的文档,还是想不出我的错在哪里。
一些不同的评论:
在你的 ability.rb 我会说使用
if user.role.name == 'admin'
而不是
if user.role.id == 5
因为除非您手动设置您的 ID,否则您可能必须更改它以用于生产。
还有
can :update, PricesController if user.role.id == 3
应该是
can :update, Price if user.role.id == 3
并在您的控制器中替换
authorize! :update, current_user
与
authorize! :update, Price
通常在 rails 更新操作中,您将只更新一个对象,并使用以下方式授权它:
authorize! :update, @price
但在你的情况下,我猜想通过模型授权是你的最佳途径。
能力定义应该是:
can :update, Price if user.role.id == 3
您授权模型 - 而不是控制器。
当调用授权时,你应该传递你正在更新的资源实例或者 class 如果没有实例:
authorize! :read, @thing
authorize! :index, Thing
但是控制器本身以一种与 CanCanCan 无关的方式从根本上被破坏了。这就是一切分崩离析的地方:
@prices.where(description: params[:description]).update(price_params)
where
returns 一组记录 - #update
是一种在 单个记录 上调用的方法。我不知道这是否是一次非常幼稚且失败的大规模更新尝试,或者您是否正在尝试做类似 slug 列(漂亮的 url)的事情。但是你可能应该坚持 rails 约定,直到你知道自己在做什么:
def update
@price = Price.find(params[:id])
authorize!(:update, @price)
if @price.update
# ...
else
# ...
end
end
在这种情况下您也可以只使用load_and_authorize_resource
而不是手动查找和授权。