【问题标题】:Nested resource authorization with devise and cancan使用 devise 和 cancan 进行嵌套资源授权
【发布时间】:2013-04-22 22:19:00
【问题描述】:

如何正确授权嵌套在 devise 和 cancan 中的资源?我已经实施了文档中建议的程序,但没有成功。

此问题涉及能力模型未使用 devise 和 cancan gem 从嵌套资源的 第三层 层获取用户 ID。但是,我可以从 secondary 层获取用户 ID。非常感谢任何帮助!

我有一个这样的嵌套资源:

  resources :users do
    resources :clients do
      resources :positions
    end
  end

  resources :clients do
    resources :positions
  end

  resources :users do
    resources :positions
  end

  resources :users
  resources :clients
  resources :positions 

使用position 模型控制器使用以下内容:

class PositionsController < ApplicationController
  before_filter :grab_client_from_client_id
  load_and_authorize_resource :user
  load_and_authorize_resource :client, through: :user, shallow: true
  load_and_authorize_resource :position, through: :client, except: [:index], shallow: true
  ...
end

ability.rb 文件:

class Ability
  include CanCan::Ability

  def initialize(user)

    user ||= User.new # guest user (not logged in)

    if user.has_role? :admin
      can :manage, :all
    elsif user.has_role? :management
      can [:create, :read, :update], :all
    else
      can :read, :all, user_id: user.id
    end

  end
end

这会导致非管理员/非管理用户收到以下错误:

undefined method 'user_id' for #&lt;User:0x5227d40&gt;

显然有些东西没有正确设置。我一遍又一遍地浏览了每个 gem 的文档,并到处寻找解决方案。

我还将在下面提供我的模型关系。


class User < ActiveRecord::Base
  has_many :clients
  has_many :positions, through: :clients
  resourcify
  ...
end


class Client < ActiveRecord::Base
  resourcify
  has_many :checklogs
  has_many :positions
  belongs_to :user
end


class Position < ActiveRecord::Base
  resourcify
  belongs_to :client
  delegate :user, to: :client, allow_nil: true
end

【问题讨论】:

    标签: ruby-on-rails ruby devise ruby-on-rails-3.2 cancan


    【解决方案1】:

    问题出在这一行:

    can :read, :all, user_id: user.id
    

    当您检查用户是否可以阅读某些内容时,它会检查您正在尝试阅读的内容。

    由于您的控制器中有这一行:

    load_and_authorize_resource :user
    

    您尝试授权的资源是用户。

    您的能力会将user.user_idcurrent_user.id 进行比较。用户没有user_id,所以这就是错误的来源。

    根据您的代码,我怀疑您希望用户只能阅读属于他的内容,除非他是经理或管理员。

    您可以通过以下方式实现此目的:

    if user.has_role? :admin
      can :manage, :all
    elsif user.has_role? :management
      can [:create, :read, :update], :all
    else
      can :read, User, id: user.id
      can :read, Client, user_id: client.id
      can :read, Position, client: { user_id: user.id }
    end
    

    这样用户只能访问那些与他有关系的模型。

    【讨论】:

    • 谢谢!这就是我一直在寻找的。​​span>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多