diff --git a/app/controllers/commentaires_controller.rb b/app/controllers/commentaires_controller.rb index 6143e3e02..f711a4ab5 100644 --- a/app/controllers/commentaires_controller.rb +++ b/app/controllers/commentaires_controller.rb @@ -11,8 +11,18 @@ class CommentairesController < ApplicationController @commentaire.dossier.next_step! 'user', 'comment' if current_user.email == @commentaire.dossier.user.email end + unless params[:piece_justificative].nil? + pj = PiecesJustificativesService.upload_one! @commentaire.dossier, current_user, params + + if pj.errors.empty? + @commentaire.piece_justificative = pj + else + flash.alert = pj.errors.full_messages.join("
").html_safe + end + end + @commentaire.body = params['texte_commentaire'] - @commentaire.save + @commentaire.save unless flash.alert if is_gestionnaire? NotificationMailer.new_answer(@commentaire.dossier).deliver_now! diff --git a/app/models/commentaire.rb b/app/models/commentaire.rb index 069179f8d..2283775d3 100644 --- a/app/models/commentaire.rb +++ b/app/models/commentaire.rb @@ -1,3 +1,5 @@ class Commentaire < ActiveRecord::Base belongs_to :dossier + + belongs_to :piece_justificative end diff --git a/app/models/piece_justificative.rb b/app/models/piece_justificative.rb index c75824f59..3b29561ba 100644 --- a/app/models/piece_justificative.rb +++ b/app/models/piece_justificative.rb @@ -1,6 +1,7 @@ class PieceJustificative < ActiveRecord::Base belongs_to :dossier belongs_to :type_de_piece_justificative + has_one :commentaire belongs_to :user @@ -10,6 +11,7 @@ class PieceJustificative < ActiveRecord::Base mount_uploader :content, PieceJustificativeUploader validates :content, :file_size => {:maximum => 3.megabytes} + validates :content, presence: true, allow_blank: false, allow_nil: false def empty? content.blank? @@ -17,7 +19,22 @@ class PieceJustificative < ActiveRecord::Base def content_url unless content.url.nil? - (Downloader.new content, type_de_piece_justificative.libelle).url + (Downloader.new content, + (type_de_piece_justificative.nil? ? content.file.original_filename : type_de_piece_justificative.libelle)).url end end + + def self.accept_format + " application/pdf, + application/msword, + application/vnd.openxmlformats-officedocument.wordprocessingml.document, + application/vnd.ms-excel, + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, + application/vnd.ms-powerpoint, + application/vnd.openxmlformats-officedocument.presentationml.presentation, + application/vnd.oasis.opendocument.text, + application/vnd.oasis.opendocument.presentation, + application/vnd.oasis.opendocument.spreadsheet + " + end end diff --git a/app/services/clamav_service.rb b/app/services/clamav_service.rb index f34c32c76..3d9b54de9 100644 --- a/app/services/clamav_service.rb +++ b/app/services/clamav_service.rb @@ -1,6 +1,10 @@ class ClamavService def self.safe_file? path_file + if Rails.env == 'development' + return CLAMAV[:response] if CLAMAV[:mock?] + end + FileUtils.chmod 0666, path_file client = ClamAV::Client.new diff --git a/app/services/pieces_justificatives_service.rb b/app/services/pieces_justificatives_service.rb index c19a7ddc8..f0402b1da 100644 --- a/app/services/pieces_justificatives_service.rb +++ b/app/services/pieces_justificatives_service.rb @@ -21,4 +21,20 @@ class PiecesJustificativesService end errors end + + def self.upload_one! dossier, user, params + if ClamavService.safe_file? params[:piece_justificative][:content].path + piece_justificative = PieceJustificative.new(content: params[:piece_justificative][:content], + dossier: dossier, + type_de_piece_justificative: nil, + user: user) + + piece_justificative.save + else + piece_justificative = PieceJustificative.new + piece_justificative.errors.add(:content, params[:piece_justificative][:content].original_filename+": Virus détecté !!") + end + + piece_justificative + end end \ No newline at end of file diff --git a/app/views/users/description/_pieces_justificatives.html.haml b/app/views/users/description/_pieces_justificatives.html.haml index 1aed8207a..e440520e8 100644 --- a/app/views/users/description/_pieces_justificatives.html.haml +++ b/app/views/users/description/_pieces_justificatives.html.haml @@ -8,27 +8,9 @@ -if @dossier.cerfa_available? %span.btn.btn-sm.btn-file.btn-success Modifier - %input{type: 'file', name:'cerfa_pdf', id:'cerfa_pdf', accept: "application/pdf, - application/msword, - application/vnd.openxmlformats-officedocument.wordprocessingml.document, - application/vnd.ms-excel, - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, - application/vnd.ms-powerpoint, - application/vnd.openxmlformats-officedocument.presentationml.presentation, - application/vnd.oasis.opendocument.text, - application/vnd.oasis.opendocument.presentation, - application/vnd.oasis.opendocument.spreadsheet", :max_file_size => 3.megabytes } + %input{type: 'file', name:'cerfa_pdf', id:'cerfa_pdf', accept: PieceJustificative.accept_format, :max_file_size => 3.megabytes } -else - %input{type: 'file', name:'cerfa_pdf', id:'cerfa_pdf', accept: "application/pdf, - application/msword, - application/vnd.openxmlformats-officedocument.wordprocessingml.document, - application/vnd.ms-excel, - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, - application/vnd.ms-powerpoint, - application/vnd.openxmlformats-officedocument.presentationml.presentation, - application/vnd.oasis.opendocument.text, - application/vnd.oasis.opendocument.presentation, - application/vnd.oasis.opendocument.spreadsheet", :max_file_size => 3.megabytes } + %input{type: 'file', name:'cerfa_pdf', id:'cerfa_pdf', accept: PieceJustificative.accept_format, :max_file_size => 3.megabytes } - @dossier.types_de_piece_justificative.each do |type_de_piece_justificative| %tr @@ -39,27 +21,9 @@ %span.text-success{ id: "piece_justificative_#{type_de_piece_justificative.id}" } Nous l'avons récupéré pour vous. -else -if @dossier.retrieve_last_piece_justificative_by_type(type_de_piece_justificative.id).nil? - = file_field_tag "piece_justificative_#{type_de_piece_justificative.id}", accept: " application/pdf, - application/msword, - application/vnd.openxmlformats-officedocument.wordprocessingml.document, - application/vnd.ms-excel, - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, - application/vnd.ms-powerpoint, - application/vnd.openxmlformats-officedocument.presentationml.presentation, - application/vnd.oasis.opendocument.text, - application/vnd.oasis.opendocument.presentation, - application/vnd.oasis.opendocument.spreadsheet", :max_file_size => 3.megabytes + = file_field_tag "piece_justificative_#{type_de_piece_justificative.id}", accept: PieceJustificative.accept_format, :max_file_size => 3.megabytes -else %span.btn.btn-sm.btn-file.btn-success Modifier - = file_field_tag "piece_justificative_#{type_de_piece_justificative.id}", accept: " application/pdf, - application/msword, - application/vnd.openxmlformats-officedocument.wordprocessingml.document, - application/vnd.ms-excel, - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, - application/vnd.ms-powerpoint, - application/vnd.openxmlformats-officedocument.presentationml.presentation, - application/vnd.oasis.opendocument.text, - application/vnd.oasis.opendocument.presentation, - application/vnd.oasis.opendocument.spreadsheet", :max_file_size => 3.megabytes + = file_field_tag "piece_justificative_#{type_de_piece_justificative.id}", accept: PieceJustificative.accept_format, :max_file_size => 3.megabytes diff --git a/app/views/users/recapitulatif/_commentaires_flux.html.haml b/app/views/users/recapitulatif/_commentaires_flux.html.haml index ec49fcb75..f666e066d 100644 --- a/app/views/users/recapitulatif/_commentaires_flux.html.haml +++ b/app/views/users/recapitulatif/_commentaires_flux.html.haml @@ -1,10 +1,10 @@ .content#commentaires_flux{style:'width:100%;'} - %div#commentaire_new{style: 'width:80%; margin-left:auto; margin-right:auto'} - = form_tag(url_for({ controller: 'commentaires', action: :create, dossier_id: @facade.dossier.id }), class: 'form-inline', method: 'POST') do - %textarea.form-control{id: 'texte_commentaire', class: 'wysihtml5', name: 'texte_commentaire', style: 'width: 100%; margin-bottom:2%', rows: '5', placeholder:"Dialoguer avec votre interlocuteur privilégié en charge de votre dossier."} + %div#commentaire_new{style: 'width:80%; margin-left:auto; margin-right:auto; margin-bottom:7%'} + = form_tag(url_for({ controller: 'commentaires', action: :create, dossier_id: @facade.dossier.id }), class: 'form-inline', method: 'POST', multipart: true) do + %textarea.form-control{id: 'texte_commentaire', class: 'wysihtml5', name: 'texte_commentaire', style: 'width: 100%; margin-bottom:2%', rows: '5', placeholder:"Commentaire"} + %h4.text-primary{style: 'margin-top: 0px'} Ajout un fichier + = file_field_tag "piece_justificative[content]", accept: PieceJustificative.accept_format, style: 'float: left; margin-left: 20px' %input.form-control.btn.btn-success{:type => 'submit', :value => 'Poster', style: 'float:right'} - %br - %br -@facade.commentaires.each do |com| %span.text-info#email_contact{style: 'font-weight:bold'} @@ -12,7 +12,15 @@ %span#created_at \- =com.created_at_fr + - unless com.piece_justificative.nil? + \- + %span#piece_justificative + %b + = link_to com.piece_justificative.content.file.original_filename, com.piece_justificative.content_url, style:'color: green', target: '_blank' + %br .description#body =com.body.html_safe + + %br diff --git a/config/initializers/clamav.rb b/config/initializers/clamav.rb new file mode 100644 index 000000000..13df38f7a --- /dev/null +++ b/config/initializers/clamav.rb @@ -0,0 +1,4 @@ +CLAMAV = Hashie::Mash.new ({ + mock?: true, + response: true + }) \ No newline at end of file diff --git a/db/migrate/20160419142017_add_piece_justificative_reference_to_commentaire.rb b/db/migrate/20160419142017_add_piece_justificative_reference_to_commentaire.rb new file mode 100644 index 000000000..d0f9bc8f9 --- /dev/null +++ b/db/migrate/20160419142017_add_piece_justificative_reference_to_commentaire.rb @@ -0,0 +1,5 @@ +class AddPieceJustificativeReferenceToCommentaire < ActiveRecord::Migration + def change + add_reference :commentaires, :piece_justificative, references: :piece_justificatives + end +end diff --git a/db/schema.rb b/db/schema.rb index 275c4e305..0aaefd46e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160317153115) do +ActiveRecord::Schema.define(version: 20160419142017) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -84,10 +84,11 @@ ActiveRecord::Schema.define(version: 20160317153115) do create_table "commentaires", force: :cascade do |t| t.string "email" - t.datetime "created_at", null: false + t.datetime "created_at", null: false t.string "body" t.integer "dossier_id" - t.datetime "updated_at", null: false + t.datetime "updated_at", null: false + t.integer "piece_justificative_id" end add_index "commentaires", ["dossier_id"], name: "index_commentaires_on_dossier_id", using: :btree diff --git a/spec/controllers/api/v1/dossiers_controller_spec.rb b/spec/controllers/api/v1/dossiers_controller_spec.rb index 74bb896ec..3570a60a3 100644 --- a/spec/controllers/api/v1/dossiers_controller_spec.rb +++ b/spec/controllers/api/v1/dossiers_controller_spec.rb @@ -181,7 +181,7 @@ describe API::V1::DossiersController do describe 'piece justificative' do before do - create :piece_justificative, dossier: dossier, type_de_piece_justificative: dossier.procedure.types_de_piece_justificative.first, user: dossier.user + create :piece_justificative, :rib, dossier: dossier, type_de_piece_justificative: dossier.procedure.types_de_piece_justificative.first, user: dossier.user end let(:field_list) { [ diff --git a/spec/controllers/backoffice/commentaires_controller_spec.rb b/spec/controllers/backoffice/commentaires_controller_spec.rb index c0806db8c..195ac87c9 100644 --- a/spec/controllers/backoffice/commentaires_controller_spec.rb +++ b/spec/controllers/backoffice/commentaires_controller_spec.rb @@ -6,6 +6,10 @@ describe Backoffice::CommentairesController, type: :controller do let(:email_commentaire) { 'test@test.com' } let(:texte_commentaire) { 'Commentaire de test' } + before do + allow(ClamavService).to receive(:safe_file?).and_return(true) + end + describe '#POST create' do before do sign_in create(:gestionnaire) @@ -17,6 +21,52 @@ describe Backoffice::CommentairesController, type: :controller do end end + context 'when document is upload whith a commentaire' do + let(:document_upload) { Rack::Test::UploadedFile.new("./spec/support/files/piece_justificative_0.pdf", 'application/pdf') } + + subject do + post :create, dossier_id: dossier_id, email_commentaire: email_commentaire, texte_commentaire: texte_commentaire, piece_justificative: {content: document_upload} + end + + it 'create a new piece justificative' do + expect { subject }.to change(PieceJustificative, :count).by(1) + end + + it 'clamav check the pj' do + expect(ClamavService).to receive(:safe_file?) + subject + end + + describe 'piece justificative created' do + let(:pj) { PieceJustificative.last } + + before do + subject + end + + it 'not have a type de pj' do + expect(pj.type_de_piece_justificative).to be_nil + end + + it 'content not be nil' do + expect(pj.content).not_to be_nil + end + end + + describe 'commentaire created' do + let(:commentaire) { Commentaire.last } + + before do + subject + end + + it 'have a piece justificative reference' do + expect(commentaire.piece_justificative).not_to be_nil + expect(commentaire.piece_justificative).to eq PieceJustificative.last + end + end + end + describe 'change dossier state after post a comment' do context 'gestionnaire is connected' do context 'when dossier is at state updated' do diff --git a/spec/controllers/users/commentaires_controller_spec.rb b/spec/controllers/users/commentaires_controller_spec.rb index 64c788cda..49e0bff77 100644 --- a/spec/controllers/users/commentaires_controller_spec.rb +++ b/spec/controllers/users/commentaires_controller_spec.rb @@ -6,6 +6,10 @@ describe Users::CommentairesController, type: :controller do let(:email_commentaire) { 'test@test.com' } let(:texte_commentaire) { 'Commentaire de test' } + before do + allow(ClamavService).to receive(:safe_file?).and_return(true) + end + describe '#POST create' do context 'création correct d\'un commentaire' do subject do @@ -26,6 +30,53 @@ describe Users::CommentairesController, type: :controller do end end + context 'when document is upload whith a commentaire' do + let(:document_upload) { Rack::Test::UploadedFile.new("./spec/support/files/piece_justificative_0.pdf", 'application/pdf') } + + subject do + sign_in dossier.user + post :create, dossier_id: dossier_id, texte_commentaire: texte_commentaire, piece_justificative: {content: document_upload} + end + + it 'create a new piece justificative' do + expect { subject }.to change(PieceJustificative, :count).by(1) + end + + it 'clamav check the pj' do + expect(ClamavService).to receive(:safe_file?) + subject + end + + describe 'piece justificative created' do + let(:pj) { PieceJustificative.last } + + before do + subject + end + + it 'not have a type de pj' do + expect(pj.type_de_piece_justificative).to be_nil + end + + it 'content not be nil' do + expect(pj.content).not_to be_nil + end + end + + describe 'commentaire created' do + let(:commentaire) { Commentaire.last } + + before do + subject + end + + it 'have a piece justificative reference' do + expect(commentaire.piece_justificative).not_to be_nil + expect(commentaire.piece_justificative).to eq PieceJustificative.last + end + end + end + describe 'change dossier state after post a comment' do context 'when user is connected' do context 'when dossier is at state replied' do @@ -39,7 +90,7 @@ describe Users::CommentairesController, type: :controller do subject { dossier.state } - it {is_expected.to eq('updated')} + it { is_expected.to eq('updated') } end end end diff --git a/spec/factories/piece_justificative.rb b/spec/factories/piece_justificative.rb index c1e87a59e..abe3f319c 100644 --- a/spec/factories/piece_justificative.rb +++ b/spec/factories/piece_justificative.rb @@ -1,11 +1,11 @@ FactoryGirl.define do factory :piece_justificative do trait :rib do - content '/chemin/vers/RIB' + content Rack::Test::UploadedFile.new("./spec/support/files/RIB.pdf", 'application/pdf') end trait :contrat do - content '/chemin/vers/Contrat' + content Rack::Test::UploadedFile.new("./spec/support/files/Contrat.pdf", 'application/pdf') end end end diff --git a/spec/models/commentaire_spec.rb b/spec/models/commentaire_spec.rb index 69c7dc942..efcf9bff1 100644 --- a/spec/models/commentaire_spec.rb +++ b/spec/models/commentaire_spec.rb @@ -6,4 +6,6 @@ describe Commentaire do it { is_expected.to have_db_column(:created_at) } it { is_expected.to have_db_column(:updated_at) } it { is_expected.to belong_to(:dossier) } + + it { is_expected.to belong_to(:piece_justificative) } end diff --git a/spec/models/piece_justificative_spec.rb b/spec/models/piece_justificative_spec.rb index ab2ae4b15..48eb6bbcc 100644 --- a/spec/models/piece_justificative_spec.rb +++ b/spec/models/piece_justificative_spec.rb @@ -10,9 +10,17 @@ describe PieceJustificative do it { is_expected.to belong_to(:dossier) } it { is_expected.to belong_to(:type_de_piece_justificative) } it { is_expected.to belong_to(:user) } + it { is_expected.to have_one(:commentaire) } end + describe 'validations' do + context 'content' do + it { is_expected.not_to allow_value(nil).for(:content) } + it { is_expected.not_to allow_value('').for(:content) } + end + end + describe 'delegation' do it { is_expected.to delegate_method(:libelle).to(:type_de_piece_justificative) } it { is_expected.to delegate_method(:api_entreprise).to(:type_de_piece_justificative) } @@ -21,10 +29,7 @@ describe PieceJustificative do describe '#empty?' do let(:piece_justificative) { create(:piece_justificative, content: content) } subject { piece_justificative.empty? } - context 'when content is nil' do - let(:content) { nil } - it { is_expected.to be_truthy } - end + context 'when content exist' do let(:content) { File.open('./spec/support/files/piece_justificative_388.pdf') } it { is_expected.to be_falsey } diff --git a/spec/support/files/Contrat.pdf b/spec/support/files/Contrat.pdf new file mode 100644 index 000000000..3ffcd4e77 Binary files /dev/null and b/spec/support/files/Contrat.pdf differ diff --git a/spec/support/files/RIB.pdf b/spec/support/files/RIB.pdf new file mode 100644 index 000000000..3ffcd4e77 Binary files /dev/null and b/spec/support/files/RIB.pdf differ diff --git a/spec/views/users/recapitulatif/_commentaires_flux_spec.rb b/spec/views/users/recapitulatif/_commentaires_flux_spec.rb index a1f98b1da..0d6652d71 100644 --- a/spec/views/users/recapitulatif/_commentaires_flux_spec.rb +++ b/spec/views/users/recapitulatif/_commentaires_flux_spec.rb @@ -4,7 +4,11 @@ describe 'users/recapitulatif/_commentaires_flux.html.haml', type: :view do let(:dossier) { create(:dossier) } let(:dossier_id) { dossier.id } let(:email_commentaire) { 'mon_mail_de_commentaire@test.com' } - let!(:commentaire) { create(:commentaire, dossier: dossier, email: email_commentaire, body: 'ma super description') } + + let(:document_upload) { Rack::Test::UploadedFile.new("./spec/support/files/piece_justificative_0.pdf", 'application/pdf') } + let(:pj) { create :piece_justificative, content: document_upload } + + let!(:commentaire) { create(:commentaire, dossier: dossier, email: email_commentaire, body: 'ma super description', piece_justificative: pj) } let(:body) { 'Commentaire de test' } before do @@ -24,6 +28,12 @@ describe 'users/recapitulatif/_commentaires_flux.html.haml', type: :view do it 'le corps du commentaire est présent' do expect(rendered).to have_selector('div[class=description][id=body]') end + + context 'when commentaire as PJ' do + it 'commentaire present the link' do + expect(rendered).to have_css('#piece_justificative') + end + end end context 'Affichage du formulaire de commentaire' do @@ -34,5 +44,11 @@ describe 'users/recapitulatif/_commentaires_flux.html.haml', type: :view do it 'Champs de texte' do expect(rendered).to have_selector('textarea[id=texte_commentaire][name=texte_commentaire]') end + + describe 'File input' do + it 'have file_input tag' do + expect(rendered).to have_css('#piece_justificative_content') + end + end end end