Merge pull request #7140 from betagouv/only_safe_pj_in_zip
fix(archive): exporte uniquement les fichiers sans virus
This commit is contained in:
commit
9b1f9f9a21
4 changed files with 85 additions and 13 deletions
|
@ -165,6 +165,7 @@ class PiecesJustificativesService
|
||||||
ActiveStorage::Attachment
|
ActiveStorage::Attachment
|
||||||
.includes(:blob)
|
.includes(:blob)
|
||||||
.where(record_type: "Champ", record_id: champ_id_dossier_id.keys)
|
.where(record_type: "Champ", record_id: champ_id_dossier_id.keys)
|
||||||
|
.filter { |a| safe_attachment(a) }
|
||||||
.map do |a|
|
.map do |a|
|
||||||
dossier_id = champ_id_dossier_id[a.record_id]
|
dossier_id = champ_id_dossier_id[a.record_id]
|
||||||
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
||||||
|
@ -181,6 +182,7 @@ class PiecesJustificativesService
|
||||||
ActiveStorage::Attachment
|
ActiveStorage::Attachment
|
||||||
.includes(:blob)
|
.includes(:blob)
|
||||||
.where(record_type: "Commentaire", record_id: commentaire_id_dossier_id.keys)
|
.where(record_type: "Commentaire", record_id: commentaire_id_dossier_id.keys)
|
||||||
|
.filter { |a| safe_attachment(a) }
|
||||||
.map do |a|
|
.map do |a|
|
||||||
dossier_id = commentaire_id_dossier_id[a.record_id]
|
dossier_id = commentaire_id_dossier_id[a.record_id]
|
||||||
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
||||||
|
@ -212,6 +214,7 @@ class PiecesJustificativesService
|
||||||
ActiveStorage::Attachment
|
ActiveStorage::Attachment
|
||||||
.includes(:blob)
|
.includes(:blob)
|
||||||
.where(record_type: "Dossier", name: "justificatif_motivation", record_id: dossiers)
|
.where(record_type: "Dossier", name: "justificatif_motivation", record_id: dossiers)
|
||||||
|
.filter { |a| safe_attachment(a) }
|
||||||
.map do |a|
|
.map do |a|
|
||||||
dossier_id = a.record_id
|
dossier_id = a.record_id
|
||||||
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
ActiveStorage::DownloadableFile.pj_and_path(dossier_id, a)
|
||||||
|
@ -262,4 +265,10 @@ class PiecesJustificativesService
|
||||||
.where(record_type: "BillSignature", record_id: bill_ids)
|
.where(record_type: "BillSignature", record_id: bill_ids)
|
||||||
.map { |bill| ActiveStorage::DownloadableFile.bill_and_path(bill) }
|
.map { |bill| ActiveStorage::DownloadableFile.bill_and_path(bill) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.safe_attachment(attachment)
|
||||||
|
attachment
|
||||||
|
.blob
|
||||||
|
.metadata[:virus_scan_result] == ActiveStorage::VirusScanner::SAFE
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,6 +23,16 @@ describe PiecesJustificativesService do
|
||||||
it { expect(subject).to match_array([pj_champ.call(dossier).piece_justificative_file.attachment]) }
|
it { expect(subject).to match_array([pj_champ.call(dossier).piece_justificative_file.attachment]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a pj not safe on a champ' do
|
||||||
|
let(:procedure) { create(:procedure, :with_piece_justificative) }
|
||||||
|
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
let(:pj_champ) { -> (d) { d.champs.find { |c| c.type == 'Champs::PieceJustificativeChamp' } } }
|
||||||
|
|
||||||
|
before { attach_file_to_champ(pj_champ.call(dossier), safe = false) }
|
||||||
|
|
||||||
|
it { expect(subject).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a private pj champ' do
|
context 'with a private pj champ' do
|
||||||
let(:procedure) { create(:procedure) }
|
let(:procedure) { create(:procedure) }
|
||||||
let(:dossier) { create(:dossier, procedure: procedure) }
|
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
@ -64,12 +74,26 @@ describe PiecesJustificativesService do
|
||||||
let(:dossier) { create(:dossier) }
|
let(:dossier) { create(:dossier) }
|
||||||
let(:witness) { create(:dossier) }
|
let(:witness) { create(:dossier) }
|
||||||
|
|
||||||
let!(:commentaire) { create(:commentaire, :with_file, dossier: dossier) }
|
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||||
let!(:witness_commentaire) { create(:commentaire, :with_file, dossier: witness) }
|
let!(:witness_commentaire) { create(:commentaire, dossier: witness) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
attach_file(commentaire.piece_jointe)
|
||||||
|
attach_file(witness_commentaire.piece_jointe)
|
||||||
|
end
|
||||||
|
|
||||||
it { expect(subject).to match_array(dossier.commentaires.first.piece_jointe.attachment) }
|
it { expect(subject).to match_array(dossier.commentaires.first.piece_jointe.attachment) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a pj not safe on a commentaire' do
|
||||||
|
let(:dossier) { create(:dossier) }
|
||||||
|
let!(:commentaire) { create(:commentaire, dossier: dossier) }
|
||||||
|
|
||||||
|
before { attach_file(commentaire.piece_jointe, safe = false) }
|
||||||
|
|
||||||
|
it { expect(subject).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
context 'with a motivation' do
|
context 'with a motivation' do
|
||||||
let(:dossier) { create(:dossier, :with_justificatif) }
|
let(:dossier) { create(:dossier, :with_justificatif) }
|
||||||
let!(:witness) { create(:dossier, :with_justificatif) }
|
let!(:witness) { create(:dossier, :with_justificatif) }
|
||||||
|
@ -77,6 +101,14 @@ describe PiecesJustificativesService do
|
||||||
it { expect(subject).to match_array(dossier.justificatif_motivation.attachment) }
|
it { expect(subject).to match_array(dossier.justificatif_motivation.attachment) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a motivation not safe' do
|
||||||
|
let(:dossier) { create(:dossier) }
|
||||||
|
|
||||||
|
before { attach_file(dossier.justificatif_motivation, safe = false) }
|
||||||
|
|
||||||
|
it { expect(subject).to be_empty }
|
||||||
|
end
|
||||||
|
|
||||||
context 'with an attestation' do
|
context 'with an attestation' do
|
||||||
let(:dossier) { create(:dossier, :with_attestation) }
|
let(:dossier) { create(:dossier, :with_attestation) }
|
||||||
let!(:witness) { create(:dossier, :with_attestation) }
|
let!(:witness) { create(:dossier, :with_attestation) }
|
||||||
|
@ -167,12 +199,20 @@ describe PiecesJustificativesService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach_file_to_champ(champ)
|
def attach_file_to_champ(champ, safe = true)
|
||||||
attach_file(champ.piece_justificative_file)
|
attach_file(champ.piece_justificative_file, safe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def attach_file(attachable)
|
def attach_file(attachable, safe = true)
|
||||||
attachable
|
to_be_attached = {
|
||||||
.attach(io: StringIO.new("toto"), filename: "toto.png", content_type: "image/png")
|
io: StringIO.new("toto"),
|
||||||
|
filename: "toto.png", content_type: "image/png"
|
||||||
|
}
|
||||||
|
|
||||||
|
if safe
|
||||||
|
to_be_attached[:metadata] = { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||||
|
end
|
||||||
|
|
||||||
|
attachable.attach(to_be_attached)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -90,8 +90,22 @@ describe 'Inviting an expert:' do
|
||||||
let(:commentaire) { create(:commentaire, instructeur: instructeur, dossier: dossier) }
|
let(:commentaire) { create(:commentaire, instructeur: instructeur, dossier: dossier) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
champ.piece_justificative_file.attach(io: File.open(path), filename: "piece_justificative_0.pdf", content_type: "application/pdf")
|
champ
|
||||||
dossier.champs_private << create(:champ_piece_justificative, :with_piece_justificative_file, private: true, dossier: dossier)
|
.piece_justificative_file
|
||||||
|
.attach(io: File.open(path),
|
||||||
|
filename: "piece_justificative_0.pdf",
|
||||||
|
content_type: "application/pdf",
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE })
|
||||||
|
|
||||||
|
dossier.champs_private << create(:champ_piece_justificative, private: true, dossier: dossier)
|
||||||
|
|
||||||
|
dossier.champs_private
|
||||||
|
.first
|
||||||
|
.piece_justificative_file
|
||||||
|
.attach(io: File.open(path),
|
||||||
|
filename: "piece_justificative_0.pdf",
|
||||||
|
content_type: "application/pdf",
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE })
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'An Expert can download an archive containing attachments without any private champ, bill signature and operations logs' do
|
scenario 'An Expert can download an archive containing attachments without any private champ, bill signature and operations logs' do
|
||||||
|
@ -102,7 +116,7 @@ describe 'Inviting an expert:' do
|
||||||
click_on '1 avis à donner'
|
click_on '1 avis à donner'
|
||||||
click_on avis.dossier.user.email
|
click_on avis.dossier.user.email
|
||||||
|
|
||||||
find(:css, '.attached').click
|
find(:css, '[aria-controls=print-pj-menu]').click
|
||||||
click_on 'Télécharger le dossier et toutes ses pièces jointes'
|
click_on 'Télécharger le dossier et toutes ses pièces jointes'
|
||||||
# For some reason, clicking the download link does not trigger the download in the headless browser ;
|
# For some reason, clicking the download link does not trigger the download in the headless browser ;
|
||||||
# So we need to go to the download link directly
|
# So we need to go to the download link directly
|
||||||
|
|
|
@ -194,14 +194,18 @@ describe 'Instructing a dossier:', js: true do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
dossier.passer_en_instruction!(instructeur: instructeur)
|
dossier.passer_en_instruction!(instructeur: instructeur)
|
||||||
champ.piece_justificative_file.attach(io: File.open(path), filename: "piece_justificative_0.pdf", content_type: "application/pdf")
|
champ.piece_justificative_file
|
||||||
|
.attach(io: File.open(path),
|
||||||
|
filename: "piece_justificative_0.pdf",
|
||||||
|
content_type: "application/pdf",
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE })
|
||||||
|
|
||||||
log_in(instructeur.email, password)
|
log_in(instructeur.email, password)
|
||||||
visit instructeur_dossier_path(procedure, dossier)
|
visit instructeur_dossier_path(procedure, dossier)
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'A instructeur can download an archive containing a single attachment' do
|
scenario 'A instructeur can download an archive containing a single attachment' do
|
||||||
find(:css, '.attached').click
|
find(:css, '[aria-controls=print-pj-menu]').click
|
||||||
click_on 'Télécharger le dossier et toutes ses pièces jointes'
|
click_on 'Télécharger le dossier et toutes ses pièces jointes'
|
||||||
# For some reason, clicking the download link does not trigger the download in the headless browser ;
|
# For some reason, clicking the download link does not trigger the download in the headless browser ;
|
||||||
# So we need to go to the download link directly
|
# So we need to go to the download link directly
|
||||||
|
@ -219,7 +223,12 @@ describe 'Instructing a dossier:', js: true do
|
||||||
end
|
end
|
||||||
|
|
||||||
scenario 'A instructeur can download an archive containing several identical attachments' do
|
scenario 'A instructeur can download an archive containing several identical attachments' do
|
||||||
commentaire.piece_jointe.attach(io: File.open(path), filename: "piece_justificative_0.pdf", content_type: "application/pdf")
|
commentaire
|
||||||
|
.piece_jointe
|
||||||
|
.attach(io: File.open(path),
|
||||||
|
filename: "piece_justificative_0.pdf",
|
||||||
|
content_type: "application/pdf",
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE })
|
||||||
|
|
||||||
visit telecharger_pjs_instructeur_dossier_path(procedure, dossier)
|
visit telecharger_pjs_instructeur_dossier_path(procedure, dossier)
|
||||||
DownloadHelpers.wait_for_download
|
DownloadHelpers.wait_for_download
|
||||||
|
|
Loading…
Reference in a new issue