FEAT: init admins group
This commit is contained in:
parent
1d0054c38e
commit
e2f792b44b
49 changed files with 708 additions and 3 deletions
|
@ -0,0 +1,9 @@
|
|||
module AdminsGroupManagers
|
||||
class AdminsGroupManagerController < ApplicationController
|
||||
before_action :authenticate_admins_group_manager!
|
||||
|
||||
def nav_bar_profile
|
||||
:admins_group_manager
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
module AdminsGroupManagers
|
||||
class AdminsGroupsController < AdminsGroupManagerController
|
||||
def index
|
||||
@admins_groups = admins_groups
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admins_groups
|
||||
admins_group_ids = current_admins_group_manager.admins_group_ids
|
||||
AdminsGroup.where(id: admins_group_ids.compact.uniq)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,7 +21,8 @@ class ApplicationController < ActionController::Base
|
|||
around_action :switch_locale
|
||||
|
||||
helper_method :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur, :current_expert, :expert_signed_in?,
|
||||
:administrateur_signed_in?, :current_administrateur, :current_account, :localization_enabled?, :set_locale, :current_expert_not_instructeur?
|
||||
:administrateur_signed_in?, :current_administrateur, :current_account, :localization_enabled?, :set_locale, :current_expert_not_instructeur?,
|
||||
:admins_group_manager_signed_in?, :current_admins_group_manager
|
||||
|
||||
before_action do
|
||||
Current.request_id = request.uuid
|
||||
|
@ -37,9 +38,12 @@ class ApplicationController < ActionController::Base
|
|||
def multiple_devise_profile_connect?
|
||||
user_signed_in? && instructeur_signed_in? ||
|
||||
instructeur_signed_in? && administrateur_signed_in? ||
|
||||
instructeur_signed_in? && admins_group_manager_signed_in? ||
|
||||
instructeur_signed_in? && expert_signed_in? ||
|
||||
user_signed_in? && administrateur_signed_in? ||
|
||||
user_signed_in? && expert_signed_in?
|
||||
user_signed_in? && admins_group_manager_signed_in? ||
|
||||
user_signed_in? && expert_signed_in? ||
|
||||
administrateur_signed_in? && admins_group_manager_signed_in?
|
||||
end
|
||||
|
||||
def current_instructeur
|
||||
|
@ -58,6 +62,14 @@ class ApplicationController < ActionController::Base
|
|||
current_administrateur.present?
|
||||
end
|
||||
|
||||
def current_admins_group_manager
|
||||
current_user&.admins_group_manager
|
||||
end
|
||||
|
||||
def admins_group_manager_signed_in?
|
||||
current_admins_group_manager.present?
|
||||
end
|
||||
|
||||
def current_expert
|
||||
current_user&.expert
|
||||
end
|
||||
|
@ -72,6 +84,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def current_account
|
||||
{
|
||||
admins_group_manager: current_admins_group_manager,
|
||||
administrateur: current_administrateur,
|
||||
instructeur: current_instructeur,
|
||||
user: current_user
|
||||
|
@ -115,6 +128,8 @@ class ApplicationController < ActionController::Base
|
|||
authenticate_expert!
|
||||
elsif administrateur_signed_in?
|
||||
authenticate_administrateur!
|
||||
elsif admins_group_manager_signed_in?
|
||||
authenticate_admins_group_manager!
|
||||
else
|
||||
authenticate_user!
|
||||
end
|
||||
|
@ -144,6 +159,12 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def authenticate_admins_group_manager!
|
||||
if !admins_group_manager_signed_in?
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
def after_sign_out_path_for(_resource_or_scope)
|
||||
stored_location_for(:user) || super
|
||||
end
|
||||
|
@ -178,6 +199,7 @@ class ApplicationController < ActionController::Base
|
|||
current_user,
|
||||
current_instructeur,
|
||||
current_administrateur,
|
||||
current_admins_group_manager,
|
||||
current_super_admin
|
||||
].compact.map { |role| role.class.name }
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module Manager
|
||||
class AdminsGroupManagersController < Manager::ApplicationController
|
||||
end
|
||||
end
|
32
app/controllers/manager/admins_groups_controller.rb
Normal file
32
app/controllers/manager/admins_groups_controller.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
module Manager
|
||||
class AdminsGroupsController < Manager::ApplicationController
|
||||
def add_admins_group_manager
|
||||
emails = (params['emails'].presence || '').split(',').to_json
|
||||
emails = JSON.parse(emails).map { EmailSanitizableConcern::EmailSanitizer.sanitize(_1) }
|
||||
|
||||
admins_group_managers, invalid_emails = admins_group.add_admins_group_managers(emails:)
|
||||
|
||||
if invalid_emails.present?
|
||||
flash[:alert] = t('.wrong_address',
|
||||
count: invalid_emails.size,
|
||||
emails: invalid_emails)
|
||||
end
|
||||
|
||||
if admins_group_managers.present?
|
||||
flash[:notice] = "Les gestionnaires ont bien été affectés au groupe d'administrateurs"
|
||||
|
||||
AdminsGroupMailer
|
||||
.notify_added_admins_group_managers(admins_group, admins_group_managers, current_super_admin.email)
|
||||
.deliver_later
|
||||
end
|
||||
|
||||
redirect_to manager_admins_groups_path(admins_group)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def admins_group
|
||||
@admins_group ||= AdminsGroup.find(params[:id])
|
||||
end
|
||||
end
|
||||
end
|
54
app/dashboards/admins_group_dashboard.rb
Normal file
54
app/dashboards/admins_group_dashboard.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
require "administrate/base_dashboard"
|
||||
|
||||
class AdminsGroupDashboard < Administrate::BaseDashboard
|
||||
# ATTRIBUTE_TYPES
|
||||
# a hash that describes the type of each of the model's fields.
|
||||
#
|
||||
# Each different type represents an Administrate::Field object,
|
||||
# which determines how the attribute is displayed
|
||||
# on pages throughout the dashboard.
|
||||
ATTRIBUTE_TYPES = {
|
||||
id: Field::Number,
|
||||
name: Field::String,
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
admins_group_managers: Field::HasMany,
|
||||
administrateurs: Field::HasMany
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's index page.
|
||||
#
|
||||
# By default, it's limited to four items to reduce clutter on index pages.
|
||||
# Feel free to add, remove, or rearrange items.
|
||||
COLLECTION_ATTRIBUTES = [
|
||||
:id,
|
||||
:created_at,
|
||||
:name,
|
||||
:admins_group_managers,
|
||||
:administrateurs
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = [
|
||||
:admins_group_managers,
|
||||
:administrateurs,
|
||||
:id,
|
||||
:created_at
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = [
|
||||
:name
|
||||
].freeze
|
||||
|
||||
# Overwrite this method to customize how users are displayed
|
||||
# across all pages of the admin dashboard.
|
||||
#
|
||||
def display_resource(admins_group)
|
||||
admins_group.name
|
||||
end
|
||||
end
|
57
app/dashboards/admins_group_manager_dashboard.rb
Normal file
57
app/dashboards/admins_group_manager_dashboard.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
require "administrate/base_dashboard"
|
||||
|
||||
class AdminsGroupManagerDashboard < Administrate::BaseDashboard
|
||||
# ATTRIBUTE_TYPES
|
||||
# a hash that describes the type of each of the model's fields.
|
||||
#
|
||||
# Each different type represents an Administrate::Field object,
|
||||
# which determines how the attribute is displayed
|
||||
# on pages throughout the dashboard.
|
||||
ATTRIBUTE_TYPES = {
|
||||
id: Field::Number,
|
||||
user: Field::HasOne.with_options(searchable: true, searchable_field: 'email'),
|
||||
created_at: Field::DateTime,
|
||||
updated_at: Field::DateTime,
|
||||
admins_groups: Field::HasMany.with_options(limit: 20),
|
||||
registration_state: Field::String.with_options(searchable: false),
|
||||
email: Field::Email.with_options(searchable: false)
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's index page.
|
||||
#
|
||||
# By default, it's limited to four items to reduce clutter on index pages.
|
||||
# Feel free to add, remove, or rearrange items.
|
||||
COLLECTION_ATTRIBUTES = [
|
||||
:id,
|
||||
:user,
|
||||
:created_at,
|
||||
:admins_groups,
|
||||
:registration_state
|
||||
].freeze
|
||||
|
||||
# SHOW_PAGE_ATTRIBUTES
|
||||
# an array of attributes that will be displayed on the model's show page.
|
||||
SHOW_PAGE_ATTRIBUTES = [
|
||||
:id,
|
||||
:user,
|
||||
:created_at,
|
||||
:updated_at,
|
||||
:registration_state,
|
||||
:admins_groups
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
# an array of attributes that will be displayed
|
||||
# on the model's form (`new` and `edit`) pages.
|
||||
FORM_ATTRIBUTES = [
|
||||
:email
|
||||
].freeze
|
||||
|
||||
# Overwrite this method to customize how users are displayed
|
||||
# across all pages of the admin dashboard.
|
||||
#
|
||||
def display_resource(admins_group_manager)
|
||||
admins_group_manager.email
|
||||
end
|
||||
end
|
|
@ -47,7 +47,8 @@ module ApplicationHelper
|
|||
def current_email
|
||||
current_user&.email ||
|
||||
current_instructeur&.email ||
|
||||
current_administrateur&.email
|
||||
current_administrateur&.email ||
|
||||
current_admins_group_manager&.email
|
||||
end
|
||||
|
||||
def staging?
|
||||
|
@ -77,6 +78,8 @@ module ApplicationHelper
|
|||
case nav_bar_profile
|
||||
when :administrateur
|
||||
[admin_procedures_path, t("admin", scope: "layouts.root_path_link_title")]
|
||||
when :admins_group_manager
|
||||
[admins_group_manager_admins_groups_path, t("admins_group_manager", scope: "layouts.root_path_link_title")]
|
||||
when :instructeur
|
||||
[instructeur_procedures_path, t("instructeur", scope: "layouts.root_path_link_title")]
|
||||
when :user
|
||||
|
|
13
app/mailers/admins_group_mailer.rb
Normal file
13
app/mailers/admins_group_mailer.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
class AdminsGroupMailer < ApplicationMailer
|
||||
layout 'mailers/layout'
|
||||
|
||||
def notify_added_admins_group_managers(admins_group, added_admins_group_managers, current_super_admin_email)
|
||||
added_admins_group_manager_emails = added_admins_group_managers.map(&:email)
|
||||
@admins_group = admins_group
|
||||
@current_super_admin_email = current_super_admin_email
|
||||
|
||||
subject = "Vous avez été ajouté(e) en tant que gestionnaire du groupe d'administrateur \"#{admins_group.name}\""
|
||||
|
||||
mail(bcc: added_admins_group_manager_emails, subject: subject)
|
||||
end
|
||||
end
|
|
@ -38,6 +38,17 @@ class UserMailer < ApplicationMailer
|
|||
reply_to: CONTACT_EMAIL)
|
||||
end
|
||||
|
||||
def invite_admins_group_manager(user, reset_password_token, admins_group)
|
||||
@reset_password_token = reset_password_token
|
||||
@user = user
|
||||
@admins_group = admins_group
|
||||
subject = "Activez votre compte gestionnaire"
|
||||
|
||||
mail(to: user.email,
|
||||
subject: subject,
|
||||
reply_to: CONTACT_EMAIL)
|
||||
end
|
||||
|
||||
def send_archive(administrateur_or_instructeur, procedure, archive)
|
||||
@archive = archive
|
||||
@procedure = procedure
|
||||
|
|
|
@ -9,6 +9,7 @@ class Administrateur < ApplicationRecord
|
|||
has_and_belongs_to_many :default_zones, class_name: 'Zone', join_table: 'default_zones_administrateurs'
|
||||
|
||||
belongs_to :user
|
||||
belongs_to :admins_group, optional: true
|
||||
|
||||
default_scope { eager_load(:user) }
|
||||
|
||||
|
|
30
app/models/admins_group.rb
Normal file
30
app/models/admins_group.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
class AdminsGroup < ApplicationRecord
|
||||
belongs_to :admins_group, optional: true # parent
|
||||
has_many :children, class_name: "AdminsGroup", inverse_of: :admins_group
|
||||
has_many :administrateurs
|
||||
has_and_belongs_to_many :admins_group_managers
|
||||
|
||||
def add(admins_group_manager)
|
||||
admins_group_managers << admins_group_manager
|
||||
end
|
||||
|
||||
def add_admins_group_managers(ids: [], emails: [])
|
||||
admins_group_managers_to_add, valid_emails, invalid_emails = AdminsGroupManager.find_all_by_identifier_with_emails(ids:, emails:)
|
||||
not_found_emails = valid_emails - admins_group_managers_to_add.map(&:email)
|
||||
|
||||
# Send invitations to users without account
|
||||
if not_found_emails.present?
|
||||
admins_group_managers_to_add += not_found_emails.map do |email|
|
||||
user = User.create_or_promote_to_admins_group_manager(email, SecureRandom.hex)
|
||||
user.invite_admins_group_manager!(self)
|
||||
user.admins_group_manager
|
||||
end
|
||||
end
|
||||
|
||||
# We dont't want to assign a user to an admins_group if they are already assigned to it
|
||||
admins_group_managers_to_add -= admins_group_managers
|
||||
admins_group_managers_to_add.each { add(_1) }
|
||||
|
||||
[admins_group_managers_to_add, invalid_emails]
|
||||
end
|
||||
end
|
41
app/models/admins_group_manager.rb
Normal file
41
app/models/admins_group_manager.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
class AdminsGroupManager < ApplicationRecord
|
||||
has_and_belongs_to_many :admins_groups
|
||||
|
||||
belongs_to :user
|
||||
|
||||
delegate :email, to: :user
|
||||
|
||||
default_scope { eager_load(:user) }
|
||||
|
||||
def self.by_email(email)
|
||||
find_by(users: { email: email })
|
||||
end
|
||||
|
||||
def self.find_all_by_identifier(ids: [], emails: [])
|
||||
find_all_by_identifier_with_emails(ids:, emails:).first
|
||||
end
|
||||
|
||||
def self.find_all_by_identifier_with_emails(ids: [], emails: [])
|
||||
valid_emails, invalid_emails = emails.partition { URI::MailTo::EMAIL_REGEXP.match?(_1) }
|
||||
|
||||
[
|
||||
where(id: ids).or(where(users: { email: valid_emails })).distinct(:id),
|
||||
valid_emails,
|
||||
invalid_emails
|
||||
]
|
||||
end
|
||||
|
||||
def can_be_deleted?
|
||||
!(root_admins_group = admins_groups.where(admins_group: nil).first) || root_admins_group.admins_group_managers.size > 1
|
||||
end
|
||||
|
||||
def registration_state
|
||||
if user.active?
|
||||
'Actif'
|
||||
elsif user.reset_password_period_valid?
|
||||
'En attente'
|
||||
else
|
||||
'Expiré'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -26,6 +26,7 @@ class User < ApplicationRecord
|
|||
has_one :france_connect_information, dependent: :destroy
|
||||
has_one :instructeur, dependent: :destroy
|
||||
has_one :administrateur, dependent: :destroy
|
||||
has_one :admins_group_manager, dependent: :destroy
|
||||
has_one :expert, dependent: :destroy
|
||||
belongs_to :requested_merge_into, class_name: 'User', optional: true
|
||||
|
||||
|
@ -76,6 +77,10 @@ class User < ApplicationRecord
|
|||
UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later
|
||||
end
|
||||
|
||||
def invite_admins_group_manager!(admins_group)
|
||||
UserMailer.invite_admins_group_manager(self, set_reset_password_token, admins_group).deliver_later
|
||||
end
|
||||
|
||||
def invite_administrateur!(administration_id)
|
||||
AdministrationMailer.invite_admin(self, set_reset_password_token, administration_id).deliver_later
|
||||
end
|
||||
|
@ -103,6 +108,16 @@ class User < ApplicationRecord
|
|||
user
|
||||
end
|
||||
|
||||
def self.create_or_promote_to_admins_group_manager(email, password)
|
||||
user = User.create_or_promote_to_administrateur(email, password)
|
||||
|
||||
if user.valid? && user.admins_group_manager.nil?
|
||||
user.create_admins_group_manager!
|
||||
end
|
||||
|
||||
user
|
||||
end
|
||||
|
||||
def self.create_or_promote_to_administrateur(email, password)
|
||||
user = User.create_or_promote_to_instructeur(email, password)
|
||||
|
||||
|
@ -145,6 +160,10 @@ class User < ApplicationRecord
|
|||
instructeur.present?
|
||||
end
|
||||
|
||||
def admins_group_manager?
|
||||
admins_group_manager.present?
|
||||
end
|
||||
|
||||
def expert?
|
||||
expert.present?
|
||||
end
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
%p= t(:hello, scope: [:views, :shared, :greetings])
|
||||
|
||||
%p
|
||||
= t(".email_body", admins_group_name: @admins_group.name, email: @current_super_admin_email, application_name: APPLICATION_NAME)
|
||||
|
||||
= render partial: "layouts/mailers/signature"
|
16
app/views/admins_group_managers/_breadcrumbs.html.haml
Normal file
16
app/views/admins_group_managers/_breadcrumbs.html.haml
Normal file
|
@ -0,0 +1,16 @@
|
|||
#breadcrumbs.sub-header
|
||||
.fr-container.flex.justify-between.align-baseline.column
|
||||
%nav.fr-breadcrumb.mt-0{ role: "navigation", aria: { label: t('you_are_here', scope: [:layouts, :breadcrumb]) } }
|
||||
%button.fr-breadcrumb__button{ aria: { expanded: "false", controls: "breadcrumb-1" } }
|
||||
= t('show', scope: [:layouts, :breadcrumb])
|
||||
|
||||
.fr-collapse#breadcrumb-1
|
||||
%ol.fr-breadcrumb__list
|
||||
%li= link_to t('root', scope: [:layouts, :breadcrumb]), root_path, class: 'fr-breadcrumb__link'
|
||||
|
||||
- steps.each.with_index do |step, i|
|
||||
- if i == steps.size - 1
|
||||
%li{ aria: { current: "page" } }
|
||||
%span.fr-breadcrumb__link= step[0]
|
||||
- else
|
||||
%li= link_to step[0], step[1], class: 'fr-breadcrumb__link'
|
|
@ -0,0 +1,17 @@
|
|||
= render partial: 'admins_group_managers/breadcrumbs',
|
||||
locals: { steps: [['Groupes d\'administrateurs', admins_group_manager_admins_groups_path]] }
|
||||
|
||||
#admins_groups-index.container
|
||||
%h1.fr-h1 Liste des groupes d'administrateurs
|
||||
|
||||
%table.fr-table.width-100.mt-3
|
||||
%thead
|
||||
%tr
|
||||
%th{ scope: "col" }
|
||||
Nom
|
||||
|
||||
%tbody
|
||||
- @admins_groups.each do |admins_group|
|
||||
%tr
|
||||
%td
|
||||
= admins_group.name
|
|
@ -30,6 +30,11 @@
|
|||
= link_to admin_procedures_path, class: "fr-nav__link" do
|
||||
%span.fr-icon-refresh-line.fr-icon--sm
|
||||
= t('go_admin', scope: [:layouts])
|
||||
- if admins_group_manager_signed_in? && nav_bar_profile != :admins_group_manager
|
||||
%li
|
||||
= link_to admins_group_manager_admins_groups_path, class: "fr-nav__link" do
|
||||
%span.fr-icon-refresh-line.fr-icon--sm
|
||||
= t('go_admins_group_manager', scope: [:layouts])
|
||||
|
||||
- if super_admin_signed_in?
|
||||
%li
|
||||
|
|
57
app/views/manager/admins_groups/show.html.erb
Normal file
57
app/views/manager/admins_groups/show.html.erb
Normal file
|
@ -0,0 +1,57 @@
|
|||
<%#
|
||||
# Show
|
||||
|
||||
This view is the template for the show page.
|
||||
It renders the attributes of a resource,
|
||||
as well as a link to its edit page.
|
||||
|
||||
## Local variables:
|
||||
|
||||
- `page`:
|
||||
An instance of [Administrate::Page::Show][1].
|
||||
Contains methods for accessing the resource to be displayed on the page,
|
||||
as well as helpers for describing how each attribute of the resource
|
||||
should be displayed.
|
||||
|
||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Show
|
||||
%>
|
||||
<% content_for(:title) { t("administrate.actions.show_resource", name: page.page_title) } %>
|
||||
<% admins_group = page.resource %>
|
||||
|
||||
<header class="main-content__header" role="banner">
|
||||
<h1 class="main-content__page-title">
|
||||
<%= content_for(:title) %>
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
<%= link_to(
|
||||
t("administrate.actions.edit_resource", name: page.page_title),
|
||||
[:edit, namespace, page.resource],
|
||||
class: "button",
|
||||
) if valid_action? :edit %>
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
<section class="main-content__body">
|
||||
<dl>
|
||||
<% page.attributes.each do |attribute| %>
|
||||
<dt class="attribute-label" id="<%= attribute.name %>">
|
||||
<%= t(
|
||||
"helpers.label.#{resource_name}.#{attribute.name}",
|
||||
default: attribute.name.titleize,
|
||||
) %>
|
||||
</dt>
|
||||
|
||||
<dd class="attribute-data attribute-data--<%=attribute.html_class%>">
|
||||
<%= render_field attribute, page: page %>
|
||||
<% if attribute.name == 'admins_group_managers' %>
|
||||
<%= form_tag(add_admins_group_manager_manager_admins_group_path(admins_group), style: 'margin-top: 1rem;') do %>
|
||||
<%= email_field_tag(:emails, '', placeholder: 'Emails', autocapitalize: 'off', autocorrect: 'off', spellcheck: 'false', style: 'margin-bottom: 1rem;width:24rem;') %>
|
||||
<button>Ajouter un gestionnaire</button>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</dd>
|
||||
<% end %>
|
||||
</dl>
|
||||
</section>
|
13
app/views/user_mailer/invite_admins_group_manager.html.haml
Normal file
13
app/views/user_mailer/invite_admins_group_manager.html.haml
Normal file
|
@ -0,0 +1,13 @@
|
|||
- content_for(:title, 'Activation de votre compte gestionnaire')
|
||||
|
||||
%p
|
||||
Bonjour,
|
||||
|
||||
%p
|
||||
Vous venez d’être nommé gestionnaire du groupe #{@admins_group.name} sur #{APPLICATION_NAME}.
|
||||
|
||||
%p
|
||||
Votre compte a été créé pour l'adresse email #{@user.email}. Pour l’activer, nous vous invitons à cliquer sur le lien suivant :
|
||||
= link_to(users_activate_url(token: @reset_password_token), users_activate_url(token: @reset_password_token))
|
||||
|
||||
= render partial: "layouts/mailers/signature"
|
|
@ -155,3 +155,6 @@ CLAMAV_ENABLED="disabled"
|
|||
|
||||
# Siret number used for API Entreprise, by default we use SIRET from dinum
|
||||
API_ENTREPRISE_DEFAULT_SIRET="put_your_own_siret"
|
||||
|
||||
# Admins group usage (gestionnaire de groupes d'administrateurs)
|
||||
ADMINS_GROUP_ENABLED="disabled"
|
|
@ -101,6 +101,7 @@ en:
|
|||
user: 'Go to files list'
|
||||
instructeur: 'Go to procedures list'
|
||||
admin: 'Go to administration panel'
|
||||
admins_group_manager: "Aller admins group panel"
|
||||
views:
|
||||
legal_notice:
|
||||
title: "Legal Notices"
|
||||
|
|
|
@ -92,6 +92,7 @@ fr:
|
|||
user: 'Aller à la liste des dossiers'
|
||||
instructeur: 'Aller à la liste des démarches'
|
||||
admin: "Aller au panneau d’administration"
|
||||
admins_group_manager: "Aller au panneau de gestionnaire"
|
||||
views:
|
||||
legal_notice:
|
||||
title: "Mentions légales"
|
||||
|
|
9
config/locales/models/admins_group/fr.yml
Normal file
9
config/locales/models/admins_group/fr.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
fr:
|
||||
activerecord:
|
||||
attributes:
|
||||
admins_group:
|
||||
admins_group_managers: Gestionnaires
|
||||
models:
|
||||
admins_group:
|
||||
one: Groupe d'administrateurs
|
||||
other: Groupes d'administrateurs
|
9
config/locales/models/admins_group_manager/fr.yml
Normal file
9
config/locales/models/admins_group_manager/fr.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
fr:
|
||||
activerecord:
|
||||
attributes:
|
||||
admins_group_manager:
|
||||
admins_groups: Groupes
|
||||
models:
|
||||
admins_group_manager:
|
||||
one: Gestionnaire
|
||||
other: Gestionnaires
|
|
@ -0,0 +1,4 @@
|
|||
en:
|
||||
admins_group_mailer:
|
||||
notify_added_admins_group_managers:
|
||||
email_body: "You were assigned as manager on the admins group %{admins_group_name} on %{application_name} by « %{email} »"
|
|
@ -0,0 +1,4 @@
|
|||
fr:
|
||||
admins_group_mailer:
|
||||
notify_added_admins_group_managers:
|
||||
email_body: "Vous venez d’être nommé gestionnaire du groupe %{admins_group_name} sur %{application_name} par « %{email} »."
|
|
@ -8,12 +8,14 @@ en:
|
|||
go_instructor: "Switch to instructor"
|
||||
go_expert: "Switch to expert"
|
||||
go_admin: "Switch to administrator"
|
||||
go_admins_group_manager: "Switch to admins group manager"
|
||||
profile: "See my profile"
|
||||
logout: "Log out"
|
||||
my_account: "My account"
|
||||
connected_as: "connected as %{profile}"
|
||||
instructeur: instructor
|
||||
administrateur: admin
|
||||
admins_group_manager: admins group manager
|
||||
expert: expert
|
||||
user: user
|
||||
guest: guest
|
||||
|
|
|
@ -8,12 +8,14 @@ fr:
|
|||
go_instructor: "Passer en instructeur"
|
||||
go_expert: "Passer en expert"
|
||||
go_admin: "Passer en administrateur"
|
||||
go_admins_group_manager: "Passer en gestionnaire"
|
||||
profile: "Voir mon profil"
|
||||
logout: "Se déconnecter"
|
||||
my_account: "Mon compte"
|
||||
connected_as: "connecté en tant qu’%{profile}"
|
||||
instructeur: instructeur
|
||||
administrateur: administrateur
|
||||
admins_group_manager: gestionnaire
|
||||
expert: expert
|
||||
user: usager
|
||||
guest: invité
|
||||
|
|
7
config/locales/views/manager/fr.yml
Normal file
7
config/locales/views/manager/fr.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
fr:
|
||||
manager:
|
||||
admins_groups:
|
||||
add_admins_group_manager:
|
||||
wrong_address:
|
||||
one: "%{emails} n’est pas une adresse email valide"
|
||||
other: "%{emails} ne sont pas des adresses emails valides"
|
|
@ -56,6 +56,14 @@ Rails.application.routes.draw do
|
|||
delete 'delete', on: :member
|
||||
end
|
||||
|
||||
if ENV.fetch('ADMINS_GROUP_ENABLED') == 'enabled'
|
||||
resources :admins_group_managers, path: 'gestionnaires', only: [:index, :show, :edit, :update]
|
||||
|
||||
resources :admins_groups, path: 'groupe_administrateurs', only: [:index, :show, :new, :create, :edit, :update] do
|
||||
post 'add_admins_group_manager', on: :member
|
||||
end
|
||||
end
|
||||
|
||||
resources :dossiers, only: [:show]
|
||||
|
||||
resources :bill_signatures, only: [:index]
|
||||
|
@ -465,6 +473,17 @@ Rails.application.routes.draw do
|
|||
end
|
||||
end
|
||||
|
||||
if ENV.fetch('ADMINS_GROUP_ENABLED') == 'enabled'
|
||||
|
||||
#
|
||||
# Admins Group Manager (gestionnaire)
|
||||
#
|
||||
|
||||
scope module: 'admins_group_managers', path: 'gestionnaire', as: 'admins_group_manager' do
|
||||
resources :admins_groups, path: 'groupe_administrateurs', only: [:index, :create]
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Administrateur
|
||||
#
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class CreateAdminsGroupManagers < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table "admins_group_managers" do |t|
|
||||
t.bigint :user_id, null: false
|
||||
t.index [:user_id], name: :index_admins_group_managers_on_user_id
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
15
db/migrate/20230813091838_create_admins_groups.rb
Normal file
15
db/migrate/20230813091838_create_admins_groups.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class CreateAdminsGroups < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
create_table "admins_groups" do |t|
|
||||
t.string :name, null: false
|
||||
t.references :admins_group
|
||||
t.index [:name], name: :index_admins_groups_on_name
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_join_table :admins_groups, :admins_group_managers do |t|
|
||||
t.index [:admins_group_id, :admins_group_manager_id], name: :index_on_admins_group_and_admins_group_manager
|
||||
t.index [:admins_group_manager_id, :admins_group_id], name: :index_on_admins_group_manager_and_admins_group
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
class AddAdminsGroupToAdministrateurs < ActiveRecord::Migration[7.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def change
|
||||
add_reference :administrateurs, :admins_group, index: { algorithm: :concurrently }, null: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddForeignKeyAdminsGroupToAdministrateurs < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
add_foreign_key :administrateurs, :admins_groups, validate: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ValidateForeignKeyAdminsGroupToAdministrateurs < ActiveRecord::Migration[7.0]
|
||||
def change
|
||||
validate_foreign_key :administrateurs, :admins_groups
|
||||
end
|
||||
end
|
26
db/schema.rb
26
db/schema.rb
|
@ -61,9 +61,11 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_28_083809) do
|
|||
end
|
||||
|
||||
create_table "administrateurs", id: :serial, force: :cascade do |t|
|
||||
t.bigint "admins_group_id"
|
||||
t.datetime "created_at", precision: 6
|
||||
t.datetime "updated_at", precision: 6
|
||||
t.bigint "user_id", null: false
|
||||
t.index ["admins_group_id"], name: "index_administrateurs_on_admins_group_id"
|
||||
t.index ["user_id"], name: "index_administrateurs_on_user_id"
|
||||
end
|
||||
|
||||
|
@ -88,6 +90,29 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_28_083809) do
|
|||
t.index ["procedure_id"], name: "index_administrateurs_procedures_on_procedure_id"
|
||||
end
|
||||
|
||||
create_table "admins_group_managers", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.bigint "user_id", null: false
|
||||
t.index ["user_id"], name: "index_admins_group_managers_on_user_id"
|
||||
end
|
||||
|
||||
create_table "admins_group_managers_groups", id: false, force: :cascade do |t|
|
||||
t.bigint "admins_group_id", null: false
|
||||
t.bigint "admins_group_manager_id", null: false
|
||||
t.index ["admins_group_id", "admins_group_manager_id"], name: "index_on_admins_group_and_admins_group_manager"
|
||||
t.index ["admins_group_manager_id", "admins_group_id"], name: "index_on_admins_group_manager_and_admins_group"
|
||||
end
|
||||
|
||||
create_table "admins_groups", force: :cascade do |t|
|
||||
t.bigint "admins_group_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "name", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["admins_group_id"], name: "index_admins_groups_on_admins_group_id"
|
||||
t.index ["name"], name: "index_admins_groups_on_name"
|
||||
end
|
||||
|
||||
create_table "api_tokens", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.bigint "administrateur_id", null: false
|
||||
t.bigint "allowed_procedure_ids", array: true
|
||||
|
@ -1034,6 +1059,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_28_083809) do
|
|||
|
||||
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
|
||||
add_foreign_key "administrateurs", "admins_groups"
|
||||
add_foreign_key "administrateurs", "users"
|
||||
add_foreign_key "administrateurs_instructeurs", "administrateurs"
|
||||
add_foreign_key "administrateurs_instructeurs", "instructeurs"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
describe AdminsGroupManagers::AdminsGroupManagerController, type: :controller do
|
||||
describe 'before actions: authenticate_admins_group_manager!' do
|
||||
it 'is present' do
|
||||
before_actions = AdminsGroupManagers::AdminsGroupManagerController
|
||||
._process_action_callbacks
|
||||
.filter { |process_action_callbacks| process_action_callbacks.kind == :before }
|
||||
.map(&:filter)
|
||||
|
||||
expect(before_actions).to include(:authenticate_admins_group_manager!)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
describe AdminsGroupManagers::AdminsGroupsController, type: :controller do
|
||||
let(:admins_group_manager) { create(:admins_group_manager) }
|
||||
|
||||
describe "#index" do
|
||||
subject { get :index }
|
||||
|
||||
context "when not logged" do
|
||||
before { subject }
|
||||
it { expect(response).to redirect_to(new_user_session_path) }
|
||||
end
|
||||
|
||||
context "when logged in" do
|
||||
let!(:admins_group) { create(:admins_group, admins_group_managers: [admins_group_manager]) }
|
||||
before do
|
||||
sign_in(admins_group_manager.user)
|
||||
subject
|
||||
end
|
||||
|
||||
it { expect(response).to have_http_status(:ok) }
|
||||
it { expect(assigns(:admins_groups)).to include(admins_group) }
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
describe Manager::AdminsGroupManagersController, type: :controller do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
let(:admins_group_manager) { create(:admins_group_manager) }
|
||||
|
||||
before { sign_in super_admin }
|
||||
|
||||
describe '#index' do
|
||||
render_views
|
||||
|
||||
it 'searches admin by email' do
|
||||
get :index, params: { search: admins_group_manager.email }
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#show' do
|
||||
render_views
|
||||
|
||||
before do
|
||||
get :show, params: { id: admins_group_manager.id }
|
||||
end
|
||||
|
||||
it { expect(response.body).to include(admins_group_manager.email) }
|
||||
end
|
||||
end
|
27
spec/controllers/manager/admins_groups_controller_spec.rb
Normal file
27
spec/controllers/manager/admins_groups_controller_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
describe Manager::AdminsGroupsController, type: :controller do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
let(:admins_group) { create(:admins_group) }
|
||||
|
||||
before { sign_in super_admin }
|
||||
|
||||
describe '#index' do
|
||||
render_views
|
||||
|
||||
before do
|
||||
admins_group
|
||||
get :index
|
||||
end
|
||||
|
||||
it { expect(response.body).to include(admins_group.name) }
|
||||
end
|
||||
|
||||
describe '#show' do
|
||||
render_views
|
||||
|
||||
before do
|
||||
get :show, params: { id: admins_group.id }
|
||||
end
|
||||
|
||||
it { expect(response.body).to include(admins_group.name) }
|
||||
end
|
||||
end
|
5
spec/factories/admins_group.rb
Normal file
5
spec/factories/admins_group.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
FactoryBot.define do
|
||||
factory :admins_group do
|
||||
sequence(:name) { |n| "Group #{n}" }
|
||||
end
|
||||
end
|
12
spec/factories/admins_group_manager.rb
Normal file
12
spec/factories/admins_group_manager.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
FactoryBot.define do
|
||||
sequence(:admins_group_manager_email) { |n| "admins_group_manager#{n}@demarches-simplifiees.fr" }
|
||||
|
||||
factory :admins_group_manager do
|
||||
user { association :user, email: email, password: password }
|
||||
|
||||
transient do
|
||||
email { generate(:admins_group_manager_email) }
|
||||
password { 'somethingverycomplated!' }
|
||||
end
|
||||
end
|
||||
end
|
16
spec/mailers/admins_group_mailer_spec.rb
Normal file
16
spec/mailers/admins_group_mailer_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
RSpec.describe AdminsGroupMailer, type: :mailer do
|
||||
describe '#notify_added_admins_group_managers' do
|
||||
let(:admins_group) { create(:admins_group) }
|
||||
|
||||
let(:admins_group_managers_to_add) { [create(:admins_group_manager, email: 'int3@g'), create(:admins_group_manager, email: 'int4@g')] }
|
||||
|
||||
let(:current_super_admin_email) { 'toto@email.com' }
|
||||
|
||||
subject { described_class.notify_added_admins_group_managers(admins_group, admins_group_managers_to_add, current_super_admin_email) }
|
||||
|
||||
before { admins_group_managers_to_add.each { admins_group.add(_1) } }
|
||||
|
||||
it { expect(subject.body).to include('Vous venez d’être nommé gestionnaire du groupe') }
|
||||
it { expect(subject.bcc).to match_array(['int3@g', 'int4@g']) }
|
||||
end
|
||||
end
|
14
spec/mailers/previews/admins_group_mailer_preview.rb
Normal file
14
spec/mailers/previews/admins_group_mailer_preview.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
class AdminsGroupMailerPreview < ActionMailer::Preview
|
||||
def notify_added_admins_group_managers
|
||||
admins_group = AdminsGroup.new(name: 'un groupe d\'admin')
|
||||
current_super_admin_email = 'admin@dgfip.com'
|
||||
admins_group_managers = [AdminsGroupManager.new(user: user)]
|
||||
AdminsGroupMailer.notify_added_admins_group_managers(admins_group, admins_group_managers, current_super_admin_email)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user
|
||||
User.new(id: 10, email: 'test@exemple.fr')
|
||||
end
|
||||
end
|
|
@ -24,6 +24,11 @@ class UserMailerPreview < ActionMailer::Preview
|
|||
UserMailer.invite_instructeur(user, 'aedfa0d0')
|
||||
end
|
||||
|
||||
def invite_admins_group_manager
|
||||
admins_group = AdminsGroup.new(name: 'Root admins group')
|
||||
UserMailer.invite_admins_group_manager(user, 'aedfa0d0', admins_group)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user
|
||||
|
|
|
@ -3,6 +3,7 @@ describe Administrateur, type: :model do
|
|||
|
||||
describe 'associations' do
|
||||
it { is_expected.to have_and_belong_to_many(:instructeurs) }
|
||||
it { is_expected.to belong_to(:admins_group).optional }
|
||||
end
|
||||
|
||||
describe "#can_be_deleted?" do
|
||||
|
|
5
spec/models/admins_group_manager_spec.rb
Normal file
5
spec/models/admins_group_manager_spec.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
describe AdminsGroupManager, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to have_and_belong_to_many(:admins_groups) }
|
||||
end
|
||||
end
|
8
spec/models/admins_group_spec.rb
Normal file
8
spec/models/admins_group_spec.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
describe AdminsGroup, type: :model do
|
||||
describe 'associations' do
|
||||
it { is_expected.to belong_to(:admins_group).optional }
|
||||
it { is_expected.to have_many(:children) }
|
||||
it { is_expected.to have_many(:administrateurs) }
|
||||
it { is_expected.to have_and_belong_to_many(:admins_group_managers) }
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue