Merge pull request #10016 from mfo/US/fix-monavis
secu(monavis): autorise uniquement les bouton mon avis des domaines (jedonnemonavis'|monavis|voxusagers).numerique.gouv.fr
This commit is contained in:
commit
da19ba5fe4
3 changed files with 69 additions and 4 deletions
|
@ -1,9 +1,31 @@
|
|||
# We need to ensure the embed code is not any random string in order to avoid injections
|
||||
class MonAvisEmbedValidator < ActiveModel::Validator
|
||||
class MonAvisEmbedError < StandardError; end
|
||||
# from time to time, they decide to change domain just for fun. if it breaks, check the new subdomain
|
||||
KNOWN_SUBDOMAIN = ['jedonnemonavis', 'monavis', 'voxusagers']
|
||||
HREF_CHECKER = /https:\/\/#{KNOWN_SUBDOMAIN.join('|')}.numerique.gouv.fr\/Demarches\/\d+.*key=[[:alnum:]]+.*/
|
||||
IMG_CHECKER = /https:\/\/#{KNOWN_SUBDOMAIN.join('|')}.numerique.gouv.fr\/(monavis-)?static\/bouton-blanc|bleu.png|svg/
|
||||
|
||||
def validate(record)
|
||||
# We need to ensure the embed code is not any random string in order to avoid injections
|
||||
r = Regexp.new('<a href="https://monavis|voxusagers.numerique.gouv.fr/Demarches/\d+.*key=[[:alnum:]]+.*">\s*<img src="https://monavis|voxusagers.numerique.gouv.fr/(monavis-)?static/bouton-blanc|bleu.png|svg" alt="Je donne mon avis" (title="Je donne mon avis sur cette démarche" )?/>\s*</a>', Regexp::MULTILINE)
|
||||
if record.monavis_embed.present? && !r.match?(record.monavis_embed)
|
||||
record.errors.add :base, :invalid, message: "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme."
|
||||
if record.monavis_embed.present?
|
||||
embed = Nokogiri::HTML(record.monavis_embed)
|
||||
check_link(embed.css('a'))
|
||||
check_img(embed.css('img'))
|
||||
end
|
||||
rescue MonAvisEmbedError => e
|
||||
record.errors.add :base, :invalid, message: "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme. #{e.message}"
|
||||
rescue # nokogiri
|
||||
record.errors.add :base, :invalid, message: "Le code fourni ne correspond pas au format des codes MonAvis reconnus par la plateforme."
|
||||
end
|
||||
|
||||
def check_link(links)
|
||||
raise MonAvisEmbedError.new("le code monavis doit comporter un seul lien") if links.size != 1
|
||||
raise MonAvisEmbedError.new("le lien du bouton mon avis doit pointer vers le bon domaine") if !HREF_CHECKER.match?(links.first['href'])
|
||||
end
|
||||
|
||||
def check_img(imgs)
|
||||
raise MonAvisEmbedError.new("le code monavis doit comporter une seule image") if imgs.size != 1
|
||||
raise MonAvisEmbedError.new("l'image du bouton mon avis ne pointe pas vers le bon domaine") if !IMG_CHECKER.match?(imgs.first['src'])
|
||||
raise MonAvisEmbedError.new("l'image du bouton mon avis n'a pas d'attribut alt") if imgs.first['alt'].blank?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
namespace :after_party do
|
||||
desc 'Deployment task: disable_invalid_monavis'
|
||||
task disable_invalid_monavis: :environment do
|
||||
puts "Running deploy task 'disable_invalid_monavis'"
|
||||
# rubocop:disable DS/Unscoped
|
||||
all_procedures = Procedure.unscoped.where.not(monavis_embed: nil)
|
||||
# rubocop:enable DS/Unscoped
|
||||
progress = ProgressReport.new(all_procedures.count)
|
||||
|
||||
all_procedures.find_each do |procedure|
|
||||
if !procedure.valid? && procedure.errors.key?(:monavis_embed)
|
||||
procedure.update_column(:monavis_embed, '')
|
||||
rake_puts "fix: #{procedure.id}"
|
||||
end
|
||||
progress.inc(1)
|
||||
end
|
||||
progress.finish
|
||||
# Update task as completed. If you remove the line below, the task will
|
||||
# run with every deploy (or every time you call after_party:run).
|
||||
AfterParty::TaskRecord
|
||||
.create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
|
||||
end
|
||||
end
|
|
@ -294,6 +294,26 @@ describe Procedure do
|
|||
let(:procedure) { build(:procedure, monavis_embed: monavis_issue_bouchra) }
|
||||
it { expect(procedure.valid?).to eq(true) }
|
||||
end
|
||||
|
||||
context 'Monavis embed code with jedonnemonavis' do
|
||||
monavis_jedonnemonavis = <<-MSG
|
||||
<a href="https://jedonnemonavis.numerique.gouv.fr/Demarches/3839?&view-mode=formulaire-avis&nd_source=button&key=6af80846f64fb213abcabaeea7a3ea8c">
|
||||
<img src="https://jedonnemonavis.numerique.gouv.fr/static/bouton-bleu.svg" alt="Je donne mon avis" />
|
||||
</a>
|
||||
MSG
|
||||
let(:procedure) { build(:procedure, monavis_embed: monavis_jedonnemonavis) }
|
||||
it { expect(procedure.valid?).to eq(true) }
|
||||
end
|
||||
|
||||
context 'Monavis embed code with kthxbye' do
|
||||
monavis_jedonnemonavis = <<-MSG
|
||||
<a href="https://kthxbye.fr/?key=6af80846f64fb213abcabaeea7a3ea8c">
|
||||
<img src="https://kthxbye.fr/static/bouton-bleu.svg" alt="Je donne mon avis" />
|
||||
</a>
|
||||
MSG
|
||||
let(:procedure) { build(:procedure, monavis_embed: monavis_jedonnemonavis) }
|
||||
it { expect(procedure.valid?).to eq(false) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'duree de conservation dans ds' do
|
||||
|
|
Loading…
Reference in a new issue