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)