如何正确授权使用devise和cancan嵌套的资源?我已经从文档中实现了建议的过程但没有成功。
此问题涉及能力模型使用设计和cancan gems无法从嵌套资源的第三层层获取用户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 #<User:0x5227d40>
显然,某些设置未正确设置。我已经遍历了每个宝石的文档,以及在各处搜索寻找解决方案。
我还将在下面提供我的模型关系。
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
答案 0 :(得分:4)
问题出在这一行:
can :read, :all, user_id: user.id
当您检查用户是否可以阅读某些内容时,它会检查您要阅读的内容。
由于你的控制器中有这一行:
load_and_authorize_resource :user
您尝试授权的资源是用户。
您的能力会将user.user_id
与current_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
这样,用户只能访问与他有关系的那些模型。