diff --git a/app/controllers/manager/users_controller.rb b/app/controllers/manager/users_controller.rb index 141359ac7..4afabcdc5 100644 --- a/app/controllers/manager/users_controller.rb +++ b/app/controllers/manager/users_controller.rb @@ -49,7 +49,7 @@ module Manager if !user.can_be_deleted? fail "Impossible de supprimer cet utilisateur. Il a des dossiers en instruction ou il est administrateur." end - user.delete_and_keep_track_dossiers(current_super_admin) + user.delete_and_keep_track_dossiers_also_delete_user(current_super_admin) logger.info("L'utilisateur #{user.id} est supprimé par #{current_super_admin.id}") flash[:notice] = "L'utilisateur #{user.id} est supprimé" diff --git a/app/models/user.rb b/app/models/user.rb index 5b1c07618..6c829d8b3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -186,7 +186,7 @@ class User < ApplicationRecord !administrateur? && !instructeur? && !expert? end - def delete_and_keep_track_dossiers(administration) + def delete_and_keep_track_dossiers_also_delete_user(super_admin) if !can_be_deleted? raise "Cannot delete this user because they are also instructeur, expert or administrateur" end @@ -195,6 +195,14 @@ class User < ApplicationRecord # delete invites Invite.where(dossier: dossiers).destroy_all + delete_and_keep_track_dossiers(super_admin) + + destroy! + end + end + + def delete_and_keep_track_dossiers(super_admin) + transaction do # delete dossiers brouillon dossiers.state_brouillon.each do |dossier| dossier.hide_and_keep_track!(dossier.user, :user_removed) @@ -212,8 +220,6 @@ class User < ApplicationRecord dossier.hide_and_keep_track!(dossier.user, :user_removed) end dossiers.update_all(deleted_user_email_never_send: email, user_id: nil, dossier_transfer_id: nil) - - destroy! end end diff --git a/lib/tasks/support.rake b/lib/tasks/support.rake index 431cf3535..b708e8c49 100644 --- a/lib/tasks/support.rake +++ b/lib/tasks/support.rake @@ -15,7 +15,7 @@ namespace :support do user = User.find_by!(email: user_email) administration = Administration.find_by!(email: administration_email) - user.delete_and_keep_track_dossiers(administration) + user.delete_and_keep_track_dossiers_also_delete_user(administration) user.destroy end @@ -43,46 +43,47 @@ namespace :support do end end - desc <<~EOD - Change the SIRET for a given dossier (specified by DOSSIER_ID) - EOD - task update_dossier_siret: :environment do - siret_number = ENV['SIRET'] - dossier_id = ENV['DOSSIER_ID'] + task remove_ex_team_member: :environment do + super_admin = SuperAdmin.find_by(email: ENV['SUPER_ADMIN_EMAIL']) + fail "Must specify the ADMIN_EMAIL of the operator performing the deletion (yourself)" if super_admin.nil? + super_admin_admin = User.find_by(email: super_admin.email).administrateur - if siret_number.nil? - fail "Must specify a SIRET" + user = User.find_by!(email: ENV['USER_EMAIL']) + fail "Must specify a USER_EMAIL" if user.nil? + + ActiveRecord::Base.transaction do + # destroy all en_instruction dossier + # because the normal workflow forbid to hide them. + rake_puts "brutally deleting #{user.dossiers.en_instruction.count} en_instruction dossiers" + user.dossiers.en_instruction.destroy_all + + # remove all the other dossier from the user side + rake_puts "hide #{user.reload.dossiers.count} dossiers" + user.delete_and_keep_track_dossiers(super_admin) + + owned_procedures, shared_procedures = user.administrateur + .procedures + .partition { _1.administrateurs.one? } + + rake_puts "unlink #{shared_procedures.count} shared procedures" + shared_procedures.each { _1.administrateurs.delete(user.administrateur) } + + procedures_without_dossier, procedures_with_dossiers = + owned_procedures.partition { _1.dossiers.empty? } + + rake_puts "discard #{procedures_without_dossier.count} procedures without dossier" + procedures_without_dossier.each { _1.discard_and_keep_track!(super_admin) } + + procedures_with_only_admin_dossiers, + other_procedures = procedures_with_dossiers.partition do |p| + p.dossiers.all? { _1.user == user || _1.deleted_user_email_never_send == user.email } + end + + rake_puts "discard #{procedures_with_only_admin_dossiers.count} procedures with only admin dossiers" + # TODO: clean this ugly hack to delete dossier from admin side + procedures_with_only_admin_dossiers.each { _1.discard_and_keep_track!(super_admin_admin) } + + rake_puts "#{other_procedures.count} remaining" end - - siret_number = siret_number.dup # Unfreeze the string - siret = Siret.new(siret: siret_number) - if siret.invalid? - fail siret.errors.full_messages.to_sentence - end - - dossier = Dossier.find(dossier_id) - - EtablissementUpdateJob.perform_now(dossier, siret_number) - end - - desc <<~EOD - Change a user’s mail from OLD_EMAIL to NEW_EMAIL. - Also works for administrateurs and instructeurs. - EOD - task change_user_email: :environment do - old_email = ENV['OLD_EMAIL'] - new_email = ENV['NEW_EMAIL'] - - if User.find_by(email: new_email).present? - fail "There is an existing account for #{new_email}, not overwriting" - end - - user = User.find_by(email: old_email) - - if user.nil? - fail "Couldn’t find existing account for #{old_email}" - end - - user.update(email: new_email) end end diff --git a/spec/lib/tasks/support_spec.rb b/spec/lib/tasks/support_spec.rb new file mode 100644 index 000000000..dbc682f62 --- /dev/null +++ b/spec/lib/tasks/support_spec.rb @@ -0,0 +1,66 @@ +describe 'support' do + describe 'remove_ex_team_member' do + let(:rake_task) { Rake::Task['support:remove_ex_team_member'] } + + subject do + ENV['SUPER_ADMIN_EMAIL'] = super_admin.email + ENV['USER_EMAIL'] = admin.email + rake_task.invoke + end + after { rake_task.reenable } + + # the admin to remove + let(:admin) { create(:administrateur) } + + # the super admin doing the removal + let(:super_admin) { create(:super_admin) } + let!(:super_admin_admin) { create(:administrateur, email: super_admin.email) } + + context 'an empty procedure is discarded' do + let!(:empty_procedure) { create(:procedure, :published, administrateur: admin) } + + it do + subject + expect(admin.procedures).to be_empty + expect(admin.procedures.with_discarded.discarded).to match_array(empty_procedure) + end + end + + context 'a procedure only with the admins dossiers is discarded' do + let!(:procedure_with_admin_dossiers) { create(:procedure, :published, administrateur: admin) } + let!(:admin_instruction_dossier) { create(:dossier, :en_instruction, procedure: procedure_with_admin_dossiers, user: admin.user) } + let!(:admin_termine_dossier) { create(:dossier, :accepte, procedure: procedure_with_admin_dossiers, user: admin.user) } + + it do + subject + expect(admin.procedures).to be_empty + expect(admin.procedures.with_discarded.discarded).to match_array(procedure_with_admin_dossiers) + expect { admin_instruction_dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect(admin_termine_dossier.reload.user).to be_nil + end + end + + context 'a procedure only with others dossiers is kept' do + let!(:procedure_with_dossiers) { create(:procedure, :published, administrateur: admin) } + let!(:admin_dossier) { create(:dossier, :en_instruction, procedure: procedure_with_dossiers, user: admin.user) } + let!(:another_dossier) { create(:dossier, :en_instruction, procedure: procedure_with_dossiers) } + + it do + subject + expect(admin.procedures).to match_array(procedure_with_dossiers) + expect { admin_dossier.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'a procedure shared with another admin' do + let!(:another_admin) { create(:administrateur) } + let!(:shared_procedure) { create(:procedure, :published, administrateurs: [admin, another_admin]) } + + it do + subject + expect(admin.procedures).to be_empty + expect(another_admin.procedures).to match_array(shared_procedure) + end + end + end +end diff --git a/spec/mailers/notification_mailer_spec.rb b/spec/mailers/notification_mailer_spec.rb index cb3f39052..005db343c 100644 --- a/spec/mailers/notification_mailer_spec.rb +++ b/spec/mailers/notification_mailer_spec.rb @@ -91,7 +91,7 @@ RSpec.describe NotificationMailer, type: :mailer do context 'when dossier user is deleted' do before do - dossier.user.delete_and_keep_track_dossiers(administrateur) + dossier.user.delete_and_keep_track_dossiers_also_delete_user(administrateur) dossier.reload end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 75447ae94..00e0c44e2 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -298,7 +298,7 @@ describe User, type: :model do end end - describe '#delete_and_keep_track_dossiers' do + describe '#delete_and_keep_track_dossiers_also_delete_user' do let(:super_admin) { create(:super_admin) } let(:user) { create(:user) } @@ -308,7 +308,7 @@ describe User, type: :model do context 'without a discarded dossier' do it "keep track of dossiers and delete user" do - user.delete_and_keep_track_dossiers(super_admin) + user.delete_and_keep_track_dossiers_also_delete_user(super_admin) expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_nil @@ -322,7 +322,7 @@ describe User, type: :model do it "keep track of dossiers and delete user" do dossier_to_delete.hide_and_keep_track!(user, :user_request) - user.delete_and_keep_track_dossiers(super_admin) + user.delete_and_keep_track_dossiers_also_delete_user(super_admin) expect(DeletedDossier.find_by(dossier_id: dossier_en_construction)).to be_present expect(DeletedDossier.find_by(dossier_id: dossier_brouillon)).to be_nil @@ -337,7 +337,7 @@ describe User, type: :model do let!(:dossier_termine) { create(:dossier, :accepte, user: user) } it "keep track of dossiers and delete user" do - user.delete_and_keep_track_dossiers(super_admin) + user.delete_and_keep_track_dossiers_also_delete_user(super_admin) expect(dossier_en_instruction.reload).to be_present expect(dossier_en_instruction.user).to be_nil