Merge pull request #4688 from betagouv/4127-fix-superadmin-supprime-compte-usager
4127 fix superadmin supprime compte usager
This commit is contained in:
commit
840efad4ea
13 changed files with 150 additions and 22 deletions
|
@ -22,11 +22,7 @@ module Manager
|
||||||
def delete
|
def delete
|
||||||
administrateur = Administrateur.find(params[:id])
|
administrateur = Administrateur.find(params[:id])
|
||||||
|
|
||||||
if !administrateur.can_be_deleted?
|
administrateur.delete_and_transfer_services
|
||||||
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
|
|
||||||
|
|
||||||
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_administration.id}")
|
logger.info("L'administrateur #{administrateur.id} est supprimé par #{current_administration.id}")
|
||||||
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
|
flash[:notice] = "L'administrateur #{administrateur.id} est supprimé"
|
||||||
|
|
|
@ -6,5 +6,19 @@ module Manager
|
||||||
flash[:notice] = "Instructeur réinvité."
|
flash[:notice] = "Instructeur réinvité."
|
||||||
redirect_to manager_instructeur_path(instructeur)
|
redirect_to manager_instructeur_path(instructeur)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,7 +24,7 @@ module Manager
|
||||||
def delete
|
def delete
|
||||||
user = User.find(params[:id])
|
user = User.find(params[:id])
|
||||||
if !user.can_be_deleted?
|
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
|
end
|
||||||
user.delete_and_keep_track_dossiers(current_administration)
|
user.delete_and_keep_track_dossiers(current_administration)
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,17 @@ class Administrateur < ApplicationRecord
|
||||||
def can_be_deleted?
|
def can_be_deleted?
|
||||||
dossiers.state_instruction_commencee.none? && procedures.all? { |p| p.administrateurs.count > 1 }
|
dossiers.state_instruction_commencee.none? && procedures.all? { |p| p.administrateurs.count > 1 }
|
||||||
end
|
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
|
end
|
||||||
|
|
|
@ -17,9 +17,9 @@ class Instructeur < ApplicationRecord
|
||||||
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
|
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
|
||||||
has_many :avis
|
has_many :avis
|
||||||
has_many :dossiers_from_avis, through: :avis, source: :dossier
|
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) }
|
default_scope { eager_load(:user) }
|
||||||
|
|
||||||
|
@ -176,6 +176,10 @@ class Instructeur < ApplicationRecord
|
||||||
trusted_device_token&.token_young?
|
trusted_device_token&.token_young?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_be_deleted?
|
||||||
|
user.administrateur.nil? && procedures.all? { |p| p.defaut_groupe_instructeur.instructeurs.count > 1 }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def annotations_hash(demande, annotations_privees, avis, messagerie)
|
def annotations_hash(demande, annotations_privees, avis, messagerie)
|
||||||
|
|
|
@ -97,7 +97,7 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_be_deleted?
|
def can_be_deleted?
|
||||||
dossiers.state_instruction_commencee.empty?
|
administrateur.nil? && instructeur.nil? && dossiers.state_instruction_commencee.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_and_keep_track_dossiers(administration)
|
def delete_and_keep_track_dossiers(administration)
|
||||||
|
@ -105,12 +105,11 @@ class User < ApplicationRecord
|
||||||
raise "Cannot delete this user because instruction has started for some dossiers"
|
raise "Cannot delete this user because instruction has started for some dossiers"
|
||||||
end
|
end
|
||||||
|
|
||||||
if can_be_deleted?
|
|
||||||
dossiers.each do |dossier|
|
dossiers.each do |dossier|
|
||||||
dossier.delete_and_keep_track(administration)
|
dossier.delete_and_keep_track(administration)
|
||||||
end
|
end
|
||||||
destroy
|
dossiers.unscoped.destroy_all
|
||||||
end
|
destroy!
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -34,7 +34,10 @@ as well as a link to its edit page.
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= link_to 'Réinviter', reinvite_manager_instructeur_path(instructeur), method: :post, class: 'button' %>
|
<%= link_to 'Réinviter', reinvite_manager_instructeur_path(instructeur), method: :post, class: 'button' %>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
<%= 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é" %>
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="main-content__body">
|
<section class="main-content__body">
|
||||||
|
|
|
@ -25,7 +25,7 @@ as well as a link to its edit page.
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<%= 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 il est administrateur ou instructeur" %>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -32,6 +32,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :instructeurs, only: [:index, :show] do
|
resources :instructeurs, only: [:index, :show] do
|
||||||
post 'reinvite', on: :member
|
post 'reinvite', on: :member
|
||||||
|
delete 'delete', on: :member
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :dossiers, only: [:show]
|
resources :dossiers, only: [:show]
|
||||||
|
|
17
spec/controllers/manager/instructeurs_controller_spec.rb
Normal file
17
spec/controllers/manager/instructeurs_controller_spec.rb
Normal file
|
@ -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
|
|
@ -46,6 +46,21 @@ describe Administrateur, type: :model do
|
||||||
end
|
end
|
||||||
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
|
# describe '#password_complexity' do
|
||||||
# let(:email) { 'mail@beta.gouv.fr' }
|
# let(:email) { 'mail@beta.gouv.fr' }
|
||||||
# let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] }
|
# let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] }
|
||||||
|
|
|
@ -424,9 +424,40 @@ describe Instructeur, type: :model do
|
||||||
it { expect(instructeur_a.procedures.all.to_ary).to eq([procedure_a]) }
|
it { expect(instructeur_a.procedures.all.to_ary).to eq([procedure_a]) }
|
||||||
end
|
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
|
private
|
||||||
|
|
||||||
def assign(procedure_to_assign)
|
def assign(procedure_to_assign, instructeur_assigne: instructeur)
|
||||||
create :assign_to, instructeur: instructeur, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur
|
create :assign_to, instructeur: instructeur_assigne, procedure: procedure_to_assign, groupe_instructeur: procedure_to_assign.defaut_groupe_instructeur
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -224,6 +224,24 @@ describe User, type: :model do
|
||||||
context 'when the user has no dossier in instruction' do
|
context 'when the user has no dossier in instruction' do
|
||||||
it { is_expected.to be true }
|
it { is_expected.to be true }
|
||||||
end
|
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
|
||||||
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
describe '#delete_and_keep_track_dossiers' do
|
describe '#delete_and_keep_track_dossiers' do
|
||||||
|
@ -241,6 +259,7 @@ describe User, type: :model do
|
||||||
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
let!(:dossier_en_construction) { create(:dossier, :en_construction, user: user) }
|
||||||
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
let!(:dossier_brouillon) { create(:dossier, user: user) }
|
||||||
|
|
||||||
|
context 'without a hidden dossier' do
|
||||||
it "keep track of dossiers and delete user" do
|
it "keep track of dossiers and delete user" do
|
||||||
user.delete_and_keep_track_dossiers(administration)
|
user.delete_and_keep_track_dossiers(administration)
|
||||||
|
|
||||||
|
@ -249,5 +268,21 @@ describe User, type: :model do
|
||||||
expect(User.find_by(id: user.id)).to be_nil
|
expect(User.find_by(id: user.id)).to be_nil
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue