Merge pull request #2810 from betagouv/frederic/fix_1961-search_by_individual
Fix #1961 search by individual
This commit is contained in:
commit
841e67b19c
3 changed files with 156 additions and 61 deletions
|
@ -20,6 +20,14 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
field_hash('Demandeur', 'user', 'email')
|
field_hash('Demandeur', 'user', 'email')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if procedure.for_individual
|
||||||
|
fields.push(
|
||||||
|
field_hash("Prénom", "individual", "prenom"),
|
||||||
|
field_hash("Nom", "individual", "nom"),
|
||||||
|
field_hash("Civilité", "individual", "gender")
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
if !procedure.for_individual || (procedure.for_individual && procedure.individual_with_siret)
|
if !procedure.for_individual || (procedure.for_individual && procedure.individual_with_siret)
|
||||||
fields.push(
|
fields.push(
|
||||||
field_hash('SIREN', 'etablissement', 'entreprise_siren'),
|
field_hash('SIREN', 'etablissement', 'entreprise_siren'),
|
||||||
|
@ -87,7 +95,7 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
.where("champs.type_de_champ_id = #{sort['column'].to_i}")
|
.where("champs.type_de_champ_id = #{sort['column'].to_i}")
|
||||||
.order("champs.value #{order}")
|
.order("champs.value #{order}")
|
||||||
.pluck(:id)
|
.pluck(:id)
|
||||||
else
|
when 'user', 'individual', 'etablissement'
|
||||||
return dossiers
|
return dossiers
|
||||||
.includes(table)
|
.includes(table)
|
||||||
.order("#{column} #{order}")
|
.order("#{column} #{order}")
|
||||||
|
@ -121,7 +129,7 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
.includes(table)
|
.includes(table)
|
||||||
.where("#{column} ILIKE ?", "%#{filter['value']}%")
|
.where("#{column} ILIKE ?", "%#{filter['value']}%")
|
||||||
end
|
end
|
||||||
when 'user'
|
when 'user', 'individual'
|
||||||
dossiers
|
dossiers
|
||||||
.includes(table)
|
.includes(table)
|
||||||
.where("#{column} ILIKE ?", "%#{filter['value']}%")
|
.where("#{column} ILIKE ?", "%#{filter['value']}%")
|
||||||
|
@ -178,10 +186,8 @@ class ProcedurePresentation < ApplicationRecord
|
||||||
case table
|
case table
|
||||||
when 'self'
|
when 'self'
|
||||||
dossier.send(column)
|
dossier.send(column)
|
||||||
when 'user'
|
when 'user', 'individual', 'etablissement'
|
||||||
dossier.user.send(column)
|
dossier.send(table)&.send(column)
|
||||||
when 'etablissement'
|
|
||||||
dossier.etablissement&.send(column)
|
|
||||||
when 'type_de_champ'
|
when 'type_de_champ'
|
||||||
dossier.champs.find { |c| c.type_de_champ_id == column.to_i }.value
|
dossier.champs.find { |c| c.type_de_champ_id == column.to_i }.value
|
||||||
when 'type_de_champ_private'
|
when 'type_de_champ_private'
|
||||||
|
|
|
@ -1,25 +1,5 @@
|
||||||
{
|
{
|
||||||
"ignored_warnings": [
|
"ignored_warnings": [
|
||||||
{
|
|
||||||
"warning_type": "SQL Injection",
|
|
||||||
"warning_code": 0,
|
|
||||||
"fingerprint": "030551e51e29561702bcb9760bdeeed15e1936d4a9537f27e5d1d13a0ebb34ef",
|
|
||||||
"check_name": "SQL",
|
|
||||||
"message": "Possible SQL injection",
|
|
||||||
"file": "app/models/procedure_presentation.rb",
|
|
||||||
"line": 130,
|
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
|
||||||
"code": "dossiers.includes(sort[\"table\"]).order(\"#{sanitized_column(sort)} #{sort[\"order\"]}\")",
|
|
||||||
"render_path": null,
|
|
||||||
"location": {
|
|
||||||
"type": "method",
|
|
||||||
"class": "ProcedurePresentation",
|
|
||||||
"method": "sorted_ids"
|
|
||||||
},
|
|
||||||
"user_input": "sanitized_column(sort)",
|
|
||||||
"confidence": "Weak",
|
|
||||||
"note": "Not an injection because of `sanitized_column`"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"warning_type": "SQL Injection",
|
"warning_type": "SQL Injection",
|
||||||
"warning_code": 0,
|
"warning_code": 0,
|
||||||
|
@ -27,7 +7,7 @@
|
||||||
"check_name": "SQL",
|
"check_name": "SQL",
|
||||||
"message": "Possible SQL injection",
|
"message": "Possible SQL injection",
|
||||||
"file": "app/models/procedure_presentation.rb",
|
"file": "app/models/procedure_presentation.rb",
|
||||||
"line": 119,
|
"line": 90,
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||||
"code": "dossiers.order(\"#{sanitized_column(sort)} #{sort[\"order\"]}\")",
|
"code": "dossiers.order(\"#{sanitized_column(sort)} #{sort[\"order\"]}\")",
|
||||||
"render_path": null,
|
"render_path": null,
|
||||||
|
@ -47,7 +27,7 @@
|
||||||
"check_name": "SQL",
|
"check_name": "SQL",
|
||||||
"message": "Possible SQL injection",
|
"message": "Possible SQL injection",
|
||||||
"file": "app/models/procedure_presentation.rb",
|
"file": "app/models/procedure_presentation.rb",
|
||||||
"line": 125,
|
"line": 96,
|
||||||
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||||
"code": "dossiers.includes(((\"type_de_champ\" == \"type_de_champ\") ? (:champs) : (:champs_private))).where(\"champs.type_de_champ_id = #{sort[\"column\"].to_i}\").order(\"champs.value #{sort[\"order\"]}\")",
|
"code": "dossiers.includes(((\"type_de_champ\" == \"type_de_champ\") ? (:champs) : (:champs_private))).where(\"champs.type_de_champ_id = #{sort[\"column\"].to_i}\").order(\"champs.value #{sort[\"order\"]}\")",
|
||||||
"render_path": null,
|
"render_path": null,
|
||||||
|
@ -59,8 +39,28 @@
|
||||||
"user_input": "sort[\"order\"]",
|
"user_input": "sort[\"order\"]",
|
||||||
"confidence": "Weak",
|
"confidence": "Weak",
|
||||||
"note": "Not an injection because `sort[\"order\"]` has passed `check_allowed_sort_order`"
|
"note": "Not an injection because `sort[\"order\"]` has passed `check_allowed_sort_order`"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"warning_type": "SQL Injection",
|
||||||
|
"warning_code": 0,
|
||||||
|
"fingerprint": "e0e5b55126891df8fe144835ea99367ffd7a92ae6d7227a923fe79f4a79f67f4",
|
||||||
|
"check_name": "SQL",
|
||||||
|
"message": "Possible SQL injection",
|
||||||
|
"file": "app/models/procedure_presentation.rb",
|
||||||
|
"line": 101,
|
||||||
|
"link": "https://brakemanscanner.org/docs/warning_types/sql_injection/",
|
||||||
|
"code": "dossiers.includes(\"user\").order(\"#{sanitized_column(sort)} #{sort[\"order\"]}\")",
|
||||||
|
"render_path": null,
|
||||||
|
"location": {
|
||||||
|
"type": "method",
|
||||||
|
"class": "ProcedurePresentation",
|
||||||
|
"method": "sorted_ids"
|
||||||
|
},
|
||||||
|
"user_input": "sanitized_column(sort)",
|
||||||
|
"confidence": "Weak",
|
||||||
|
"note": "Not an injection because of `sanitized_column`"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"updated": "2018-10-05 16:12:32 +0200",
|
"updated": "2018-10-11 12:09:03 +0200",
|
||||||
"brakeman_version": "4.3.1"
|
"brakeman_version": "4.3.1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,42 +49,56 @@ describe ProcedurePresentation do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#fields" do
|
describe "#fields" do
|
||||||
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, :types_de_champ_count => 4, :types_de_champ_private_count => 4) }
|
context 'when the procedure can have a SIRET number' do
|
||||||
let(:tdc_1) { procedure.types_de_champ[0] }
|
let(:procedure) { create(:procedure, :with_type_de_champ, :with_type_de_champ_private, :types_de_champ_count => 4, :types_de_champ_private_count => 4) }
|
||||||
let(:tdc_2) { procedure.types_de_champ[1] }
|
let(:tdc_1) { procedure.types_de_champ[0] }
|
||||||
let(:tdc_private_1) { procedure.types_de_champ_private[0] }
|
let(:tdc_2) { procedure.types_de_champ[1] }
|
||||||
let(:tdc_private_2) { procedure.types_de_champ_private[1] }
|
let(:tdc_private_1) { procedure.types_de_champ_private[0] }
|
||||||
let(:expected) {
|
let(:tdc_private_2) { procedure.types_de_champ_private[1] }
|
||||||
[
|
let(:expected) {
|
||||||
{ "label" => 'Créé le', "table" => 'self', "column" => 'created_at' },
|
[
|
||||||
{ "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at' },
|
{ "label" => 'Créé le', "table" => 'self', "column" => 'created_at' },
|
||||||
{ "label" => 'Demandeur', "table" => 'user', "column" => 'email' },
|
{ "label" => 'Mis à jour le', "table" => 'self', "column" => 'updated_at' },
|
||||||
{ "label" => 'SIREN', "table" => 'etablissement', "column" => 'entreprise_siren' },
|
{ "label" => 'Demandeur', "table" => 'user', "column" => 'email' },
|
||||||
{ "label" => 'Forme juridique', "table" => 'etablissement', "column" => 'entreprise_forme_juridique' },
|
{ "label" => 'SIREN', "table" => 'etablissement', "column" => 'entreprise_siren' },
|
||||||
{ "label" => 'Nom commercial', "table" => 'etablissement', "column" => 'entreprise_nom_commercial' },
|
{ "label" => 'Forme juridique', "table" => 'etablissement', "column" => 'entreprise_forme_juridique' },
|
||||||
{ "label" => 'Raison sociale', "table" => 'etablissement', "column" => 'entreprise_raison_sociale' },
|
{ "label" => 'Nom commercial', "table" => 'etablissement', "column" => 'entreprise_nom_commercial' },
|
||||||
{ "label" => 'SIRET siège social', "table" => 'etablissement', "column" => 'entreprise_siret_siege_social' },
|
{ "label" => 'Raison sociale', "table" => 'etablissement', "column" => 'entreprise_raison_sociale' },
|
||||||
{ "label" => 'Date de création', "table" => 'etablissement', "column" => 'entreprise_date_creation' },
|
{ "label" => 'SIRET siège social', "table" => 'etablissement', "column" => 'entreprise_siret_siege_social' },
|
||||||
{ "label" => 'SIRET', "table" => 'etablissement', "column" => 'siret' },
|
{ "label" => 'Date de création', "table" => 'etablissement', "column" => 'entreprise_date_creation' },
|
||||||
{ "label" => 'Libellé NAF', "table" => 'etablissement', "column" => 'libelle_naf' },
|
{ "label" => 'SIRET', "table" => 'etablissement', "column" => 'siret' },
|
||||||
{ "label" => 'Code postal', "table" => 'etablissement', "column" => 'code_postal' },
|
{ "label" => 'Libellé NAF', "table" => 'etablissement', "column" => 'libelle_naf' },
|
||||||
{ "label" => tdc_1.libelle, "table" => 'type_de_champ', "column" => tdc_1.id.to_s },
|
{ "label" => 'Code postal', "table" => 'etablissement', "column" => 'code_postal' },
|
||||||
{ "label" => tdc_2.libelle, "table" => 'type_de_champ', "column" => tdc_2.id.to_s },
|
{ "label" => tdc_1.libelle, "table" => 'type_de_champ', "column" => tdc_1.id.to_s },
|
||||||
{ "label" => tdc_private_1.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_1.id.to_s },
|
{ "label" => tdc_2.libelle, "table" => 'type_de_champ', "column" => tdc_2.id.to_s },
|
||||||
{ "label" => tdc_private_2.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_2.id.to_s }
|
{ "label" => tdc_private_1.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_1.id.to_s },
|
||||||
]
|
{ "label" => tdc_private_2.libelle, "table" => 'type_de_champ_private', "column" => tdc_private_2.id.to_s }
|
||||||
}
|
]
|
||||||
|
}
|
||||||
|
|
||||||
before do
|
before do
|
||||||
procedure.types_de_champ[2].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:header_section))
|
procedure.types_de_champ[2].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:header_section))
|
||||||
procedure.types_de_champ[3].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:explication))
|
procedure.types_de_champ[3].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:explication))
|
||||||
procedure.types_de_champ_private[2].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:header_section))
|
procedure.types_de_champ_private[2].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:header_section))
|
||||||
procedure.types_de_champ_private[3].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:explication))
|
procedure.types_de_champ_private[3].update_attribute(:type_champ,TypeDeChamp.type_champs.fetch(:explication))
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure)) }
|
||||||
|
|
||||||
|
it { expect(subject.fields).to eq(expected) }
|
||||||
end
|
end
|
||||||
|
|
||||||
subject { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure)) }
|
context 'when the procedure is for individuals' do
|
||||||
|
let(:name_field) { { "label" => "Prénom", "table" => "individual", "column" => "prenom" } }
|
||||||
|
let(:surname_field) { { "label" => "Nom", "table" => "individual", "column" => "nom" } }
|
||||||
|
let(:gender_field) { { "label" => "Civilité", "table" => "individual", "column" => "gender" } }
|
||||||
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
|
let(:procedure_presentation) { create(:procedure_presentation, assign_to: create(:assign_to, procedure: procedure)) }
|
||||||
|
|
||||||
it { expect(subject.fields).to eq(expected) }
|
subject { procedure_presentation.fields }
|
||||||
|
|
||||||
|
it { is_expected.to include(name_field, surname_field, gender_field) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#fields_for_select" do
|
describe "#fields_for_select" do
|
||||||
|
@ -133,6 +147,29 @@ describe ProcedurePresentation do
|
||||||
it { is_expected.to eq('bla@yopmail.com') }
|
it { is_expected.to eq('bla@yopmail.com') }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'for individual table' do
|
||||||
|
let(:table) { 'individual' }
|
||||||
|
let(:dossier) { create(:dossier, procedure: procedure, individual: create(:individual, nom: 'Martin', prenom: 'Jacques', gender: 'M.')) }
|
||||||
|
|
||||||
|
context 'for prenom column' do
|
||||||
|
let(:column) { 'prenom' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('Jacques') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for nom column' do
|
||||||
|
let(:column) { 'nom' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('Martin') }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for gender column' do
|
||||||
|
let(:column) { 'gender' }
|
||||||
|
|
||||||
|
it { is_expected.to eq('M.') }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'for etablissement table' do
|
context 'for etablissement table' do
|
||||||
let(:table) { 'etablissement' }
|
let(:table) { 'etablissement' }
|
||||||
let(:column) { 'code_postal' } # All other columns work the same, no extra test required
|
let(:column) { 'code_postal' } # All other columns work the same, no extra test required
|
||||||
|
@ -249,6 +286,34 @@ describe ProcedurePresentation do
|
||||||
it { is_expected.to eq([biere_dossier, vin_dossier].map(&:id)) }
|
it { is_expected.to eq([biere_dossier, vin_dossier].map(&:id)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'for individual table' do
|
||||||
|
let(:table) { 'individual' }
|
||||||
|
let(:order) { 'asc' } # Desc works the same, no extra test required
|
||||||
|
|
||||||
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
|
|
||||||
|
let!(:first_dossier) { create(:dossier, procedure: procedure, individual: create(:individual, gender: 'M', prenom: 'Alain', nom: 'Antonelli')) }
|
||||||
|
let!(:last_dossier) { create(:dossier, procedure: procedure, individual: create(:individual, gender: 'Mme', prenom: 'Zora', nom: 'Zemmour')) }
|
||||||
|
|
||||||
|
context 'for gender column' do
|
||||||
|
let(:column) { 'gender' }
|
||||||
|
|
||||||
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for prenom column' do
|
||||||
|
let(:column) { 'prenom' }
|
||||||
|
|
||||||
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for nom column' do
|
||||||
|
let(:column) { 'nom' }
|
||||||
|
|
||||||
|
it { is_expected.to eq([first_dossier, last_dossier].map(&:id)) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'for other tables' do
|
context 'for other tables' do
|
||||||
# All other columns and tables work the same so it’s ok to test only one
|
# All other columns and tables work the same so it’s ok to test only one
|
||||||
let(:table) { 'etablissement' }
|
let(:table) { 'etablissement' }
|
||||||
|
@ -345,5 +410,29 @@ describe ProcedurePresentation do
|
||||||
|
|
||||||
it { is_expected.to contain_exactly(kept_dossier.id) }
|
it { is_expected.to contain_exactly(kept_dossier.id) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'for individual table' do
|
||||||
|
let(:procedure) { create(:procedure, :for_individual) }
|
||||||
|
let!(:kept_dossier) { create(:dossier, procedure: procedure, individual: create(:individual, gender: 'Mme', prenom: 'Josephine', nom: 'Baker')) }
|
||||||
|
let!(:discarded_dossier) { create(:dossier, procedure: procedure, individual: create(:individual, gender: 'M', prenom: 'Jean', nom: 'Tremblay')) }
|
||||||
|
|
||||||
|
context 'for gender column' do
|
||||||
|
let(:filter) { [{ 'table' => 'individual', 'column' => 'gender', 'value' => 'Mme' }] }
|
||||||
|
|
||||||
|
it { is_expected.to contain_exactly(kept_dossier.id) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for prenom column' do
|
||||||
|
let(:filter) { [{ 'table' => 'individual', 'column' => 'prenom', 'value' => 'Josephine' }] }
|
||||||
|
|
||||||
|
it { is_expected.to contain_exactly(kept_dossier.id) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for nom column' do
|
||||||
|
let(:filter) { [{ 'table' => 'individual', 'column' => 'nom', 'value' => 'Baker' }] }
|
||||||
|
|
||||||
|
it { is_expected.to contain_exactly(kept_dossier.id) }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Reference in a new issue