User : Ajoute le type de champ Expression régulière coté utilisateur

This commit is contained in:
Kara Diaby 2023-09-29 21:09:41 +00:00
parent c22e36c35c
commit a26df43577
14 changed files with 112 additions and 8 deletions

View file

@ -0,0 +1,5 @@
class EditableChamp::ExpressionReguliereComponent < EditableChamp::EditableChampBaseComponent
def dsfr_input_classname
'fr-input'
end
end

View file

@ -0,0 +1 @@
= @form.text_field(:value, input_opts(id: @champ.input_id, placeholder: @champ.expression_reguliere_exemple_text, required: @champ.required?, aria: { describedby: @champ.describedby_id }))

View file

@ -540,6 +540,9 @@ module Users
@dossier.check_mandatory_and_visible_champs.map do |error_on_champ|
errors.import(error_on_champ)
end
@dossier.check_expressions_regulieres_champs.map do |error_on_champ|
errors.import(error_on_champ) if error_on_champ.present?
end
errors
end

View file

@ -58,6 +58,9 @@ class Champ < ApplicationRecord
:character_limit?,
:character_limit,
:yes_no?,
:expression_reguliere,
:expression_reguliere_exemple_text,
:expression_reguliere_error_message,
to: :type_de_champ
delegate :to_typed_id, :to_typed_id_for_query, to: :type_de_champ, prefix: true

View file

@ -0,0 +1,3 @@
class Champs::ExpressionReguliereChamp < Champ
validates_with ExpressionReguliereValidator, if: -> { validation_context != :brouillon }
end

View file

@ -1152,6 +1152,20 @@ class Dossier < ApplicationRecord
end
end
def check_expressions_regulieres_champs
champs_public.filter { _1.expression_reguliere && _1.visible? }.map do |champ|
if champ.value.present?
begin
if !champ.value.match(Regexp.new(champ.expression_reguliere, timeout: 5.0))
champ.errors.add(:value, :invalid)
end
rescue Regexp::TimeoutError
self.errors.add(:value, I18n.t('errors.messages.evil_regexp'))
end
end
end
end
def demander_un_avis!(avis)
log_dossier_operation(avis.claimant, :demander_un_avis, avis)
end

View file

@ -416,8 +416,11 @@ class ProcedureRevision < ApplicationRecord
def expressions_regulieres_are_valid?
types_de_champ_public.to_a
.flat_map { _1.repetition? ? children_of(_1) : _1 }
.filter { _1.expression_reguliere? && _1.invalid_regexp? }
.each { |tdc| errors.add(:expression_reguliere, type_de_champ: tdc) }
.each do |tdc|
if tdc.expression_reguliere? && tdc.invalid_regexp?
errors.add(:expression_reguliere, type_de_champ: tdc)
end
end
end
def errors_for_header_sections_order(tdcs)

View file

@ -0,0 +1,14 @@
class ExpressionReguliereValidator < ActiveModel::Validator
def validate(record)
if record.value.present?
begin
if !record.value.match?(Regexp.new(record.expression_reguliere, timeout: 5.0))
record.errors.add(:value, I18n.t('errors.messages.invalid_regexp', expression_reguliere_error_message: record.expression_reguliere_error_message))
end
rescue Regexp::TimeoutError
record.errors.add(:expression_reguliere, I18n.t('errors.messages.evil_regexp'))
end
end
end
end

View file

@ -684,6 +684,10 @@ en:
procedure_archived:
with_service_and_phone_email: This procedure has been closed, it is no longer possible to submit a file. For more information, please contact the service %{service_name}, available at %{service_phone_number} or by email %{service_email}
with_organisation_only: This procedure has been closed, it is no longer possible to submit a file. For more information, please contact the organisation %{organisation_name}
evil_regexp: The regular expression you have entered is potentially dangerous and could lead to performance issues.
mismatch_regexp: The provided example must match the regular expression
syntax_error_regexp: The syntax of the regular expression is invalid
invalid_regexp: "%{expression_reguliere_error_message}"
# # procedure_not_draft: "This procedure is not a draft anymore."
# cadastres_empty:
# one: "Aucune parcelle cadastrale sur la zone sélectionnée"

