首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails授权CanCanCan

Rails授权CanCanCan
EN

Stack Overflow用户
提问于 2019-11-28 16:06:41
回答 2查看 1.6K关注 0票数 2

我正在尝试用CanCanCan gem实现对路由的一些授权,但是对于某些路由,它不起作用,无论什么授权还是根本没有授权,它都是授权的。

我希望只有角色id为5 (admin)的用户访问价格控制器的更新操作,这是我的ability.rb代码:

代码语言:javascript
复制
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也是正确的。因此,错误必须在我的控制器中,这是我的代码:

代码语言:javascript
复制
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的实例变量,那么没有人可以执行控制器操作。

我也在处理例外情况:

代码语言:javascript
复制
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

我一遍又一遍地阅读文档,但我不知道我的错在哪里。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-28 16:53:55

几点不同的评论:

在你的ability.rb里我会说用

代码语言:javascript
复制
if user.role.name == 'admin'

而不是

代码语言:javascript
复制
if user.role.id == 5

因为除非您手动设置ids,否则您很可能不得不为了生产而更改这个ids。

也是

代码语言:javascript
复制
can :update, PricesController if user.role.id == 3

应该是

代码语言:javascript
复制
can :update, Price if user.role.id == 3

在您的控制器中替换

代码语言:javascript
复制
authorize! :update, current_user

使用

代码语言:javascript
复制
authorize! :update, Price

通常,在rails更新操作中,您只更新一个对象,并使用以下方法授权它:

代码语言:javascript
复制
authorize! :update, @price

但在你的情况下,我想通过模型授权是你最好的途径。

票数 2
EN

Stack Overflow用户

发布于 2019-11-28 17:11:41

能力的定义应该是:

代码语言:javascript
复制
can :update, Price if user.role.id == 3

你授权模特-不是控制器。

调用授权时,如果没有实例,则应传递要更新的资源实例或类:

代码语言:javascript
复制
authorize! :read, @thing
authorize! :index, Thing

但是控制器本身是从根本上破坏的,这与CanCanCan无关。这就是一切分崩离析的地方:

代码语言:javascript
复制
@prices.where(description: params[:description]).update(price_params)

where返回一个记录集合-- #update是在上调用的一个方法,一个记录。我不知道这是一个非常天真和失败的尝试大规模更新,或您是否试图做一些类似弹格列(漂亮的urls)。但是,您可能应该坚持rails的约定,直到您知道自己在做什么:

代码语言:javascript
复制
def update
  @price = Price.find(params[:id])
  authorize!(:update, @price)
  if @price.update
    # ...
  else
    # ...
  end
end

在这种情况下,您也可以只使用load_and_authorize_resource,而不是手动查找和授权。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59092732

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档