0

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

此问题涉及能力模型未使用 devise 和 cancan gem 从嵌套资源的第三层获取用户 ID。但是,我能够从辅助层获取用户 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

能力.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 #<User:0x5227d40>

显然有些东西没有正确设置。我一遍又一遍地浏览了每个 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
4

1 回答 1

4

问题出在这一行:

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

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

于 2013-04-23T14:45:08.723 回答