Merge pull request #8083 from demarches-simplifiees/admin_or_not_admin
feat(procedure_admins): permet à un admin de se retirer lui-même d'une procédure
This commit is contained in:
commit
b29d0fc346
12 changed files with 106 additions and 50 deletions
|
@ -9,4 +9,8 @@ class ApplicationComponent < ViewComponent::Base
|
|||
def current_user
|
||||
controller.current_user
|
||||
end
|
||||
|
||||
def current_administrateur
|
||||
controller.current_administrateur
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
|
||||
def initialize(champ:, seen_at: nil)
|
||||
@champ, @seen_at = champ, seen_at
|
||||
end
|
||||
|
@ -12,8 +14,4 @@ class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
|||
def highlight?
|
||||
@champ.updated_at.present? && @seen_at&.<(@champ.updated_at)
|
||||
end
|
||||
|
||||
def try_format_datetime(datetime)
|
||||
datetime.present? ? I18n.l(datetime) : ''
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
class Procedure::ProcedureAdministrateurs::AdministrateurComponent < ApplicationComponent
|
||||
include ApplicationHelper
|
||||
|
||||
def initialize(procedure:, administrateur:)
|
||||
@procedure = procedure
|
||||
@administrateur = administrateur
|
||||
end
|
||||
|
||||
def email
|
||||
if @administrateur == current_administrateur
|
||||
"#{@administrateur.email} (C’est vous !)"
|
||||
else
|
||||
@administrateur.email
|
||||
end
|
||||
end
|
||||
|
||||
def created_at
|
||||
try_format_datetime(@administrateur.created_at)
|
||||
end
|
||||
|
||||
def registration_state
|
||||
@administrateur.registration_state
|
||||
end
|
||||
|
||||
def remove_button
|
||||
if is_there_at_least_another_active_admin?
|
||||
button_to 'Retirer',
|
||||
admin_procedure_administrateur_path(@procedure, @administrateur),
|
||||
method: :delete,
|
||||
class: 'button',
|
||||
form: { data: { turbo: true, turbo_confirm: "Retirer « #{@administrateur.email} » des administrateurs de « #{@procedure.libelle} » ?" } }
|
||||
end
|
||||
end
|
||||
|
||||
def is_there_at_least_another_active_admin?
|
||||
if @administrateur.active?
|
||||
@procedure.administrateurs.count(&:active?) > 1
|
||||
else
|
||||
@procedure.administrateurs.count(&:active?) >= 1
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
%tr{ id: dom_id(@administrateur) }
|
||||
%td= email
|
||||
%td= created_at
|
||||
%td= registration_state
|
||||
%td= remove_button
|
|
@ -29,20 +29,24 @@ module Administrateurs
|
|||
end
|
||||
|
||||
def destroy
|
||||
administrateur = @procedure.administrateurs.find(params[:id])
|
||||
admin_to_delete = @procedure.administrateurs.find(params[:id])
|
||||
|
||||
# Prevent self-removal (Also enforced in the UI)
|
||||
if administrateur == current_administrateur
|
||||
flash.alert = "Vous ne pouvez pas vous retirer vous-même d’une démarche."
|
||||
return
|
||||
if (@procedure.administrateurs - [admin_to_delete]).filter(&:active?).empty?
|
||||
flash.alert = "Il doit rester au moins un administrateur actif."
|
||||
else
|
||||
begin
|
||||
# Actually remove the admin
|
||||
@procedure.administrateurs.delete(admin_to_delete)
|
||||
@administrateur = admin_to_delete
|
||||
flash.notice = "L’administrateur \« #{admin_to_delete.email} » a été retiré de la démarche « #{@procedure.libelle} »."
|
||||
|
||||
if current_administrateur == admin_to_delete
|
||||
redirect_to admin_procedures_path
|
||||
end
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.alert = e.message
|
||||
end
|
||||
end
|
||||
|
||||
# Actually remove the admin
|
||||
@procedure.administrateurs.delete(administrateur)
|
||||
@administrateur = administrateur
|
||||
flash.notice = "L’administrateur \« #{administrateur.email} » a été retiré de la démarche « #{@procedure.libelle} »."
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
flash.alert = e.message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
class Administrateur < ApplicationRecord
|
||||
include ActiveRecord::SecureToken
|
||||
|
||||
self.ignored_columns = [:active]
|
||||
|
||||
UNUSED_ADMIN_THRESHOLD = 6.months
|
||||
|
||||
has_and_belongs_to_many :instructeurs
|
||||
|
@ -42,6 +44,10 @@ class Administrateur < ApplicationRecord
|
|||
user&.email
|
||||
end
|
||||
|
||||
def active?
|
||||
user&.active?
|
||||
end
|
||||
|
||||
def self.find_inactive_by_token(reset_password_token)
|
||||
self.inactive.with_reset_password_token(reset_password_token)
|
||||
end
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
%tr{ id: dom_id(administrateur) }
|
||||
%td= administrateur.email
|
||||
%td= try_format_datetime(administrateur.created_at)
|
||||
%td= administrateur.registration_state
|
||||
%td
|
||||
- if administrateur == current_administrateur
|
||||
C’est vous !
|
||||
- else
|
||||
= button_to 'Retirer',
|
||||
admin_procedure_administrateur_path(procedure, administrateur),
|
||||
method: :delete,
|
||||
class: 'button',
|
||||
form: { data: { turbo: true, turbo_confirm: "Retirer « #{administrateur.email} » des administrateurs de « #{procedure.libelle} » ?" } }
|
|
@ -1,3 +1,4 @@
|
|||
- if @administrateur.present?
|
||||
= turbo_stream.append "administrateurs", partial: 'administrateur', locals: { procedure: @procedure, administrateur: @administrateur }
|
||||
= turbo_stream.update 'administrateurs',
|
||||
render(Procedure::ProcedureAdministrateurs::AdministrateurComponent.with_collection(@procedure.administrateurs.order('users.email'), procedure: @procedure))
|
||||
= turbo_stream.replace "new_administrateur", partial: 'add_admin_form', locals: { procedure: @procedure, disabled_as_super_admin: administrateur_as_manager? }
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
- if @administrateur.present?
|
||||
= turbo_stream.remove(@administrateur)
|
||||
= turbo_stream.update 'administrateurs',
|
||||
render(Procedure::ProcedureAdministrateurs::AdministrateurComponent.with_collection(@procedure.administrateurs.order('users.email'), procedure: @procedure))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
%th= 'Enregistré le'
|
||||
%th= 'État'
|
||||
%tbody#administrateurs
|
||||
= render partial: 'administrateur', collection: @procedure.administrateurs.order('users.email'), locals: { procedure: @procedure }
|
||||
= render(Procedure::ProcedureAdministrateurs::AdministrateurComponent.with_collection(@procedure.administrateurs.order('users.email'), procedure: @procedure))
|
||||
%tfoot
|
||||
%tr
|
||||
%th{ colspan: 4 }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
describe Administrateurs::ProcedureAdministrateursController, type: :controller do
|
||||
let(:signed_in_admin) { create(:administrateur) }
|
||||
let(:other_admin) { create(:administrateur) }
|
||||
let(:signed_in_admin) { create(:administrateur).tap { _1.user.update(last_sign_in_at: Time.zone.now) } }
|
||||
let(:other_admin) { create(:administrateur).tap { _1.user.update(last_sign_in_at: Time.zone.now) } }
|
||||
let!(:administrateurs_procedure) { create(:administrateurs_procedure, administrateur: signed_in_admin, procedure: procedure, manager: manager) }
|
||||
let!(:procedure) { create(:procedure, administrateurs: [other_admin]) }
|
||||
render_views
|
||||
|
@ -19,29 +19,41 @@ describe Administrateurs::ProcedureAdministrateursController, type: :controller
|
|||
|
||||
describe '#destroy' do
|
||||
let(:manager) { false }
|
||||
subject do
|
||||
|
||||
def destroy_admin(admin_to_remove)
|
||||
delete :destroy, params: { procedure_id: procedure.id, id: admin_to_remove.id }, format: :turbo_stream
|
||||
end
|
||||
|
||||
context 'when removing another admin' do
|
||||
let(:admin_to_remove) { other_admin }
|
||||
before do
|
||||
destroy_admin(other_admin)
|
||||
end
|
||||
|
||||
it 'removes the admin from the procedure' do
|
||||
subject
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(subject.body).to include('alert-success')
|
||||
expect(admin_to_remove.procedures.reload).not_to include(procedure)
|
||||
expect(response.body).to include('alert-success')
|
||||
expect(other_admin.procedures.reload).not_to include(procedure)
|
||||
end
|
||||
|
||||
context 'then removing oneself' do
|
||||
before do
|
||||
destroy_admin(signed_in_admin)
|
||||
end
|
||||
|
||||
it 'removes the admin from the procedure' do
|
||||
expect(response.body).to include('alert-danger')
|
||||
expect(signed_in_admin.procedures.reload).to include(procedure)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when removing oneself from a procedure' do
|
||||
let(:admin_to_remove) { signed_in_admin }
|
||||
before do
|
||||
destroy_admin(signed_in_admin)
|
||||
end
|
||||
|
||||
it 'denies the right for an admin to remove itself' do
|
||||
subject
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(subject.body).to include('alert-danger')
|
||||
expect(admin_to_remove.procedures.reload).to include(procedure)
|
||||
it 'removes the admin from the procedure' do
|
||||
expect(response).to redirect_to admin_procedures_path
|
||||
expect(signed_in_admin.procedures.reload).not_to include(procedure)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,7 +23,6 @@ describe 'Administrateurs can manage administrateurs', js: true do
|
|||
scenario 'the administrator can add another administrator' do
|
||||
another_administrateur = create(:administrateur)
|
||||
visit admin_procedure_administrateurs_path(procedure)
|
||||
find('#administrateurs').click
|
||||
|
||||
fill_in('administrateur_email', with: another_administrateur.email)
|
||||
|
||||
|
@ -41,8 +40,6 @@ describe 'Administrateurs can manage administrateurs', js: true do
|
|||
administrateur.administrateurs_procedures.update_all(manager: true)
|
||||
visit admin_procedure_administrateurs_path(procedure)
|
||||
|
||||
find('#administrateurs').click
|
||||
|
||||
expect(page).to have_css("#administrateur_email[disabled=\"disabled\"]")
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue