confirm adding a new admin to a procedure

For clarity and a better understanding, use a dedicated controller
to allow the current admin to confirm adding an administrateur
to a procedure.
This commit is contained in:
sebastiencarceles 2022-09-09 14:48:40 +02:00
parent 4123709e72
commit f154bb56e6
8 changed files with 255 additions and 16 deletions

View file

@ -0,0 +1,52 @@
module Manager
class AdministrateurConfirmationsController < Manager::ApplicationController
before_action :set_procedure
before_action :decrypt_params
before_action :ensure_not_inviter, unless: -> { Rails.env.development? }
before_action :ensure_not_invited, unless: -> { Rails.env.development? }
def new
@inviter = SuperAdmin.find(@inviter_id)
end
def create
administrateur = Administrateur.by_email(@invited_email)
AdministrateursProcedure.create!(procedure: @procedure, administrateur: administrateur)
flash[:notice] = "Ladministrateur \"#{administrateur.email}\" a été ajouté à la démarche."
redirect_to manager_procedure_path(@procedure)
end
private
def ensure_not_inviter
redirect_unallowed if @inviter_id.to_i == current_super_admin.id
end
def ensure_not_invited
redirect_unallowed if @invited_email == current_super_admin.email
end
def redirect_unallowed
flash[:alert] = "Veuillez partager ce lien avec un autre super administrateur pour qu'il confirme votre action"
redirect_to manager_procedure_path(@procedure)
end
def decrypt_params
@inviter_id = decrypted_params[:inviter_id]
@invited_email = decrypted_params[:email]
rescue ActiveSupport::MessageVerifier::InvalidSignature, ArgumentError
flash[:error] = "Le lien que vous avez utilisé est invalide. Veuillez contacter la personne qui vous l'a envoyé."
redirect_to manager_procedure_path(@procedure)
end
def decrypted_params
@decrypted_params ||= ActiveSupport::MessageVerifier.new(
Rails.application.key_generator.generate_key(ENV["SECRET_KEY_BASE"])
).verify(Base64.urlsafe_decode64(params[:q]))
end
def set_procedure
@procedure = Procedure.with_discarded.find(params[:procedure_id])
end
end
end

View file

