我正在尝试用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我一遍又一遍地阅读文档,但我不知道我的错在哪里。
发布于 2019-11-28 16:53:55
几点不同的评论:
在你的ability.rb里我会说用
if user.role.name == 'admin'而不是
if user.role.id == 5因为除非您手动设置ids,否则您很可能不得不为了生产而更改这个ids。
也是
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但在你的情况下,我想通过模型授权是你最好的途径。
发布于 2019-11-28 17:11:41
能力的定义应该是:
can :update, Price if user.role.id == 3你授权模特-不是控制器。
调用授权时,如果没有实例,则应传递要更新的资源实例或类:
authorize! :read, @thing
authorize! :index, Thing但是控制器本身是从根本上破坏的,这与CanCanCan无关。这就是一切分崩离析的地方:
@prices.where(description: params[:description]).update(price_params)where返回一个记录集合-- #update是在上调用的一个方法,一个记录。我不知道这是一个非常天真和失败的尝试大规模更新,或您是否试图做一些类似弹格列(漂亮的urls)。但是,您可能应该坚持rails的约定,直到您知道自己在做什么:
def update
@price = Price.find(params[:id])
authorize!(:update, @price)
if @price.update
# ...
else
# ...
end
end在这种情况下,您也可以只使用load_and_authorize_resource,而不是手动查找和授权。
https://stackoverflow.com/questions/59092732
复制相似问题