Refactor message attachements to use active_storage
This commit is contained in:
parent
85f7412fa6
commit
3cb39c2840
20 changed files with 59 additions and 66 deletions
|
@ -138,7 +138,7 @@ module Gestionnaires
|
||||||
end
|
end
|
||||||
|
|
||||||
def commentaire_params
|
def commentaire_params
|
||||||
params.require(:commentaire).permit(:body, :file)
|
params.require(:commentaire).permit(:body, :piece_jointe)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -166,7 +166,7 @@ module Gestionnaires
|
||||||
end
|
end
|
||||||
|
|
||||||
def commentaire_params
|
def commentaire_params
|
||||||
params.require(:commentaire).permit(:body, :file)
|
params.require(:commentaire).permit(:body, :piece_jointe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def champs_private_params
|
def champs_private_params
|
||||||
|
|
|
@ -52,7 +52,7 @@ class SupportController < ApplicationController
|
||||||
email: email,
|
email: email,
|
||||||
phone: params[:phone],
|
phone: params[:phone],
|
||||||
text: params[:text],
|
text: params[:text],
|
||||||
file: params[:file],
|
file: params[:piece_jointe],
|
||||||
dossier_id: dossier&.id,
|
dossier_id: dossier&.id,
|
||||||
browser: browser_name,
|
browser: browser_name,
|
||||||
tags: tags
|
tags: tags
|
||||||
|
@ -61,7 +61,7 @@ class SupportController < ApplicationController
|
||||||
|
|
||||||
def create_commentaire
|
def create_commentaire
|
||||||
attributes = {
|
attributes = {
|
||||||
file: params[:file],
|
piece_jointe: params[:piece_jointe],
|
||||||
body: "[#{params[:subject]}]<br><br>#{params[:text]}"
|
body: "[#{params[:subject]}]<br><br>#{params[:text]}"
|
||||||
}
|
}
|
||||||
commentaire = CommentaireService.build(current_user, dossier, attributes)
|
commentaire = CommentaireService.build(current_user, dossier, attributes)
|
||||||
|
|
|
@ -354,7 +354,7 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
def commentaire_params
|
def commentaire_params
|
||||||
params.require(:commentaire).permit(:body, :file)
|
params.require(:commentaire).permit(:body, :piece_jointe)
|
||||||
end
|
end
|
||||||
|
|
||||||
def passage_en_construction?
|
def passage_en_construction?
|
||||||
|
|
|
@ -5,9 +5,10 @@ class Commentaire < ApplicationRecord
|
||||||
belongs_to :gestionnaire
|
belongs_to :gestionnaire
|
||||||
|
|
||||||
mount_uploader :file, CommentaireFileUploader
|
mount_uploader :file, CommentaireFileUploader
|
||||||
validates :file, file_size: { maximum: 20.megabytes, message: "La taille du fichier doit être inférieure à 20 Mo" }
|
|
||||||
validate :is_virus_free?
|
|
||||||
validate :messagerie_available?, on: :create
|
validate :messagerie_available?, on: :create
|
||||||
|
|
||||||
|
has_one_attached :piece_jointe
|
||||||
|
|
||||||
validates :body, presence: { message: "Votre message ne peut être vide" }
|
validates :body, presence: { message: "Votre message ne peut être vide" }
|
||||||
|
|
||||||
default_scope { order(created_at: :asc) }
|
default_scope { order(created_at: :asc) }
|
||||||
|
@ -47,10 +48,15 @@ class Commentaire < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def file_url
|
def file_url
|
||||||
if Flipflop.remote_storage?
|
if piece_jointe.attached?
|
||||||
|
if piece_jointe.virus_scanner.safe?
|
||||||
|
Rails.application.routes.url_helpers.url_for(piece_jointe)
|
||||||
|
end
|
||||||
|
elsif Flipflop.remote_storage?
|
||||||
RemoteDownloader.new(file.path).url
|
RemoteDownloader.new(file.path).url
|
||||||
else
|
elsif file&.url
|
||||||
file.url
|
# FIXME: this is horrible but used only in dev and will be removed after migration
|
||||||
|
File.join(LOCAL_DOWNLOAD_URL, file.url)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -74,12 +80,6 @@ class Commentaire < ApplicationRecord
|
||||||
DossierMailer.notify_new_answer(dossier).deliver_later
|
DossierMailer.notify_new_answer(dossier).deliver_later
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_virus_free?
|
|
||||||
if file.present? && file_changed? && !ClamavService.safe_file?(file.path)
|
|
||||||
errors.add(:file, "Virus détecté dans le fichier joint, merci de changer de fichier")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def messagerie_available?
|
def messagerie_available?
|
||||||
return if sent_by_system?
|
return if sent_by_system?
|
||||||
if dossier.present? && !dossier.messagerie_available?
|
if dossier.present? && !dossier.messagerie_available?
|
||||||
|
|
|
@ -117,7 +117,7 @@ class Dossier < ApplicationRecord
|
||||||
scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) }
|
scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) }
|
||||||
scope :since, -> (since) { where('dossiers.en_construction_at >= ?', since) }
|
scope :since, -> (since) { where('dossiers.en_construction_at >= ?', since) }
|
||||||
scope :for_api, -> {
|
scope :for_api, -> {
|
||||||
includes(commentaires: [],
|
includes(commentaires: { piece_jointe_attachment: :blob },
|
||||||
champs: [
|
champs: [
|
||||||
:geo_areas,
|
:geo_areas,
|
||||||
:etablissement,
|
:etablissement,
|
||||||
|
|
|
@ -13,6 +13,11 @@ class CommentaireService
|
||||||
|
|
||||||
def build_with_email(email, dossier, params)
|
def build_with_email(email, dossier, params)
|
||||||
attributes = params.merge(email: email, dossier: dossier)
|
attributes = params.merge(email: email, dossier: dossier)
|
||||||
|
# For some reason ActiveStorage trows an error in tests if we passe an empty string here.
|
||||||
|
# I suspect it could be resolved in rails 6 by using explicit `attach()`
|
||||||
|
if attributes[:piece_jointe].blank?
|
||||||
|
attributes.delete(:piece_jointe)
|
||||||
|
end
|
||||||
Commentaire.new(attributes)
|
Commentaire.new(attributes)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ class LocalDownloader
|
||||||
end
|
end
|
||||||
|
|
||||||
def url
|
def url
|
||||||
@url ||= File.join(TPS::Application::URL, 'downloads', random_folder_name, "#{@filename_suffix}.#{@extension}")
|
@url ||= File.join(LOCAL_DOWNLOAD_URL, 'downloads', random_folder_name, "#{@filename_suffix}.#{@extension}")
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
.messagerie
|
.messagerie
|
||||||
%ul.messages-list
|
%ul.messages-list
|
||||||
- @dossier.commentaires.each do |commentaire|
|
- @dossier.commentaires.with_attached_piece_jointe.each do |commentaire|
|
||||||
%li
|
%li
|
||||||
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: current_gestionnaire, messagerie_seen_at: nil }
|
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: current_gestionnaire, messagerie_seen_at: nil }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.messagerie.container
|
.messagerie.container
|
||||||
%ul.messages-list
|
%ul.messages-list
|
||||||
- dossier.commentaires.each do |commentaire|
|
- dossier.commentaires.with_attached_piece_jointe.each do |commentaire|
|
||||||
%li.message{ class: commentaire_is_from_me_class(commentaire, connected_user) }
|
%li.message{ class: commentaire_is_from_me_class(commentaire, connected_user) }
|
||||||
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: connected_user, messagerie_seen_at: messagerie_seen_at }
|
= render partial: "shared/dossiers/messages/message", locals: { commentaire: commentaire, connected_user: connected_user, messagerie_seen_at: messagerie_seen_at }
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
= f.text_area :body, rows: 5, placeholder: 'Répondre ici', required: true, class: 'message-textarea'
|
= f.text_area :body, rows: 5, placeholder: 'Répondre ici', required: true, class: 'message-textarea'
|
||||||
.flex.justify-between.wrap
|
.flex.justify-between.wrap
|
||||||
%div
|
%div
|
||||||
= f.file_field :file, id: :file, accept: commentaire.file.accept_extension_list
|
= f.file_field :piece_jointe, id: 'piece_jointe', direct_upload: true
|
||||||
%label{ for: :file }
|
%label{ for: :piece_jointe }
|
||||||
.notice
|
.notice
|
||||||
(taille max : 20 Mo)
|
(taille max : 20 Mo)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
= commentaire_date(commentaire)
|
= commentaire_date(commentaire)
|
||||||
.rich-text= sanitize(simple_format(commentaire.body))
|
.rich-text= sanitize(simple_format(commentaire.body))
|
||||||
|
|
||||||
- if commentaire.file.present?
|
- if commentaire.piece_jointe.attached?
|
||||||
|
.attachment-link
|
||||||
|
= render partial: "shared/attachment/show", locals: { attachment: commentaire.piece_jointe.attachment }
|
||||||
|
- elsif commentaire.file.present?
|
||||||
.attachment-link
|
.attachment-link
|
||||||
= link_to commentaire.file_url, class: "button", target: "_blank", rel: "noopener", title: "Télécharger" do
|
= link_to commentaire.file_url, class: "button", target: "_blank", rel: "noopener", title: "Télécharger" do
|
||||||
%span.icon.attachment
|
%span.icon.attachment
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
Une capture d’écran peut nous aider à identifier plus facilement l’endroit à améliorer.
|
Une capture d’écran peut nous aider à identifier plus facilement l’endroit à améliorer.
|
||||||
.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AUTRE } }
|
.notice.hidden{ data: { 'contact-type-only': Helpscout::FormAdapter::TYPE_AUTRE } }
|
||||||
Une capture d’écran peut nous aider à identifier plus facilement le problème.
|
Une capture d’écran peut nous aider à identifier plus facilement le problème.
|
||||||
= file_field_tag :file
|
= file_field_tag :piece_jointe
|
||||||
|
|
||||||
= hidden_field_tag :tags, @tags&.join(',')
|
= hidden_field_tag :tags, @tags&.join(',')
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,6 @@ module TPS
|
||||||
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
|
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
|
||||||
config.assets.precompile += ['.woff']
|
config.assets.precompile += ['.woff']
|
||||||
|
|
||||||
URL = ENV['APP_HOST'] || "http://localhost:3000/"
|
|
||||||
|
|
||||||
config.active_job.queue_adapter = :delayed_job
|
config.active_job.queue_adapter = :delayed_job
|
||||||
|
|
||||||
config.action_view.sanitized_allowed_tags = ActionView::Base.sanitized_allowed_tags + ['u']
|
config.action_view.sanitized_allowed_tags = ActionView::Base.sanitized_allowed_tags + ['u']
|
||||||
|
|
|
@ -28,3 +28,6 @@ FAQ_ADMIN_URL = "https://faq.demarches-simplifiees.fr/collection/1-administrateu
|
||||||
COMMENT_TROUVER_MA_DEMARCHE_URL = [FAQ_URL, "article", "59-comment-trouver-ma-demarche"].join("/")
|
COMMENT_TROUVER_MA_DEMARCHE_URL = [FAQ_URL, "article", "59-comment-trouver-ma-demarche"].join("/")
|
||||||
STATUS_PAGE_URL = "https://status.demarches-simplifiees.fr"
|
STATUS_PAGE_URL = "https://status.demarches-simplifiees.fr"
|
||||||
MATOMO_IFRAME_URL = "https://stats.data.gouv.fr/index.php?module=CoreAdminHome&action=optOut&language=fr&&fontColor=333333&fontSize=16px&fontFamily=Muli"
|
MATOMO_IFRAME_URL = "https://stats.data.gouv.fr/index.php?module=CoreAdminHome&action=optOut&language=fr&&fontColor=333333&fontSize=16px&fontFamily=Muli"
|
||||||
|
|
||||||
|
# FIXME: This is only used in dev in couple of places and should be removed after PJ migration
|
||||||
|
LOCAL_DOWNLOAD_URL = "http://#{ENV.fetch('APP_HOST', 'localhost:3000')}"
|
||||||
|
|
|
@ -92,7 +92,7 @@ describe Gestionnaires::AvisController, type: :controller do
|
||||||
let(:file) { nil }
|
let(:file) { nil }
|
||||||
let(:scan_result) { true }
|
let(:scan_result) { true }
|
||||||
|
|
||||||
subject { post :create_commentaire, params: { id: avis_without_answer.id, commentaire: { body: 'commentaire body', file: file } } }
|
subject { post :create_commentaire, params: { id: avis_without_answer.id, commentaire: { body: 'commentaire body', piece_jointe: file } } }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
|
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
|
||||||
|
@ -110,16 +110,10 @@ describe Gestionnaires::AvisController, type: :controller do
|
||||||
|
|
||||||
it do
|
it do
|
||||||
subject
|
subject
|
||||||
expect(Commentaire.last.file.path).to include("piece_justificative_0.pdf")
|
expect(Commentaire.last.piece_jointe.filename).to eq("piece_justificative_0.pdf")
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect { subject }.to change(Commentaire, :count).by(1) }
|
it { expect { subject }.to change(Commentaire, :count).by(1) }
|
||||||
|
|
||||||
context "and a virus" do
|
|
||||||
let(:scan_result) { false }
|
|
||||||
|
|
||||||
it { expect { subject }.not_to change(Commentaire, :count) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -350,15 +350,15 @@ describe Gestionnaires::DossiersController, type: :controller do
|
||||||
expect(flash.notice).to be_present
|
expect(flash.notice).to be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the commentaire creation fails" do
|
context "when the commentaire created with virus file" do
|
||||||
let(:scan_result) { false }
|
let(:scan_result) { false }
|
||||||
|
|
||||||
it "renders the messagerie page with the invalid commentaire" do
|
it "creates a commentaire (shows message that file have a virus)" do
|
||||||
expect { subject }.not_to change(Commentaire, :count)
|
expect { subject }.to change(Commentaire, :count).by(1)
|
||||||
|
expect(gestionnaire.followed_dossiers).to include(dossier)
|
||||||
|
|
||||||
expect(response).to render_template :messagerie
|
expect(response).to redirect_to(messagerie_gestionnaire_dossier_path(dossier.procedure, dossier))
|
||||||
expect(flash.alert).to be_present
|
expect(flash.notice).to be_present
|
||||||
expect(assigns(:commentaire).body).to eq("avant\napres")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -806,7 +806,7 @@ describe Users::DossiersController, type: :controller do
|
||||||
id: dossier.id,
|
id: dossier.id,
|
||||||
commentaire: {
|
commentaire: {
|
||||||
body: body,
|
body: body,
|
||||||
file: file
|
piece_jointe: file
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,18 +822,6 @@ describe Users::DossiersController, type: :controller do
|
||||||
expect(response).to redirect_to(messagerie_dossier_path(dossier))
|
expect(response).to redirect_to(messagerie_dossier_path(dossier))
|
||||||
expect(flash.notice).to be_present
|
expect(flash.notice).to be_present
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when the commentaire creation fails" do
|
|
||||||
let(:scan_result) { false }
|
|
||||||
|
|
||||||
it "renders the messagerie page with the invalid commentaire" do
|
|
||||||
expect { subject }.not_to change(Commentaire, :count)
|
|
||||||
|
|
||||||
expect(response).to render_template :messagerie
|
|
||||||
expect(flash.alert).to be_present
|
|
||||||
expect(assigns(:commentaire).body).to eq("avant\napres")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#ask_deletion' do
|
describe '#ask_deletion' do
|
||||||
|
|
|
@ -7,5 +7,9 @@ FactoryBot.define do
|
||||||
commentaire.dossier = create :dossier, :en_construction
|
commentaire.dossier = create :dossier, :en_construction
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :with_file do
|
||||||
|
file { Rack::Test::UploadedFile.new("./spec/fixtures/files/logo_test_procedure.png", 'application/pdf') }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe CommentaireService do
|
describe CommentaireService do
|
||||||
|
include ActiveJob::TestHelper
|
||||||
|
|
||||||
describe '.create' do
|
describe '.create' do
|
||||||
let(:dossier) { create :dossier, :en_construction }
|
let(:dossier) { create :dossier, :en_construction }
|
||||||
let(:sender) { dossier.user }
|
let(:sender) { dossier.user }
|
||||||
let(:body) { 'Contenu du message.' }
|
let(:body) { 'Contenu du message.' }
|
||||||
let(:file) { nil }
|
let(:file) { nil }
|
||||||
let(:scan_result) { true }
|
|
||||||
|
|
||||||
subject(:commentaire) { CommentaireService.build(sender, dossier, { body: body, file: file }) }
|
subject(:commentaire) { CommentaireService.build(sender, dossier, { body: body, piece_jointe: file }) }
|
||||||
|
|
||||||
before do
|
|
||||||
allow(ClamavService).to receive(:safe_file?).and_return(scan_result)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'creates a new valid commentaire' do
|
it 'creates a new valid commentaire' do
|
||||||
expect(commentaire.email).to eq sender.email
|
expect(commentaire.email).to eq sender.email
|
||||||
expect(commentaire.dossier).to eq dossier
|
expect(commentaire.dossier).to eq dossier
|
||||||
expect(commentaire.body).to eq 'Contenu du message.'
|
expect(commentaire.body).to eq 'Contenu du message.'
|
||||||
expect(commentaire.file).to be_blank
|
expect(commentaire.piece_jointe.attached?).to be_falsey
|
||||||
expect(commentaire).to be_valid
|
expect(commentaire).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -34,14 +31,15 @@ describe CommentaireService do
|
||||||
context 'when it has a file' do
|
context 'when it has a file' do
|
||||||
let(:file) { Rack::Test::UploadedFile.new("./spec/fixtures/files/piece_justificative_0.pdf", 'application/pdf') }
|
let(:file) { Rack::Test::UploadedFile.new("./spec/fixtures/files/piece_justificative_0.pdf", 'application/pdf') }
|
||||||
|
|
||||||
it 'saves the attached file' do
|
before do
|
||||||
expect(commentaire.file).to be_present
|
expect(ClamavService).to receive(:safe_file?).and_return(true)
|
||||||
expect(commentaire).to be_valid
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'and a virus' do
|
it 'saves the attached file' do
|
||||||
let(:scan_result) { false }
|
perform_enqueued_jobs do
|
||||||
it { expect(commentaire).not_to be_valid }
|
commentaire.save
|
||||||
|
expect(commentaire.piece_jointe.attached?).to be_truthy
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue