diff --git a/lib/invisible_captcha/controller_ext.rb b/lib/invisible_captcha/controller_ext.rb index 038b2b1..015582b 100644 --- a/lib/invisible_captcha/controller_ext.rb +++ b/lib/invisible_captcha/controller_ext.rb @@ -76,7 +76,12 @@ def timestamp_spam?(options = {}) end def spinner_spam? - if InvisibleCaptcha.spinner_enabled && (params[:spinner].blank? || params[:spinner] != session[:invisible_captcha_spinner]) + return false unless InvisibleCaptcha.spinner_enabled + + spinner_value = params[:spinner] + session_value = session.delete(:invisible_captcha_spinner) + + if spinner_value.blank? || spinner_value != session_value warn_spam("Spinner value mismatch") return true end diff --git a/spec/controllers_spec.rb b/spec/controllers_spec.rb index 7649cfb..8c81bfa 100644 --- a/spec/controllers_spec.rb +++ b/spec/controllers_spec.rb @@ -242,26 +242,38 @@ def custom_timestamp_callback end context 'spinner attribute' do + let(:spinner_value) do + '32ab649161f9f6faeeb323746de1a25d' + end + + let(:valid_params) do + { title: 'foobar', author: 'author', body: 'body that passes validation' } + end + before(:each) do InvisibleCaptcha.spinner_enabled = true InvisibleCaptcha.secret = 'secret' session[:invisible_captcha_timestamp] = Time.zone.now.iso8601 - session[:invisible_captcha_spinner] = '32ab649161f9f6faeeb323746de1a25d' + session[:invisible_captcha_spinner] = spinner_value # Wait for valid submission sleep InvisibleCaptcha.timestamp_threshold end it 'fails with no spam, but mismatch of spinner' do - post :create, params: { topic: { title: 'foo' }, spinner: 'mismatch' } + post :create, params: { topic: valid_params, spinner: spinner_value.reverse } - expect(response.body).to be_blank + expect(response).to have_http_status(:success) + expect(flash.notice).to be_blank + expect(session).not_to have_key(:invisible_captcha_spinner) end it 'passes with no spam and spinner match' do - post :create, params: { topic: { title: 'foo' }, spinner: '32ab649161f9f6faeeb323746de1a25d' } - - expect(response.body).to be_present + post :create, params: { topic: valid_params, spinner: spinner_value } + + expect(response).to have_http_status(:redirect) + expect(flash.notice).to be_present + expect(session).not_to have_key(:invisible_captcha_spinner) end end end