Pundit:在嵌套资源中使用auhorize Index

Gal*_*len 3 authorization nested ruby-on-rails-4 pundit

使用Rails 4.2.4与Devise(3.5.2)和Pundit(1.0.1).Decent_exposure(2.3.2).

我有一个简单的嵌套关联用户和想法:

class User < ActiveRecord::Base
has_many :ideas
...

class Idea < ActiveRecord::Base
belongs_to :user
...
Run Code Online (Sandbox Code Playgroud)

在routes.rb中

devise_for :users

resources :users do
  resources :ideas
end
Run Code Online (Sandbox Code Playgroud)

然后我只是试图禁止访问users/1/ideas如果current_user不是Ideas的所有者(在本例中,如果current_user.id!= 1).我无法弄清楚该怎么做.我能够在Index视图中只显示current_user Ideas:

[创意控制器]

def show
  authorize idea
end
Run Code Online (Sandbox Code Playgroud)

[思想政策]

def show?
  @current_user == @idea.user
end
Run Code Online (Sandbox Code Playgroud)

但是,如何阻止用户只是导航到其他用户的Idea索引页面?我想在Ideas控制器中我应该使用类似的东西:

def index
  authorize user
end
Run Code Online (Sandbox Code Playgroud)

但那又怎样?如何向用户政策发送有关Idea集合的信息?或者我应该通过创意政策本身进行授权?

dee*_*our 8

在GitHub上复制我的回复,因为这会获得更多流量.


一种方法是创建Idea用户拥有的存根以进行授权.

def index
  @user = User::find(params[:user_id])
  idea  = Idea.new(user_id: @user.id)

  authorize idea

  # ...
end
Run Code Online (Sandbox Code Playgroud)

index?你的方法IdeaPolicy

def index?
  record.user_id = user.id
end
Run Code Online (Sandbox Code Playgroud)

另一种方法是改变你要授权的内容.而不是授权反对Idea,授权反对User.

def index
  @user = User::find(params[:user_id])

  authorize @user, :show_ideas?

  # ...
end
Run Code Online (Sandbox Code Playgroud)

并为show_ideas?您创建一个新方法UserPolicy

def show_ideas?
  user.id == record.id
end
Run Code Online (Sandbox Code Playgroud)

  • @SzilardMagyar第一条路对我好.第二种方法,虽然乍一看可能更具可读性,但在我看来,污染了"UserPolicy".我更愿意将政策行动视为尽可能粗暴:`索引?新?创建?编辑?更新?毁灭?`.当我开始考虑创建像'can_apply_batch_action?'这样的动作时,它通常意味着我试图对错误的模型进行授权. (5认同)