2016-01-08 3 views
0

Я пытаюсь убедиться, что люди не могут отправить действие create, если они отправляют запись с идентификатором, отличным от их собственного. Для этого я создал тест следующим образом:Rails: не удается пройти тест на создание действия

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 увеличивается на единицу, поэтому @user может создать сообщение с ID @ other_user (это правильный код, чтобы создать запись с идентификатором другого пользователя?)

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 вызывается с индексной страницы. Я подозреваю, что проблема действительно с авторизацией, так как мой тест может войти в систему пользователя и создать фактическую запись.

Может ли кто-нибудь выявить проблему?

ответ

1

Ваш код проверяет, есть ли у current_user какие-либо записи, но нет никакой проверки на user_id записи, которая будет отправлена ​​в действие create. Более того, даже если у пользователя нет записей, переменная @entries будет [], которая не является nil (поэтому correct_user никогда не будет перенаправлен на root). Правильная проверка была бы @entries.empty?, но объект был бы создан с неправильным пользователем, если у current_user уже есть некоторые записи, принадлежащие им.

Способ, которым я обычно обходился, заключается не в том, чтобы разрешить параметр user_id (с сильными параметрами) и путем установки права собственности на новые объекты на 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 
+0

Спасибо, что указали это на метод 'correct_user' - я использовал @ entries.nil? с тех пор, как Майкл Хартл использовал его в учебнике Rails. Однако изменение этого не влияет на тест. Гм! –

+0

О да, простите, я пропустил это, тест должен быть «post: create, entry: {content:« Lorem Ipsum »* 10, user_id: @other_user}'. В противном случае этот параметр id будет просто проигнорирован. – taglia

+0

Не беспокойтесь! Он не прошел тест, так как неважно, передаете ли вы 'user_id' или' id'. То же самое происходит со мной и с моим действием по обновлению - я думаю, что я еще не обошел авторизацию post/patch-действий. –

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 
Смежные вопросы