feat(support#create): block with invisible captcha [avoid painful captcha]

This commit is contained in:
Martin 2021-12-29 14:00:47 +01:00
parent ec6c71beea
commit 252eee272b
9 changed files with 87 additions and 42 deletions

View file

@ -47,6 +47,7 @@ gem 'i18n_data'
gem 'i18n-tasks', require: false gem 'i18n-tasks', require: false
gem 'iban-tools' gem 'iban-tools'
gem 'image_processing' gem 'image_processing'
gem 'invisible_captcha'
gem 'json_schemer' gem 'json_schemer'
gem 'jwt' gem 'jwt'
gem 'kaminari', '1.2.1' # Pagination gem 'kaminari', '1.2.1' # Pagination

View file

@ -369,6 +369,8 @@ GEM
image_processing (1.12.1) image_processing (1.12.1)
mini_magick (>= 4.9.5, < 5) mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3) ruby-vips (>= 2.0.17, < 3)
invisible_captcha (2.0.0)
rails (>= 5.0)
ipaddress (0.8.3) ipaddress (0.8.3)
jquery-rails (4.4.0) jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
@ -838,6 +840,7 @@ DEPENDENCIES
i18n_data i18n_data
iban-tools iban-tools
image_processing image_processing
invisible_captcha
json_schemer json_schemer
jwt jwt
kaminari (= 1.2.1) kaminari (= 1.2.1)

View file

@ -1,4 +1,6 @@
class SupportController < ApplicationController class SupportController < ApplicationController
invisible_captcha only: [:create], on_spam: :redirect_to_root
def index def index
setup_context setup_context
end end
@ -92,4 +94,8 @@ class SupportController < ApplicationController
def email def email
current_user&.email || params[:email] current_user&.email || params[:email]
end end
def redirect_to_root
redirect_to root_path, alert: t('invisible_captcha.custom_message')
end
end end

View file

@ -25,6 +25,9 @@
= label_tag :type do = label_tag :type do
= t('.your_question') = t('.your_question')
= hidden_field_tag :type, params[:type] = hidden_field_tag :type, params[:type]
= invisible_captcha
%dl %dl
- @options.each do |(question, question_type, link)| - @options.each do |(question, question_type, link)|
%dt %dt

View file

@ -122,3 +122,5 @@ API_EDUCATION_URL="https://data.education.gouv.fr/api/records/1.0"
# Clé de chriffrement des données sensibles en base # Clé de chriffrement des données sensibles en base
ENCRYPTION_SERVICE_SALT="" ENCRYPTION_SERVICE_SALT=""
INVISIBLE_CAPTCHA_SECRET="kikooloool"

View file

@ -0,0 +1,12 @@
InvisibleCaptcha.setup do |config|
# config.honeypots << ['more', 'fake', 'attribute', 'names']
# config.visual_honeypots = false
# config.timestamp_threshold = 2
config.timestamp_enabled = !Rails.env.test?
# config.injectable_styles = false
config.spinner_enabled = !Rails.env.test?
# Leave these unset if you want to use I18n (see below)
# config.sentence_for_humans = 'If you are a human, ignore this field'
# config.timestamp_error_message = 'Sorry, that was too quick! Please resubmit.'
end

View file

@ -30,6 +30,9 @@
# available at http://guides.rubyonrails.org/i18n.html. # available at http://guides.rubyonrails.org/i18n.html.
en: en:
invisible_captcha:
custom_message: 'If you are a human, ignore this field'
help: 'Help' help: 'Help'
utils: utils:
'yes': Yes 'yes': Yes

View file

@ -20,6 +20,9 @@
# available at http://guides.rubyonrails.org/i18n.html. # available at http://guides.rubyonrails.org/i18n.html.
fr: fr:
invisible_captcha:
custom_message: 'Si vous êtes un humain, veuillez ignorer ce champs'
help: 'Aide' help: 'Aide'
utils: utils:
'yes': Oui 'yes': Oui

View file

