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
|
def current_user
|
||||||
controller.current_user
|
controller.current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def current_administrateur
|
||||||
|
controller.current_administrateur
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
||||||
|
include ApplicationHelper
|
||||||
|
|
||||||
def initialize(champ:, seen_at: nil)
|
def initialize(champ:, seen_at: nil)
|
||||||
@champ, @seen_at = champ, seen_at
|
@champ, @seen_at = champ, seen_at
|
||||||
end
|
end
|
||||||
|
@ -12,8 +14,4 @@ class EditableChamp::ChampLabelContentComponent < ApplicationComponent
|
||||||
def highlight?
|
def highlight?
|
||||||
@champ.updated_at.present? && @seen_at&.<(@champ.updated_at)
|
@champ.updated_at.present? && @seen_at&.<(@champ.updated_at)
|
||||||
end
|
end
|
||||||
|
|
||||||
def try_format_datetime(datetime)
|
|
||||||
datetime.present? ? I18n.l(datetime) : ''
|
|
||||||
end
|
|
||||||
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
|
end
|
||||||
|
|
||||||
def destroy
|
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 (@procedure.administrateurs - [admin_to_delete]).filter(&:active?).empty?
|
||||||
if administrateur == current_administrateur
|
flash.alert = "Il doit rester au moins un administrateur actif."
|
||||||
flash.alert = "Vous ne pouvez pas vous retirer vous-même d’une démarche."
|
else
|
||||||
return
|
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
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
class Administrateur < ApplicationRecord
|
class Administrateur < ApplicationRecord
|
||||||
include ActiveRecord::SecureToken
|
include ActiveRecord::SecureToken
|
||||||
|
|
||||||
|
self.ignored_columns = [:active]
|
||||||
|
|
||||||
UNUSED_ADMIN_THRESHOLD = 6.months
|
UNUSED_ADMIN_THRESHOLD = 6.months
|
||||||
|
|
||||||
has_and_belongs_to_many :instructeurs
|
has_and_belongs_to_many :instructeurs
|
||||||
|
@ -42,6 +44,10 @@ class Administrateur < ApplicationRecord
|
||||||
user&.email
|
user&.email
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def active?
|
||||||
|
user&.active?
|
||||||
|
end
|
||||||
|
|
||||||
def self.find_inactive_by_token(reset_password_token)
|
def self.find_inactive_by_token(reset_password_token)
|
||||||
self.inactive.with_reset_password_token(reset_password_token)
|
self.inactive.with_reset_password_token(reset_password_token)
|
||||||
end
|
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?
|
- 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? }
|
= 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.update 'administrateurs',
|
||||||
= turbo_stream.remove(@administrateur)
|
render(Procedure::ProcedureAdministrateurs::AdministrateurComponent.with_collection(@procedure.administrateurs.order('users.email'), procedure: @procedure))
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
%th= 'Enregistré le'
|
%th= 'Enregistré le'
|
||||||
%th= 'État'
|
%th= 'État'
|
||||||
%tbody#administrateurs
|
%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
|
%tfoot
|
||||||
%tr
|
%tr
|
||||||
%th{ colspan: 4 }
|
%th{ colspan: 4 }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe Administrateurs::ProcedureAdministrateursController, type: :controller do
|
describe Administrateurs::ProcedureAdministrateursController, type: :controller do
|
||||||
let(:signed_in_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) }
|
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!(:administrateurs_procedure) { create(:administrateurs_procedure, administrateur: signed_in_admin, procedure: procedure, manager: manager) }
|
||||||
let!(:procedure) { create(:procedure, administrateurs: [other_admin]) }
|
let!(:procedure) { create(:procedure, administrateurs: [other_admin]) }
|
||||||
render_views
|
render_views
|
||||||
|
@ -19,29 +19,41 @@ describe Administrateurs::ProcedureAdministrateursController, type: :controller
|
||||||
|
|
||||||
describe '#destroy' do
|
describe '#destroy' do
|
||||||
let(:manager) { false }
|
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
|
delete :destroy, params: { procedure_id: procedure.id, id: admin_to_remove.id }, format: :turbo_stream
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when removing another admin' do
|
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
|
it 'removes the admin from the procedure' do
|
||||||
subject
|
expect(response.body).to include('alert-success')
|
||||||
expect(response).to have_http_status(:ok)
|
expect(other_admin.procedures.reload).not_to include(procedure)
|
||||||
expect(subject.body).to include('alert-success')
|
end
|
||||||
expect(admin_to_remove.procedures.reload).not_to include(procedure)
|
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when removing oneself from a procedure' do
|
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
|
it 'removes the admin from the procedure' do
|
||||||
subject
|
expect(response).to redirect_to admin_procedures_path
|
||||||
expect(response).to have_http_status(:ok)
|
expect(signed_in_admin.procedures.reload).not_to include(procedure)
|
||||||
expect(subject.body).to include('alert-danger')
|
|
||||||
expect(admin_to_remove.procedures.reload).to include(procedure)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,6 @@ describe 'Administrateurs can manage administrateurs', js: true do
|
||||||
scenario 'the administrator can add another administrator' do
|
scenario 'the administrator can add another administrator' do
|
||||||
another_administrateur = create(:administrateur)
|
another_administrateur = create(:administrateur)
|
||||||
visit admin_procedure_administrateurs_path(procedure)
|
visit admin_procedure_administrateurs_path(procedure)
|
||||||
find('#administrateurs').click
|
|
||||||
|
|
||||||
fill_in('administrateur_email', with: another_administrateur.email)
|
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)
|
administrateur.administrateurs_procedures.update_all(manager: true)
|
||||||
visit admin_procedure_administrateurs_path(procedure)
|
visit admin_procedure_administrateurs_path(procedure)
|
||||||
|
|
||||||
find('#administrateurs').click
|
|
||||||
|
|
||||||
expect(page).to have_css("#administrateur_email[disabled=\"disabled\"]")
|
expect(page).to have_css("#administrateur_email[disabled=\"disabled\"]")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue