From 02bbf26d3f7506cd2f73a45ee7c2d9c044b3aa1e Mon Sep 17 00:00:00 2001 From: mfo Date: Tue, 10 Sep 2024 17:40:18 +0200 Subject: [PATCH] feat(ProcedurePresentation): validates that ProcedurePresentation.filters using a value casted as an integer [search by id] is not out of pg integer range --- app/models/procedure_presentation.rb | 13 +++++++++++++ spec/models/procedure_presentation_spec.rb | 10 +++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/app/models/procedure_presentation.rb b/app/models/procedure_presentation.rb index bb6e6d874..278d6fc2c 100644 --- a/app/models/procedure_presentation.rb +++ b/app/models/procedure_presentation.rb @@ -14,6 +14,8 @@ class ProcedurePresentation < ApplicationRecord TYPE_DE_CHAMP = 'type_de_champ' FILTERS_VALUE_MAX_LENGTH = 100 + # https://www.postgresql.org/docs/current/datatype-numeric.html + PG_INTEGER_MAX_VALUE = 2147483647 belongs_to :assign_to, optional: false has_many :exports, dependent: :destroy @@ -25,6 +27,7 @@ class ProcedurePresentation < ApplicationRecord validate :check_allowed_sort_order validate :check_allowed_filter_columns validate :check_filters_max_length + validate :check_filters_max_integer def displayed_fields_for_headers [ @@ -313,6 +316,16 @@ class ProcedurePresentation < ApplicationRecord end end + def check_filters_max_integer + filters.values.flatten.each do |filter| + next if !filter.is_a?(Hash) + next if filter['column'] != 'id' + next if filter['value']&.to_i&. < PG_INTEGER_MAX_VALUE + + errors.add(:base, "Le filtre #{filter['label']} n'est pas un numéro de dossier possible") + end + end + def valid_column?(table, column, extra_columns = {}) valid_columns_for_table(table).include?(column) || extra_columns[table]&.include?(column) diff --git a/spec/models/procedure_presentation_spec.rb b/spec/models/procedure_presentation_spec.rb index d9e6e88ab..581798c2e 100644 --- a/spec/models/procedure_presentation_spec.rb +++ b/spec/models/procedure_presentation_spec.rb @@ -55,6 +55,11 @@ describe ProcedurePresentation do context 'of filters' do it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "reset_password_token", "order" => "asc" }] })).to be_invalid } it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "user", column: "email", "value" => "exceedingly long filter value" * 10 }] })).to be_invalid } + + describe 'check_filters_max_integer' do + it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "self", column: "id", "value" => 2147483647.to_s }] })).to be_invalid } + it { expect(build(:procedure_presentation, filters: { "suivis" => [{ table: "self", column: "id", "value" => (2147483647 - 1).to_s }] })).to be_valid } + end end end @@ -331,11 +336,6 @@ describe ProcedurePresentation do subject { procedure_presentation.send(:filtered_ids, procedure.dossiers.joins(:user), 'suivis') } context 'for self table' do - context 'for id column' do - let(:filter) { [{ 'table' => 'self', 'column' => 'id', 'value' => '88116030300015' }] } - - it { is_expected.not_to raise_error(PG::NumericValueOutOfRange) } - end context 'for created_at column' do let(:filter) { [{ 'table' => 'self', 'column' => 'created_at', 'value' => '18/9/2018' }] }