diff --git a/Gemfile b/Gemfile
index 876ff1e07..2b0cae0a2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -35,7 +35,7 @@ gem 'foundation-rails'
gem 'foundation_rails_helper'
gem 'acts_as_votable'
gem 'ckeditor', '~> 4.1.5'
-gem 'invisible_captcha'
+gem 'invisible_captcha', git: 'https://github.com/kikito/invisible_captcha', branch: 'timestamp_in_session'
gem 'cancancan'
gem 'social-share-button', git: 'https://github.com/huacnlee/social-share-button.git', ref: 'e46a6a3e82b86023bc'
gem 'initialjs-rails', '0.2.0.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6502986af..2d1ec45d4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -7,6 +7,14 @@ GIT
coffee-rails
sass-rails
+GIT
+ remote: https://github.com/kikito/invisible_captcha
+ revision: b5c6ebe4cfaa029012de7279314ce26709d80199
+ branch: timestamp_in_session
+ specs:
+ invisible_captcha (0.8.1)
+ rails
+
GEM
remote: https://rubygems.org/
specs:
@@ -202,8 +210,6 @@ GEM
terminal-table (>= 1.5.1)
initialjs-rails (0.2.0.1)
railties (>= 3.1, < 5.0)
- invisible_captcha (0.8.1)
- rails
jquery-rails (4.1.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@@ -469,7 +475,7 @@ DEPENDENCIES
groupdate
i18n-tasks
initialjs-rails (= 0.2.0.1)
- invisible_captcha
+ invisible_captcha!
jquery-rails
jquery-ui-rails
kaminari
diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb
index 40e198148..e077e5e8a 100644
--- a/app/controllers/debates_controller.rb
+++ b/app/controllers/debates_controller.rb
@@ -11,6 +11,8 @@ class DebatesController < ApplicationController
feature_flag :debates
+ invisible_captcha only: [:create, :update], honeypot: :subtitle
+
has_orders %w{hot_score confidence_score created_at relevance}, only: :index
has_orders %w{most_voted newest oldest}, only: :show
diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb
index 9153df449..8ec71b8f6 100644
--- a/app/controllers/proposals_controller.rb
+++ b/app/controllers/proposals_controller.rb
@@ -10,6 +10,8 @@ class ProposalsController < ApplicationController
before_action :load_geozones, only: [:edit, :map, :summary]
before_action :authenticate_user!, except: [:index, :show, :map, :summary]
+ invisible_captcha only: [:create, :update], honeypot: :subtitle
+
has_orders %w{hot_score confidence_score created_at relevance}, only: :index
has_orders %w{most_voted newest oldest}, only: :show
diff --git a/app/controllers/spending_proposals_controller.rb b/app/controllers/spending_proposals_controller.rb
index 64172ed56..3f590f414 100644
--- a/app/controllers/spending_proposals_controller.rb
+++ b/app/controllers/spending_proposals_controller.rb
@@ -8,6 +8,8 @@ class SpendingProposalsController < ApplicationController
feature_flag :spending_proposals
+ invisible_captcha only: [:create, :update], honeypot: :subtitle
+
respond_to :html, :js
def index
diff --git a/app/views/debates/_form.html.erb b/app/views/debates/_form.html.erb
index 2e19b5d2b..30152b366 100644
--- a/app/views/debates/_form.html.erb
+++ b/app/views/debates/_form.html.erb
@@ -1,5 +1,8 @@
<%= form_for(@debate) do |f| %>
+
+
<%= render 'shared/errors', resource: @debate %>
+
<%= f.label :title, t("debates.form.debate_title") %>
@@ -11,6 +14,8 @@
<%= f.cktext_area :description, maxlength: Debate.description_max_length, ckeditor: { language: I18n.locale }, label: false %>
+ <%= f.invisible_captcha :subtitle %>
+
<%= f.label :tag_list, t("debates.form.tags_label") %>
<%= t("debates.form.tags_instructions") %>
diff --git a/app/views/proposals/_form.html.erb b/app/views/proposals/_form.html.erb
index 4b37ae554..3eda38cd1 100644
--- a/app/views/proposals/_form.html.erb
+++ b/app/views/proposals/_form.html.erb
@@ -8,6 +8,8 @@
+ <%= f.invisible_captcha :subtitle %>
+
<%= f.label :question, t("proposals.form.proposal_question") %>
diff --git a/app/views/spending_proposals/_form.html.erb b/app/views/spending_proposals/_form.html.erb
index 083d04861..2976b1803 100644
--- a/app/views/spending_proposals/_form.html.erb
+++ b/app/views/spending_proposals/_form.html.erb
@@ -7,6 +7,8 @@
<%= f.text_field :title, maxlength: SpendingProposal.title_max_length, placeholder: t("spending_proposals.form.title"), label: false %>
+ <%= f.invisible_captcha :subtitle %>
+
<%= f.label :description, t("spending_proposals.form.description") %>
<%= f.cktext_area :description, maxlength: SpendingProposal.description_max_length, ckeditor: { language: I18n.locale }, label: false %>
diff --git a/config/initializers/invisible_captcha.rb b/config/initializers/invisible_captcha.rb
new file mode 100644
index 000000000..0dd1c5a5c
--- /dev/null
+++ b/config/initializers/invisible_captcha.rb
@@ -0,0 +1,8 @@
+InvisibleCaptcha.setup do |config|
+ config.visual_honeypots = false
+ config.timestamp_threshold = 4.seconds
+ # Leave these unset if you want to use I18n (see below)
+ # config.error_message = 'You are a robot!'
+ # config.sentence_for_humans = 'If you are a human, ignore this field'
+ # config.timestamp_error_message = 'Sorry, that was too quick! Please resubmit.'
+end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f3002983b..57dcb4e87 100755
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -582,3 +582,8 @@ en:
text_sign_in: "login"
text_sign_up: "sign up"
alt: "Select the text you want to comment and press the button with the pencil."
+ invisible_captcha:
+ sentence_for_humans: "If you are human, ignore this field"
+ error_message: "Robot activity detected"
+ timestamp_error_message: "Sorry, that was too quick! Please resubmit."
+
diff --git a/config/locales/es.yml b/config/locales/es.yml
index dfd00b2f0..84cafe4d2 100755
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -582,3 +582,7 @@ es:
text_sign_in: "iniciar sesión"
text_sign_up: "registrarte"
alt: "Selecciona el texto que quieres comentar y pulsa en el botón con el lápiz."
+ inv invisible_captcha:
+ sentence_for_humans: "Si eres humano, por favor ignora este campo"
+ error_message: "Eres un robot!"
+ timestamp_error_message: "Eso ha sido demasiado rápido. Por favor, reenvía el formulario."
diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb
index c2d8c5aaf..f37896c6a 100644
--- a/spec/features/proposals_spec.rb
+++ b/spec/features/proposals_spec.rb
@@ -145,6 +145,29 @@ feature 'Proposals' do
expect(page).to have_content I18n.l(Proposal.last.created_at.to_date)
end
+ scenario 'Create with invisible_captcha honeypot field' do
+ # Display the honeypot so capybara can fill it as a spammer would do
+ allow(InvisibleCaptcha).to receive(:visual_honeypots).and_return(true)
+
+ author = create(:user)
+ login_as(author)
+
+ visit new_proposal_path
+ fill_in 'proposal_title', with: 'I am a bot'
+ fill_in 'proposal_subtitle', with: 'This is the honeypot field'
+ fill_in 'proposal_question', with: 'This is a question'
+ fill_in 'proposal_summary', with: 'This is the summary'
+ fill_in 'proposal_description', with: 'This is the description'
+ fill_in 'proposal_external_url', with: 'http://google.com/robots.txt'
+ fill_in 'proposal_responsible_name', with: 'Some other robot'
+ check 'proposal_terms_of_service'
+
+ click_button 'Create proposal'
+
+ expect(page).to_not have_content 'Proposal created successfully.'
+ expect(current_path).to eq(root_path)
+ end
+
scenario 'Responsible name is stored for anonymous users' do
author = create(:user)
login_as(author)