From d8a51f986f8b607100864f4b256024fc656b34d0 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 15 Jan 2020 10:54:12 +0100 Subject: [PATCH 1/6] =?UTF-8?q?supprime=20un=20utilisateur=20qui=20a=20des?= =?UTF-8?q?=20dossiers=20cach=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/user.rb | 9 ++++----- spec/models/user_spec.rb | 27 ++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 4838da20d..8fc852bde 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -105,12 +105,11 @@ class User < ApplicationRecord raise "Cannot delete this user because instruction has started for some dossiers" end - if can_be_deleted? - dossiers.each do |dossier| - dossier.delete_and_keep_track(administration) - end - destroy + dossiers.each do |dossier| + dossier.delete_and_keep_track(administration) end + dossiers.unscoped.destroy_all + destroy end private diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b127d35c6..a09927084 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -241,12 +241,29 @@ describe User, type: :model do let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) } let!(:dossier_brouillon) { create(:dossier, user: user) } - it "keep track of dossiers and delete user" do - user.delete_and_keep_track_dossiers(administration) + context 'without a hidden dossier' do + it "keep track of dossiers and delete user" do + user.delete_and_keep_track_dossiers(administration) - expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present - expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_present - expect(User.find_by(id: user.id)).to be_nil + expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present + expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_present + expect(User.find_by(id: user.id)).to be_nil + end + end + + context 'with a hidden dossier' do + let!(:dossier_cache) do + create(:dossier, :en_construction, user: user) + end + + it "keep track of dossiers and delete user" do + dossier_cache.delete_and_keep_track(administration) + user.delete_and_keep_track_dossiers(administration) + + expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present + expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_present + expect(User.find_by(id: user.id)).to be_nil + end end end end From d4de5769ee10bb17e35cb6d1681ddf5491ed5231 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 15 Jan 2020 14:31:30 +0100 Subject: [PATCH 2/6] =?UTF-8?q?emp=C3=AAche=20la=20suppression=20d'un=20us?= =?UTF-8?q?er=20qui=20est=20admin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/manager/users_controller.rb | 2 +- app/models/user.rb | 2 +- app/views/manager/users/show.html.erb | 2 +- spec/models/user_spec.rb | 10 ++++++++++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/controllers/manager/users_controller.rb b/app/controllers/manager/users_controller.rb index 9e1a9fc54..eb2c9e169 100644 --- a/app/controllers/manager/users_controller.rb +++ b/app/controllers/manager/users_controller.rb @@ -24,7 +24,7 @@ module Manager def delete user = User.find(params[:id]) if !user.can_be_deleted? - fail "Impossible de supprimer cet utilisateur car il a des dossiers en instruction" + fail "Impossible de supprimer cet utilisateur. Il a des dossiers en instruction ou il est administrateur." end user.delete_and_keep_track_dossiers(current_administration) diff --git a/app/models/user.rb b/app/models/user.rb index 8fc852bde..16412ddf8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -97,7 +97,7 @@ class User < ApplicationRecord end def can_be_deleted? - dossiers.state_instruction_commencee.empty? + administrateur.nil? && dossiers.state_instruction_commencee.empty? end def delete_and_keep_track_dossiers(administration) diff --git a/app/views/manager/users/show.html.erb b/app/views/manager/users/show.html.erb index ab51789a6..2d3f24982 100644 --- a/app/views/manager/users/show.html.erb +++ b/app/views/manager/users/show.html.erb @@ -25,7 +25,7 @@ as well as a link to its edit page.
- <%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur a des dossiers dont l'instruction a commencé et ne peut être supprimé" %> + <%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur ne peut être supprimé. Il a des dossiers dont l'instruction a commencé ou c'est un administrateur" %>
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index a09927084..9c3c6bde8 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -224,6 +224,16 @@ describe User, type: :model do context 'when the user has no dossier in instruction' do it { is_expected.to be true } end + + context 'when the user is an administrateur' do + it 'cannot be deleted' do + administrateur = create(:administrateur) + user = administrateur.user + + expect(user.can_be_deleted?).to be_falsy + end + end + end describe '#delete_and_keep_track_dossiers' do From a6d007dbd3e84a81f1ad0e24b40f113ed31b52e4 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 15 Jan 2020 19:10:46 +0100 Subject: [PATCH 3/6] supprime un instructeur --- .../manager/instructeurs_controller.rb | 14 ++++++++ app/models/instructeur.rb | 8 +++-- app/views/manager/instructeurs/show.html.erb | 3 ++ config/routes.rb | 1 + .../manager/instructeurs_controller_spec.rb | 17 +++++++++ spec/models/instructeur_spec.rb | 35 +++++++++++++++++-- 6 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 spec/controllers/manager/instructeurs_controller_spec.rb diff --git a/app/controllers/manager/instructeurs_controller.rb b/app/controllers/manager/instructeurs_controller.rb index 82b1e11eb..d2ea33d47 100644 --- a/app/controllers/manager/instructeurs_controller.rb +++ b/app/controllers/manager/instructeurs_controller.rb @@ -6,5 +6,19 @@ module Manager flash[:notice] = "Instructeur réinvité." redirect_to manager_instructeur_path(instructeur) end + + def delete + instructeur = Instructeur.find(params[:id]) + + if !instructeur.can_be_deleted? + fail "Impossible de supprimer cet instructeur car il est administrateur ou il est le seul instructeur sur une démarche" + end + instructeur.destroy + + logger.info("L'instructeur #{instructeur.id} est supprimé par #{current_administration.id}") + flash[:notice] = "L'instructeur #{instructeur.id} est supprimé" + + redirect_to manager_instructeurs_path + end end end diff --git a/app/models/instructeur.rb b/app/models/instructeur.rb index 4c142b870..97b2b0a49 100644 --- a/app/models/instructeur.rb +++ b/app/models/instructeur.rb @@ -17,9 +17,9 @@ class Instructeur < ApplicationRecord has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier has_many :avis has_many :dossiers_from_avis, through: :avis, source: :dossier - has_many :trusted_device_tokens + has_many :trusted_device_tokens, dependent: :destroy - has_one :user + has_one :user, dependent: :nullify default_scope { eager_load(:user) } @@ -176,6 +176,10 @@ class Instructeur < ApplicationRecord trusted_device_token&.token_young? end + def can_be_deleted? + user.administrateur.nil? && procedures.all? { |p| p.defaut_groupe_instructeur.instructeurs.count > 1 } + end + private def annotations_hash(demande, annotations_privees, avis, messagerie) diff --git a/app/views/manager/instructeurs/show.html.erb b/app/views/manager/instructeurs/show.html.erb index e423414a9..983e171e9 100644 --- a/app/views/manager/instructeurs/show.html.erb +++ b/app/views/manager/instructeurs/show.html.erb @@ -34,7 +34,10 @@ as well as a link to its edit page.
<%= link_to 'Réinviter', reinvite_manager_instructeur_path(instructeur), method: :post, class: 'button' %> +
+ <%= button_to "Supprimer", delete_manager_instructeur_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'instructeur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet instructeur est administrateur ou a des démarches dont il est le seul instructeur et ne peut être supprimé" %> +
diff --git a/config/routes.rb b/config/routes.rb index 09f0d8fb8..e69a44a60 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -32,6 +32,7 @@ Rails.application.routes.draw do resources :instructeurs, only: [:index, :show] do post 'reinvite', on: :member + delete 'delete', on: :member end resources :dossiers, only: [:show] diff --git a/spec/controllers/manager/instructeurs_controller_spec.rb b/spec/controllers/manager/instructeurs_controller_spec.rb new file mode 100644 index 000000000..3a0164d4b --- /dev/null +++ b/spec/controllers/manager/instructeurs_controller_spec.rb @@ -0,0 +1,17 @@ +describe Manager::InstructeursController, type: :controller do + let(:administration) { create(:administration) } + + describe '#delete' do + let!(:instructeur) { create(:instructeur) } + + before { sign_in administration } + + subject { delete :delete, params: { id: instructeur.id } } + + it 'deletes the instructeur' do + subject + + expect(Instructeur.find_by(id: instructeur.id)).to be_nil + end + end +end diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 37917bf18..78737bf89 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -424,9 +424,40 @@ describe Instructeur, type: :model do it { expect(instructeur_a.procedures.all.to_ary).to eq([procedure_a]) } end + describe "#can_be_deleted?" do + subject { instructeur.can_be_deleted? } + + context 'when the instructeur is an administrateur' do + let!(:administrateur) { create(:administrateur) } + let(:instructeur) { administrateur.instructeur } + + it { is_expected.to be false } + end + + context "when the instructeur's procedures have other instructeurs" do + let(:instructeur_not_admin) { create(:instructeur) } + let(:autre_instructeur) { create(:instructeur) } + + it "can be deleted" do + assign(procedure, instructeur_assigne: instructeur_not_admin) + assign(procedure, instructeur_assigne: autre_instructeur) + expect(autre_instructeur.can_be_deleted?).to be_truthy + end + end + + context "when the instructeur's procedures is the only one" do + let(:instructeur_not_admin) { create :instructeur } + let(:autre_procedure) { create :procedure } + it "can be deleted" do + assign(autre_procedure, instructeur_assigne: instructeur_not_admin) + expect(instructeur_not_admin.can_be_deleted?).to be_falsy + end + end + end + private - def assign(procedure_to_assign) - create :assign_to, instructeur: instructeur, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur + def assign(procedure_to_assign, instructeur_assigne: instructeur) + create :assign_to, instructeur: instructeur_assigne, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur end end From d9570eedc66763317a54117fd04f5b4300568af7 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 15 Jan 2020 19:48:11 +0100 Subject: [PATCH 4/6] =?UTF-8?q?emp=C3=AAche=20suppression=20d'un=20user=20?= =?UTF-8?q?qui=20est=20instructeur?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/user.rb | 2 +- app/views/manager/users/show.html.erb | 2 +- spec/models/user_spec.rb | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 16412ddf8..5201df213 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -97,7 +97,7 @@ class User < ApplicationRecord end def can_be_deleted? - administrateur.nil? && dossiers.state_instruction_commencee.empty? + administrateur.nil? && instructeur.nil? && dossiers.state_instruction_commencee.empty? end def delete_and_keep_track_dossiers(administration) diff --git a/app/views/manager/users/show.html.erb b/app/views/manager/users/show.html.erb index 2d3f24982..833e79723 100644 --- a/app/views/manager/users/show.html.erb +++ b/app/views/manager/users/show.html.erb @@ -25,7 +25,7 @@ as well as a link to its edit page.
- <%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur ne peut être supprimé. Il a des dossiers dont l'instruction a commencé ou c'est un administrateur" %> + <%= button_to "supprimer", delete_manager_user_path(page.resource), method: :delete, disabled: !page.resource.can_be_deleted?, class: "button", data: { confirm: "Confirmez-vous la suppression de l'utilisateur ?" }, title: page.resource.can_be_deleted? ? "Supprimer" : "Cet utilisateur ne peut être supprimé. Il a des dossiers dont l'instruction a commencé ou il est administrateur ou instructeur" %>
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 9c3c6bde8..19b317f40 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -234,6 +234,14 @@ describe User, type: :model do end end + context 'when the user is an instructeur' do + it 'cannot be deleted' do + instructeur = create(:instructeur) + user = instructeur.user + + expect(user.can_be_deleted?).to be_falsy + end + end end describe '#delete_and_keep_track_dossiers' do From 675bbdad1547a73d5d06cc2c2a00dd9206d0363d Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Fri, 17 Jan 2020 16:24:33 +0100 Subject: [PATCH 5/6] transfere les services lors de suppression admin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lorsqu'un administrateur est supprimé, ses services sont transférés à un autre administrateur pour chacune de ses procédures --- .../manager/administrateurs_controller.rb | 6 +----- app/models/administrateur.rb | 13 +++++++++++++ spec/models/administrateur_spec.rb | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/controllers/manager/administrateurs_controller.rb b/app/controllers/manager/administrateurs_controller.rb index f976f3cf6..10dec19d5 100644 --- a/app/controllers/manager/administrateurs_controller.rb +++ b/app/controllers/manager/administrateurs_controller.rb @@ -22,11 +22,7 @@ module Manager def delete administrateur = Administrateur.find(params[:id]) - if !administrateur.can_be_deleted? - fail "Impossible de supprimer cet administrateur car il a des dossiers ou des procédures" - end - administrateur.dossiers.each(&:delete_and_keep_track) - administrateur.destroy + administrateur.delete_and_transfer_services logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_administration.id}") flash[:notice] = "L'administrateur #{administrateur.id} est supprimé" diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 4d4b84d4a..1174d4b60 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -70,4 +70,17 @@ class Administrateur < ApplicationRecord def can_be_deleted? dossiers.state_instruction_commencee.none? && procedures.all? { |p| p.administrateurs.count > 1 } end + + def delete_and_transfer_services + if !can_be_deleted? + fail "Impossible de supprimer cet administrateur car il a des dossiers ou des procédures" + end + dossiers.each(&:delete_and_keep_track) + + procedures.each do |procedure| + next_administrateur = procedure.administrateurs.where.not(id: self.id).first + procedure.service.update(administrateur: next_administrateur) + end + destroy + end end diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb index 9f0c30923..3e6864466 100644 --- a/spec/models/administrateur_spec.rb +++ b/spec/models/administrateur_spec.rb @@ -46,6 +46,21 @@ describe Administrateur, type: :model do end end + describe '#delete_and_transfer_services' do + let!(:administrateur) { create(:administrateur) } + let!(:autre_administrateur) { create(:administrateur) } + let!(:procedure) { create(:procedure, :with_service, administrateurs: [administrateur, autre_administrateur]) } + let(:service) { procedure.service } + + it "delete and transfer services to other admin" do + service.update(administrateur: administrateur) + administrateur.delete_and_transfer_services + + expect(Administrateur.find_by(id: administrateur.id)).to be_nil + expect(service.reload.administrateur).to eq(autre_administrateur) + end + end + # describe '#password_complexity' do # let(:email) { 'mail@beta.gouv.fr' } # let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] } From 88e73d4039ea768c643bab811f7c0c104b38ce98 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Tue, 21 Jan 2020 14:28:04 +0100 Subject: [PATCH 6/6] raise exception if problem with destroy --- app/controllers/manager/instructeurs_controller.rb | 2 +- app/models/user.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/manager/instructeurs_controller.rb b/app/controllers/manager/instructeurs_controller.rb index d2ea33d47..ed2107c45 100644 --- a/app/controllers/manager/instructeurs_controller.rb +++ b/app/controllers/manager/instructeurs_controller.rb @@ -13,7 +13,7 @@ module Manager if !instructeur.can_be_deleted? fail "Impossible de supprimer cet instructeur car il est administrateur ou il est le seul instructeur sur une démarche" end - instructeur.destroy + instructeur.destroy! logger.info("L'instructeur #{instructeur.id} est supprimé par #{current_administration.id}") flash[:notice] = "L'instructeur #{instructeur.id} est supprimé" diff --git a/app/models/user.rb b/app/models/user.rb index 5201df213..35c0edd5e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -109,7 +109,7 @@ class User < ApplicationRecord dossier.delete_and_keep_track(administration) end dossiers.unscoped.destroy_all - destroy + destroy! end private