@ -51,30 +51,11 @@ describe SupportController, type: :controller do
describe "send form" do describe "send form" do
subject do subject do
post :create, params: { subject: 'bonjour', text: 'un message' } post :create, params: params
end end
it 'creates a conversation on HelpScout' do context "when invisible captcha is ignored" do
expect_any_instance_of(Helpscout::FormAdapter).to receive(:send_form).and_return(true) let(:params) { { subject: 'bonjour', text: 'un message' } }
expect { subject }.to change(Commentaire, :count).by(0)
expect(flash[:notice]).to match('Votre message a été envoyé.')
expect(response).to redirect_to root_path(formulaire_contact_general_submitted: true)
end
context 'when a drafted dossier is mentionned' do
let(:dossier) { create(:dossier) }
let(:user) { dossier.user }
subject do
post :create, params: {
dossier_id: dossier.id,
type: Helpscout::FormAdapter::TYPE_INSTRUCTION,
subject: 'bonjour',
text: 'un message'
}
end
it 'creates a conversation on HelpScout' do it 'creates a conversation on HelpScout' do
expect_any_instance_of(Helpscout::FormAdapter).to receive(:send_form).and_return(true) expect_any_instance_of(Helpscout::FormAdapter).to receive(:send_form).and_return(true)
@ -84,33 +65,64 @@ describe SupportController, type: :controller do
expect(flash[:notice]).to match('Votre message a été envoyé.') expect(flash[:notice]).to match('Votre message a été envoyé.')
expect(response).to redirect_to root_path(formulaire_contact_general_submitted: true) expect(response).to redirect_to root_path(formulaire_contact_general_submitted: true)
end end
end
context 'when a submitted dossier is mentionned' do context 'when a drafted dossier is mentionned' do
let(:dossier) { create(:dossier, :en_construction) } let(:dossier) { create(:dossier) }
let(:user) { dossier.user } let(:user) { dossier.user }
subject do subject do
post :create, params: { post :create, params: {
dossier_id: dossier.id, dossier_id: dossier.id,
type: Helpscout::FormAdapter::TYPE_INSTRUCTION, type: Helpscout::FormAdapter::TYPE_INSTRUCTION,
subject: 'bonjour', subject: 'bonjour',
text: 'un message' text: 'un message'
} }
end
it 'creates a conversation on HelpScout' do
expect_any_instance_of(Helpscout::FormAdapter).to receive(:send_form).and_return(true)
expect { subject }.to change(Commentaire, :count).by(0)
expect(flash[:notice]).to match('Votre message a été envoyé.')
expect(response).to redirect_to root_path(formulaire_contact_general_submitted: true)
end
end end
it 'posts the message to the dossier messagerie' do context 'when a submitted dossier is mentionned' do
expect_any_instance_of(Helpscout::FormAdapter).not_to receive(:send_form) let(:dossier) { create(:dossier, :en_construction) }
let(:user) { dossier.user }
expect { subject }.to change(Commentaire, :count).by(1) subject do
post :create, params: {
dossier_id: dossier.id,
type: Helpscout::FormAdapter::TYPE_INSTRUCTION,
subject: 'bonjour',
text: 'un message'
}
end
expect(Commentaire.last.email).to eq(user.email) it 'posts the message to the dossier messagerie' do
expect(Commentaire.last.dossier).to eq(dossier) expect_any_instance_of(Helpscout::FormAdapter).not_to receive(:send_form)
expect(Commentaire.last.body).to include('[bonjour]')
expect(Commentaire.last.body).to include('un message')
expect(flash[:notice]).to match('Votre message a été envoyé sur la messagerie de votre dossier.') expect { subject }.to change(Commentaire, :count).by(1)
expect(response).to redirect_to messagerie_dossier_path(dossier)
expect(Commentaire.last.email).to eq(user.email)
expect(Commentaire.last.dossier).to eq(dossier)
expect(Commentaire.last.body).to include('[bonjour]')
expect(Commentaire.last.body).to include('un message')
expect(flash[:notice]).to match('Votre message a été envoyé sur la messagerie de votre dossier.')
expect(response).to redirect_to messagerie_dossier_path(dossier)
end
end
end
context "when invisible captcha is filled" do
let(:params) { { subject: 'bonjour', text: 'un message', InvisibleCaptcha.honeypots.sample => 'boom' } }
it 'does not create a conversation on HelpScout' do
expect { subject }.not_to change(Commentaire, :count)
expect(flash[:alert]).to eq(I18n.t('invisible_captcha.custom_message'))
end end
end end
end end