Rails:无法通过测试来传递创建操作

时间:2016-01-08 01:53:14

标签: ruby-on-rails ruby ruby-on-rails-4

我试图确保如果人们提交的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动作。我怀疑问题确实是授权的,因为我的测试可以登录用户并创建一个实际的条目。

有人能发现问题吗?

2 个答案:

答案 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