@ -4,7 +4,7 @@ module Manager
before_action :ensure_not_already_added
def new
@url = confirm_add_administrateur_manager_procedure_url(
@url = new_manager_procedure_administrateur_confirmation_url(
procedure.id,
q: encrypt({ email: params[:email], inviter_id: current_super_admin.id })
)

View file

@ -68,18 +68,6 @@ module Manager
redirect_to new_manager_procedure_confirmation_url_path(procedure, email: params[:email])
end
def confirm_add_administrateur
administrateur_email = params[:email]
if administrateur_email != current_super_admin.email
administrateur = Administrateur.by_email(params[:email])
AdministrateursProcedure.create!(procedure: procedure, administrateur: administrateur)
flash[:notice] = "Ladministrateur \"#{administrateur.email}\" a été ajouté à la démarche."
else
flash[:alert] = "Veuillez partager ce lien avec un autre super administrateur pour qu'il confirme votre action"
end
redirect_to manager_procedure_path(procedure)
end
def delete_administrateur
administrateur = procedure.administrateurs.find { |admin| admin.email == current_super_admin.email }
if administrateur.present?

View file

@ -0,0 +1,35 @@
<% content_for(:title) { "Confirmation d'ajout d'un administrateur" } %>
<header class="main-content__header" role="banner">
<h1 class="main-content__page-title">
<%= content_for(:title) %>
</h1>
</header>
<section class="main-content__body">
<p>
Vous avez été invité·e par
<em>
<%= @inviter.email %>
</em>
à confirmer l'ajout de
<em>
<%= @invited_email %>
</em>
à la démarche
<strong>
<%= @procedure.libelle %>
(<%= @procedure.id %>).
</strong>
</p>
<p>
Confirmez-vous cet ajout ?
</p>
<%= form_tag manager_procedure_administrateur_confirmations_path(@procedure) do %>
<%= hidden_field_tag :q, params[:q] %>
<%= submit_tag "Oui, je confirme l'ajout" %>
<%= link_to "Non, je ne confirme pas l'ajout", :back %>
<% end %>
</section>

View file

@ -12,7 +12,7 @@ as defined by the routes in the `admin/` namespace
<hr />
<% Administrate::Namespace.new(namespace).resources.select { |resource| resource.to_s != "confirmation_urls" }.each do |resource| %>
<% Administrate::Namespace.new(namespace).resources.select { |resource| !resource.to_s.in?(%w(confirmation_urls administrateur_confirmations)) }.each do |resource| %>
<%= link_to(
display_resource_name(resource),

View file

@ -18,10 +18,10 @@ Rails.application.routes.draw do
put 'delete_administrateur', on: :member
post 'add_administrateur_and_instructeur', on: :member
post 'add_administrateur_with_confirmation', on: :member
get 'confirm_add_administrateur', on: :member
post 'change_piece_justificative_template', on: :member
get 'export_mail_brouillons', on: :member
resources :confirmation_urls, only: :new
resources :administrateur_confirmations, only: [:new, :create]
end
resources :archives, only: [:index, :show]

View file

@ -0,0 +1,164 @@
require 'rails_helper'
RSpec.describe Manager::AdministrateurConfirmationsController, type: :controller do
let(:inviter_super_admin) { create(:super_admin) }
let(:inviter_administrateur) { create(:administrateur, email: inviter_super_admin.email) }
let(:invited_super_admin) { create(:super_admin) }
let(:invited_administrateur) { create(:administrateur, email: invited_super_admin.email) }
let(:confirmer_super_admin) { create(:super_admin) }
let(:procedure) { create(:procedure, administrateurs: [inviter_administrateur]) }
describe "GET #new" do
subject(:new_request) do
get :new, params: {
procedure_id: procedure.id,
q: encrypt({ email: invited_administrateur.email, inviter_id: inviter_super_admin.id })
}
end
shared_examples "current admin is allowed to confirm adding another one" do
before { new_request }
it { expect(response).to render_template(:new) }
end
shared_examples "current admin isn't allowed to confirm adding another one" do
before { new_request }
it { expect(flash[:alert]).to match(/Veuillez partager ce lien avec un autre super administrateur/) }
it { expect(response).to redirect_to(manager_procedure_path(procedure)) }
end
context 'when the current admin is the invited' do
before { sign_in invited_super_admin }
it_behaves_like "current admin isn't allowed to confirm adding another one"
end
context 'when the current admin is the inviter' do
before { sign_in inviter_super_admin }
it_behaves_like "current admin isn't allowed to confirm adding another one"
end
context 'when the current admin is not the invited nor the inviter' do
before { sign_in confirmer_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
describe 'edge cases' do
context 'when the environment is development' do
before { Rails.env.stub(development?: true) }
context 'when the current admin is the inviter' do
before { sign_in inviter_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
context 'when the current admin is the invited' do
before { sign_in invited_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
end
context 'when the encrypted params are invalid' do
before { sign_in inviter_super_admin }
before { get :new, params: { procedure_id: procedure.id, q: "something that is invalid" } }
it { expect(flash[:error]).to match(/Le lien que vous avez utilisé est invalide/) }
end
end
end
describe "GET #create" do
subject(:create_request) do
post :create, params: {
procedure_id: procedure.id,
q: encrypt({ email: invited_administrateur.email, inviter_id: inviter_super_admin.id })
}
end
shared_examples "current admin is allowed to confirm adding another one" do
it "flashes the success message" do
create_request
expect(flash[:notice]).to include(invited_administrateur.email)
expect(flash[:notice]).to match(/ajouté à la démarche/)
end
it "adds the admin to the procedure" do
expect { create_request }.to change { procedure.administrateurs.count }.by(1)
end
it "redirects to the procedure" do
create_request
expect(response).to redirect_to(manager_procedure_path(procedure))
end
end
shared_examples "current admin isn't allowed to confirm adding another one" do
before { create_request }
it { expect(flash[:alert]).to match(/Veuillez partager ce lien avec un autre super administrateur/) }
it { expect(response).to redirect_to(manager_procedure_path(procedure)) }
end
context 'when the current admin is the invited' do
before { sign_in invited_super_admin }
it_behaves_like "current admin isn't allowed to confirm adding another one"
end
context 'when the current admin is the inviter' do
before { sign_in inviter_super_admin }
it_behaves_like "current admin isn't allowed to confirm adding another one"
end
context 'when the current admin is not the invited nor the inviter' do
before { sign_in confirmer_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
describe 'edge cases' do
context 'when the environment is development' do
before { Rails.env.stub(development?: true) }
context 'when the current admin is the inviter' do
before { sign_in inviter_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
context 'when the current admin is the invited' do
before { sign_in invited_super_admin }
it_behaves_like "current admin is allowed to confirm adding another one"
end
end
context 'when the encrypted params are invalid' do
before { sign_in inviter_super_admin }
before { post :create, params: { procedure_id: procedure.id, q: "something that is invalid" } }
it { expect(flash[:error]).to match(/Le lien que vous avez utilisé est invalide/) }
end
end
end
private
def encrypt(parameters)
key = Rails.application.key_generator.generate_key(ENV["SECRET_KEY_BASE"])
verifier = ActiveSupport::MessageVerifier.new(key)
Base64.urlsafe_encode64(verifier.generate(parameters))
end
end

View file

@ -27,7 +27,7 @@ describe Manager::ConfirmationUrlsController, type: :controller do
it "shows the confirmation url with encrypted parameters" do
expect(response.body).to include(
confirm_add_administrateur_manager_procedure_url(
new_manager_procedure_administrateur_confirmation_url(
procedure,
q: encrypt({ email: invited_administrateur.email, inviter_id: inviter_super_admin.id })
)