fix(carte): gracefully ignore invalid year and kind params

Empêche d'envoyer une date invalide à PG et polluer les logs.
This commit is contained in:
Colin Darie 2024-05-15 23:29:45 +02:00
parent 40e952e8d2
commit 3d52601155
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
5 changed files with 31 additions and 29 deletions

View file

@ -1,6 +1,13 @@
class CarteController < ApplicationController class CarteController < ApplicationController
def show def show
@map_filter = MapFilter.new(params) @map_filter = MapFilter.new(params.fetch(:map_filter, {}).permit(:kind, :year))
@map_filter.validate
# Reset to default params in case of invalid params injection
@map_filter.kind = MapFilter.new.kind if @map_filter.errors.key?(:kind)
@map_filter.year = MapFilter.new.year if @map_filter.errors.key?(:year)
@map_filter.errors.clear
@map_filter.stats = stats @map_filter.stats = stats
end end

View file

@ -1,34 +1,21 @@
class MapFilter class MapFilter
# https://api.rubyonrails.org/v7.1.1/classes/ActiveModel/Errors.html include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Conversion
extend ActiveModel::Translation
extend ActiveModel::Naming
LEGEND = { LEGEND = {
nb_demarches: { 'nothing': -1, 'small': 20, 'medium': 50, 'large': 100, 'xlarge': 500 }, "nb_demarches" => { 'nothing': -1, 'small': 20, 'medium': 50, 'large': 100, 'xlarge': 500 },
nb_dossiers: { 'nothing': -1, 'small': 500, 'medium': 2000, 'large': 10000, 'xlarge': 50000 } "nb_dossiers" => { 'nothing': -1, 'small': 500, 'medium': 2000, 'large': 10000, 'xlarge': 50000 }
} }.freeze
YEARS_INTERVAL = 2018..Date.current.year
attr_accessor :stats attr_accessor :stats
attr_reader :errors
def initialize(params) attribute :year, :integer
@params = params[:map_filter]&.permit(:kind, :year) || {} validates :year, numericality: { only_integer: true, greater_than_or_equal_to: YEARS_INTERVAL.begin, less_than_or_equal_to: YEARS_INTERVAL.end }
@errors = ActiveModel::Errors.new(self)
end
def persisted? attribute :kind, default: "nb_demarches"
false validates :kind, inclusion: { in: LEGEND.keys }
end
def kind
@params[:kind]&.to_sym || :nb_demarches
end
def year
@params[:year].presence
end
def kind_buttons def kind_buttons
LEGEND.keys.map do LEGEND.keys.map do
@ -41,7 +28,7 @@ class MapFilter
end end
def css_class_for_departement(departement) def css_class_for_departement(departement)
if kind == :nb_demarches if kind == "nb_demarches"
kind_legend_keys.reverse.find do kind_legend_keys.reverse.find do
nb_demarches_for_departement(departement) > LEGEND[kind][_1] nb_demarches_for_departement(departement) > LEGEND[kind][_1]
end end

View file

@ -249,7 +249,7 @@
<% end %> <% end %>
<div class="fr-select-group"> <div class="fr-select-group">
<%= map_form.label :year, class: 'fr-label' %> <%= map_form.label :year, class: 'fr-label' %>
<%= map_form.select(:year, (2018..Date.current.year).to_a.reverse, { include_blank: t(:from_beginning, scope: 'activemodel.attributes.map_filter') }, { class: "fr-select" }) %> <%= map_form.select(:year, MapFilter::YEARS_INTERVAL.to_a.reverse, { include_blank: t(:from_beginning, scope: 'activemodel.attributes.map_filter') }, { class: "fr-select" }) %>
</div> </div>
<%= map_form.submit(name: nil, class: 'hidden', data: { autosubmit_target: 'submitter' } ) %> <%= map_form.submit(name: nil, class: 'hidden', data: { autosubmit_target: 'submitter' } ) %>
<% end %> <% end %>

View file

@ -18,5 +18,13 @@ describe CarteController do
get :show, params: { map_filter: { year: 2020 } } get :show, params: { map_filter: { year: 2020 } }
expect(subject.stats['75']).to eq({ nb_demarches: 1, nb_dossiers: 20 }) expect(subject.stats['75']).to eq({ nb_demarches: 1, nb_dossiers: 20 })
end end
it 'gracefully ignore invalid params' do
get :show, params: { map_filter: { year: "not!" } }
expect(subject.stats['75']).to eq({ nb_demarches: 2, nb_dossiers: 50 })
get :show, params: { map_filter: { kind: "nimp" } }
expect(subject.stats['75']).to eq({ nb_demarches: 2, nb_dossiers: 50 })
end
end end
end end

View file

@ -6,7 +6,7 @@ describe MapFilter do
end end
describe 'css_class_for_departement' do describe 'css_class_for_departement' do
let(:params) { { kind: :nb_demarches } } let(:params) { { kind: "nb_demarches" } }
context 'for nb_demarches' do context 'for nb_demarches' do
it 'return class css' do it 'return class css' do
expect(map_filter.css_class_for_departement('63')).to eq :medium expect(map_filter.css_class_for_departement('63')).to eq :medium
@ -14,7 +14,7 @@ describe MapFilter do
end end
context 'fr nb_dossiers' do context 'fr nb_dossiers' do
let(:params) { { kind: :nb_dossiers } } let(:params) { { kind: "nb_dossiers" } }
it 'return class css' do it 'return class css' do
expect(map_filter.css_class_for_departement('63')).to eq :medium expect(map_filter.css_class_for_departement('63')).to eq :medium
end end