我试图确保如果人们提交的ID不是他们自己的ID,那么他们就无法提交create
行为。为此,我将测试设置如下:
entries_controller_test.rb
def setup
@user = users(:thierry)
@other_user = users(:steve)
end
...
test "should redirect create action on entry with id that doesn't belong to you" do
log_in_as(@user)
assert_no_difference 'Entry.count' do
post :create, entry: { content: "Lorem Ipsum"*10, id: @other_user }
end
end
测试的结果是Entry.count
增加1,因此@user可以使用ID @other_user创建一个帖子(代码是否正确以创建具有其他用户ID的条目?)
entries_controller.rb :我的create
操作目前看起来像这样。
def create
@entry = @entries.build(entry_params)
if @entry.save
flash[:success] = "Your entry has been saved."
redirect_to root_path
else
flash.now[:danger] = "Your entry has not been saved."
render 'index'
end
end
通过在操作上调用before_action :correct_user
将实例变量传递给操作。这是correct_user method
。
def correct_user
@entries = current_user.entries
redirect_to root_url if @entries.nil?
end
顺便说一下,正在从索引页面调用create动作。我怀疑问题确实是授权的,因为我的测试可以登录用户并创建一个实际的条目。
有人能发现问题吗?
答案 0 :(得分:1)
您的代码仅检查current_user是否包含某些条目,但是对提交给create操作的条目的user_id没有验证。此外,即使用户没有条目,@entries
变量也将是[]
,而不是nil
(因此correct_user永远不会重定向到root)。正确的检查将是@entries.empty?
,但是仍然会使用不正确的用户创建对象,只要current_user已经有一些属于它们的条目。
我通常采用的方法是不允许user_id参数(使用strong_parameters),并将新对象的所有权设置为current_user。如果要执行检查,您的correct_user应该看起来更像这样:
def correct_user
unless current_user.id == params[:entry][:user_id]
flash[:alert] = "Some error message"
sign_out # This action looks like a hack attempt, thus it's better to destroy the session logging the user out
redirect_to root_url
end
end
答案 1 :(得分:0)
我认为这可能有用。
在您的条目控制器中。
class EntriesController < ApplicationController
before_action :correct_user, only: [:edit, :update]
def correct_user
unless correct_user.id == params[:entry][:user_id]
else
redirect_to root_url
end
end
end