View file

@ -689,7 +689,10 @@ fr:
procedure_archived:
with_service_and_phone_email: Cette démarche en ligne a été close, il nest plus possible de déposer de dossier. Pour plus dinformations veuillez contacter le service %{service_name} au %{service_phone_number} ou par email à %{service_email}
with_organisation_only: Cette démarche en ligne a été close, il nest plus possible de déposer de dossier. Pour plus dinformations veuillez contacter le service %{organisation_name}
evil_regexp: L'expression régulière que vous avez entrée est potentiellement dangereuse et pourrait entraîner des problèmes de performance
mismatch_regexp: L'exemple doit correspondre à l'expression régulière fournie
syntax_error_regexp: La syntaxe de l'expression régulière n'est pas valide
invalid_regexp: "%{expression_reguliere_error_message}"
empty_repetition: '« %{value} » doit comporter au moins un champ répétable'
empty_drop_down: '« %{value} » doit comporter au moins un choix sélectionnable'
# procedure_not_draft: "Cette démarche nest maintenant plus en brouillon."

View file

@ -243,6 +243,10 @@ FactoryBot.define do
type_de_champ { association :type_de_champ_cojo, procedure: dossier.procedure }
end
factory :champ_expression_reguliere, class: 'Champs::ExpressionReguliereChamp' do
type_de_champ { association :type_de_champ_expression_reguliere, procedure: dossier.procedure }
end
factory :champ_repetition, class: 'Champs::RepetitionChamp' do
type_de_champ { association :type_de_champ_repetition, procedure: dossier.procedure }

View file

@ -14,9 +14,9 @@ describe '20220705164551_remove_unused_champs' do
describe 'remove_unused_champs' do
it "with bad champs" do
expect(Champ.where(dossier: dossier).count).to eq(41)
expect(Champ.where(dossier: dossier).count).to eq(42)
run_task
expect(Champ.where(dossier: dossier).count).to eq(40)
expect(Champ.where(dossier: dossier).count).to eq(41)
end
end
end

View file

@ -1575,6 +1575,50 @@ describe Dossier, type: :model do
end
end
describe "#check_expressions_regulieres_champs" do
include Logic
let(:procedure) { create(:procedure, types_de_champ_public: types_de_champ) }
let(:dossier) { create(:dossier, procedure: procedure) }
let(:types_de_champ) { [type_de_champ] }
let(:type_de_champ) { { type: :expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text: } }
let(:errors) { dossier.check_expressions_regulieres_champs }
context "with bad example" do
let(:expression_reguliere_exemple_text) { "01234567" }
let(:expression_reguliere) { "[A-Z]+" }
before do
champ = dossier.champs_public.first
champ.value = expression_reguliere_exemple_text
champ.save!
dossier.reload
end
it 'should have errors' do
expect(errors).not_to be_empty
expect(errors.first.full_message).to eq("n'est pas valide")
end
end
context "with good example" do
let(:expression_reguliere_exemple_text) { "AZERTY" }
let(:expression_reguliere) { "[A-Z]+" }
before do
champ = dossier.champs_public.first
champ.value = expression_reguliere_exemple_text
champ.save!
dossier.reload
end
it 'should not have errors' do
expect(errors).not_to be_empty
expect(errors.first).to be_nil
end
end
end
describe 'index_for_section_header' do
let(:procedure) { create(:procedure, types_de_champ_public: types_de_champ) }
let(:dossier) { create(:dossier, procedure: procedure) }

View file

@ -89,7 +89,8 @@ describe ProcedureExportService do
"epci",
"epci (Code)",
"epci (Département)",
"cojo"
"cojo",
"expression_reguliere"
]
end
@ -200,7 +201,8 @@ describe ProcedureExportService do
"epci",
"epci (Code)",
"epci (Département)",
"cojo"
"cojo",
"expression_reguliere"
]
end
@ -294,7 +296,8 @@ describe ProcedureExportService do
"epci",
"epci (Code)",
"epci (Département)",
"cojo"
"cojo",
"expression_reguliere"
]
end