From 3b5bbb077958c76990d80690ac0338d6ea647e17 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Thu, 28 Sep 2023 13:14:29 +0000 Subject: [PATCH 1/9] Add new type de champ expression_reguliere with tests --- .../champ_component/champ_component.fr.yml | 5 +++ .../champ_component/champ_component.html.haml | 17 ++++++++++ .../types_de_champ_controller.rb | 3 ++ app/models/type_de_champ.rb | 32 +++++++++++++++++-- .../expression_reguliere_type_de_champ.rb | 2 ++ config/locales/models/type_de_champ/en.yml | 1 + config/locales/models/type_de_champ/fr.yml | 1 + spec/factories/type_de_champ.rb | 3 ++ spec/models/type_de_champ_spec.rb | 25 +++++++++++++++ 9 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 app/models/types_de_champ/expression_reguliere_type_de_champ.rb diff --git a/app/components/types_de_champ_editor/champ_component/champ_component.fr.yml b/app/components/types_de_champ_editor/champ_component/champ_component.fr.yml index 012e5311e..6cfb012fe 100644 --- a/app/components/types_de_champ_editor/champ_component/champ_component.fr.yml +++ b/app/components/types_de_champ_editor/champ_component/champ_component.fr.yml @@ -13,3 +13,8 @@ fr: character_limit: unlimited: Pas de limite de caractères limit: Limité à %{limit} caractères + expression_reguliere: + labels: + regex: Saisissez votre expression régulière, essayez-la sur https://rubular.com + valid_exemple: Exemple valide qui passe l'expression régulière + error_message: Message d'erreur à afficher à l'usager en cas de saisie invalide diff --git a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml index ac4f70776..0ecadd5a8 100644 --- a/app/components/types_de_champ_editor/champ_component/champ_component.html.haml +++ b/app/components/types_de_champ_editor/champ_component/champ_component.html.haml @@ -46,6 +46,23 @@ %p %small Nous numérotons automatiquement les titres lorsqu’aucun de vos titres ne commence par un chiffre. + - if type_de_champ.expression_reguliere? + .cell.mt-1 + = form.label :expression_reguliere, for: dom_id(type_de_champ, :expression_reguliere) do + = t('.expression_reguliere.labels.regex') + = form.text_field :expression_reguliere, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere) + + .cell.mt-1 + = form.label :expression_reguliere_exemple_text, for: dom_id(type_de_champ, :expression_reguliere_exemple_text) do + = t('.expression_reguliere.labels.valid_exemple') + = form.text_field :expression_reguliere_exemple_text, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_exemple_text) + - if type_de_champ.invalid_regexp? + %p.fr-message.fr-message--error + = type_de_champ.errors[:expression_reguliere_exemple_text].join(", ") + .cell.mt-1 + = form.label :expression_reguliere_error_message, for: dom_id(type_de_champ, :expression_reguliere_error_message) do + = t('.expression_reguliere.labels.error_message') + = form.text_field :expression_reguliere_error_message, class: "fr-input small-margin small", id: dom_id(type_de_champ, :expression_reguliere_error_message) - if !type_de_champ.header_section? && !type_de_champ.titre_identite? .cell.mt-1 = form.label :description, "Description du champ (optionnel)", for: dom_id(type_de_champ, :description) diff --git a/app/controllers/administrateurs/types_de_champ_controller.rb b/app/controllers/administrateurs/types_de_champ_controller.rb index 200e673bf..7e729afae 100644 --- a/app/controllers/administrateurs/types_de_champ_controller.rb +++ b/app/controllers/administrateurs/types_de_champ_controller.rb @@ -130,6 +130,9 @@ module Administrateurs :collapsible_explanation_text, :header_section_level, :character_limit, + :expression_reguliere, + :expression_reguliere_exemple_text, + :expression_reguliere_error_message, editable_options: [ :cadastres, :unesco, diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 951569c43..a35a63b27 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -55,7 +55,8 @@ class TypeDeChamp < ApplicationRecord dgfip: REFERENTIEL_EXTERNE, pole_emploi: REFERENTIEL_EXTERNE, mesri: REFERENTIEL_EXTERNE, - cojo: REFERENTIEL_EXTERNE + cojo: REFERENTIEL_EXTERNE, + expression_reguliere: STANDARD } enum type_champs: { @@ -95,7 +96,8 @@ class TypeDeChamp < ApplicationRecord pole_emploi: 'pole_emploi', mesri: 'mesri', epci: 'epci', - cojo: 'cojo' + cojo: 'cojo', + expression_reguliere: 'expression_reguliere' } ROUTABLE_TYPES = [ @@ -116,6 +118,9 @@ class TypeDeChamp < ApplicationRecord :drop_down_secondary_description, :drop_down_other, :character_limit, + :expression_reguliere, + :expression_reguliere_exemple_text, + :expression_reguliere_error_message, :collapsible_explanation_enabled, :collapsible_explanation_text, :header_section_level @@ -184,6 +189,7 @@ class TypeDeChamp < ApplicationRecord before_validation :check_mandatory before_validation :normalize_libelle + before_save :remove_piece_justificative_template, if: -> { type_champ_changed? } before_validation :remove_drop_down_list, if: -> { type_champ_changed? } before_save :remove_block, if: -> { type_champ_changed? } @@ -414,6 +420,10 @@ class TypeDeChamp < ApplicationRecord type_champ == TypeDeChamp.type_champs.fetch(:checkbox) end + def expression_reguliere? + type_champ == TypeDeChamp.type_champs.fetch(:expression_reguliere) + end + def public? !private? end @@ -604,6 +614,24 @@ class TypeDeChamp < ApplicationRecord type_champ.in?(ROUTABLE_TYPES) end + def invalid_regexp? + return false if expression_reguliere.blank? + return false if expression_reguliere_exemple_text.blank? + begin + if expression_reguliere_exemple_text.match?(Regexp.new(expression_reguliere, timeout: 2.0)) + return false + end + rescue Regexp::TimeoutError + self.errors.add(:expression_reguliere, I18n.t('errors.messages.evil_regexp')) + end + + self.errors.add(:expression_reguliere_exemple_text, I18n.t('errors.messages.mismatch_regexp')) + true + rescue RegexpError + self.errors.add(:expression_reguliere, I18n.t('errors.messages.syntax_error_regexp')) + true + end + private DEFAULT_EMPTY = [''] diff --git a/app/models/types_de_champ/expression_reguliere_type_de_champ.rb b/app/models/types_de_champ/expression_reguliere_type_de_champ.rb new file mode 100644 index 000000000..9dcbe14af --- /dev/null +++ b/app/models/types_de_champ/expression_reguliere_type_de_champ.rb @@ -0,0 +1,2 @@ +class TypesDeChamp::ExpressionReguliereTypeDeChamp < TypesDeChamp::TypeDeChampBase +end diff --git a/config/locales/models/type_de_champ/en.yml b/config/locales/models/type_de_champ/en.yml index baa3f77c7..18e9e3f3f 100644 --- a/config/locales/models/type_de_champ/en.yml +++ b/config/locales/models/type_de_champ/en.yml @@ -55,6 +55,7 @@ en: mesri: "Data from Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation" epci: "EPCI" cojo: "Accreditation Paris 2024" + expression_reguliere: 'Regular expression' errors: type_de_champ: attributes: diff --git a/config/locales/models/type_de_champ/fr.yml b/config/locales/models/type_de_champ/fr.yml index 810bb8736..9e33a3eb3 100644 --- a/config/locales/models/type_de_champ/fr.yml +++ b/config/locales/models/type_de_champ/fr.yml @@ -55,6 +55,7 @@ fr: mesri: "Données du Ministère de l’Enseignement Supérieur, de la Recherche et de l’Innovation" epci: "EPCI" cojo: "Accréditation Paris 2024" + expression_reguliere: 'Expression régulière' errors: type_de_champ: attributes: diff --git a/spec/factories/type_de_champ.rb b/spec/factories/type_de_champ.rb index cea0c942c..17cee985d 100644 --- a/spec/factories/type_de_champ.rb +++ b/spec/factories/type_de_champ.rb @@ -99,6 +99,9 @@ FactoryBot.define do type_champ { TypeDeChamp.type_champs.fetch(:linked_drop_down_list) } drop_down_list_value { "--primary--\nsecondary\n" } end + factory :type_de_champ_expression_reguliere do + type_champ { TypeDeChamp.type_champs.fetch(:expression_reguliere) } + end factory :type_de_champ_pays do type_champ { TypeDeChamp.type_champs.fetch(:pays) } end diff --git a/spec/models/type_de_champ_spec.rb b/spec/models/type_de_champ_spec.rb index ebd4ba125..9c96050b6 100644 --- a/spec/models/type_de_champ_spec.rb +++ b/spec/models/type_de_champ_spec.rb @@ -166,6 +166,31 @@ describe TypeDeChamp do end end + describe "validate_regexp" do + let(:tdc) { create(:type_de_champ_expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text:) } + subject { tdc.invalid_regexp? } + + context "expression_reguliere and bad example" do + let(:expression_reguliere_exemple_text) { "01234567" } + let(:expression_reguliere) { "[A-Z]+" } + + it "should add error message" do + expect(subject).to be_truthy + expect(tdc.errors.messages[:expression_reguliere_exemple_text]).to be_present + end + end + + context "Bad expression_reguliere" do + let(:expression_reguliere_exemple_text) { "0123456789" } + let(:expression_reguliere) { "(" } + + it "should add error message" do + expect(subject).to be_truthy + expect(tdc.errors.messages[:expression_reguliere]).to be_present + end + end + end + describe '#drop_down_list_options' do let(:value) do <<~EOS From 9bf1c65dec452b029f3b05d86b95222b8c5acb08 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Thu, 28 Sep 2023 13:56:32 +0000 Subject: [PATCH 2/9] Procedure Revision and tests --- app/models/procedure_revision.rb | 8 +++ spec/models/procedure_revision_spec.rb | 69 ++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 2369087f7..e10e3b4c4 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -19,6 +19,7 @@ class ProcedureRevision < ApplicationRecord validate :conditions_are_valid? validate :header_sections_are_valid? + validate :expressions_regulieres_are_valid? delegate :path, to: :procedure, prefix: true @@ -412,6 +413,13 @@ class ProcedureRevision < ApplicationRecord repetition_tdcs_errors + root_tdcs_errors end + 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) } + end + def errors_for_header_sections_order(tdcs) tdcs .map.with_index diff --git a/spec/models/procedure_revision_spec.rb b/spec/models/procedure_revision_spec.rb index 96dd11ce2..a967538a2 100644 --- a/spec/models/procedure_revision_spec.rb +++ b/spec/models/procedure_revision_spec.rb @@ -908,6 +908,75 @@ describe ProcedureRevision do end end + describe "expressions_regulieres_are_valid" do + let(:procedure) do + create(:procedure).tap do |p| + p.draft_revision.add_type_de_champ(type_champ: :expression_reguliere, libelle: 'exemple', expression_reguliere:, expression_reguliere_exemple_text:) + end + end + let(:draft_revision) { procedure.draft_revision } + + subject do + draft_revision.save + draft_revision.errors + end + + context "When no regexp and no example" do + let(:expression_reguliere_exemple_text) { nil } + let(:expression_reguliere) { nil } + + it { is_expected.to be_empty } + end + + context "When expression_reguliere but no example" do + let(:expression_reguliere) { "[A-Z]+" } + let(:expression_reguliere_exemple_text) { nil } + + it { is_expected.to be_empty } + end + + context "When expression_reguliere and bad example" do + let(:expression_reguliere_exemple_text) { "01234567" } + let(:expression_reguliere) { "[A-Z]+" } + + it { is_expected.not_to be_empty } + end + + context "When expression_reguliere and good example" do + let(:expression_reguliere_exemple_text) { "A" } + let(:expression_reguliere) { "[A-Z]+" } + it { is_expected.to be_empty } + end + + context "When bad expression_reguliere" do + let(:expression_reguliere_exemple_text) { "0123456789" } + let(:expression_reguliere) { "(" } + + it { is_expected.not_to be_empty } + end + + context "When repetition" do + let(:procedure) do + create(:procedure, + types_de_champ_public: [{ type: :repetition, children: [{ type: :expression_reguliere, expression_reguliere:, expression_reguliere_exemple_text: }] }]) + end + + context "When bad expression_reguliere" do + let(:expression_reguliere_exemple_text) { "0123456789" } + let(:expression_reguliere) { "(" } + + it { is_expected.not_to be_empty } + end + + context "When expression_reguliere and bad example" do + let(:expression_reguliere_exemple_text) { "01234567" } + let(:expression_reguliere) { "[A-Z]+" } + + it { is_expected.not_to be_empty } + end + end + end + describe "#dependent_conditions" do include Logic From c22e36c35cb0b5dcc0e1a5a25021a27bd5cbd2c2 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Fri, 29 Sep 2023 10:20:34 +0000 Subject: [PATCH 3/9] =?UTF-8?q?Si=20l'exemple=20ne=20passe=20pas=20la=20re?= =?UTF-8?q?gexp,=20la=20publication=20de=20la=20d=C3=A9marche=20est=20imop?= =?UTF-8?q?ssible?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/types_de_champ_editor/errors_summary.rb | 4 ++++ .../errors_summary/errors_summary.fr.yml | 4 ++++ .../errors_summary/errors_summary.html.haml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/app/components/types_de_champ_editor/errors_summary.rb b/app/components/types_de_champ_editor/errors_summary.rb index b5e750e18..b5367eaf1 100644 --- a/app/components/types_de_champ_editor/errors_summary.rb +++ b/app/components/types_de_champ_editor/errors_summary.rb @@ -15,6 +15,10 @@ class TypesDeChampEditor::ErrorsSummary < ApplicationComponent @revision.errors.include?(:header_section) end + def expression_reguliere_errors? + @revision.errors.include?(:expression_reguliere) + end + private def errors_for(key) diff --git a/app/components/types_de_champ_editor/errors_summary/errors_summary.fr.yml b/app/components/types_de_champ_editor/errors_summary/errors_summary.fr.yml index 7a97025db..08d594931 100644 --- a/app/components/types_de_champ_editor/errors_summary/errors_summary.fr.yml +++ b/app/components/types_de_champ_editor/errors_summary/errors_summary.fr.yml @@ -6,3 +6,7 @@ fr: fix_header_section: one: 'Le titre de section suivant est invalide, veuillez le corriger :' other: 'Les titres de section suivants sont invalides, veuillez les corriger :' + + fix_expressions_regulieres: + one: "L'expression régulière suivante est invalide, veuillez la corriger :" + other: 'Les expressions régulières suivantes sont invalides, veuillez les corriger :' diff --git a/app/components/types_de_champ_editor/errors_summary/errors_summary.html.haml b/app/components/types_de_champ_editor/errors_summary/errors_summary.html.haml index 3b2c84db7..1ab253953 100644 --- a/app/components/types_de_champ_editor/errors_summary/errors_summary.html.haml +++ b/app/components/types_de_champ_editor/errors_summary/errors_summary.html.haml @@ -9,3 +9,7 @@ - if header_section_errors? %p= t('.fix_header_section', count: errors_for(:header_section).size) = error_message_for(:header_section) + + - if expression_reguliere_errors? + %p= t('.fix_expressions_regulieres', count: errors_for(:expression_reguliere).size) + = error_message_for(:expression_reguliere) From a26df43577dabb0196e7d3d07eee3bc5ef903481 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Fri, 29 Sep 2023 21:09:41 +0000 Subject: [PATCH 4/9] =?UTF-8?q?User=20:=20Ajoute=20le=20type=20de=20champ?= =?UTF-8?q?=20Expression=20r=C3=A9guli=C3=A8re=20cot=C3=A9=20utilisateur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../expression_reguliere_component.rb | 5 +++ .../expression_reguliere_component.html.haml | 1 + app/controllers/users/dossiers_controller.rb | 3 ++ app/models/champ.rb | 3 ++ .../champs/expression_reguliere_champ.rb | 3 ++ app/models/dossier.rb | 14 ++++++ app/models/procedure_revision.rb | 7 ++- .../expression_reguliere_validator.rb | 14 ++++++ config/locales/en.yml | 4 ++ config/locales/fr.yml | 5 ++- spec/factories/champ.rb | 4 ++ ...0220705164551_remove_unused_champs_spec.rb | 4 +- spec/models/dossier_spec.rb | 44 +++++++++++++++++++ .../services/procedure_export_service_spec.rb | 9 ++-- 14 files changed, 112 insertions(+), 8 deletions(-) create mode 100644 app/components/editable_champ/expression_reguliere_component.rb create mode 100644 app/components/editable_champ/expression_reguliere_component/expression_reguliere_component.html.haml create mode 100644 app/models/champs/expression_reguliere_champ.rb create mode 100644 app/validators/expression_reguliere_validator.rb diff --git a/app/components/editable_champ/expression_reguliere_component.rb b/app/components/editable_champ/expression_reguliere_component.rb new file mode 100644 index 000000000..7e6a6d52c --- /dev/null +++ b/app/components/editable_champ/expression_reguliere_component.rb @@ -0,0 +1,5 @@ +class EditableChamp::ExpressionReguliereComponent < EditableChamp::EditableChampBaseComponent + def dsfr_input_classname + 'fr-input' + end +end diff --git a/app/components/editable_champ/expression_reguliere_component/expression_reguliere_component.html.haml b/app/components/editable_champ/expression_reguliere_component/expression_reguliere_component.html.haml new file mode 100644 index 000000000..ec253b98b --- /dev/null +++ b/app/components/editable_champ/expression_reguliere_component/expression_reguliere_component.html.haml @@ -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 })) diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 5a4c047d1..09b480260 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -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 diff --git a/app/models/champ.rb b/app/models/champ.rb index 69b13de87..dab924f19 100644 --- a/app/models/champ.rb +++ b/app/models/champ.rb @@ -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 diff --git a/app/models/champs/expression_reguliere_champ.rb b/app/models/champs/expression_reguliere_champ.rb new file mode 100644 index 000000000..c8f1f3a74 --- /dev/null +++ b/app/models/champs/expression_reguliere_champ.rb @@ -0,0 +1,3 @@ +class Champs::ExpressionReguliereChamp < Champ + validates_with ExpressionReguliereValidator, if: -> { validation_context != :brouillon } +end diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 17931f171..2a534cf62 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -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 diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index e10e3b4c4..44aa5d5c5 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -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) diff --git a/app/validators/expression_reguliere_validator.rb b/app/validators/expression_reguliere_validator.rb new file mode 100644 index 000000000..16ea42548 --- /dev/null +++ b/app/validators/expression_reguliere_validator.rb @@ -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 diff --git a/config/locales/en.yml b/config/locales/en.yml index 0fa24b26a..f56eccf0b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 1d7e7b642..a3b2e23f6 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -689,7 +689,10 @@ fr: procedure_archived: with_service_and_phone_email: Cette démarche en ligne a été close, il n’est plus possible de déposer de dossier. Pour plus d’informations 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 n’est plus possible de déposer de dossier. Pour plus d’informations 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 n’est maintenant plus en brouillon." diff --git a/spec/factories/champ.rb b/spec/factories/champ.rb index b3a15774d..304e51c89 100644 --- a/spec/factories/champ.rb +++ b/spec/factories/champ.rb @@ -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 } diff --git a/spec/lib/tasks/deployment/20220705164551_remove_unused_champs_spec.rb b/spec/lib/tasks/deployment/20220705164551_remove_unused_champs_spec.rb index 8056bbbec..a00707ba9 100644 --- a/spec/lib/tasks/deployment/20220705164551_remove_unused_champs_spec.rb +++ b/spec/lib/tasks/deployment/20220705164551_remove_unused_champs_spec.rb @@ -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 diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 001ce8494..1d5f8ff23 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -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) } diff --git a/spec/services/procedure_export_service_spec.rb b/spec/services/procedure_export_service_spec.rb index fc2d3dd27..ca2f09184 100644 --- a/spec/services/procedure_export_service_spec.rb +++ b/spec/services/procedure_export_service_spec.rb @@ -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 From 4145f25210e37fa1ef3825db489bbb083f6c9504 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Tue, 10 Oct 2023 12:07:13 +0000 Subject: [PATCH 5/9] Ajoute le feature flag sur le nouveau champ expression reguliere --- app/models/type_de_champ.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index a35a63b27..020d02b16 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -3,7 +3,8 @@ class TypeDeChamp < ApplicationRecord FILE_MAX_SIZE = 200.megabytes FEATURE_FLAGS = { - cojo: :cojo_type_de_champ + cojo: :cojo_type_de_champ, + expression_reguliere: :expression_reguliere_type_de_champ } MINIMUM_TEXTAREA_CHARACTER_LIMIT_LENGTH = 400 From 5b08f54665659109984b03447caec9fcadcff699 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Tue, 10 Oct 2023 13:42:43 +0000 Subject: [PATCH 6/9] =?UTF-8?q?Ajoute=20les=20changements=20=C3=A0=20l'API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/graphql/api/v2/schema.rb | 3 +- app/graphql/schema.graphql | 33 +++++++++++++++++++ app/graphql/types/champ_descriptor_type.rb | 2 ++ ...ression_reguliere_champ_descriptor_type.rb | 5 +++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 app/graphql/types/champs/descriptor/expression_reguliere_champ_descriptor_type.rb diff --git a/app/graphql/api/v2/schema.rb b/app/graphql/api/v2/schema.rb index 93c62ef1e..867a36126 100644 --- a/app/graphql/api/v2/schema.rb +++ b/app/graphql/api/v2/schema.rb @@ -114,7 +114,8 @@ class API::V2::Schema < GraphQL::Schema Types::Champs::Descriptor::TextareaChampDescriptorType, Types::Champs::Descriptor::TextChampDescriptorType, Types::Champs::Descriptor::TitreIdentiteChampDescriptorType, - Types::Champs::Descriptor::YesNoChampDescriptorType + Types::Champs::Descriptor::YesNoChampDescriptorType, + Types::Champs::Descriptor::ExpressionReguliereChampDescriptorType def self.unauthorized_object(error) # Add a top-level error to the response instead of returning nil: diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index 0fc35e4f4..0d0ea7a2f 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -2284,6 +2284,34 @@ type ExplicationChampDescriptor implements ChampDescriptor { type: TypeDeChamp! @deprecated(reason: "Utilisez le champ `__typename` à la place.") } +type ExpressionReguliereChampDescriptor implements ChampDescriptor { + """ + Description des champs d’un bloc répétable. + """ + champDescriptors: [ChampDescriptor!] @deprecated(reason: "Utilisez le champ `RepetitionChampDescriptor.champ_descriptors` à la place.") + + """ + Description du champ. + """ + description: String + id: ID! + + """ + Libellé du champ. + """ + label: String! + + """ + Est-ce que le champ est obligatoire ? + """ + required: Boolean! + + """ + Type de la valeur du champ. + """ + type: TypeDeChamp! @deprecated(reason: "Utilisez le champ `__typename` à la place.") +} + type File { byteSize: Int! @deprecated(reason: "Utilisez le champ `byteSizeBigInt` à la place.") byteSizeBigInt: BigInt! @@ -3945,6 +3973,11 @@ enum TypeDeChamp { """ explication + """ + Expression régulière + """ + expression_reguliere + """ Titre de section """ diff --git a/app/graphql/types/champ_descriptor_type.rb b/app/graphql/types/champ_descriptor_type.rb index 3e59bec96..6bc69823d 100644 --- a/app/graphql/types/champ_descriptor_type.rb +++ b/app/graphql/types/champ_descriptor_type.rb @@ -96,6 +96,8 @@ module Types Types::Champs::Descriptor::EpciChampDescriptorType when TypeDeChamp.type_champs.fetch(:cojo) Types::Champs::Descriptor::COJOChampDescriptorType + when TypeDeChamp.type_champs.fetch(:expression_reguliere) + Types::Champs::Descriptor::ExpressionReguliereChampDescriptorType end end end diff --git a/app/graphql/types/champs/descriptor/expression_reguliere_champ_descriptor_type.rb b/app/graphql/types/champs/descriptor/expression_reguliere_champ_descriptor_type.rb new file mode 100644 index 000000000..430c4a00d --- /dev/null +++ b/app/graphql/types/champs/descriptor/expression_reguliere_champ_descriptor_type.rb @@ -0,0 +1,5 @@ +module Types::Champs::Descriptor + class ExpressionReguliereChampDescriptorType < Types::BaseObject + implements Types::ChampDescriptorType + end +end From 1d66b473004242d14c739dd8742bacb047370028 Mon Sep 17 00:00:00 2001 From: Kara Diaby Date: Thu, 12 Oct 2023 15:09:32 +0000 Subject: [PATCH 7/9] =?UTF-8?q?Prend=20en=20charge=20les=20r=C3=A9visions?= =?UTF-8?q?=20sur=20les=20d=C3=A9marches?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../revision_changes_component.fr.yml | 6 ++++++ .../revision_changes_component.html.haml | 21 +++++++++++++++++++ app/models/procedure_revision.rb | 19 +++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml b/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml index a0b8a56ad..15b3c7b02 100644 --- a/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml +++ b/app/components/procedure/revision_changes_component/revision_changes_component.fr.yml @@ -40,6 +40,12 @@ fr: update_condition: La condition du champ « %{label} » a été modifiée. La nouvelle condition est « %{to} ». update_character_limit: La limite de caractères du champ texte « %{label} » a été modifiée. La nouvelle limite est « %{to} ». remove_character_limit: La limite de caractères du champ texte « %{label} » a été supprimée. + remove_expression_reguliere: L’expression régulière du champ « %{label} » a été supprimée. + update_expression_reguliere: L’expression régulière du champ « %{label} » a été modifiée. La nouvelle expression est « %{to} ». + remove_expression_reguliere_exemple_text: L’exemple d’expression régulière du champ « %{label} » a été supprimé. + update_expression_reguliere_exemple_text: L’exemple d’expression régulière du champ « %{label} » a été modifié. Le nouvel exemple est « %{to} ». + remove_expression_reguliere_error_message: Le message d’erreur de l’expression régulière du champ « %{label} » a été supprimé. + update_expression_reguliere_error_message: Le message d’erreur de l’expression régulière du champ « %{label} » a été modifié. Le nouveau message est « %{to} ». private: add: L’annotation privée « %{label} » a été ajoutée. remove: L’annotation privée « %{label} » a été supprimée. diff --git a/app/components/procedure/revision_changes_component/revision_changes_component.html.haml b/app/components/procedure/revision_changes_component/revision_changes_component.html.haml index 8e71cab08..6dd90ef49 100644 --- a/app/components/procedure/revision_changes_component/revision_changes_component.html.haml +++ b/app/components/procedure/revision_changes_component/revision_changes_component.html.haml @@ -141,6 +141,27 @@ - else - list.with_item do = t(".#{prefix}.update_character_limit", label: change.label, to: change.to) + - when :expression_reguliere + - if change.to.blank? + - list.with_item do + = t(".#{prefix}.remove_expression_reguliere", label: change.label, to: change.to) + - else + - list.with_item do + = t(".#{prefix}.update_expression_reguliere", label: change.label, to: change.to) + - when :expression_reguliere_exemple_text + - if change.to.blank? + - list.with_item do + = t(".#{prefix}.remove_expression_reguliere_exemple_text", label: change.label, to: change.to) + - else + - list.with_item do + = t(".#{prefix}.update_expression_reguliere_exemple_text", label: change.label, to: change.to) + - when :expression_reguliere_error_message + - if change.to.blank? + - list.with_item do + = t(".#{prefix}.remove_expression_reguliere_error_message", label: change.label, to: change.to) + - else + - list.with_item do + = t(".#{prefix}.update_expression_reguliere_error_message", label: change.label, to: change.to) - if @public_move_changes.present? - list.with_item do diff --git a/app/models/procedure_revision.rb b/app/models/procedure_revision.rb index 44aa5d5c5..636d22911 100644 --- a/app/models/procedure_revision.rb +++ b/app/models/procedure_revision.rb @@ -376,6 +376,25 @@ class ProcedureRevision < ApplicationRecord from_type_de_champ.character_limit, to_type_de_champ.character_limit) end + elsif to_type_de_champ.expression_reguliere? + if from_type_de_champ.expression_reguliere != to_type_de_champ.expression_reguliere + changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ, + :expression_reguliere, + from_type_de_champ.expression_reguliere, + to_type_de_champ.expression_reguliere) + end + if from_type_de_champ.expression_reguliere_exemple_text != to_type_de_champ.expression_reguliere_exemple_text + changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ, + :expression_reguliere_exemple_text, + from_type_de_champ.expression_reguliere_exemple_text, + to_type_de_champ.expression_reguliere_exemple_text) + end + if from_type_de_champ.expression_reguliere_error_message != to_type_de_champ.expression_reguliere_error_message + changes << ProcedureRevisionChange::UpdateChamp.new(from_type_de_champ, + :expression_reguliere_error_message, + from_type_de_champ.expression_reguliere_error_message, + to_type_de_champ.expression_reguliere_error_message) + end end changes end From 30bc4aa5d3e4654776c48360219d9c5fd765b06c Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 13 Oct 2023 14:27:03 +0200 Subject: [PATCH 8/9] amelioration(champ.expression_reguliere): pas besoin d'executer la validation du champs expression reguliere dans controller, le validateur le fait sur le champ au moment de sauver le dossier avec le bon context --- app/controllers/users/dossiers_controller.rb | 3 --- app/models/dossier.rb | 14 -------------- app/models/type_de_champ.rb | 11 ++++------- app/validators/expression_reguliere_validator.rb | 11 ++++------- .../champs/expression_reguliere_champ/en.yml | 8 ++++++++ .../champs/expression_reguliere_champ/fr.yml | 8 ++++++++ spec/models/dossier_spec.rb | 10 +++------- 7 files changed, 27 insertions(+), 38 deletions(-) create mode 100644 config/locales/models/champs/expression_reguliere_champ/en.yml create mode 100644 config/locales/models/champs/expression_reguliere_champ/fr.yml diff --git a/app/controllers/users/dossiers_controller.rb b/app/controllers/users/dossiers_controller.rb index 09b480260..5a4c047d1 100644 --- a/app/controllers/users/dossiers_controller.rb +++ b/app/controllers/users/dossiers_controller.rb @@ -540,9 +540,6 @@ 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 diff --git a/app/models/dossier.rb b/app/models/dossier.rb index 2a534cf62..17931f171 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -1152,20 +1152,6 @@ 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 diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index 020d02b16..42eac1d5e 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -618,16 +618,13 @@ class TypeDeChamp < ApplicationRecord def invalid_regexp? return false if expression_reguliere.blank? return false if expression_reguliere_exemple_text.blank? - begin - if expression_reguliere_exemple_text.match?(Regexp.new(expression_reguliere, timeout: 2.0)) - return false - end - rescue Regexp::TimeoutError - self.errors.add(:expression_reguliere, I18n.t('errors.messages.evil_regexp')) - end + return false if expression_reguliere_exemple_text.match?(Regexp.new(expression_reguliere, timeout: 2.0)) self.errors.add(:expression_reguliere_exemple_text, I18n.t('errors.messages.mismatch_regexp')) true + rescue Regexp::TimeoutError + self.errors.add(:expression_reguliere, I18n.t('errors.messages.evil_regexp')) + true rescue RegexpError self.errors.add(:expression_reguliere, I18n.t('errors.messages.syntax_error_regexp')) true diff --git a/app/validators/expression_reguliere_validator.rb b/app/validators/expression_reguliere_validator.rb index 16ea42548..7ba53525a 100644 --- a/app/validators/expression_reguliere_validator.rb +++ b/app/validators/expression_reguliere_validator.rb @@ -1,14 +1,11 @@ - 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')) + 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 end + rescue Regexp::TimeoutError + record.errors.add(:expression_reguliere, :evil_regexp) end end diff --git a/config/locales/models/champs/expression_reguliere_champ/en.yml b/config/locales/models/champs/expression_reguliere_champ/en.yml new file mode 100644 index 000000000..29554a792 --- /dev/null +++ b/config/locales/models/champs/expression_reguliere_champ/en.yml @@ -0,0 +1,8 @@ +en: + activerecord: + errors: + models: + champs/expression_reguliere_champ: + attributes: + value: + invalid_regexp: does not match expected format diff --git a/config/locales/models/champs/expression_reguliere_champ/fr.yml b/config/locales/models/champs/expression_reguliere_champ/fr.yml new file mode 100644 index 000000000..a266b3f6a --- /dev/null +++ b/config/locales/models/champs/expression_reguliere_champ/fr.yml @@ -0,0 +1,8 @@ +fr: + activerecord: + errors: + models: + champs/expression_reguliere_champ: + attributes: + value: + invalid_regexp: ne correspond pas au format attendu diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 1d5f8ff23..30a00691b 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1576,13 +1576,10 @@ describe Dossier, type: :model do 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" } @@ -1591,13 +1588,12 @@ describe Dossier, type: :model do before do champ = dossier.champs_public.first champ.value = expression_reguliere_exemple_text - champ.save! - dossier.reload + dossier.save end it 'should have errors' do - expect(errors).not_to be_empty - expect(errors.first.full_message).to eq("n'est pas valide") + expect(dossier.errors).not_to be_empty + expect(dossier.errors.full_messages.join(',')).to include("ne correspond pas au format attendu") end end From 86b44cd0a4e9da22acf59188849209762a55b12d Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 13 Oct 2023 14:27:03 +0200 Subject: [PATCH 9/9] iamelioration(champ.expression_reguliere): empeche le rebase lorsqu'il y a un changement sur un type de champ expression reguliere. Plus quelques adaptation de style cf: pas besoin d'executer la validation du champs expression reguliere dans controller, le validateur le fait sur le champ au moment de sauver le dossier avec le bon context --- app/models/concerns/dossier_rebase_concern.rb | 4 ++++ app/models/procedure_revision_change.rb | 3 +-- app/validators/expression_reguliere_validator.rb | 2 +- config/locales/en.yml | 1 - config/locales/fr.yml | 1 - .../models/concern/dossier_rebase_concern_spec.rb | 15 +++++++++++++++ spec/models/dossier_spec.rb | 6 ++---- 7 files changed, 23 insertions(+), 9 deletions(-) diff --git a/app/models/concerns/dossier_rebase_concern.rb b/app/models/concerns/dossier_rebase_concern.rb index 90c0909a0..8b0ab50ba 100644 --- a/app/models/concerns/dossier_rebase_concern.rb +++ b/app/models/concerns/dossier_rebase_concern.rb @@ -32,6 +32,10 @@ module DossierRebaseConcern !champs.filter { _1.stable_id == stable_id }.any? { _1.in?(options) } end + def can_rebase_expression_reguliere_change?(stable_id, expression_reguliere) + false + end + private def accepted_en_construction_changes? diff --git a/app/models/procedure_revision_change.rb b/app/models/procedure_revision_change.rb index 8079c8cdb..2bb4a95f9 100644 --- a/app/models/procedure_revision_change.rb +++ b/app/models/procedure_revision_change.rb @@ -60,7 +60,6 @@ class ProcedureRevisionChange def can_rebase?(dossier = nil) return true if private? - case attribute when :drop_down_options (from - to).empty? || dossier&.can_rebase_drop_down_options_change?(stable_id, from - to) @@ -68,7 +67,7 @@ class ProcedureRevisionChange !from && to when :mandatory (from && !to) || dossier&.can_rebase_mandatory_change?(stable_id) - when :type_champ, :condition + when :type_champ, :condition, :expression_reguliere false else true diff --git a/app/validators/expression_reguliere_validator.rb b/app/validators/expression_reguliere_validator.rb index 7ba53525a..72994f767 100644 --- a/app/validators/expression_reguliere_validator.rb +++ b/app/validators/expression_reguliere_validator.rb @@ -2,7 +2,7 @@ class ExpressionReguliereValidator < ActiveModel::Validator def validate(record) if record.value.present? 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)) + record.errors.add(:value, :invalid_regexp) end end rescue Regexp::TimeoutError diff --git a/config/locales/en.yml b/config/locales/en.yml index f56eccf0b..b42a1b05e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -687,7 +687,6 @@ en: 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" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index a3b2e23f6..080c89d98 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -692,7 +692,6 @@ fr: 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 n’est maintenant plus en brouillon." diff --git a/spec/models/concern/dossier_rebase_concern_spec.rb b/spec/models/concern/dossier_rebase_concern_spec.rb index d43a9c339..3a90ff4b4 100644 --- a/spec/models/concern/dossier_rebase_concern_spec.rb +++ b/spec/models/concern/dossier_rebase_concern_spec.rb @@ -124,6 +124,21 @@ describe DossierRebaseConcern do end end + context 'with type de champ regexp and regexp change' do + let(:procedure) { create(:procedure, types_de_champ_public: [{ mandatory: true }, { type: :expression_reguliere }], types_de_champ_private: [{}]) } + + before do + procedure.draft_revision.find_and_ensure_exclusive_use(type_de_champ.stable_id).update(expression_reguliere: /\d+/) + procedure.publish_revision! + dossier.reload + end + + it 'should be false' do + expect(dossier.pending_changes).not_to be_empty + expect(dossier.can_rebase?).to be_falsey + end + end + context 'with removed type de champ' do before do procedure.draft_revision.remove_type_de_champ(type_de_champ.stable_id) diff --git a/spec/models/dossier_spec.rb b/spec/models/dossier_spec.rb index 30a00691b..e6a332d6c 100644 --- a/spec/models/dossier_spec.rb +++ b/spec/models/dossier_spec.rb @@ -1604,13 +1604,11 @@ describe Dossier, type: :model do before do champ = dossier.champs_public.first champ.value = expression_reguliere_exemple_text - champ.save! - dossier.reload + dossier.save end it 'should not have errors' do - expect(errors).not_to be_empty - expect(errors.first).to be_nil + expect(dossier.errors).to be_empty end end end