Merge pull request #7557 from mfo/US/super-admin-can-not-export
feat(export/archive): prevent creation of archives from user having a SuperAdmin user with the same email
This commit is contained in:
commit
ee0280de17
38 changed files with 403 additions and 110 deletions
|
@ -1,12 +1,12 @@
|
|||
module Administrateurs
|
||||
class AdministrateurController < ApplicationController
|
||||
before_action :authenticate_administrateur!
|
||||
helper_method :administrateur_as_manager?
|
||||
|
||||
def retrieve_procedure
|
||||
id = params[:procedure_id] || params[:id]
|
||||
|
||||
@procedure = current_administrateur.procedures.find(id)
|
||||
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash.alert = 'Démarche inexistante'
|
||||
redirect_to admin_procedures_path, status: 404
|
||||
|
@ -31,5 +31,20 @@ module Administrateurs
|
|||
@procedure.reset!
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_not_super_admin!
|
||||
if administrateur_as_manager?
|
||||
redirect_back fallback_location: root_url, alert: "Interdit aux super admins", status: 403
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def administrateur_as_manager?
|
||||
id = params[:procedure_id] || params[:id]
|
||||
|
||||
current_administrateur.administrateurs_procedures
|
||||
.exists?(procedure_id: id, manager: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module Administrateurs
|
||||
class ArchivesController < AdministrateurController
|
||||
before_action :retrieve_procedure, only: [:index, :create]
|
||||
before_action :retrieve_procedure
|
||||
before_action :ensure_not_super_admin!
|
||||
|
||||
helper_method :create_archive_url
|
||||
|
||||
def index
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Administrateurs
|
||||
class ExportsController < AdministrateurController
|
||||
before_action :retrieve_procedure, only: [:download]
|
||||
before_action :retrieve_procedure
|
||||
before_action :ensure_not_super_admin!
|
||||
|
||||
def download
|
||||
export = Export.find_or_create_export(export_format, all_groupe_instructeurs, **export_options)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
module Administrateurs
|
||||
class GroupeInstructeursController < AdministrateurController
|
||||
include ActiveSupport::NumberHelper
|
||||
|
||||
before_action :ensure_not_super_admin!, only: [:add_instructeur]
|
||||
|
||||
ITEMS_PER_PAGE = 25
|
||||
CSV_MAX_SIZE = 1.megabytes
|
||||
CSV_ACCEPTED_CONTENT_TYPES = [
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Administrateurs
|
||||
class ProcedureAdministrateursController < AdministrateurController
|
||||
before_action :retrieve_procedure, except: [:new]
|
||||
before_action :ensure_not_super_admin!, only: [:create]
|
||||
|
||||
def index
|
||||
end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module Instructeurs
|
||||
class ArchivesController < InstructeurController
|
||||
before_action :retrieve_procedure, only: [:index, :create]
|
||||
before_action :retrieve_procedure
|
||||
before_action :ensure_not_super_admin!
|
||||
|
||||
helper_method :create_archive_url
|
||||
|
||||
def index
|
||||
|
|
|
@ -5,5 +5,24 @@ module Instructeurs
|
|||
def nav_bar_profile
|
||||
:instructeur
|
||||
end
|
||||
|
||||
def ensure_not_super_admin!
|
||||
if instructeur_as_manager?
|
||||
redirect_back fallback_location: root_url, alert: "Interdit aux super admins", status: 403
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def instructeur_as_manager?
|
||||
procedure_id = params[:procedure_id]
|
||||
|
||||
current_instructeur.assign_to
|
||||
.where(instructeur: current_instructeur,
|
||||
groupe_instructeur: current_instructeur.groupe_instructeurs.where(procedure_id: procedure_id),
|
||||
manager: true)
|
||||
.count
|
||||
.positive?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
module Instructeurs
|
||||
class ProceduresController < InstructeurController
|
||||
before_action :ensure_ownership!, except: [:index]
|
||||
before_action :ensure_not_super_admin!, only: [:download_export]
|
||||
|
||||
ITEMS_PER_PAGE = 25
|
||||
|
||||
|
@ -60,7 +61,7 @@ module Instructeurs
|
|||
@counts = current_instructeur
|
||||
.dossiers_count_summary(groupe_instructeur_ids)
|
||||
.symbolize_keys
|
||||
@can_download_dossiers = (@counts[:tous] + @counts[:archives]) > 0
|
||||
@can_download_dossiers = (@counts[:tous] + @counts[:archives]) > 0 && !instructeur_as_manager?
|
||||
|
||||
dossiers = Dossier.where(groupe_instructeur_id: groupe_instructeur_ids)
|
||||
dossiers_count = @counts[statut.underscore.to_sym]
|
||||
|
@ -101,7 +102,7 @@ module Instructeurs
|
|||
@a_suivre_count, @suivis_count, @traites_count, @tous_count, @archives_count, @supprimes_recemment_count, @expirant_count = current_instructeur
|
||||
.dossiers_count_summary(groupe_instructeur_ids)
|
||||
.fetch_values('a_suivre', 'suivis', 'traites', 'tous', 'archives', 'supprimes_recemment', 'expirant')
|
||||
@can_download_dossiers = (@tous_count + @archives_count) > 0
|
||||
@can_download_dossiers = (@tous_count + @archives_count) > 0 && !instructeur_as_manager?
|
||||
|
||||
notifications = current_instructeur.notifications_for_groupe_instructeurs(groupe_instructeur_ids)
|
||||
@has_en_cours_notifications = notifications[:en_cours].present?
|
||||
|
@ -145,7 +146,7 @@ module Instructeurs
|
|||
@can_download_dossiers = current_instructeur
|
||||
.dossiers
|
||||
.visible_by_administration
|
||||
.exists?(groupe_instructeur_id: groupe_instructeur_ids)
|
||||
.exists?(groupe_instructeur_id: groupe_instructeur_ids) && !instructeur_as_manager?
|
||||
|
||||
export = Export.find_or_create_export(export_format, groupe_instructeurs, **export_options)
|
||||
|
||||
|
|
|
@ -46,23 +46,39 @@ module Manager
|
|||
send_data(emails.join("\n"), :filename => "brouillons-#{procedure.id}-au-#{date}.csv")
|
||||
end
|
||||
|
||||
def add_administrateur
|
||||
add_self = params[:email].blank?
|
||||
administrateur_email = add_self ? current_super_admin.email : params[:email]
|
||||
administrateur = Administrateur.by_email(administrateur_email)
|
||||
if administrateur
|
||||
AdministrateursProcedure.create(procedure: procedure, administrateur: administrateur, manager: add_self)
|
||||
if add_self
|
||||
flash[:notice] = "L’administrateur \"#{administrateur_email}\" est ajouté à la démarche pour la journée."
|
||||
else
|
||||
flash[:notice] = "L’administrateur \"#{administrateur_email}\" est ajouté à la démarche."
|
||||
def add_administrateur_and_instructeur
|
||||
administrateur = Administrateur.by_email(current_super_admin.email)
|
||||
instructeur = Instructeur.by_email(current_super_admin.email)
|
||||
if administrateur && instructeur
|
||||
ActiveRecord::Base.transaction do
|
||||
AdministrateursProcedure.create!(procedure: procedure, administrateur: administrateur, manager: true)
|
||||
procedure.groupe_instructeurs.map do |groupe_instructeur|
|
||||
instructeur.assign_to.create(groupe_instructeur: groupe_instructeur, manager: true)
|
||||
end
|
||||
end
|
||||
|
||||
flash[:notice] = "L’administrateur \"#{administrateur.email}\" a été ajouté à la démarche. L'instructeur \"#{instructeur.email}\" a été ajouté aux #{procedure.groupe_instructeurs.count} groupes d'instructeurs"
|
||||
else
|
||||
if add_self
|
||||
flash[:alert] = "Vous n’êtes pas connecté en tant qu’administrateur."
|
||||
else
|
||||
flash[:alert] = "L’administrateur \"#{administrateur_email}\" est introuvable."
|
||||
end
|
||||
flash[:alert] = "L’administrateur \"#{administrateur.email}\" est introuvable."
|
||||
end
|
||||
redirect_to manager_procedure_path(procedure)
|
||||
end
|
||||
|
||||
def add_administrateur_with_confirmation
|
||||
confirmation_url = confirm_add_administrateur_manager_procedure_url(id: procedure.id, email: current_super_admin.email)
|
||||
|
||||
flash[:notice] = "Veuillez partager ce lien : #{confirmation_url} avec un autre super admin pour que l'operation soit effectuée"
|
||||
redirect_to manager_procedure_path(procedure)
|
||||
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] = "L’administrateur \"#{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
|
||||
|
|
|
@ -4,5 +4,6 @@ class Cron::PurgeManagerAdministrateurSessionsJob < Cron::CronJob
|
|||
def perform
|
||||
# TODO: add id column to administrateurs_procedures and use destroy_all
|
||||
AdministrateursProcedure.where(manager: true).delete_all
|
||||
AssignTo.where(manager: true).destroy_all
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,7 +15,8 @@ class Administrateur < ApplicationRecord
|
|||
UNUSED_ADMIN_THRESHOLD = 6.months
|
||||
|
||||
has_and_belongs_to_many :instructeurs
|
||||
has_and_belongs_to_many :procedures
|
||||
has_many :administrateurs_procedures
|
||||
has_many :procedures, through: :administrateurs_procedures
|
||||
has_many :services
|
||||
|
||||
belongs_to :user
|
||||
|
@ -102,7 +103,7 @@ class Administrateur < ApplicationRecord
|
|||
# We can't destroy a service if it has procedures, even if those procedures are archived
|
||||
service.destroy unless service.procedures.with_discarded.any?
|
||||
end
|
||||
|
||||
AdministrateursProcedure.where(administrateur_id: self.id).delete_all
|
||||
destroy
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# daily_email_notifications_enabled :boolean default(FALSE), not null
|
||||
# instant_email_dossier_notifications_enabled :boolean default(FALSE), not null
|
||||
# instant_email_message_notifications_enabled :boolean default(FALSE), not null
|
||||
# manager :boolean default(FALSE)
|
||||
# weekly_email_notifications_enabled :boolean default(TRUE), not null
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
.container
|
||||
%h1.mb-2
|
||||
Archives
|
||||
-# index not renderable as administrateur flagged as manager, so render it anyway
|
||||
= render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, export_url: method(:download_admin_procedure_exports_path))
|
||||
|
||||
= render partial: "shared/archives/notice"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
-# not renderable as administrateur flagged as manager, so render it anyway
|
||||
- if @can_download_dossiers
|
||||
= turbo_stream.update_all '.procedure-actions' do
|
||||
= render Dossiers::ExportComponent.new(procedure: @procedure, exports: @exports, count: @dossiers_count, export_url: method(:admin_procedure_exports_path))
|
||||
|
|
|
@ -5,15 +5,20 @@
|
|||
.instructeur-wrapper
|
||||
- if !procedure.routee?
|
||||
%p.notice Entrez les adresses email des instructeurs que vous souhaitez affecter à cette démarche
|
||||
= hidden_field_tag :emails, nil
|
||||
= react_component("ComboMultiple",
|
||||
options: available_instructeur_emails, selected: [], disabled: [],
|
||||
group: '.instructeur-wrapper',
|
||||
name: 'emails',
|
||||
label: 'Emails',
|
||||
acceptNewValues: true)
|
||||
|
||||
= f.submit 'Affecter', class: 'button primary send'
|
||||
- if disabled_as_super_admin
|
||||
= f.select :emails, available_instructeur_emails, {}, disabled: disabled_as_super_admin, id: 'instructeur_emails'
|
||||
- else
|
||||
= hidden_field_tag :emails, nil
|
||||
= react_component("ComboMultiple",
|
||||
options: available_instructeur_emails, selected: [], disabled: [],
|
||||
group: '.instructeur-wrapper',
|
||||
id: 'instructeur_emails',
|
||||
name: 'emails',
|
||||
label: 'Emails',
|
||||
acceptNewValues: true)
|
||||
|
||||
= f.submit 'Affecter', class: 'button primary send', disabled: disabled_as_super_admin
|
||||
|
||||
%table.table.mt-2
|
||||
%thead
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.card
|
||||
.card-title
|
||||
= t('.title')
|
||||
%h2.card-title= t('.title')
|
||||
|
||||
- if !procedure.routee?
|
||||
%p.notice= t('.notice_html')
|
||||
|
||||
|
@ -9,16 +9,16 @@
|
|||
= link_to t('.button.routing_disable'), update_routing_enabled_admin_procedure_groupe_instructeurs_path(procedure, routing: :disable), class: 'button primary mt-1', method: 'patch'
|
||||
- else
|
||||
= link_to t('.button.routing_enable'), update_routing_enabled_admin_procedure_groupe_instructeurs_path(procedure, routing: :enable), class: 'button primary mt-1', method: 'patch'
|
||||
.card
|
||||
%h2.card-title L‘autogestion des instructeurs
|
||||
%p.notice= t('.self_managment_notice_html')
|
||||
|
||||
.card-title.mt-4 L‘autogestion des instructeurs
|
||||
%p.notice= t('.self_managment_notice_html')
|
||||
|
||||
= form_for procedure,
|
||||
method: :patch,
|
||||
url: update_instructeurs_self_management_enabled_admin_procedure_groupe_instructeurs_path(procedure),
|
||||
html: { class: 'form procedure-form__column--form no-background' } do |f|
|
||||
%label.toggle-switch
|
||||
= f.check_box :instructeurs_self_management_enabled, class: 'toggle-switch-checkbox', onchange: 'this.form.submit()'
|
||||
%span.toggle-switch-control.round
|
||||
%span.toggle-switch-label.on
|
||||
%span.toggle-switch-label.off
|
||||
= form_for procedure,
|
||||
method: :patch,
|
||||
url: update_instructeurs_self_management_enabled_admin_procedure_groupe_instructeurs_path(procedure),
|
||||
html: { class: 'form procedure-form__column--form no-background' } do |f|
|
||||
%label.toggle-switch
|
||||
= f.check_box :instructeurs_self_management_enabled, class: 'toggle-switch-checkbox', onchange: 'this.form.submit()'
|
||||
%span.toggle-switch-control.round
|
||||
%span.toggle-switch-label.on
|
||||
%span.toggle-switch-label.off
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
'Instructeurs'] }
|
||||
|
||||
.container.groupe-instructeur
|
||||
%h1 Gérer les instructeurs et les options d'instruction de « #{@procedure.libelle} »
|
||||
|
||||
= render partial: 'administrateurs/groupe_instructeurs/routing', locals: { procedure: @procedure }
|
||||
|
||||
- if @procedure.routee?
|
||||
|
@ -19,4 +21,5 @@
|
|||
locals: { procedure: @procedure,
|
||||
groupe_instructeur: @procedure.defaut_groupe_instructeur,
|
||||
instructeurs: @instructeurs,
|
||||
available_instructeur_emails: @available_instructeur_emails }
|
||||
available_instructeur_emails: @available_instructeur_emails,
|
||||
disabled_as_super_admin: administrateur_as_manager? }
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
= render partial: 'administrateurs/breadcrumbs',
|
||||
locals: { steps: [link_to('Démarches', admin_procedures_path),
|
||||
link_to(@procedure.libelle, admin_procedure_path(@procedure)),
|
||||
|
@ -11,4 +10,5 @@
|
|||
locals: { procedure: @procedure,
|
||||
groupe_instructeur: @groupe_instructeur,
|
||||
instructeurs: @instructeurs,
|
||||
available_instructeur_emails: @available_instructeur_emails }
|
||||
available_instructeur_emails: @available_instructeur_emails,
|
||||
disabled_as_super_admin: administrateur_as_manager? }
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
= form_for procedure.administrateurs.new(user: User.new),
|
||||
url: { controller: 'procedure_administrateurs' },
|
||||
html: { class: 'form', id: "new_administrateur" },
|
||||
html: { class: 'form', id: "new_administrateur" },
|
||||
data: { turbo: true } do |f|
|
||||
= f.label :email do
|
||||
Ajouter un administrateur
|
||||
%p.notice Renseignez l’email d’un administrateur déjà enregistré sur #{APPLICATION_NAME} pour lui permettre de modifier « #{procedure.libelle} ».
|
||||
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true
|
||||
= f.submit 'Ajouter comme administrateur', class: 'button primary send'
|
||||
= f.email_field :email, placeholder: 'marie.dupont@exemple.fr', required: true, disabled: disabled_as_super_admin
|
||||
= f.submit 'Ajouter comme administrateur', class: 'button primary send', disabled: disabled_as_super_admin
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
- if @administrateur.present?
|
||||
= turbo_stream.append "administrateurs", partial: 'administrateur', locals: { procedure: @procedure, administrateur: @administrateur }
|
||||
= turbo_stream.replace "new_administrateur", partial: 'add_admin_form', locals: { procedure: @procedure }
|
||||
= turbo_stream.replace "new_administrateur", partial: 'add_admin_form', locals: { procedure: @procedure, disabled_as_super_admin: administrateur_as_manager? }
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
'Administrateurs'], preview: false }
|
||||
|
||||
.container
|
||||
%h1 Administrateurs de « #{@procedure.libelle} »
|
||||
%h1 Gérer les administrateurs de « #{@procedure.libelle} »
|
||||
|
||||
%table.table
|
||||
%thead
|
||||
%th= 'Adresse email'
|
||||
|
@ -15,4 +16,4 @@
|
|||
%tfoot
|
||||
%tr
|
||||
%th{ colspan: 4 }
|
||||
= render 'add_admin_form', procedure: @procedure
|
||||
= render 'add_admin_form', procedure: @procedure, disabled_as_super_admin: administrateur_as_manager?
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
-# not renderable as instructeur flagged as manager, so render it anyway
|
||||
- if @can_download_dossiers
|
||||
- if @statut.nil?
|
||||
= turbo_stream.update_all '.procedure-actions' do
|
||||
|
|
|
@ -64,17 +64,19 @@ as well as a link to its edit page.
|
|||
<dd class="attribute-data attribute-data--<%=attribute.html_class%>">
|
||||
<%= render_field attribute, page: page %>
|
||||
<% if attribute.name == 'administrateurs' %>
|
||||
<%= form_tag(add_administrateur_manager_procedure_path(procedure), style: 'margin-top: 1rem;') do %>
|
||||
<%= form_tag(add_administrateur_with_confirmation_manager_procedure_path(procedure), style: 'margin-top: 1rem;') do %>
|
||||
<%= email_field_tag(:email, '', placeholder: 'Email', autocapitalize: 'off', autocorrect: 'off', spellcheck: 'false', style: 'margin-bottom: 1rem;width:24rem;') %>
|
||||
<button>Ajouter un administrateur</button>
|
||||
<button>Ajouter un administrateur (pour toujours)</button>
|
||||
<p>J'utilise cette option ETQ support quand un usager a besoin de devenir administrateur sur une démarche</p>
|
||||
<% end %>
|
||||
<% if procedure.administrateurs.find { |admin| admin.email == current_super_admin.email } %>
|
||||
<p style="margin-top: 20px;">Vous êtes déjà administrateur sur cette démarche</p>
|
||||
<%= link_to 'Me retirer de cette démarche', delete_administrateur_manager_procedure_path(procedure), method: :put, class: 'button' %>
|
||||
|
||||
<% else %>
|
||||
<%= form_tag(add_administrateur_manager_procedure_path(procedure), style: 'margin-top: 1rem;') do %>
|
||||
<button>Devenir administrateur (pour la journée)</button>
|
||||
<%= form_tag(add_administrateur_and_instructeur_manager_procedure_path(procedure), style: 'margin-top: 1rem;') do %>
|
||||
<button>Devenir administrateur & instructeur (pour la journée)</button>
|
||||
<p>J'utilise cette option temporairement à des fins de support.</p>
|
||||
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -15,8 +15,10 @@ Rails.application.routes.draw do
|
|||
post 'draft', on: :member
|
||||
post 'discard', on: :member
|
||||
post 'restore', on: :member
|
||||
post 'add_administrateur', on: :member
|
||||
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
|
||||
end
|
||||
|
|
10
db/migrate/20220712141913_add_manager_to_assign_tos.rb
Normal file
10
db/migrate/20220712141913_add_manager_to_assign_tos.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class AddManagerToAssignTos < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
add_column :assign_tos, :manager, :boolean
|
||||
change_column_default :assign_tos, :manager, false
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :assign_tos, :manager
|
||||
end
|
||||
end
|
10
db/migrate/20220712141945_backfill_assign_tos_manager.rb
Normal file
10
db/migrate/20220712141945_backfill_assign_tos_manager.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class BackfillAssignTosManager < ActiveRecord::Migration[6.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
AssignTo.in_batches do |relation|
|
||||
relation.update_all manager: false
|
||||
sleep(0.01)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -112,6 +112,7 @@ ActiveRecord::Schema.define(version: 2022_07_28_084804) do
|
|||
t.boolean "instant_email_dossier_notifications_enabled", default: false, null: false
|
||||
t.boolean "instant_email_message_notifications_enabled", default: false, null: false
|
||||
t.integer "instructeur_id"
|
||||
t.boolean "manager", default: false
|
||||
t.datetime "updated_at"
|
||||
t.boolean "weekly_email_notifications_enabled", default: true, null: false
|
||||
t.index ["groupe_instructeur_id", "instructeur_id"], name: "unique_couple_groupe_instructeur_instructeur", unique: true
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
describe Administrateurs::ArchivesController, type: :controller do
|
||||
let(:admin) { create(:administrateur) }
|
||||
let(:procedure) { create :procedure, administrateur: admin, groupe_instructeurs: [groupe_instructeur1, groupe_instructeur2] }
|
||||
let(:procedure) { create :procedure, groupe_instructeurs: [groupe_instructeur1, groupe_instructeur2] }
|
||||
let(:administrateur_procedure) { create(:administrateurs_procedure, procedure: procedure, administrateur: admin, manager: manager) }
|
||||
let(:groupe_instructeur1) { create(:groupe_instructeur) }
|
||||
let(:groupe_instructeur2) { create(:groupe_instructeur) }
|
||||
|
||||
|
@ -10,8 +11,11 @@ describe Administrateurs::ArchivesController, type: :controller do
|
|||
context 'when logged out' do
|
||||
it { is_expected.to have_http_status(302) }
|
||||
end
|
||||
context 'when logged in' do
|
||||
|
||||
context 'when logged in as administrateur_procedure.manager=false' do
|
||||
let(:manager) { false }
|
||||
before do
|
||||
administrateur_procedure
|
||||
sign_in(admin.user)
|
||||
end
|
||||
|
||||
|
@ -22,15 +26,30 @@ describe Administrateurs::ArchivesController, type: :controller do
|
|||
subject
|
||||
end
|
||||
end
|
||||
context 'when logged in as administrateur_procedure.manager=true' do
|
||||
let(:manager) { true }
|
||||
|
||||
before do
|
||||
administrateur_procedure
|
||||
sign_in(admin.user)
|
||||
end
|
||||
|
||||
it { is_expected.to have_http_status(403) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET #create' do
|
||||
subject { post :create, params: { procedure_id: procedure.id, month: '22-06', type: 'monthly' } }
|
||||
|
||||
context 'when logged out' do
|
||||
it { is_expected.to have_http_status(302) }
|
||||
end
|
||||
context 'when logged in' do
|
||||
|
||||
context 'when logged in in as administrateur_procedure.manager=false' do
|
||||
let(:manager) { false }
|
||||
|
||||
before do
|
||||
administrateur_procedure
|
||||
sign_in(admin.user)
|
||||
end
|
||||
|
||||
|
@ -39,5 +58,19 @@ describe Administrateurs::ArchivesController, type: :controller do
|
|||
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure, an_instance_of(Archive), admin)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in in as administrateur_procedure.manager=true' do
|
||||
let(:manager) { true }
|
||||
|
||||
before do
|
||||
administrateur_procedure
|
||||
sign_in(admin.user)
|
||||
end
|
||||
|
||||
it { is_expected.to have_http_status(403) }
|
||||
it 'does not enqueue the creation job' do
|
||||
expect { subject }.not_to have_enqueued_job(ArchiveCreationJob)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -63,5 +63,22 @@ describe Administrateurs::ExportsController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when admin is allowed present as manager' do
|
||||
let!(:procedure) { create(:procedure) }
|
||||
let!(:administrateur_procedure) { create(:administrateurs_procedure, procedure: procedure, administrateur: administrateur, manager: true) }
|
||||
|
||||
context 'get #index.html' do
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
context 'get #index.turbo_stream' do
|
||||
it 'is forbidden' do
|
||||
post :download,
|
||||
params: { export_format: :csv, procedure_id: procedure.id },
|
||||
format: :turbo_stream
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -208,10 +208,11 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
|
|||
end
|
||||
|
||||
describe '#add_instructeur_procedure_non_routee' do
|
||||
let(:procedure) { create :procedure, administrateur: admin }
|
||||
let(:procedure) { create :procedure }
|
||||
let!(:groupe_instructeur) { create(:administrateurs_procedure, procedure: procedure, administrateur: admin, manager: manager) }
|
||||
let(:emails) { ['instructeur_3@ministere_a.gouv.fr', 'instructeur_4@ministere_b.gouv.fr'].to_json }
|
||||
subject { post :add_instructeur, params: { emails: emails, procedure_id: procedure.id, id: gi_1_1.id } }
|
||||
|
||||
let(:manager) { false }
|
||||
context 'when all emails are valid' do
|
||||
let(:emails) { ['test@b.gouv.fr', 'test2@b.gouv.fr'].to_json }
|
||||
it { expect(response.status).to eq(200) }
|
||||
|
@ -233,18 +234,17 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
|
|||
it { expect(subject.request.flash[:alert]).to be_present }
|
||||
it { expect(subject).to redirect_to admin_procedure_groupe_instructeurs_path(procedure) }
|
||||
end
|
||||
|
||||
context 'when signed in admin comes from manager' do
|
||||
let(:manager) { true }
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add_instructeur' do
|
||||
let!(:instructeur) { create(:instructeur) }
|
||||
let(:gi_1_2) { procedure.groupe_instructeurs.create(label: 'groupe instructeur 2') }
|
||||
|
||||
before do
|
||||
gi_1_2.instructeurs << instructeur
|
||||
|
||||
allow(GroupeInstructeurMailer).to receive(:add_instructeurs)
|
||||
.and_return(double(deliver_later: true))
|
||||
|
||||
let(:do_request) do
|
||||
post :add_instructeur,
|
||||
params: {
|
||||
procedure_id: procedure.id,
|
||||
|
@ -252,10 +252,16 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
|
|||
emails: new_instructeur_emails.to_json
|
||||
}
|
||||
end
|
||||
before do
|
||||
gi_1_2.instructeurs << instructeur
|
||||
|
||||
allow(GroupeInstructeurMailer).to receive(:add_instructeurs)
|
||||
.and_return(double(deliver_later: true))
|
||||
end
|
||||
|
||||
context 'of a news instructeurs' do
|
||||
let(:new_instructeur_emails) { ['new_i1@mail.com', 'new_i2@mail.com'] }
|
||||
|
||||
before { do_request }
|
||||
it { expect(gi_1_2.instructeurs.pluck(:email)).to include(*new_instructeur_emails) }
|
||||
it { expect(flash.notice).to be_present }
|
||||
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
||||
|
@ -271,22 +277,32 @@ describe Administrateurs::GroupeInstructeursController, type: :controller do
|
|||
|
||||
context 'of an instructeur already in the group' do
|
||||
let(:new_instructeur_emails) { [instructeur.email] }
|
||||
|
||||
before { do_request }
|
||||
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
||||
end
|
||||
|
||||
context 'of badly formed email' do
|
||||
let(:new_instructeur_emails) { ['badly_formed_email'] }
|
||||
|
||||
before { do_request }
|
||||
it { expect(flash.alert).to be_present }
|
||||
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
||||
end
|
||||
|
||||
context 'of an empty string' do
|
||||
let(:new_instructeur_emails) { [''] }
|
||||
|
||||
before { do_request }
|
||||
it { expect(response).to redirect_to(admin_procedure_groupe_instructeur_path(procedure, gi_1_2)) }
|
||||
end
|
||||
|
||||
context 'when connected as an administrateur from manager' do
|
||||
let(:new_instructeur_emails) { [instructeur.email] }
|
||||
before do
|
||||
admin.administrateurs_procedures.update_all(manager: true)
|
||||
do_request
|
||||
end
|
||||
|
||||
it { expect(response).to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_instructeur' do
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
describe Administrateurs::ProcedureAdministrateursController, type: :controller do
|
||||
let(:signed_in_admin) { create(:administrateur) }
|
||||
let(:other_admin) { create(:administrateur) }
|
||||
let(:procedure) { create(:procedure, administrateurs: [signed_in_admin, other_admin]) }
|
||||
let!(:administrateurs_procedure) { create(:administrateurs_procedure, administrateur: signed_in_admin, procedure: procedure, manager: manager) }
|
||||
let!(:procedure) { create(:procedure, administrateurs: [other_admin]) }
|
||||
render_views
|
||||
|
||||
before do
|
||||
sign_in(signed_in_admin.user)
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
context 'as manager' do
|
||||
let(:manager) { true }
|
||||
subject { post :create, params: { procedure_id: procedure.id, administrateur: { email: create(:administrateur).email } }, format: :turbo_stream }
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#destroy' do
|
||||
let(:manager) { false }
|
||||
subject do
|
||||
delete :destroy, params: { procedure_id: procedure.id, id: admin_to_remove.id }, format: :turbo_stream
|
||||
end
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
describe Instructeurs::ArchivesController, type: :controller do
|
||||
let(:procedure1) { create(:procedure, :published, groupe_instructeurs: [gi1]) }
|
||||
let(:procedure1) { create(:procedure, :published, groupe_instructeurs: [assign_to.groupe_instructeur]) }
|
||||
let(:procedure2) { create(:procedure, :published, groupe_instructeurs: [gi2]) }
|
||||
let!(:instructeur) { create(:instructeur, groupe_instructeurs: [gi1, gi2]) }
|
||||
let!(:archive1) { create(:archive, :generated, groupe_instructeurs: [gi1]) }
|
||||
let!(:instructeur) { create(:instructeur, groupe_instructeurs: [gi2]) }
|
||||
let!(:archive1) { create(:archive, :generated, groupe_instructeurs: [assign_to.groupe_instructeur]) }
|
||||
let!(:archive2) { create(:archive, :generated, groupe_instructeurs: [gi2]) }
|
||||
let(:gi1) { create(:groupe_instructeur) }
|
||||
let!(:assign_to) { create(:assign_to, instructeur: instructeur, groupe_instructeur: build(:groupe_instructeur), manager: manager) }
|
||||
let(:gi2) { create(:groupe_instructeur) }
|
||||
|
||||
before do
|
||||
sign_in(instructeur.user)
|
||||
end
|
||||
|
||||
after { Timecop.return }
|
||||
|
||||
describe '#index' do
|
||||
|
@ -20,24 +19,50 @@ describe Instructeurs::ArchivesController, type: :controller do
|
|||
create_dossier_for_month(procedure1, 2021, 2)
|
||||
Timecop.freeze(Time.zone.local(2021, 3, 5))
|
||||
end
|
||||
subject { get :index, params: { procedure_id: procedure1.id } }
|
||||
|
||||
it 'displays archives' do
|
||||
get :index, params: { procedure_id: procedure1.id }
|
||||
context 'signed in not as manager' do
|
||||
let(:manager) { false }
|
||||
|
||||
expect(assigns(:archives)).to eq([archive1])
|
||||
it { is_expected.to have_http_status(:success) }
|
||||
it 'assigns archives' do
|
||||
subject
|
||||
expect(assigns(:archives)).to eq([archive1])
|
||||
end
|
||||
end
|
||||
|
||||
context 'signed in as manager' do
|
||||
let(:manager) { true }
|
||||
|
||||
before do
|
||||
sign_in(instructeur.user)
|
||||
end
|
||||
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
let(:month) { '21-03' }
|
||||
let(:date_month) { Date.strptime(month, "%Y-%m") }
|
||||
let(:subject) do
|
||||
post :create, params: { procedure_id: procedure1.id, type: 'monthly', month: month }
|
||||
end
|
||||
|
||||
it "performs archive creation job" do
|
||||
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure1, an_instance_of(Archive), instructeur)
|
||||
expect(flash.notice).to include("Votre demande a été prise en compte")
|
||||
let(:month) { '21-03' }
|
||||
let(:date_month) { Date.strptime(month, "%Y-%m") }
|
||||
|
||||
context 'signed in not as manager' do
|
||||
let(:manager) { false }
|
||||
|
||||
it "performs archive creation job" do
|
||||
expect { subject }.to have_enqueued_job(ArchiveCreationJob).with(procedure1, an_instance_of(Archive), instructeur)
|
||||
expect(flash.notice).to include("Votre demande a été prise en compte")
|
||||
end
|
||||
end
|
||||
|
||||
context 'signed in as manager' do
|
||||
let(:manager) { true }
|
||||
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -468,9 +468,10 @@ describe Instructeurs::ProceduresController, type: :controller do
|
|||
describe '#download_export' do
|
||||
let(:instructeur) { create(:instructeur) }
|
||||
let!(:procedure) { create(:procedure) }
|
||||
let!(:gi_0) { procedure.defaut_groupe_instructeur }
|
||||
let!(:assign_to) { create(:assign_to, instructeur: instructeur, groupe_instructeur: build(:groupe_instructeur, procedure: procedure), manager: manager) }
|
||||
let!(:gi_0) { assign_to.groupe_instructeur }
|
||||
let!(:gi_1) { create(:groupe_instructeur, label: 'gi_1', procedure: procedure, instructeurs: [instructeur]) }
|
||||
|
||||
let(:manager) { false }
|
||||
before { sign_in(instructeur.user) }
|
||||
|
||||
subject do
|
||||
|
@ -498,7 +499,7 @@ describe Instructeurs::ProceduresController, type: :controller do
|
|||
end
|
||||
|
||||
context 'when the export is ready' do
|
||||
let(:export) { create(:export, groupe_instructeurs: [gi_1], job_status: 'generated') }
|
||||
let(:export) { create(:export, groupe_instructeurs: [gi_1, gi_0], job_status: 'generated') }
|
||||
|
||||
before do
|
||||
export.file.attach(io: StringIO.new('export'), filename: 'file.csv')
|
||||
|
@ -511,7 +512,7 @@ describe Instructeurs::ProceduresController, type: :controller do
|
|||
end
|
||||
|
||||
context 'when another export is ready' do
|
||||
let(:export) { create(:export, groupe_instructeurs: [gi_0, gi_1]) }
|
||||
let(:export) { create(:export, groupe_instructeurs: [gi_0]) }
|
||||
|
||||
before do
|
||||
export.file.attach(io: StringIO.new('export'), filename: 'file.csv')
|
||||
|
@ -535,6 +536,11 @@ describe Instructeurs::ProceduresController, type: :controller do
|
|||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in through super admin' do
|
||||
let(:manager) { true }
|
||||
it { is_expected.to have_http_status(:forbidden) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create_multiple_commentaire' do
|
||||
|
|
6
spec/factories/administrateurs_procedure.rb
Normal file
6
spec/factories/administrateurs_procedure.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
FactoryBot.define do
|
||||
factory :administrateurs_procedure do
|
||||
association :administrateur
|
||||
association :procedure
|
||||
end
|
||||
end
|
|
@ -3,7 +3,6 @@ describe Administrateur, type: :model do
|
|||
|
||||
describe 'associations' do
|
||||
it { is_expected.to have_and_belong_to_many(:instructeurs) }
|
||||
it { is_expected.to have_and_belong_to_many(:procedures) }
|
||||
end
|
||||
|
||||
describe "#renew_api_token" do
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
require 'system/administrateurs/procedure_spec_helper'
|
||||
|
||||
describe 'Administrateurs can manage administrateurs', js: true do
|
||||
include ProcedureSpecHelper
|
||||
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let!(:procedure) { create(:procedure) }
|
||||
let!(:administrateurs_procedure) { create(:administrateurs_procedure, administrateur: administrateur, procedure: procedure, manager: manager) }
|
||||
let(:manager) { false }
|
||||
before do
|
||||
login_as administrateur.user, scope: :user
|
||||
end
|
||||
|
||||
scenario 'card is clickable' do
|
||||
visit admin_procedure_path(procedure)
|
||||
find('#administrateurs').click
|
||||
expect(page).to have_css("h1", text: "Gérer les administrateurs de « #{procedure.libelle} »")
|
||||
end
|
||||
|
||||
context 'as admin not flagged from manager' do
|
||||
let(:manager) { false }
|
||||
|
||||
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)
|
||||
|
||||
click_on 'Ajouter comme administrateur'
|
||||
|
||||
within('.alert-success') do
|
||||
expect(page).to have_content(another_administrateur.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'as admin flagged from manager' do
|
||||
let(:manager) { true }
|
||||
scenario 'the administrator from manager can not add another administrator' 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
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
require 'system/administrateurs/procedure_spec_helper'
|
||||
|
||||
describe 'Manage procedure instructeurs', js: true do
|
||||
include ProcedureSpecHelper
|
||||
|
||||
let(:administrateur) { create(:administrateur) }
|
||||
let!(:procedure) { create(:procedure) }
|
||||
let!(:administrateurs_procedure) { create(:administrateurs_procedure, administrateur: administrateur, procedure: procedure, manager: manager) }
|
||||
let(:manager) { false }
|
||||
before do
|
||||
login_as administrateur.user, scope: :user
|
||||
end
|
||||
|
||||
context 'is accessible via card' do
|
||||
let(:manager) { false }
|
||||
|
||||
scenario 'it works' do
|
||||
visit admin_procedure_path(procedure)
|
||||
find('#groupe-instructeurs').click
|
||||
expect(page).to have_css("h1", text: "Gérer les instructeurs et les options d'instruction de « #{procedure.libelle} »")
|
||||
end
|
||||
end
|
||||
|
||||
context 'as admin not from manager' do
|
||||
let(:manager) { false }
|
||||
|
||||
scenario 'can add instructeur' do
|
||||
visit admin_procedure_groupe_instructeurs_path(procedure)
|
||||
|
||||
expect {
|
||||
fill_in "instructeur_emails", with: create(:instructeur).email
|
||||
click_on "Affecter"
|
||||
}.to change { procedure.instructeurs.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'as admin from manager' do
|
||||
let(:manager) { true }
|
||||
|
||||
scenario 'cannot add instructeur' do
|
||||
visit admin_procedure_groupe_instructeurs_path(procedure)
|
||||
|
||||
expect(page).to have_css("#instructeur_emails[disabled=\"disabled\"]")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -58,18 +58,4 @@ describe 'Administrateurs can edit procedures', js: true do
|
|||
expect(page).to have_selector('.breadcrumbs li', text: 'Ma petite démarche')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'the administrator can add another administrator' do
|
||||
another_administrateur = create(:administrateur)
|
||||
visit admin_procedure_path(procedure)
|
||||
find('#administrateurs').click
|
||||
|
||||
fill_in('administrateur_email', with: another_administrateur.email)
|
||||
|
||||
click_on 'Ajouter comme administrateur'
|
||||
|
||||
within('.alert-success') do
|
||||
expect(page).to have_content(another_administrateur.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue