Merge pull request #4188 from betagouv/dev

2019-08-12-01
This commit is contained in:
LeSim 2019-08-12 15:26:20 +02:00 committed by GitHub
commit 796d5b8cd6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
242 changed files with 2006 additions and 1752 deletions

View file

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -312,8 +312,8 @@
} }
.explication { .explication {
margin-bottom: 2 * $default-padding; margin-bottom: $default-padding;
padding: $default-padding; padding: $default-padding / 2;
background-color: $light-grey; background-color: $light-grey;
p:not(:last-child) { p:not(:last-child) {

View file

@ -2,33 +2,39 @@
@import "constants"; @import "constants";
$strength-bg: #EEEEEE; $strength-bg: #EEEEEE;
$weak-strength-color: $lighter-red; $strength-color-0: $lighter-red;
$medium-strength-color: $orange; $strength-color-1: #FF5000;
$strong-strength-color: $green; $strength-color-2: $orange;
$strength-color-3: #FFD000;
$strength-color-4: $green;
.password-strength { .password-strength {
margin-top: -24px; margin-top: -24px;
width: 100%; width: 100%;
min-height: 22px; height: 12px;
background: $strength-bg; background: $strength-bg;
display: block; display: block;
margin-bottom: $default-spacer; margin-bottom: $default-spacer;
text-align: center; text-align: center;
border-radius: 8px;
&.strength-0 {
background: linear-gradient(to right, $strength-color-0 00%, $strength-bg 20%);
}
&.strength-1 { &.strength-1 {
background: linear-gradient(to right, $weak-strength-color 0%, $weak-strength-color 25%, $strength-bg 25%, $strength-bg 100%); background: linear-gradient(to right, $strength-color-1 20%, $strength-bg 40%);
} }
&.strength-2 { &.strength-2 {
background: linear-gradient(to right, $medium-strength-color 0%, $medium-strength-color 50%, $strength-bg 50%, $strength-bg 100%); background: linear-gradient(to right, $strength-color-2 40%, $strength-bg 60%);
} }
&.strength-3 { &.strength-3 {
background: linear-gradient(to right, $medium-strength-color 0%, $medium-strength-color 75%, $strength-bg 75%, $strength-bg 100%); background: linear-gradient(to right, $strength-color-3 60%, $strength-bg 80%);
} }
&.strength-4 { &.strength-4 {
background: $strong-strength-color; background: $strength-color-4;
color: #FFFFFF;
} }
} }

View file

@ -0,0 +1,54 @@
class Admin::AssignsController < AdminController
include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper
before_action :retrieve_procedure
ASSIGN = 'assign'
NOT_ASSIGN = 'not_assign'
def show
assign_scope = @procedure.instructeurs
@instructeurs_assign = smart_listing_create :instructeurs_assign,
assign_scope,
partial: "admin/assigns/list_assign",
array: true
not_assign_scope = current_administrateur.instructeurs.where.not(id: assign_scope.ids)
if params[:filter]
not_assign_scope = not_assign_scope.where("email LIKE ?", "%#{params[:filter]}%")
end
@instructeurs_not_assign = smart_listing_create :instructeurs_not_assign,
not_assign_scope,
partial: "admin/assigns/list_not_assign",
array: true
@instructeur ||= Instructeur.new
end
def update
instructeur = Instructeur.find(params[:instructeur_id])
procedure = Procedure.find(params[:procedure_id])
to = params[:to]
case to
when ASSIGN
if instructeur.assign_to_procedure(procedure)
flash.notice = "L'instructeur a bien été affecté"
else
flash.alert = "L'instructeur a déjà été affecté"
end
when NOT_ASSIGN
if instructeur.remove_from_procedure(procedure)
flash.notice = "L'instructeur a bien été désaffecté"
else
flash.alert = "L'instructeur a déjà été désaffecté"
end
end
redirect_to admin_procedure_assigns_path, procedure_id: params[:procedure_id]
end
end

View file

@ -1,72 +0,0 @@
class Admin::GestionnairesController < AdminController
include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper
def index
@gestionnaires = smart_listing_create :gestionnaires,
current_administrateur.gestionnaires,
partial: "admin/gestionnaires/list",
array: true
@gestionnaire ||= Gestionnaire.new
end
def create
email = params[:gestionnaire][:email].downcase
@gestionnaire = Gestionnaire.find_by(email: email)
procedure_id = params[:procedure_id]
if @gestionnaire.nil?
invite_gestionnaire(params[:gestionnaire][:email])
else
assign_gestionnaire!
end
if procedure_id.present?
redirect_to admin_procedure_instructeurs_path(procedure_id: procedure_id)
else
redirect_to admin_gestionnaires_path
end
end
def destroy
Gestionnaire.find(params[:id]).administrateurs.delete current_administrateur
redirect_to admin_gestionnaires_path
end
private
def invite_gestionnaire(email)
password = SecureRandom.hex
@gestionnaire = Gestionnaire.create(
email: email,
password: password,
password_confirmation: password,
administrateurs: [current_administrateur]
)
if @gestionnaire.errors.messages.empty?
@gestionnaire.invite!
if User.exists?(email: @gestionnaire.email)
GestionnaireMailer.user_to_gestionnaire(@gestionnaire.email).deliver_later
else
User.create(email: email, password: password, confirmed_at: Time.zone.now)
end
flash.notice = 'Instructeur ajouté'
else
flash.alert = @gestionnaire.errors.full_messages
end
end
def assign_gestionnaire!
if current_administrateur.gestionnaires.include?(@gestionnaire)
flash.alert = 'Instructeur déjà ajouté'
else
@gestionnaire.administrateurs.push current_administrateur
flash.notice = 'Instructeur ajouté'
# TODO Mailer no assign_to
end
end
end

View file

@ -2,53 +2,71 @@ class Admin::InstructeursController < AdminController
include SmartListing::Helper::ControllerExtensions include SmartListing::Helper::ControllerExtensions
helper SmartListing::Helper helper SmartListing::Helper
before_action :retrieve_procedure def index
@instructeurs = smart_listing_create :instructeurs,
ASSIGN = 'assign' current_administrateur.instructeurs,
NOT_ASSIGN = 'not_assign' partial: "admin/instructeurs/list",
def show
assign_scope = @procedure.gestionnaires
@instructeurs_assign = smart_listing_create :instructeurs_assign,
assign_scope,
partial: "admin/instructeurs/list_assign",
array: true array: true
not_assign_scope = current_administrateur.gestionnaires.where.not(id: assign_scope.ids) @instructeur ||= Instructeur.new
if params[:filter]
not_assign_scope = not_assign_scope.where("email LIKE ?", "%#{params[:filter]}%")
end
@instructeurs_not_assign = smart_listing_create :instructeurs_not_assign,
not_assign_scope,
partial: "admin/instructeurs/list_not_assign",
array: true
@gestionnaire ||= Gestionnaire.new
end end
def update def create
gestionnaire = Gestionnaire.find(params[:instructeur_id]) email = params[:instructeur][:email].downcase
procedure = Procedure.find(params[:procedure_id]) @instructeur = Instructeur.find_by(email: email)
to = params[:to] procedure_id = params[:procedure_id]
case to if @instructeur.nil?
when ASSIGN invite_instructeur(params[:instructeur][:email])
if gestionnaire.assign_to_procedure(procedure) else
flash.notice = "L'instructeur a bien été affecté" assign_instructeur!
else
flash.alert = "L'instructeur a déjà été affecté"
end
when NOT_ASSIGN
if gestionnaire.remove_from_procedure(procedure)
flash.notice = "L'instructeur a bien été désaffecté"
else
flash.alert = "L'instructeur a déjà été désaffecté"
end
end end
redirect_to admin_procedure_instructeurs_path, procedure_id: params[:procedure_id] if procedure_id.present?
redirect_to admin_procedure_assigns_path(procedure_id: procedure_id)
else
redirect_to admin_instructeurs_path
end
end
def destroy
Instructeur.find(params[:id]).administrateurs.delete current_administrateur
redirect_to admin_instructeurs_path
end
private
def invite_instructeur(email)
password = SecureRandom.hex
@instructeur = Instructeur.create(
email: email,
password: password,
password_confirmation: password,
administrateurs: [current_administrateur]
)
if @instructeur.errors.messages.empty?
@instructeur.invite!
if User.exists?(email: @instructeur.email)
InstructeurMailer.user_to_instructeur(@instructeur.email).deliver_later
else
User.create(email: email, password: password, confirmed_at: Time.zone.now)
end
flash.notice = 'Instructeur ajouté'
else
flash.alert = @instructeur.errors.full_messages
end
end
def assign_instructeur!
if current_administrateur.instructeurs.include?(@instructeur)
flash.alert = 'Instructeur déjà ajouté'
else
@instructeur.administrateurs.push current_administrateur
flash.notice = 'Instructeur ajouté'
# TODO Mailer no assign_to
end
end end
end end

View file

@ -76,9 +76,9 @@ class Admin::ProceduresController < AdminController
render 'new' render 'new'
else else
flash.notice = 'Démarche enregistrée.' flash.notice = 'Démarche enregistrée.'
gestionnaire = Gestionnaire.find_by(email: current_administrateur.email) instructeur = Instructeur.find_by(email: current_administrateur.email)
if gestionnaire if instructeur
gestionnaire.assign_to_procedure(@procedure) instructeur.assign_to_procedure(@procedure)
end end
redirect_to champs_procedure_path(@procedure) redirect_to champs_procedure_path(@procedure)

View file

@ -1,10 +1,9 @@
require 'zxcvbn'
class Administrateurs::ActivateController < ApplicationController class Administrateurs::ActivateController < ApplicationController
include TrustedDeviceConcern include TrustedDeviceConcern
def new def new
@administrateur = Administrateur.find_inactive_by_token(params[:token]) @token = params[:token]
@administrateur = Administrateur.find_inactive_by_token(@token)
if @administrateur if @administrateur
# the administrateur activates its account from an email # the administrateur activates its account from an email
@ -25,7 +24,7 @@ class Administrateurs::ActivateController < ApplicationController
if administrateur && administrateur.errors.empty? if administrateur && administrateur.errors.empty?
sign_in(administrateur, scope: :administrateur) sign_in(administrateur, scope: :administrateur)
try_to_authenticate(User, administrateur.email, password) try_to_authenticate(User, administrateur.email, password)
try_to_authenticate(Gestionnaire, administrateur.email, password) try_to_authenticate(Instructeur, administrateur.email, password)
flash.notice = "Mot de passe enregistré" flash.notice = "Mot de passe enregistré"
redirect_to admin_procedures_path redirect_to admin_procedures_path
else else
@ -34,10 +33,6 @@ class Administrateurs::ActivateController < ApplicationController
end end
end end
def test_password_strength
@score = Zxcvbn.test(params[:administrateur][:password], [], ZXCVBN_DICTIONNARIES).score
end
private private
def update_administrateur_params def update_administrateur_params

View file

@ -0,0 +1,69 @@
class Administrateurs::PasswordsController < Devise::PasswordsController
after_action :try_to_authenticate_user, only: [:update]
after_action :try_to_authenticate_instructeur, only: [:update]
# GET /resource/password/new
# def new
# super
# end
# POST /resource/password
# def create
# super
# end
# GET /resource/password/edit?reset_password_token=abcdef
# def edit
# super
# end
# PUT /resource/password
# def update
# # params[:user][:password_confirmation] = params[:user][:password]
# super
# end
# protected
# def after_resetting_password_path_for(resource)
# super(resource)
# end
# The path used after sending reset password instructions
# def after_sending_reset_password_instructions_path_for(resource_name)
# super(resource_name)
# end
def try_to_authenticate_user
if administrateur_signed_in?
user = User.find_by(email: current_administrateur.email)
if user
sign_in user
end
end
end
def try_to_authenticate_instructeur
if administrateur_signed_in?
instructeur = Instructeur.find_by(email: current_administrateur.email)
if instructeur
sign_in instructeur
end
end
end
def test_strength
@score, @words, @length = ZxcvbnService.new(password_params[:password]).complexity
@min_length = PASSWORD_MIN_LENGTH
@min_complexity = PASSWORD_COMPLEXITY_FOR_ADMIN
render 'shared/password/test_strength'
end
private
def password_params
params.require(:administrateur).permit(:reset_password_token, :password)
end
end

View file

@ -47,7 +47,7 @@ class ApplicationController < ActionController::Base
def pundit_user def pundit_user
{ {
administrateur: current_administrateur, administrateur: current_administrateur,
gestionnaire: current_gestionnaire, instructeur: current_instructeur,
user: current_user user: current_user
}.compact }.compact
end end
@ -55,8 +55,8 @@ class ApplicationController < ActionController::Base
protected protected
def authenticate_logged_user! def authenticate_logged_user!
if gestionnaire_signed_in? if instructeur_signed_in?
authenticate_gestionnaire! authenticate_instructeur!
elsif administrateur_signed_in? elsif administrateur_signed_in?
authenticate_administrateur! authenticate_administrateur!
else else
@ -64,8 +64,8 @@ class ApplicationController < ActionController::Base
end end
end end
def authenticate_gestionnaire! def authenticate_instructeur!
if gestionnaire_signed_in? if instructeur_signed_in?
super super
else else
redirect_to new_user_session_path redirect_to new_user_session_path
@ -88,7 +88,7 @@ class ApplicationController < ActionController::Base
def set_current_roles def set_current_roles
Current.administrateur = current_administrateur Current.administrateur = current_administrateur
Current.gestionnaire = current_gestionnaire Current.instructeur = current_instructeur
end end
def set_active_storage_host def set_active_storage_host
@ -108,7 +108,7 @@ class ApplicationController < ActionController::Base
def logged_users def logged_users
@logged_users ||= [ @logged_users ||= [
current_user, current_user,
current_gestionnaire, current_instructeur,
current_administrateur, current_administrateur,
current_administration current_administration
].compact ].compact
@ -162,14 +162,14 @@ class ApplicationController < ActionController::Base
elsif api_request elsif api_request
render json: { error: MAINTENANCE_MESSAGE }.to_json, status: :service_unavailable render json: { error: MAINTENANCE_MESSAGE }.to_json, status: :service_unavailable
else else
[:user, :gestionnaire, :administrateur].each { |role| sign_out(role) } [:user, :instructeur, :administrateur].each { |role| sign_out(role) }
flash[:alert] = MAINTENANCE_MESSAGE flash[:alert] = MAINTENANCE_MESSAGE
redirect_to root_path redirect_to root_path
end end
end end
def redirect_if_untrusted def redirect_if_untrusted
if gestionnaire_signed_in? && if instructeur_signed_in? &&
sensitive_path && sensitive_path &&
Flipflop.enable_email_login_token? && Flipflop.enable_email_login_token? &&
!IPService.ip_trusted?(request.headers['X-Forwarded-For']) && !IPService.ip_trusted?(request.headers['X-Forwarded-For']) &&
@ -179,8 +179,8 @@ class ApplicationController < ActionController::Base
# after the device is trusted # after the device is trusted
store_location_for(:user, request.fullpath) store_location_for(:user, request.fullpath)
send_login_token_or_bufferize(current_gestionnaire) send_login_token_or_bufferize(current_instructeur)
redirect_to link_sent_path(email: current_gestionnaire.email) redirect_to link_sent_path(email: current_instructeur.email)
end end
end end
@ -238,7 +238,7 @@ class ApplicationController < ActionController::Base
DS_CREATED_AT: current_administrateur&.created_at, DS_CREATED_AT: current_administrateur&.created_at,
DS_ACTIVE: current_administrateur&.active, DS_ACTIVE: current_administrateur&.active,
DS_ID: current_administrateur&.id, DS_ID: current_administrateur&.id,
DS_GESTIONNAIRE_ID: current_gestionnaire&.id, DS_GESTIONNAIRE_ID: current_instructeur&.id,
DS_ROLES: logged_user_roles DS_ROLES: logged_user_roles
} }
} }
@ -266,7 +266,7 @@ class ApplicationController < ActionController::Base
def current_email def current_email
current_user&.email || current_user&.email ||
current_gestionnaire&.email || current_instructeur&.email ||
current_administrateur&.email current_administrateur&.email
end end
end end

View file

@ -17,7 +17,7 @@ module CreateAvisConcern
{ {
email: email, email: email,
introduction: create_avis_params[:introduction], introduction: create_avis_params[:introduction],
claimant: current_gestionnaire, claimant: current_instructeur,
dossier: dossier, dossier: dossier,
confidentiel: confidentiel confidentiel: confidentiel
} }

View file

@ -40,8 +40,8 @@ class FranceConnect::ParticulierController < ApplicationController
sign_out :user sign_out :user
end end
if gestionnaire_signed_in? if instructeur_signed_in?
sign_out :gestionnaire sign_out :instructeur
end end
if administrateur_signed_in? if administrateur_signed_in?

View file

@ -1,50 +0,0 @@
class Gestionnaires::ActivateController < ApplicationController
include TrustedDeviceConcern
def new
@gestionnaire = Gestionnaire.with_reset_password_token(params[:token])
if @gestionnaire
# the gestionnaire activates its account from an email
trust_device(Time.zone.now)
else
flash.alert = "Le lien de validation du compte instructeur a expiré, #{helpers.contact_link('contactez-nous', tags: 'lien expiré')} pour obtenir un nouveau lien."
redirect_to root_path
end
end
def create
password = create_gestionnaire_params[:password]
gestionnaire = Gestionnaire.reset_password_by_token({
password: password,
password_confirmation: password,
reset_password_token: create_gestionnaire_params[:reset_password_token]
})
if gestionnaire && gestionnaire.errors.empty?
sign_in(gestionnaire, scope: :gestionnaire)
try_to_authenticate(User, gestionnaire.email, password)
try_to_authenticate(Administrateur, gestionnaire.email, password)
flash.notice = "Mot de passe enregistré"
redirect_to gestionnaire_procedures_path
else
flash.alert = gestionnaire.errors.full_messages
redirect_to gestionnaire_activate_path(token: create_gestionnaire_params[:reset_password_token])
end
end
private
def create_gestionnaire_params
params.require(:gestionnaire).permit(:reset_password_token, :password)
end
def try_to_authenticate(klass, email, password)
resource = klass.find_for_database_authentication(email: email)
if resource&.valid_password?(password)
sign_in resource
resource.force_sync_credentials
end
end
end

View file

@ -1,9 +0,0 @@
module Gestionnaires
class GestionnaireController < ApplicationController
before_action :authenticate_gestionnaire!
def nav_bar_profile
:gestionnaire
end
end
end

View file

@ -1,12 +0,0 @@
module Gestionnaires
class RechercheController < GestionnaireController
def index
@search_terms = params[:q]
@dossiers = DossierSearchService.matching_dossiers_for_gestionnaire(@search_terms, current_gestionnaire)
@followed_dossiers_id = current_gestionnaire
.followed_dossiers
.where(procedure_id: @dossiers.pluck(:procedure_id))
.pluck(:id)
end
end
end

View file

@ -0,0 +1,50 @@
class Instructeurs::ActivateController < ApplicationController
include TrustedDeviceConcern
def new
@instructeur = Instructeur.with_reset_password_token(params[:token])
if @instructeur
# the instructeur activates its account from an email
trust_device(Time.zone.now)
else
flash.alert = "Le lien de validation du compte instructeur a expiré, #{helpers.contact_link('contactez-nous', tags: 'lien expiré')} pour obtenir un nouveau lien."
redirect_to root_path
end
end
def create
password = create_instructeur_params[:password]
instructeur = Instructeur.reset_password_by_token({
password: password,
password_confirmation: password,
reset_password_token: create_instructeur_params[:reset_password_token]
})
if instructeur && instructeur.errors.empty?
sign_in(instructeur, scope: :instructeur)
try_to_authenticate(User, instructeur.email, password)
try_to_authenticate(Administrateur, instructeur.email, password)
flash.notice = "Mot de passe enregistré"
redirect_to instructeur_procedures_path
else
flash.alert = instructeur.errors.full_messages
redirect_to instructeur_activate_path(token: create_instructeur_params[:reset_password_token])
end
end
private
def create_instructeur_params
params.require(:instructeur).permit(:reset_password_token, :password)
end
def try_to_authenticate(klass, email, password)
resource = klass.find_for_database_authentication(email: email)
if resource&.valid_password?(password)
sign_in resource
resource.force_sync_credentials
end
end
end

View file

@ -1,19 +1,19 @@
module Gestionnaires module Instructeurs
class AvisController < GestionnaireController class AvisController < InstructeurController
include CreateAvisConcern include CreateAvisConcern
before_action :authenticate_gestionnaire!, except: [:sign_up, :create_gestionnaire] before_action :authenticate_instructeur!, except: [:sign_up, :create_instructeur]
before_action :redirect_if_no_sign_up_needed, only: [:sign_up] before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_gestionnaire] before_action :check_avis_exists_and_email_belongs_to_avis, only: [:sign_up, :create_instructeur]
before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire, :update] before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire, :update]
A_DONNER_STATUS = 'a-donner' A_DONNER_STATUS = 'a-donner'
DONNES_STATUS = 'donnes' DONNES_STATUS = 'donnes'
def index def index
gestionnaire_avis = current_gestionnaire.avis.includes(dossier: [:procedure, :user]) instructeur_avis = current_instructeur.avis.includes(dossier: [:procedure, :user])
@avis_a_donner = gestionnaire_avis.without_answer @avis_a_donner = instructeur_avis.without_answer
@avis_donnes = gestionnaire_avis.with_answer @avis_donnes = instructeur_avis.with_answer
@statut = params[:statut].presence || A_DONNER_STATUS @statut = params[:statut].presence || A_DONNER_STATUS
@ -37,7 +37,7 @@ module Gestionnaires
def update def update
if @avis.update(avis_params) if @avis.update(avis_params)
flash.notice = 'Votre réponse est enregistrée.' flash.notice = 'Votre réponse est enregistrée.'
redirect_to instruction_gestionnaire_avis_path(@avis) redirect_to instruction_instructeur_avis_path(@avis)
else else
flash.now.alert = @avis.errors.full_messages flash.now.alert = @avis.errors.full_messages
@new_avis = Avis.new @new_avis = Avis.new
@ -50,11 +50,11 @@ module Gestionnaires
end end
def create_commentaire def create_commentaire
@commentaire = CommentaireService.build(current_gestionnaire, avis.dossier, commentaire_params) @commentaire = CommentaireService.build(current_instructeur, avis.dossier, commentaire_params)
if @commentaire.save if @commentaire.save
flash.notice = "Message envoyé" flash.notice = "Message envoyé"
redirect_to messagerie_gestionnaire_avis_path(avis) redirect_to messagerie_instructeur_avis_path(avis)
else else
flash.alert = @commentaire.errors.full_messages flash.alert = @commentaire.errors.full_messages
render :messagerie render :messagerie
@ -65,7 +65,7 @@ module Gestionnaires
@new_avis = create_avis_from_params(avis.dossier, avis.confidentiel) @new_avis = create_avis_from_params(avis.dossier, avis.confidentiel)
if @new_avis.nil? if @new_avis.nil?
redirect_to instruction_gestionnaire_avis_path(avis) redirect_to instruction_instructeur_avis_path(avis)
else else
set_avis_and_dossier set_avis_and_dossier
render :instruction render :instruction
@ -79,26 +79,26 @@ module Gestionnaires
render render
end end
def create_gestionnaire def create_instructeur
email = params[:email] email = params[:email]
password = params['gestionnaire']['password'] password = params['instructeur']['password']
gestionnaire = Gestionnaire.new(email: email, password: password) instructeur = Instructeur.new(email: email, password: password)
if gestionnaire.save if instructeur.save
user = User.find_by(email: email) user = User.find_by(email: email)
if user.blank? if user.blank?
user = User.create(email: email, password: password, confirmed_at: Time.zone.now) user = User.create(email: email, password: password, confirmed_at: Time.zone.now)
end end
sign_in(user) sign_in(user)
sign_in(gestionnaire, scope: :gestionnaire) sign_in(instructeur, scope: :instructeur)
Avis.link_avis_to_gestionnaire(gestionnaire) Avis.link_avis_to_instructeur(instructeur)
redirect_to url_for(gestionnaire_avis_index_path) redirect_to url_for(instructeur_avis_index_path)
else else
flash[:alert] = gestionnaire.errors.full_messages flash[:alert] = instructeur.errors.full_messages
redirect_to url_for(sign_up_gestionnaire_avis_path(params[:id], email)) redirect_to url_for(sign_up_instructeur_avis_path(params[:id], email))
end end
end end
@ -112,14 +112,14 @@ module Gestionnaires
def redirect_if_no_sign_up_needed def redirect_if_no_sign_up_needed
avis = Avis.find(params[:id]) avis = Avis.find(params[:id])
if current_gestionnaire.present? if current_instructeur.present?
# a gestionnaire is authenticated ... lets see if it can view the dossier # a instructeur is authenticated ... lets see if it can view the dossier
redirect_to gestionnaire_avis_url(avis) redirect_to instructeur_avis_url(avis)
elsif avis.gestionnaire&.email == params[:email] elsif avis.instructeur&.email == params[:email]
# the avis gestionnaire has already signed up and it sould sign in # the avis instructeur has already signed up and it sould sign in
redirect_to new_gestionnaire_session_url redirect_to new_instructeur_session_url
end end
end end
@ -130,7 +130,7 @@ module Gestionnaires
end end
def avis def avis
current_gestionnaire.avis.includes(dossier: [:avis, :commentaires]).find(params[:id]) current_instructeur.avis.includes(dossier: [:avis, :commentaires]).find(params[:id])
end end
def avis_params def avis_params

View file

@ -1,4 +1,4 @@
module Gestionnaires module Instructeurs
class DossiersController < ProceduresController class DossiersController < ProceduresController
include ActionView::Helpers::NumberHelper include ActionView::Helpers::NumberHelper
include ActionView::Helpers::TextHelper include ActionView::Helpers::TextHelper
@ -22,72 +22,72 @@ module Gestionnaires
end end
def show def show
@demande_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.demande_seen_at @demande_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.demande_seen_at
end end
def messagerie def messagerie
@commentaire = Commentaire.new @commentaire = Commentaire.new
@messagerie_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.messagerie_seen_at @messagerie_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.messagerie_seen_at
end end
def annotations_privees def annotations_privees
@annotations_privees_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.annotations_privees_seen_at @annotations_privees_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.annotations_privees_seen_at
end end
def avis def avis
@avis_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.avis_seen_at @avis_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.avis_seen_at
@avis = Avis.new @avis = Avis.new
end end
def personnes_impliquees def personnes_impliquees
@following_instructeurs_emails = dossier.followers_gestionnaires.pluck(:email) @following_instructeurs_emails = dossier.followers_instructeurs.pluck(:email)
previous_followers = dossier.previous_followers_gestionnaires - dossier.followers_gestionnaires previous_followers = dossier.previous_followers_instructeurs - dossier.followers_instructeurs
@previous_following_instructeurs_emails = previous_followers.pluck(:email) @previous_following_instructeurs_emails = previous_followers.pluck(:email)
@avis_emails = dossier.avis.includes(:gestionnaire).map(&:email_to_display) @avis_emails = dossier.avis.includes(:instructeur).map(&:email_to_display)
@invites_emails = dossier.invites.map(&:email) @invites_emails = dossier.invites.map(&:email)
@potential_recipients = procedure.gestionnaires.reject { |g| g == current_gestionnaire } @potential_recipients = procedure.instructeurs.reject { |g| g == current_instructeur }
end end
def send_to_instructeurs def send_to_instructeurs
recipients = Gestionnaire.find(params[:recipients]) recipients = Instructeur.find(params[:recipients])
recipients.each do |recipient| recipients.each do |recipient|
GestionnaireMailer.send_dossier(current_gestionnaire, dossier, recipient).deliver_later InstructeurMailer.send_dossier(current_instructeur, dossier, recipient).deliver_later
end end
flash.notice = "Dossier envoyé" flash.notice = "Dossier envoyé"
redirect_to(personnes_impliquees_gestionnaire_dossier_path(procedure, dossier)) redirect_to(personnes_impliquees_instructeur_dossier_path(procedure, dossier))
end end
def follow def follow
current_gestionnaire.follow(dossier) current_instructeur.follow(dossier)
flash.notice = 'Dossier suivi' flash.notice = 'Dossier suivi'
redirect_back(fallback_location: gestionnaire_procedures_url) redirect_back(fallback_location: instructeur_procedures_url)
end end
def unfollow def unfollow
current_gestionnaire.unfollow(dossier) current_instructeur.unfollow(dossier)
flash.notice = "Vous ne suivez plus le dossier nº #{dossier.id}" flash.notice = "Vous ne suivez plus le dossier nº #{dossier.id}"
redirect_back(fallback_location: gestionnaire_procedures_url) redirect_back(fallback_location: instructeur_procedures_url)
end end
def archive def archive
dossier.update(archived: true) dossier.update(archived: true)
current_gestionnaire.unfollow(dossier) current_instructeur.unfollow(dossier)
redirect_back(fallback_location: gestionnaire_procedures_url) redirect_back(fallback_location: instructeur_procedures_url)
end end
def unarchive def unarchive
dossier.update(archived: false) dossier.update(archived: false)
redirect_back(fallback_location: gestionnaire_procedures_url) redirect_back(fallback_location: instructeur_procedures_url)
end end
def passer_en_instruction def passer_en_instruction
if dossier.en_instruction? if dossier.en_instruction?
flash.notice = 'Le dossier est déjà en instruction.' flash.notice = 'Le dossier est déjà en instruction.'
else else
dossier.passer_en_instruction!(current_gestionnaire) dossier.passer_en_instruction!(current_instructeur)
flash.notice = 'Dossier passé en instruction.' flash.notice = 'Dossier passé en instruction.'
end end
@ -98,7 +98,7 @@ module Gestionnaires
if dossier.en_construction? if dossier.en_construction?
flash.notice = 'Le dossier est déjà en construction.' flash.notice = 'Le dossier est déjà en construction.'
else else
dossier.repasser_en_construction!(current_gestionnaire) dossier.repasser_en_construction!(current_instructeur)
flash.notice = 'Dossier repassé en construction.' flash.notice = 'Dossier repassé en construction.'
end end
@ -113,7 +113,7 @@ module Gestionnaires
flash.notice = 'Il nest pas possible de repasser un dossier accepté en instruction.' flash.notice = 'Il nest pas possible de repasser un dossier accepté en instruction.'
else else
flash.notice = "Le dossier #{dossier.id} a été repassé en instruction." flash.notice = "Le dossier #{dossier.id} a été repassé en instruction."
dossier.repasser_en_instruction!(current_gestionnaire) dossier.repasser_en_instruction!(current_instructeur)
end end
end end
@ -129,13 +129,13 @@ module Gestionnaires
else else
case params[:process_action] case params[:process_action]
when "refuser" when "refuser"
dossier.refuser!(current_gestionnaire, motivation, justificatif) dossier.refuser!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier considéré comme refusé." flash.notice = "Dossier considéré comme refusé."
when "classer_sans_suite" when "classer_sans_suite"
dossier.classer_sans_suite!(current_gestionnaire, motivation, justificatif) dossier.classer_sans_suite!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier considéré comme sans suite." flash.notice = "Dossier considéré comme sans suite."
when "accepter" when "accepter"
dossier.accepter!(current_gestionnaire, motivation, justificatif) dossier.accepter!(current_instructeur, motivation, justificatif)
flash.notice = "Dossier traité avec succès." flash.notice = "Dossier traité avec succès."
end end
end end
@ -144,12 +144,12 @@ module Gestionnaires
end end
def create_commentaire def create_commentaire
@commentaire = CommentaireService.build(current_gestionnaire, dossier, commentaire_params) @commentaire = CommentaireService.build(current_instructeur, dossier, commentaire_params)
if @commentaire.save if @commentaire.save
current_gestionnaire.follow(dossier) current_instructeur.follow(dossier)
flash.notice = "Message envoyé" flash.notice = "Message envoyé"
redirect_to messagerie_gestionnaire_dossier_path(procedure, dossier) redirect_to messagerie_instructeur_dossier_path(procedure, dossier)
else else
flash.alert = @commentaire.errors.full_messages flash.alert = @commentaire.errors.full_messages
render :messagerie render :messagerie
@ -160,18 +160,18 @@ module Gestionnaires
@avis = create_avis_from_params(dossier) @avis = create_avis_from_params(dossier)
if @avis.nil? if @avis.nil?
redirect_to avis_gestionnaire_dossier_path(procedure, dossier) redirect_to avis_instructeur_dossier_path(procedure, dossier)
else else
@avis_seen_at = current_gestionnaire.follows.find_by(dossier: dossier)&.avis_seen_at @avis_seen_at = current_instructeur.follows.find_by(dossier: dossier)&.avis_seen_at
render :avis render :avis
end end
end end
def update_annotations def update_annotations
dossier = current_gestionnaire.dossiers.includes(champs_private: :type_de_champ).find(params[:dossier_id]) dossier = current_instructeur.dossiers.includes(champs_private: :type_de_champ).find(params[:dossier_id])
dossier.update(champs_private_params) dossier.update(champs_private_params)
dossier.modifier_annotations!(current_gestionnaire) dossier.modifier_annotations!(current_instructeur)
redirect_to annotations_privees_gestionnaire_dossier_path(procedure, dossier) redirect_to annotations_privees_instructeur_dossier_path(procedure, dossier)
end end
def print def print
@ -190,7 +190,7 @@ module Gestionnaires
private private
def dossier def dossier
@dossier ||= current_gestionnaire.dossiers.find(params[:dossier_id]) @dossier ||= current_instructeur.dossiers.find(params[:dossier_id])
end end
def commentaire_params def commentaire_params
@ -205,19 +205,19 @@ module Gestionnaires
end end
def mark_demande_as_read def mark_demande_as_read
current_gestionnaire.mark_tab_as_seen(dossier, :demande) current_instructeur.mark_tab_as_seen(dossier, :demande)
end end
def mark_messagerie_as_read def mark_messagerie_as_read
current_gestionnaire.mark_tab_as_seen(dossier, :messagerie) current_instructeur.mark_tab_as_seen(dossier, :messagerie)
end end
def mark_avis_as_read def mark_avis_as_read
current_gestionnaire.mark_tab_as_seen(dossier, :avis) current_instructeur.mark_tab_as_seen(dossier, :avis)
end end
def mark_annotations_privees_as_read def mark_annotations_privees_as_read
current_gestionnaire.mark_tab_as_seen(dossier, :annotations_privees) current_instructeur.mark_tab_as_seen(dossier, :annotations_privees)
end end
end end
end end

View file

@ -0,0 +1,9 @@
module Instructeurs
class InstructeurController < ApplicationController
before_action :authenticate_instructeur!
def nav_bar_profile
:instructeur
end
end
end

View file

@ -1,4 +1,4 @@
class Gestionnaires::PasswordsController < Devise::PasswordsController class Instructeurs::PasswordsController < Devise::PasswordsController
after_action :try_to_authenticate_user, only: [:update] after_action :try_to_authenticate_user, only: [:update]
after_action :try_to_authenticate_administrateur, only: [:update] after_action :try_to_authenticate_administrateur, only: [:update]
@ -34,8 +34,8 @@ class Gestionnaires::PasswordsController < Devise::PasswordsController
# end # end
def try_to_authenticate_user def try_to_authenticate_user
if gestionnaire_signed_in? if instructeur_signed_in?
user = User.find_by(email: current_gestionnaire.email) user = User.find_by(email: current_instructeur.email)
if user if user
sign_in user sign_in user
@ -44,8 +44,8 @@ class Gestionnaires::PasswordsController < Devise::PasswordsController
end end
def try_to_authenticate_administrateur def try_to_authenticate_administrateur
if gestionnaire_signed_in? if instructeur_signed_in?
administrateur = Administrateur.find_by(email: current_gestionnaire.email) administrateur = Administrateur.find_by(email: current_instructeur.email)
if administrateur if administrateur
sign_in administrateur sign_in administrateur

View file

@ -1,20 +1,20 @@
module Gestionnaires module Instructeurs
class ProceduresController < GestionnaireController class ProceduresController < InstructeurController
before_action :ensure_ownership!, except: [:index] before_action :ensure_ownership!, except: [:index]
before_action :redirect_to_avis_if_needed, only: [:index] before_action :redirect_to_avis_if_needed, only: [:index]
ITEMS_PER_PAGE = 25 ITEMS_PER_PAGE = 25
def index def index
@procedures = current_gestionnaire.visible_procedures.order(archived_at: :desc, published_at: :desc, created_at: :desc) @procedures = current_instructeur.visible_procedures.order(archived_at: :desc, published_at: :desc, created_at: :desc)
dossiers = current_gestionnaire.dossiers dossiers = current_instructeur.dossiers
@dossiers_count_per_procedure = dossiers.all_state.group(:procedure_id).reorder(nil).count @dossiers_count_per_procedure = dossiers.all_state.group(:procedure_id).reorder(nil).count
@dossiers_a_suivre_count_per_procedure = dossiers.without_followers.en_cours.group(:procedure_id).reorder(nil).count @dossiers_a_suivre_count_per_procedure = dossiers.without_followers.en_cours.group(:procedure_id).reorder(nil).count
@dossiers_archived_count_per_procedure = dossiers.archived.group(:procedure_id).count @dossiers_archived_count_per_procedure = dossiers.archived.group(:procedure_id).count
@dossiers_termines_count_per_procedure = dossiers.termine.group(:procedure_id).reorder(nil).count @dossiers_termines_count_per_procedure = dossiers.termine.group(:procedure_id).reorder(nil).count
@followed_dossiers_count_per_procedure = current_gestionnaire @followed_dossiers_count_per_procedure = current_instructeur
.followed_dossiers .followed_dossiers
.en_cours .en_cours
.where(procedure: @procedures) .where(procedure: @procedures)
@ -39,13 +39,13 @@ module Gestionnaires
.without_followers .without_followers
.en_cours .en_cours
@followed_dossiers = current_gestionnaire @followed_dossiers = current_instructeur
.followed_dossiers .followed_dossiers
.includes(:user) .includes(:user)
.where(procedure: @procedure) .where(procedure: @procedure)
.en_cours .en_cours
@followed_dossiers_id = current_gestionnaire @followed_dossiers_id = current_instructeur
.followed_dossiers .followed_dossiers
.where(procedure: @procedure) .where(procedure: @procedure)
.pluck(:id) .pluck(:id)
@ -69,7 +69,7 @@ module Gestionnaires
@archived_dossiers @archived_dossiers
end end
sorted_ids = procedure_presentation.sorted_ids(@dossiers, current_gestionnaire) sorted_ids = procedure_presentation.sorted_ids(@dossiers, current_instructeur)
if @current_filters.count > 0 if @current_filters.count > 0
filtered_ids = procedure_presentation.filtered_ids(@dossiers, statut) filtered_ids = procedure_presentation.filtered_ids(@dossiers, statut)
@ -112,7 +112,7 @@ module Gestionnaires
procedure_presentation.update(sort: Procedure.default_sort) procedure_presentation.update(sort: Procedure.default_sort)
end end
redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) redirect_back(fallback_location: instructeur_procedure_url(procedure))
end end
def update_sort def update_sort
@ -134,7 +134,7 @@ module Gestionnaires
procedure_presentation.update(sort: sort) procedure_presentation.update(sort: sort)
redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) redirect_back(fallback_location: instructeur_procedure_url(procedure))
end end
def add_filter def add_filter
@ -153,7 +153,7 @@ module Gestionnaires
procedure_presentation.update(filters: filters) procedure_presentation.update(filters: filters)
end end
redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) redirect_back(fallback_location: instructeur_procedure_url(procedure))
end end
def remove_filter def remove_filter
@ -164,7 +164,7 @@ module Gestionnaires
procedure_presentation.update(filters: filters) procedure_presentation.update(filters: filters)
redirect_back(fallback_location: gestionnaire_procedure_url(procedure)) redirect_back(fallback_location: instructeur_procedure_url(procedure))
end end
def download_dossiers def download_dossiers
@ -195,7 +195,7 @@ module Gestionnaires
assign_to.update!(email_notifications_enabled: params[:assign_to][:email_notifications_enabled]) assign_to.update!(email_notifications_enabled: params[:assign_to][:email_notifications_enabled])
flash.notice = 'Vos notifications sont enregistrées.' flash.notice = 'Vos notifications sont enregistrées.'
redirect_to gestionnaire_procedure_path(procedure) redirect_to instructeur_procedure_path(procedure)
end end
private private
@ -209,7 +209,7 @@ module Gestionnaires
end end
def assign_to def assign_to
current_gestionnaire.assign_to.find_by(procedure: procedure) current_instructeur.assign_to.find_by(procedure: procedure)
end end
def statut def statut
@ -221,15 +221,15 @@ module Gestionnaires
end end
def ensure_ownership! def ensure_ownership!
if !procedure.gestionnaires.include?(current_gestionnaire) if !procedure.instructeurs.include?(current_instructeur)
flash[:alert] = "Vous n'avez pas accès à cette démarche" flash[:alert] = "Vous n'avez pas accès à cette démarche"
redirect_to root_path redirect_to root_path
end end
end end
def redirect_to_avis_if_needed def redirect_to_avis_if_needed
if current_gestionnaire.visible_procedures.count == 0 && current_gestionnaire.avis.count > 0 if current_instructeur.visible_procedures.count == 0 && current_instructeur.avis.count > 0
redirect_to gestionnaire_avis_index_path redirect_to instructeur_avis_index_path
end end
end end
@ -238,7 +238,7 @@ module Gestionnaires
end end
def get_procedure_presentation def get_procedure_presentation
procedure_presentation, errors = current_gestionnaire.procedure_presentation_and_errors_for_procedure_id(params[:procedure_id]) procedure_presentation, errors = current_instructeur.procedure_presentation_and_errors_for_procedure_id(params[:procedure_id])
if errors.present? if errors.present?
flash[:alert] = "Votre affichage a dû être réinitialisé en raison du problème suivant : " + errors.full_messages.join(', ') flash[:alert] = "Votre affichage a dû être réinitialisé en raison du problème suivant : " + errors.full_messages.join(', ')
end end

View file

@ -0,0 +1,12 @@
module Instructeurs
class RechercheController < InstructeurController
def index
@search_terms = params[:q]
@dossiers = DossierSearchService.matching_dossiers_for_instructeur(@search_terms, current_instructeur)
@followed_dossiers_id = current_instructeur
.followed_dossiers
.where(procedure_id: @dossiers.pluck(:procedure_id))
.pluck(:id)
end
end
end

View file

@ -1,4 +1,4 @@
class Gestionnaires::SessionsController < Sessions::SessionsController class Instructeurs::SessionsController < Sessions::SessionsController
def new def new
redirect_to new_user_session_path redirect_to new_user_session_path
end end

View file

@ -1,24 +0,0 @@
module Manager
class GestionnairesController < Manager::ApplicationController
def reinvite
gestionnaire = Gestionnaire.find(params[:id])
gestionnaire.invite!
flash[:notice] = "Instructeur réinvité."
redirect_to manager_gestionnaire_path(gestionnaire)
end
def enable_feature
gestionnaire = Gestionnaire.find(params[:id])
params[:features].each do |key, enable|
if enable
gestionnaire.enable_feature(key.to_sym)
else
gestionnaire.disable_feature(key.to_sym)
end
end
head :ok
end
end
end

View file

@ -0,0 +1,24 @@
module Manager
class InstructeursController < Manager::ApplicationController
def reinvite
instructeur = Instructeur.find(params[:id])
instructeur.invite!
flash[:notice] = "Instructeur réinvité."
redirect_to manager_instructeur_path(instructeur)
end
def enable_feature
instructeur = Instructeur.find(params[:id])
params[:features].each do |key, enable|
if enable
instructeur.enable_feature(key.to_sym)
else
instructeur.disable_feature(key.to_sym)
end
end
head :ok
end
end
end

View file

@ -2,8 +2,8 @@ class RootController < ApplicationController
def index def index
if administrateur_signed_in? if administrateur_signed_in?
return redirect_to admin_procedures_path return redirect_to admin_procedures_path
elsif gestionnaire_signed_in? elsif instructeur_signed_in?
return redirect_to gestionnaire_procedures_path return redirect_to instructeur_procedures_path
elsif user_signed_in? elsif user_signed_in?
return redirect_to dossiers_path return redirect_to dossiers_path
elsif administration_signed_in? elsif administration_signed_in?

View file

@ -8,8 +8,8 @@ class Sessions::SessionsController < Devise::SessionsController
sign_out :user sign_out :user
end end
if gestionnaire_signed_in? if instructeur_signed_in?
sign_out :gestionnaire sign_out :instructeur
end end
if administrateur_signed_in? if administrateur_signed_in?

View file

@ -223,6 +223,10 @@ module Users
dossier = Dossier.create!(procedure: procedure, user: current_user, state: Dossier.states.fetch(:brouillon)) dossier = Dossier.create!(procedure: procedure, user: current_user, state: Dossier.states.fetch(:brouillon))
if dossier.procedure.for_individual if dossier.procedure.for_individual
if current_user.france_connect_information.present?
dossier.update_with_france_connect(current_user.france_connect_information)
end
redirect_to identite_dossier_path(dossier) redirect_to identite_dossier_path(dossier)
else else
redirect_to siret_dossier_path(id: dossier.id) redirect_to siret_dossier_path(id: dossier.id)

View file

@ -1,5 +1,5 @@
class Users::PasswordsController < Devise::PasswordsController class Users::PasswordsController < Devise::PasswordsController
after_action :try_to_authenticate_gestionnaire, only: [:update] after_action :try_to_authenticate_instructeur, only: [:update]
after_action :try_to_authenticate_administrateur, only: [:update] after_action :try_to_authenticate_administrateur, only: [:update]
# GET /resource/password/new # GET /resource/password/new
@ -8,9 +8,19 @@ class Users::PasswordsController < Devise::PasswordsController
# end # end
# POST /resource/password # POST /resource/password
# def create def create
# super # Check the credentials associated to the mail to generate a correct reset link
# end email = params[:user][:email]
if Administrateur.find_by(email: email)
@devise_mapping = Devise.mappings[:administrateur]
params[:administrateur] = params[:user]
# uncomment to check password complexity for Instructeur
# elsif Instructeur.find_by(email: email)
# @devise_mapping = Devise.mappings[:instructeur]
# params[:instructeur] = params[:user]
end
super
end
# GET /resource/password/edit?reset_password_token=abcdef # GET /resource/password/edit?reset_password_token=abcdef
# def edit # def edit
@ -19,6 +29,7 @@ class Users::PasswordsController < Devise::PasswordsController
# PUT /resource/password # PUT /resource/password
# def update # def update
# # params[:user][:password_confirmation] = params[:user][:password]
# super # super
# end # end
@ -33,12 +44,12 @@ class Users::PasswordsController < Devise::PasswordsController
# super(resource_name) # super(resource_name)
# end # end
def try_to_authenticate_gestionnaire def try_to_authenticate_instructeur
if user_signed_in? if user_signed_in?
gestionnaire = Gestionnaire.find_by(email: current_user.email) instructeur = Instructeur.find_by(email: current_user.email)
if gestionnaire if instructeur
sign_in gestionnaire sign_in instructeur
end end
end end
end end
@ -52,4 +63,15 @@ class Users::PasswordsController < Devise::PasswordsController
end end
end end
end end
def test_strength
@score, @words, @length = ZxcvbnService.new(password_params[:password]).complexity
@min_length = PASSWORD_MIN_LENGTH
@min_complexity = PASSWORD_COMPLEXITY_FOR_USER
render 'shared/password/test_strength'
end
def password_params
params.require(:user).permit(:reset_password_token, :password)
end
end end

View file

@ -17,7 +17,7 @@ class Users::SessionsController < Sessions::SessionsController
remember_me = params[:user][:remember_me] == '1' remember_me = params[:user][:remember_me] == '1'
if resource_locked?(try_to_authenticate(User, remember_me)) || if resource_locked?(try_to_authenticate(User, remember_me)) ||
resource_locked?(try_to_authenticate(Gestionnaire, remember_me)) || resource_locked?(try_to_authenticate(Instructeur, remember_me)) ||
resource_locked?(try_to_authenticate(Administrateur, remember_me)) resource_locked?(try_to_authenticate(Administrateur, remember_me))
flash.alert = 'Votre compte est verrouillé.' flash.alert = 'Votre compte est verrouillé.'
new new
@ -28,7 +28,7 @@ class Users::SessionsController < Sessions::SessionsController
current_user.update(loged_in_with_france_connect: nil) current_user.update(loged_in_with_france_connect: nil)
end end
if gestionnaire_signed_in? || user_signed_in? if instructeur_signed_in? || user_signed_in?
set_flash_message :notice, :signed_in set_flash_message :notice, :signed_in
redirect_to after_sign_in_path_for(:user) redirect_to after_sign_in_path_for(:user)
else else
@ -44,8 +44,8 @@ class Users::SessionsController < Sessions::SessionsController
# DELETE /resource/sign_out # DELETE /resource/sign_out
def destroy def destroy
if gestionnaire_signed_in? if instructeur_signed_in?
sign_out :gestionnaire sign_out :instructeur
end end
if administrateur_signed_in? if administrateur_signed_in?
@ -74,8 +74,8 @@ class Users::SessionsController < Sessions::SessionsController
end end
def sign_in_by_link def sign_in_by_link
gestionnaire = Gestionnaire.find(params[:id]) instructeur = Instructeur.find(params[:id])
trusted_device_token = gestionnaire trusted_device_token = instructeur
.trusted_device_tokens .trusted_device_tokens
.find_by(token: params[:jeton]) .find_by(token: params[:jeton])
@ -89,7 +89,7 @@ class Users::SessionsController < Sessions::SessionsController
# redirect to procedure'url if stored by store_location_for(:user) in dossiers_controller # redirect to procedure'url if stored by store_location_for(:user) in dossiers_controller
# redirect to root_path otherwise # redirect to root_path otherwise
if gestionnaire_signed_in? if instructeur_signed_in?
redirect_to after_sign_in_path_for(:user) redirect_to after_sign_in_path_for(:user)
else else
redirect_to new_user_session_path redirect_to new_user_session_path
@ -97,8 +97,8 @@ class Users::SessionsController < Sessions::SessionsController
else else
flash[:alert] = 'Votre lien est invalide ou expiré, un nouveau vient de vous être envoyé.' flash[:alert] = 'Votre lien est invalide ou expiré, un nouveau vient de vous être envoyé.'
send_login_token_or_bufferize(gestionnaire) send_login_token_or_bufferize(instructeur)
redirect_to link_sent_path(email: gestionnaire.email) redirect_to link_sent_path(email: instructeur.email)
end end
end end

View file

@ -4,7 +4,7 @@ class WebhookController < ActionController::Base
def helpscout def helpscout
email = params[:customer][:email].downcase email = params[:customer][:email].downcase
user = User.find_by(email: email) user = User.find_by(email: email)
gestionnaire = Gestionnaire.find_by(email: email) instructeur = Instructeur.find_by(email: email)
administrateur = Administrateur.find_by(email: email) administrateur = Administrateur.find_by(email: email)
html = [] html = []
@ -13,9 +13,9 @@ class WebhookController < ActionController::Base
html << link_to_manager(user, url) html << link_to_manager(user, url)
end end
if gestionnaire if instructeur
url = manager_gestionnaire_url(gestionnaire) url = manager_instructeur_url(instructeur)
html << link_to_manager(gestionnaire, url) html << link_to_manager(instructeur, url)
end end
if administrateur if administrateur

View file

@ -1,6 +1,6 @@
require "administrate/base_dashboard" require "administrate/base_dashboard"
class GestionnaireDashboard < Administrate::BaseDashboard class InstructeurDashboard < Administrate::BaseDashboard
# ATTRIBUTE_TYPES # ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields. # a hash that describes the type of each of the model's fields.
# #
@ -48,7 +48,7 @@ class GestionnaireDashboard < Administrate::BaseDashboard
# Overwrite this method to customize how users are displayed # Overwrite this method to customize how users are displayed
# across all pages of the admin dashboard. # across all pages of the admin dashboard.
# #
def display_resource(gestionnaire) def display_resource(instructeur)
gestionnaire.email instructeur.email
end end
end end

View file

@ -12,7 +12,7 @@ class ProcedureDashboard < Administrate::BaseDashboard
types_de_champ_private: TypesDeChampCollectionField, types_de_champ_private: TypesDeChampCollectionField,
path: ProcedureLinkField, path: ProcedureLinkField,
dossiers: Field::HasMany, dossiers: Field::HasMany,
gestionnaires: Field::HasMany, instructeurs: Field::HasMany,
administrateurs: Field::HasMany, administrateurs: Field::HasMany,
id: Field::Number.with_options(searchable: true), id: Field::Number.with_options(searchable: true),
libelle: Field::String, libelle: Field::String,
@ -73,7 +73,7 @@ class ProcedureDashboard < Administrate::BaseDashboard
:types_de_champ_private, :types_de_champ_private,
:for_individual, :for_individual,
:auto_archive_on, :auto_archive_on,
:gestionnaires, :instructeurs,
:initiated_mail_template, :initiated_mail_template,
:received_mail_template, :received_mail_template,
:closed_mail_template, :closed_mail_template,

View file

@ -86,7 +86,7 @@ module ApplicationHelper
def current_email def current_email
current_user&.email || current_user&.email ||
current_gestionnaire&.email || current_instructeur&.email ||
current_administrateur&.email current_administrateur&.email
end end
@ -104,8 +104,8 @@ module ApplicationHelper
def root_path_for_profile(nav_bar_profile) def root_path_for_profile(nav_bar_profile)
case nav_bar_profile case nav_bar_profile
when :gestionnaire when :instructeur
gestionnaire_procedures_path instructeur_procedures_path
when :user when :user
dossiers_path dossiers_path
else else

View file

@ -1,12 +1,12 @@
module DossierLinkHelper module DossierLinkHelper
def dossier_linked_path(user, dossier) def dossier_linked_path(user, dossier)
if user.is_a?(Gestionnaire) if user.is_a?(Instructeur)
if dossier.procedure.gestionnaires.include?(user) if dossier.procedure.instructeurs.include?(user)
gestionnaire_dossier_path(dossier.procedure, dossier) instructeur_dossier_path(dossier.procedure, dossier)
else else
avis = dossier.avis.find_by(gestionnaire: user) avis = dossier.avis.find_by(instructeur: user)
if avis.present? if avis.present?
gestionnaire_avis_path(avis) instructeur_avis_path(avis)
end end
end end
elsif user.owns_or_invite?(dossier) elsif user.owns_or_invite?(dossier)

View file

@ -55,7 +55,7 @@ module ProcedureHelper
end end
def procedure_dossiers_download_path(procedure, format:, version:) def procedure_dossiers_download_path(procedure, format:, version:)
download_dossiers_gestionnaire_procedure_path(format: format, download_dossiers_instructeur_procedure_path(format: format,
procedure_id: procedure.id, procedure_id: procedure.id,
tables: [:etablissements], tables: [:etablissements],
version: version) version: version)

View file

@ -2,8 +2,8 @@ module TableauDeBordHelper
def tableau_de_bord_helper_path def tableau_de_bord_helper_path
if current_administrateur.present? if current_administrateur.present?
admin_procedures_path admin_procedures_path
elsif current_gestionnaire.present? elsif current_instructeur.present?
gestionnaire_procedures_path instructeur_procedures_path
else else
dossiers_path dossiers_path
end end

View file

@ -1,7 +0,0 @@
class GestionnaireEmailNotificationJob < ApplicationJob
queue_as :cron
def perform(*args)
NotificationService.send_gestionnaire_email_notification
end
end

View file

@ -0,0 +1,7 @@
class InstructeurEmailNotificationJob < ApplicationJob
queue_as :cron
def perform(*args)
NotificationService.send_instructeur_email_notification
end
end

View file

@ -4,10 +4,10 @@ class WeeklyOverviewJob < ApplicationJob
def perform(*args) def perform(*args)
# Feature flipped to avoid mails in staging due to unprocessed dossier # Feature flipped to avoid mails in staging due to unprocessed dossier
if Rails.application.config.ds_weekly_overview if Rails.application.config.ds_weekly_overview
Gestionnaire.all Instructeur.all
.map { |gestionnaire| [gestionnaire, gestionnaire.last_week_overview] } .map { |instructeur| [instructeur, instructeur.last_week_overview] }
.reject { |_, overview| overview.nil? } .reject { |_, overview| overview.nil? }
.each { |gestionnaire, _| GestionnaireMailer.last_week_overview(gestionnaire).deliver_later } .each { |instructeur, _| InstructeurMailer.last_week_overview(instructeur).deliver_later }
end end
end end
end end

View file

@ -10,7 +10,7 @@ module Flipflop::Strategies
def enabled?(feature) def enabled?(feature)
find_current_administrateur&.feature_enabled?(feature) || find_current_administrateur&.feature_enabled?(feature) ||
find_current_gestionnaire&.feature_enabled?(feature) find_current_instructeur&.feature_enabled?(feature)
end end
private private
@ -22,10 +22,10 @@ module Flipflop::Strategies
end end
end end
def find_current_gestionnaire def find_current_instructeur
gestionnaire_id = Current.gestionnaire&.id instructeur_id = Current.instructeur&.id
if gestionnaire_id if instructeur_id
Gestionnaire.find_by(id: gestionnaire_id) Instructeur.find_by(id: instructeur_id)
end end
end end
end end

View file

@ -4,7 +4,7 @@ class AvisMailer < ApplicationMailer
def avis_invitation(avis) def avis_invitation(avis)
@avis = avis @avis = avis
email = @avis.gestionnaire&.email || @avis.email email = @avis.instructeur&.email || @avis.email
subject = "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})" subject = "Donnez votre avis sur le dossier nº #{@avis.dossier.id} (#{@avis.dossier.procedure.libelle})"
mail(to: email, subject: subject) mail(to: email, subject: subject)

View file

@ -1,28 +1,28 @@
# Preview all emails at http://localhost:3000/rails/mailers/gestionnaire_mailer # Preview all emails at http://localhost:3000/rails/mailers/instructeur_mailer
class GestionnaireMailer < ApplicationMailer class InstructeurMailer < ApplicationMailer
layout 'mailers/layout' layout 'mailers/layout'
def invite_gestionnaire(gestionnaire, reset_password_token) def invite_instructeur(instructeur, reset_password_token)
@reset_password_token = reset_password_token @reset_password_token = reset_password_token
@gestionnaire = gestionnaire @instructeur = instructeur
subject = "Activez votre compte instructeur" subject = "Activez votre compte instructeur"
mail(to: gestionnaire.email, mail(to: instructeur.email,
subject: subject, subject: subject,
reply_to: CONTACT_EMAIL) reply_to: CONTACT_EMAIL)
end end
def user_to_gestionnaire(email) def user_to_instructeur(email)
@email = email @email = email
subject = "Vous avez été nommé instructeur" subject = "Vous avez été nommé instructeur"
mail(to: @email, subject: subject) mail(to: @email, subject: subject)
end end
def last_week_overview(gestionnaire) def last_week_overview(instructeur)
email = gestionnaire.email email = instructeur.email
@subject = 'Votre activité hebdomadaire' @subject = 'Votre activité hebdomadaire'
@overview = gestionnaire.last_week_overview @overview = instructeur.last_week_overview
if @overview.present? if @overview.present?
headers['X-mailjet-campaign'] = 'last_week_overview' headers['X-mailjet-campaign'] = 'last_week_overview'
@ -38,18 +38,18 @@ class GestionnaireMailer < ApplicationMailer
mail(to: recipient.email, subject: subject) mail(to: recipient.email, subject: subject)
end end
def send_login_token(gestionnaire, login_token) def send_login_token(instructeur, login_token)
@gestionnaire_id = gestionnaire.id @instructeur_id = instructeur.id
@login_token = login_token @login_token = login_token
subject = "Connexion sécurisée à demarches-simplifiees.fr" subject = "Connexion sécurisée à demarches-simplifiees.fr"
mail(to: gestionnaire.email, subject: subject) mail(to: instructeur.email, subject: subject)
end end
def send_notifications(gestionnaire, data) def send_notifications(instructeur, data)
@data = data @data = data
subject = "Vous avez du nouveau sur vos démarches" subject = "Vous avez du nouveau sur vos démarches"
mail(to: gestionnaire.email, subject: subject) mail(to: instructeur.email, subject: subject)
end end
end end

View file

@ -6,7 +6,7 @@ class Administrateur < ApplicationRecord
devise :database_authenticatable, :registerable, :async, devise :database_authenticatable, :registerable, :async,
:recoverable, :rememberable, :trackable, :validatable, :lockable :recoverable, :rememberable, :trackable, :validatable, :lockable
has_and_belongs_to_many :gestionnaires has_and_belongs_to_many :instructeurs
has_many :administrateurs_procedures has_many :administrateurs_procedures
has_many :procedures, through: :administrateurs_procedures has_many :procedures, through: :administrateurs_procedures
has_many :services has_many :services
@ -20,11 +20,8 @@ class Administrateur < ApplicationRecord
validate :password_complexity, if: Proc.new { |a| Devise.password_length.include?(a.password.try(:size)) } validate :password_complexity, if: Proc.new { |a| Devise.password_length.include?(a.password.try(:size)) }
def password_complexity def password_complexity
if password.present? if password.present? && ZxcvbnService.new(password).score < PASSWORD_COMPLEXITY_FOR_ADMIN
score = Zxcvbn.test(password, [], ZXCVBN_DICTIONNARIES).score errors.add(:password, :not_strong)
if score < 4
errors.add(:password, :not_strength)
end
end end
end end
@ -120,8 +117,8 @@ class Administrateur < ApplicationRecord
procedure.administrateurs.include?(self) procedure.administrateurs.include?(self)
end end
def gestionnaire def instructeur
Gestionnaire.find_by(email: email) Instructeur.find_by(email: email)
end end
def can_be_deleted? def can_be_deleted?

View file

@ -26,7 +26,7 @@ class Administration < ApplicationRecord
confirmed_at: Time.zone.now confirmed_at: Time.zone.now
}) })
Gestionnaire.create({ Instructeur.create({
email: email, email: email,
password: password password: password
}) })

View file

@ -1,6 +1,6 @@
class AssignTo < ApplicationRecord class AssignTo < ApplicationRecord
belongs_to :procedure belongs_to :procedure
belongs_to :gestionnaire belongs_to :instructeur
has_one :procedure_presentation, dependent: :destroy has_one :procedure_presentation, dependent: :destroy
scope :with_email_notifications, -> { where(email_notifications_enabled: true) } scope :with_email_notifications, -> { where(email_notifications_enabled: true) }

View file

@ -2,8 +2,8 @@ class Avis < ApplicationRecord
include EmailSanitizableConcern include EmailSanitizableConcern
belongs_to :dossier, inverse_of: :avis, touch: true belongs_to :dossier, inverse_of: :avis, touch: true
belongs_to :gestionnaire belongs_to :instructeur
belongs_to :claimant, class_name: 'Gestionnaire' belongs_to :claimant, class_name: 'Instructeur'
has_one_attached :piece_justificative_file has_one_attached :piece_justificative_file
@ -11,8 +11,8 @@ class Avis < ApplicationRecord
validates :claimant, presence: true validates :claimant, presence: true
before_validation -> { sanitize_email(:email) } before_validation -> { sanitize_email(:email) }
before_create :try_to_assign_gestionnaire before_create :try_to_assign_instructeur
after_create :notify_gestionnaire after_create :notify_instructeur
default_scope { joins(:dossier) } default_scope { joins(:dossier) }
scope :with_answer, -> { where.not(answer: nil) } scope :with_answer, -> { where.not(answer: nil) }
@ -26,11 +26,11 @@ class Avis < ApplicationRecord
attr_accessor :emails attr_accessor :emails
def email_to_display def email_to_display
gestionnaire&.email || email instructeur&.email || email
end end
def self.link_avis_to_gestionnaire(gestionnaire) def self.link_avis_to_instructeur(instructeur)
Avis.where(email: gestionnaire.email).update_all(email: nil, gestionnaire_id: gestionnaire.id) Avis.where(email: instructeur.email).update_all(email: nil, instructeur_id: instructeur.id)
end end
def self.avis_exists_and_email_belongs_to_avis?(avis_id, email) def self.avis_exists_and_email_belongs_to_avis?(avis_id, email)
@ -49,14 +49,14 @@ class Avis < ApplicationRecord
private private
def notify_gestionnaire def notify_instructeur
AvisMailer.avis_invitation(self).deliver_later AvisMailer.avis_invitation(self).deliver_later
end end
def try_to_assign_gestionnaire def try_to_assign_instructeur
gestionnaire = Gestionnaire.find_by(email: email) instructeur = Instructeur.find_by(email: email)
if gestionnaire if instructeur
self.gestionnaire = gestionnaire self.instructeur = instructeur
self.email = nil self.email = nil
end end
end end

View file

@ -2,7 +2,7 @@ class Commentaire < ApplicationRecord
belongs_to :dossier, inverse_of: :commentaires, touch: true belongs_to :dossier, inverse_of: :commentaires, touch: true
belongs_to :user belongs_to :user
belongs_to :gestionnaire belongs_to :instructeur
mount_uploader :file, CommentaireFileUploader mount_uploader :file, CommentaireFileUploader
validate :messagerie_available?, on: :create validate :messagerie_available?, on: :create
@ -19,8 +19,8 @@ class Commentaire < ApplicationRecord
def email def email
if user if user
user.email user.email
elsif gestionnaire elsif instructeur
gestionnaire.email instructeur.email
else else
read_attribute(:email) read_attribute(:email)
end end
@ -31,8 +31,8 @@ class Commentaire < ApplicationRecord
end end
def redacted_email def redacted_email
if gestionnaire.present? if instructeur.present?
gestionnaire.email.split('@').first instructeur.email.split('@').first
else else
email email
end end
@ -40,7 +40,7 @@ class Commentaire < ApplicationRecord
def sent_by_system? def sent_by_system?
[CONTACT_EMAIL, OLD_CONTACT_EMAIL].include?(email) && [CONTACT_EMAIL, OLD_CONTACT_EMAIL].include?(email) &&
user.nil? && gestionnaire.nil? user.nil? && instructeur.nil?
end end
def sent_by?(someone) def sent_by?(someone)
@ -70,7 +70,7 @@ class Commentaire < ApplicationRecord
# of an automated notification email we sent to a user, so do nothing. # of an automated notification email we sent to a user, so do nothing.
# - If a user or an invited user posted a commentaire, do nothing, # - If a user or an invited user posted a commentaire, do nothing,
# the notification system will properly # the notification system will properly
# - Otherwise, a gestionnaire posted a commentaire, we need to notify the user # - Otherwise, a instructeur posted a commentaire, we need to notify the user
if !email.in?([CONTACT_EMAIL, dossier_user_email, *invited_users_emails]) if !email.in?([CONTACT_EMAIL, dossier_user_email, *invited_users_emails])
notify_user notify_user
end end

View file

@ -17,10 +17,10 @@ module TrustedDeviceConcern
(Time.zone.now - TRUSTED_DEVICE_PERIOD) < trusted_device_cookie_created_at (Time.zone.now - TRUSTED_DEVICE_PERIOD) < trusted_device_cookie_created_at
end end
def send_login_token_or_bufferize(gestionnaire) def send_login_token_or_bufferize(instructeur)
if !gestionnaire.young_login_token? if !instructeur.young_login_token?
login_token = gestionnaire.create_trusted_device_token login_token = instructeur.create_trusted_device_token
GestionnaireMailer.send_login_token(gestionnaire, login_token).deliver_later InstructeurMailer.send_login_token(instructeur, login_token).deliver_later
end end
end end

View file

@ -1,3 +1,3 @@
class Current < ActiveSupport::CurrentAttributes class Current < ActiveSupport::CurrentAttributes
attribute :gestionnaire, :administrateur attribute :instructeur, :administrateur
end end

View file

@ -29,8 +29,8 @@ class Dossier < ApplicationRecord
has_many :invites, dependent: :destroy has_many :invites, dependent: :destroy
has_many :follows, -> { active }, inverse_of: :dossier has_many :follows, -> { active }, inverse_of: :dossier
has_many :previous_follows, -> { inactive }, class_name: 'Follow', inverse_of: :dossier has_many :previous_follows, -> { inactive }, class_name: 'Follow', inverse_of: :dossier
has_many :followers_gestionnaires, through: :follows, source: :gestionnaire has_many :followers_instructeurs, through: :follows, source: :instructeur
has_many :previous_followers_gestionnaires, -> { distinct }, through: :previous_follows, source: :gestionnaire has_many :previous_followers_instructeurs, -> { distinct }, through: :previous_follows, source: :instructeur
has_many :avis, inverse_of: :dossier, dependent: :destroy has_many :avis, inverse_of: :dossier, dependent: :destroy
has_many :dossier_operation_logs, dependent: :destroy has_many :dossier_operation_logs, dependent: :destroy
@ -114,7 +114,7 @@ class Dossier < ApplicationRecord
.includes( .includes(
:user, :user,
:individual, :individual,
:followers_gestionnaires, :followers_instructeurs,
:avis, :avis,
etablissement: :champ, etablissement: :champ,
champs: { champs: {
@ -129,7 +129,7 @@ class Dossier < ApplicationRecord
} }
scope :en_cours, -> { not_archived.state_en_construction_ou_instruction } scope :en_cours, -> { not_archived.state_en_construction_ou_instruction }
scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) } scope :without_followers, -> { left_outer_joins(:follows).where(follows: { id: nil }) }
scope :followed_by, -> (gestionnaire) { joins(:follows).where(follows: { gestionnaire: gestionnaire }) } scope :followed_by, -> (instructeur) { joins(:follows).where(follows: { instructeur: instructeur }) }
scope :with_champs, -> { includes(champs: :type_de_champ) } scope :with_champs, -> { includes(champs: :type_de_champ) }
scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) } scope :nearing_end_of_retention, -> (duration = '1 month') { joins(:procedure).where("en_instruction_at + (duree_conservation_dossiers_dans_ds * interval '1 month') - now() < interval ?", duration) }
scope :since, -> (since) { where('dossiers.en_construction_at >= ?', since) } scope :since, -> (since) { where('dossiers.en_construction_at >= ?', since) }
@ -273,14 +273,14 @@ class Dossier < ApplicationRecord
parts.join parts.join
end end
def avis_for(gestionnaire) def avis_for(instructeur)
if gestionnaire.dossiers.include?(self) if instructeur.dossiers.include?(self)
avis.order(created_at: :asc) avis.order(created_at: :asc)
else else
avis avis
.where(confidentiel: false) .where(confidentiel: false)
.or(avis.where(claimant: gestionnaire)) .or(avis.where(claimant: instructeur))
.or(avis.where(gestionnaire: gestionnaire)) .or(avis.where(instructeur: instructeur))
.order(created_at: :asc) .order(created_at: :asc)
end end
end end
@ -335,7 +335,7 @@ class Dossier < ApplicationRecord
update(hidden_at: deleted_dossier.deleted_at) update(hidden_at: deleted_dossier.deleted_at)
if en_construction? if en_construction?
administration_emails = followers_gestionnaires.present? ? followers_gestionnaires.pluck(:email) : procedure.administrateurs.pluck(:email) administration_emails = followers_instructeurs.present? ? followers_instructeurs.pluck(:email) : procedure.administrateurs.pluck(:email)
administration_emails.each do |email| administration_emails.each do |email|
DossierMailer.notify_deletion_to_administration(deleted_dossier, email).deliver_later DossierMailer.notify_deletion_to_administration(deleted_dossier, email).deliver_later
end end
@ -345,34 +345,34 @@ class Dossier < ApplicationRecord
log_dossier_operation(author, :supprimer, self) log_dossier_operation(author, :supprimer, self)
end end
def after_passer_en_instruction(gestionnaire) def after_passer_en_instruction(instructeur)
gestionnaire.follow(self) instructeur.follow(self)
log_dossier_operation(gestionnaire, :passer_en_instruction) log_dossier_operation(instructeur, :passer_en_instruction)
end end
def after_passer_automatiquement_en_instruction def after_passer_automatiquement_en_instruction
log_automatic_dossier_operation(:passer_en_instruction) log_automatic_dossier_operation(:passer_en_instruction)
end end
def after_repasser_en_construction(gestionnaire) def after_repasser_en_construction(instructeur)
self.en_instruction_at = nil self.en_instruction_at = nil
save! save!
log_dossier_operation(gestionnaire, :repasser_en_construction) log_dossier_operation(instructeur, :repasser_en_construction)
end end
def after_repasser_en_instruction(gestionnaire) def after_repasser_en_instruction(instructeur)
self.processed_at = nil self.processed_at = nil
self.motivation = nil self.motivation = nil
attestation&.destroy attestation&.destroy
save! save!
DossierMailer.notify_revert_to_instruction(self).deliver_later DossierMailer.notify_revert_to_instruction(self).deliver_later
log_dossier_operation(gestionnaire, :repasser_en_instruction) log_dossier_operation(instructeur, :repasser_en_instruction)
end end
def after_accepter(gestionnaire, motivation, justificatif = nil) def after_accepter(instructeur, motivation, justificatif = nil)
self.motivation = motivation self.motivation = motivation
if justificatif if justificatif
@ -385,7 +385,7 @@ class Dossier < ApplicationRecord
save! save!
NotificationMailer.send_closed_notification(self).deliver_later NotificationMailer.send_closed_notification(self).deliver_later
log_dossier_operation(gestionnaire, :accepter, self) log_dossier_operation(instructeur, :accepter, self)
end end
def after_accepter_automatiquement def after_accepter_automatiquement
@ -400,7 +400,7 @@ class Dossier < ApplicationRecord
log_automatic_dossier_operation(:accepter, self) log_automatic_dossier_operation(:accepter, self)
end end
def after_refuser(gestionnaire, motivation, justificatif = nil) def after_refuser(instructeur, motivation, justificatif = nil)
self.motivation = motivation self.motivation = motivation
if justificatif if justificatif
@ -409,10 +409,10 @@ class Dossier < ApplicationRecord
save! save!
NotificationMailer.send_refused_notification(self).deliver_later NotificationMailer.send_refused_notification(self).deliver_later
log_dossier_operation(gestionnaire, :refuser, self) log_dossier_operation(instructeur, :refuser, self)
end end
def after_classer_sans_suite(gestionnaire, motivation, justificatif = nil) def after_classer_sans_suite(instructeur, motivation, justificatif = nil)
self.motivation = motivation self.motivation = motivation
if justificatif if justificatif
@ -421,7 +421,7 @@ class Dossier < ApplicationRecord
save! save!
NotificationMailer.send_without_continuation_notification(self).deliver_later NotificationMailer.send_without_continuation_notification(self).deliver_later
log_dossier_operation(gestionnaire, :classer_sans_suite, self) log_dossier_operation(instructeur, :classer_sans_suite, self)
end end
def check_mandatory_champs def check_mandatory_champs
@ -432,9 +432,9 @@ class Dossier < ApplicationRecord
end end
end end
def modifier_annotations!(gestionnaire) def modifier_annotations!(instructeur)
champs_private.select(&:value_previously_changed?).each do |champ| champs_private.select(&:value_previously_changed?).each do |champ|
log_dossier_operation(gestionnaire, :modifier_annotation, champ) log_dossier_operation(instructeur, :modifier_annotation, champ)
end end
end end
@ -457,7 +457,7 @@ class Dossier < ApplicationRecord
['Passé en instruction le', :en_instruction_at], ['Passé en instruction le', :en_instruction_at],
['Traité le', :processed_at], ['Traité le', :processed_at],
['Motivation de la décision', :motivation], ['Motivation de la décision', :motivation],
['Instructeurs', followers_gestionnaires.map(&:email).join(' ')] ['Instructeurs', followers_instructeurs.map(&:email).join(' ')]
] + champs_for_export + annotations_for_export ] + champs_for_export + annotations_for_export
end end
@ -477,6 +477,10 @@ class Dossier < ApplicationRecord
!PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP !PiecesJustificativesService.liste_pieces_justificatives(self).empty? && PiecesJustificativesService.pieces_justificatives_total_size(self) < Dossier::TAILLE_MAX_ZIP
end end
def update_with_france_connect(fc_information)
self.individual = Individual.create_from_france_connect(fc_information)
end
private private
def log_dossier_operation(author, operation, subject = nil) def log_dossier_operation(author, operation, subject = nil)

View file

@ -1,8 +1,8 @@
class Follow < ApplicationRecord class Follow < ApplicationRecord
belongs_to :gestionnaire belongs_to :instructeur
belongs_to :dossier belongs_to :dossier
validates :gestionnaire_id, uniqueness: { scope: [:dossier_id, :unfollowed_at] } validates :instructeur_id, uniqueness: { scope: [:dossier_id, :unfollowed_at] }
before_create :set_default_date before_create :set_default_date

View file

@ -5,4 +5,15 @@ class Individual < ApplicationRecord
validates :gender, presence: true, allow_nil: false, on: :update validates :gender, presence: true, allow_nil: false, on: :update
validates :nom, presence: true, allow_blank: false, allow_nil: false, on: :update validates :nom, presence: true, allow_blank: false, allow_nil: false, on: :update
validates :prenom, presence: true, allow_blank: false, allow_nil: false, on: :update validates :prenom, presence: true, allow_blank: false, allow_nil: false, on: :update
GENDER_MALE = 'M.'
GENDER_FEMALE = 'Mme'
def self.create_from_france_connect(fc_information)
create(
nom: fc_information.family_name,
prenom: fc_information.given_name,
gender: fc_information.gender == 'female' ? GENDER_FEMALE : GENDER_MALE
)
end
end end

View file

@ -1,4 +1,4 @@
class Gestionnaire < ApplicationRecord class Instructeur < ApplicationRecord
include CredentialsSyncableConcern include CredentialsSyncableConcern
include EmailSanitizableConcern include EmailSanitizableConcern
@ -12,12 +12,12 @@ class Gestionnaire < ApplicationRecord
has_many :assign_to, dependent: :destroy has_many :assign_to, dependent: :destroy
has_many :procedures, through: :assign_to has_many :procedures, through: :assign_to
has_many :assign_to_with_email_notifications, -> { with_email_notifications }, class_name: 'AssignTo', inverse_of: :gestionnaire has_many :assign_to_with_email_notifications, -> { with_email_notifications }, class_name: 'AssignTo', inverse_of: :instructeur
has_many :procedures_with_email_notifications, through: :assign_to_with_email_notifications, source: :procedure has_many :procedures_with_email_notifications, through: :assign_to_with_email_notifications, source: :procedure
has_many :dossiers, -> { state_not_brouillon }, through: :procedures has_many :dossiers, -> { state_not_brouillon }, through: :procedures
has_many :follows, -> { active }, inverse_of: :gestionnaire has_many :follows, -> { active }, inverse_of: :instructeur
has_many :previous_follows, -> { inactive }, class_name: 'Follow', inverse_of: :gestionnaire has_many :previous_follows, -> { inactive }, class_name: 'Follow', inverse_of: :instructeur
has_many :followed_dossiers, through: :follows, source: :dossier has_many :followed_dossiers, through: :follows, source: :dossier
has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier has_many :previously_followed_dossiers, -> { distinct }, through: :previous_follows, source: :dossier
has_many :avis has_many :avis
@ -37,7 +37,7 @@ class Gestionnaire < ApplicationRecord
# Database uniqueness constraint # Database uniqueness constraint
rescue ActiveRecord::RecordInvalid => e rescue ActiveRecord::RecordInvalid => e
# ActiveRecord validation # ActiveRecord validation
raise unless e.record.errors.details.dig(:gestionnaire_id, 0, :error) == :taken raise unless e.record.errors.details.dig(:instructeur_id, 0, :error) == :taken
end end
end end
@ -90,7 +90,7 @@ class Gestionnaire < ApplicationRecord
def notifications_for_dossier(dossier) def notifications_for_dossier(dossier)
follow = Follow follow = Follow
.includes(dossier: [:champs, :avis, :commentaires]) .includes(dossier: [:champs, :avis, :commentaires])
.find_by(gestionnaire: self, dossier: dossier) .find_by(instructeur: self, dossier: dossier)
if follow.present? if follow.present?
demande = follow.dossier.champs.updated_since?(follow.demande_seen_at).any? demande = follow.dossier.champs.updated_since?(follow.demande_seen_at).any?
@ -175,13 +175,13 @@ class Gestionnaire < ApplicationRecord
def mark_tab_as_seen(dossier, tab) def mark_tab_as_seen(dossier, tab)
attributes = {} attributes = {}
attributes["#{tab}_seen_at"] = Time.zone.now attributes["#{tab}_seen_at"] = Time.zone.now
Follow.where(gestionnaire: self, dossier: dossier).update_all(attributes) Follow.where(instructeur: self, dossier: dossier).update_all(attributes)
end end
def invite! def invite!
reset_password_token = set_reset_password_token reset_password_token = set_reset_password_token
GestionnaireMailer.invite_gestionnaire(self, reset_password_token).deliver_later InstructeurMailer.invite_instructeur(self, reset_password_token).deliver_later
end end
def feature_enabled?(feature) def feature_enabled?(feature)

View file

@ -17,7 +17,7 @@ class Procedure < ApplicationRecord
has_many :assign_to, dependent: :destroy has_many :assign_to, dependent: :destroy
has_many :administrateurs_procedures has_many :administrateurs_procedures
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! } has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
has_many :gestionnaires, through: :assign_to has_many :instructeurs, through: :assign_to
has_one :initiated_mail, class_name: "Mails::InitiatedMail", dependent: :destroy has_one :initiated_mail, class_name: "Mails::InitiatedMail", dependent: :destroy
has_one :received_mail, class_name: "Mails::ReceivedMail", dependent: :destroy has_one :received_mail, class_name: "Mails::ReceivedMail", dependent: :destroy
@ -243,7 +243,7 @@ class Procedure < ApplicationRecord
procedure.service = self.service.clone_and_assign_to_administrateur(admin) procedure.service = self.service.clone_and_assign_to_administrateur(admin)
end end
admin.gestionnaire.assign_to_procedure(procedure) admin.instructeur.assign_to_procedure(procedure)
procedure procedure
end end
@ -402,7 +402,7 @@ class Procedure < ApplicationRecord
result << :service result << :service
end end
if gestionnaires.empty? if instructeurs.empty?
result << :instructeurs result << :instructeurs
end end

View file

@ -19,7 +19,7 @@ class ProcedurePresentation < ApplicationRecord
field_hash('En construction le', 'self', 'en_construction_at'), field_hash('En construction le', 'self', 'en_construction_at'),
field_hash('Mis à jour le', 'self', 'updated_at'), field_hash('Mis à jour le', 'self', 'updated_at'),
field_hash('Demandeur', 'user', 'email'), field_hash('Demandeur', 'user', 'email'),
field_hash('Email instructeur', 'followers_gestionnaires', 'email') field_hash('Email instructeur', 'followers_instructeurs', 'email')
] ]
if procedure.for_individual if procedure.for_individual
@ -73,13 +73,13 @@ class ProcedurePresentation < ApplicationRecord
displayed_fields.map { |field| get_value(dossier, field['table'], field['column']) } displayed_fields.map { |field| get_value(dossier, field['table'], field['column']) }
end end
def sorted_ids(dossiers, gestionnaire) def sorted_ids(dossiers, instructeur)
dossiers.each { |dossier| assert_matching_procedure(dossier) } dossiers.each { |dossier| assert_matching_procedure(dossier) }
table, column, order = sort.values_at('table', 'column', 'order') table, column, order = sort.values_at('table', 'column', 'order')
case table case table
when 'notifications' when 'notifications'
dossiers_id_with_notification = gestionnaire.dossiers_id_with_notifications(dossiers) dossiers_id_with_notification = instructeur.dossiers_id_with_notifications(dossiers)
if order == 'desc' if order == 'desc'
return dossiers_id_with_notification + return dossiers_id_with_notification +
(dossiers.order('dossiers.updated_at desc').ids - dossiers_id_with_notification) (dossiers.order('dossiers.updated_at desc').ids - dossiers_id_with_notification)
@ -93,7 +93,7 @@ class ProcedurePresentation < ApplicationRecord
.where("champs.type_de_champ_id = #{column.to_i}") .where("champs.type_de_champ_id = #{column.to_i}")
.order("champs.value #{order}") .order("champs.value #{order}")
.pluck(:id) .pluck(:id)
when 'self', 'user', 'individual', 'etablissement', 'followers_gestionnaires' when 'self', 'user', 'individual', 'etablissement', 'followers_instructeurs'
return (table == 'self' ? dossiers : dossiers.includes(table)) return (table == 'self' ? dossiers : dossiers.includes(table))
.order("#{self.class.sanitized_column(table, column)} #{order}") .order("#{self.class.sanitized_column(table, column)} #{order}")
.pluck(:id) .pluck(:id)
@ -129,7 +129,7 @@ class ProcedurePresentation < ApplicationRecord
.includes(table) .includes(table)
.filter_ilike(table, column, values) .filter_ilike(table, column, values)
end end
when 'user', 'individual', 'followers_gestionnaires' when 'user', 'individual', 'followers_instructeurs'
dossiers dossiers
.includes(table) .includes(table)
.filter_ilike(table, column, values) .filter_ilike(table, column, values)
@ -202,7 +202,7 @@ class ProcedurePresentation < ApplicationRecord
dossier.send(column)&.strftime('%d/%m/%Y') dossier.send(column)&.strftime('%d/%m/%Y')
when 'user', 'individual', 'etablissement' when 'user', 'individual', 'etablissement'
dossier.send(table)&.send(column) dossier.send(table)&.send(column)
when 'followers_gestionnaires' when 'followers_instructeurs'
dossier.send(table)&.map { |g| g.send(column) }&.join(', ') dossier.send(table)&.map { |g| g.send(column) }&.join(', ')
when 'type_de_champ' when 'type_de_champ'
dossier.champs.find { |c| c.type_de_champ_id == column.to_i }.value dossier.champs.find { |c| c.type_de_champ_id == column.to_i }.value

View file

@ -2,7 +2,7 @@ class TrustedDeviceToken < ApplicationRecord
LOGIN_TOKEN_VALIDITY = 1.week LOGIN_TOKEN_VALIDITY = 1.week
LOGIN_TOKEN_YOUTH = 15.minutes LOGIN_TOKEN_YOUTH = 15.minutes
belongs_to :gestionnaire belongs_to :instructeur
has_secure_token has_secure_token
def token_valid? def token_valid?

View file

@ -35,11 +35,11 @@ class ApplicationPolicy
end end
class Scope class Scope
attr_reader :user, :gestionnaire, :administrateur, :scope attr_reader :user, :instructeur, :administrateur, :scope
def initialize(account, scope) def initialize(account, scope)
@user = account[:user] @user = account[:user]
@gestionnaire = account[:gestionnaire] @instructeur = account[:instructeur]
@administrateur = account[:administrateur] @administrateur = account[:administrateur]
@scope = scope @scope = scope
end end

View file

@ -94,7 +94,7 @@ class DossierSerializer < ActiveModel::Serializer
end end
def instructeurs def instructeurs
object.followers_gestionnaires.pluck(:email) object.followers_instructeurs.pluck(:email)
end end
def created_at def created_at

View file

@ -5,7 +5,7 @@ class OperationAuthorSerializer < ActiveModel::Serializer
case object case object
when User when User
"Usager##{object.id}" "Usager##{object.id}"
when Gestionnaire when Instructeur
"Instructeur##{object.id}" "Instructeur##{object.id}"
when Administrateur when Administrateur
"Administrateur##{object.id}" "Administrateur##{object.id}"

View file

@ -120,7 +120,7 @@ class AdministrateurUsageStatisticsService
end end
def nb_instructeurs_by_administrateur_id def nb_instructeurs_by_administrateur_id
@nb_instructeurs_by_administrateur_id ||= with_default(0, Administrateur.joins(:gestionnaires).group(:administrateur_id).count) @nb_instructeurs_by_administrateur_id ||= with_default(0, Administrateur.joins(:instructeurs).group(:administrateur_id).count)
end end
def nb_dossiers_by_administrateur_id_and_procedure_id_and_synthetic_state def nb_dossiers_by_administrateur_id_and_procedure_id_and_synthetic_state

View file

@ -4,8 +4,8 @@ class CommentaireService
case sender case sender
when User when User
params[:user] = sender params[:user] = sender
when Gestionnaire when Instructeur
params[:gestionnaire] = sender params[:instructeur] = sender
end end
build_with_email(sender.email, dossier, params) build_with_email(sender.email, dossier, params)

View file

@ -1,22 +1,22 @@
class DossierSearchService class DossierSearchService
def self.matching_dossiers_for_gestionnaire(search_terms, gestionnaire) def self.matching_dossiers_for_instructeur(search_terms, instructeur)
dossier_by_exact_id_for_gestionnaire(search_terms, gestionnaire) dossier_by_exact_id_for_instructeur(search_terms, instructeur)
.presence || dossier_by_full_text_for_gestionnaire(search_terms, gestionnaire) .presence || dossier_by_full_text_for_instructeur(search_terms, instructeur)
end end
private private
def self.dossier_by_exact_id_for_gestionnaire(search_terms, gestionnaire) def self.dossier_by_exact_id_for_instructeur(search_terms, instructeur)
id = search_terms.to_i id = search_terms.to_i
if id != 0 && id_compatible?(id) # Sometimes gestionnaire is searching dossiers with a big number (ex: SIRET), ActiveRecord can't deal with them and throws ActiveModel::RangeError. id_compatible? prevents this. if id != 0 && id_compatible?(id) # Sometimes instructeur is searching dossiers with a big number (ex: SIRET), ActiveRecord can't deal with them and throws ActiveModel::RangeError. id_compatible? prevents this.
dossiers_by_id(id, gestionnaire) dossiers_by_id(id, instructeur)
else else
Dossier.none Dossier.none
end end
end end
def self.dossiers_by_id(id, gestionnaire) def self.dossiers_by_id(id, instructeur)
(gestionnaire.dossiers.where(id: id) + gestionnaire.dossiers_from_avis.where(id: id)).uniq (instructeur.dossiers.where(id: id) + instructeur.dossiers_from_avis.where(id: id)).uniq
end end
def self.id_compatible?(number) def self.id_compatible?(number)
@ -26,11 +26,11 @@ class DossierSearchService
false false
end end
def self.dossier_by_full_text_for_gestionnaire(search_terms, gestionnaire) def self.dossier_by_full_text_for_instructeur(search_terms, instructeur)
ts_vector = "to_tsvector('french', search_terms || private_search_terms)" ts_vector = "to_tsvector('french', search_terms || private_search_terms)"
ts_query = "to_tsquery('french', #{Dossier.connection.quote(to_tsquery(search_terms))})" ts_query = "to_tsquery('french', #{Dossier.connection.quote(to_tsquery(search_terms))})"
gestionnaire instructeur
.dossiers .dossiers
.state_not_brouillon .state_not_brouillon
.where("#{ts_vector} @@ #{ts_query}") .where("#{ts_vector} @@ #{ts_query}")

View file

@ -1,19 +1,19 @@
class NotificationService class NotificationService
class << self class << self
def send_gestionnaire_email_notification def send_instructeur_email_notification
Gestionnaire Instructeur
.includes(assign_to: { procedure: :dossiers }) .includes(assign_to: { procedure: :dossiers })
.where(assign_tos: { email_notifications_enabled: true }) .where(assign_tos: { email_notifications_enabled: true })
.find_in_batches { |gestionnaires| send_batch_of_gestionnaires_email_notification(gestionnaires) } .find_in_batches { |instructeurs| send_batch_of_instructeurs_email_notification(instructeurs) }
end end
private private
def send_batch_of_gestionnaires_email_notification(gestionnaires) def send_batch_of_instructeurs_email_notification(instructeurs)
gestionnaires instructeurs
.map { |gestionnaire| [gestionnaire, gestionnaire.email_notification_data] } .map { |instructeur| [instructeur, instructeur.email_notification_data] }
.reject { |(_gestionnaire, data)| data.empty? } .reject { |(_instructeur, data)| data.empty? }
.each { |(gestionnaire, data)| GestionnaireMailer.send_notifications(gestionnaire, data).deliver_later } .each { |(instructeur, data)| InstructeurMailer.send_notifications(instructeur, data).deliver_later }
end end
end end
end end

View file

@ -167,7 +167,7 @@ class ProcedureExportService
when :individual_gender when :individual_gender
dossier.individual&.gender dossier.individual&.gender
when :emails_instructeurs when :emails_instructeurs
dossier.followers_gestionnaires.map(&:email).join(' ') dossier.followers_instructeurs.map(&:email).join(' ')
else else
dossier.read_attribute(key) dossier.read_attribute(key)
end end

View file

@ -4,8 +4,8 @@ class SwitchDeviseProfileService
end end
def multiple_devise_profile_connect? def multiple_devise_profile_connect?
user_signed_in? && gestionnaire_signed_in? || user_signed_in? && instructeur_signed_in? ||
gestionnaire_signed_in? && administrateur_signed_in? || instructeur_signed_in? && administrateur_signed_in? ||
user_signed_in? && administrateur_signed_in? user_signed_in? && administrateur_signed_in?
end end
@ -15,8 +15,8 @@ class SwitchDeviseProfileService
@warden.authenticate(:scope => :user).present? @warden.authenticate(:scope => :user).present?
end end
def gestionnaire_signed_in? def instructeur_signed_in?
@warden.authenticate(:scope => :gestionnaire).present? @warden.authenticate(:scope => :instructeur).present?
end end
def administrateur_signed_in? def administrateur_signed_in?

View file

@ -14,9 +14,9 @@ class SyncCredentialsService
end end
end end
if @klass != Gestionnaire if @klass != Instructeur
gestionnaire = Gestionnaire.find_by(email: @email_before_last_save) instructeur = Instructeur.find_by(email: @email_before_last_save)
if gestionnaire && !gestionnaire.update_columns(email: @email, encrypted_password: @encrypted_password) if instructeur && !instructeur.update_columns(email: @email, encrypted_password: @encrypted_password)
return false return false
end end
end end

View file

@ -0,0 +1,23 @@
class ZxcvbnService
def initialize(password)
@password = password
end
def complexity
wxcvbn = compute_zxcvbn
score = wxcvbn.score
length = @password.blank? ? 0 : @password.length
vulnerabilities = wxcvbn.match_sequence.map { |m| m.matched_word.nil? ? m.token : m.matched_word }.select { |s| s.length > 2 }.join(', ')
[score, vulnerabilities, length]
end
def score
compute_zxcvbn.score
end
private
def compute_zxcvbn
Zxcvbn.test(@password, [], ZXCVBN_DICTIONNARIES)
end
end

View file

@ -1,7 +1,7 @@
.row{ style: 'height: 34px;' } .row{ style: 'height: 34px;' }
- if smart_listing.present? - if smart_listing.present?
%table.table#liste-gestionnaire %table.table#liste-instructeur
%thead %thead
%th Enlever %th Enlever
%th#email{ style: 'text-align: right;' } Email %th#email{ style: 'text-align: right;' } Email
@ -9,7 +9,7 @@
- @instructeurs_assign.each do |instructeur| - @instructeurs_assign.each do |instructeur|
%tr %tr
%td.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center %td.col-md-1.col-lg-1.col-sm-1.col-xs-1.col-sm-1.col-xs-1.center
= link_to "#{admin_procedure_instructeurs_path(procedure_id: @procedure.id, instructeur_id: instructeur.id, to: Admin::InstructeursController::NOT_ASSIGN)}", class: "btn btn-primary", 'data-method' => 'put' do = link_to "#{admin_procedure_assigns_path(procedure_id: @procedure.id, instructeur_id: instructeur.id, to: Admin::AssignsController::NOT_ASSIGN)}", class: "btn btn-primary", 'data-method' => 'put' do
.fa.fa-arrow-left .fa.fa-arrow-left
%td{ style: 'padding-top: 11px; font-size: 15px; text-align: right;' }= instructeur.email %td{ style: 'padding-top: 11px; font-size: 15px; text-align: right;' }= instructeur.email

View file

@ -7,7 +7,7 @@
- if smart_listing.present? - if smart_listing.present?
%table.table#liste-gestionnaire %table.table#liste-instructeur
%thead %thead
%th#email Email %th#email Email
%th Ajouter %th Ajouter
@ -16,7 +16,7 @@
%tr %tr
%td.col-xs-11{ style: 'padding-top: 11px; font-size: 15px;' }= instructeur.email %td.col-xs-11{ style: 'padding-top: 11px; font-size: 15px;' }= instructeur.email
%td.center %td.center
= link_to "#{admin_procedure_instructeurs_path(procedure_id: @procedure.id, instructeur_id: instructeur.id, to: Admin::InstructeursController::ASSIGN)}", class: "btn btn-success gestionnaire-affectation", 'data-method' => 'put' do = link_to "#{admin_procedure_assigns_path(procedure_id: @procedure.id, instructeur_id: instructeur.id, to: Admin::AssignsController::ASSIGN)}", class: "btn btn-success instructeur-affectation", 'data-method' => 'put' do
.fa.fa-arrow-right .fa.fa-arrow-right

View file

@ -9,15 +9,15 @@
%h3 %h3
= t('dynamics.admin.procedure.onglet_instructeurs.add.title') = t('dynamics.admin.procedure.onglet_instructeurs.add.title')
#procedure_new.section.section-label #procedure_new.section.section-label
= form_for @gestionnaire, url: { controller: 'admin/gestionnaires', action: :create } do |f| = form_for @instructeur, url: { controller: 'admin/instructeurs', action: :create } do |f|
.row .row
.col-xs-5 .col-xs-5
= hidden_field_tag :procedure_id, params[:procedure_id] = hidden_field_tag :procedure_id, params[:procedure_id]
= render partial: 'admin/gestionnaires/informations', locals: { f: f } = render partial: 'admin/instructeurs/informations', locals: { f: f }
.col-xs-2 .col-xs-2
%br %br
%br %br
= f.submit 'Valider', class: 'btn btn-info', style: 'float: left;', id: 'add-gestionnaire-email' = f.submit 'Valider', class: 'btn btn-info', style: 'float: left;', id: 'add-instructeur-email'
.col-xs-6 .col-xs-6
%h3.text-success Affectés %h3.text-success Affectés
= smart_listing_render :instructeurs_assign = smart_listing_render :instructeurs_assign

View file

@ -1 +0,0 @@
<%= smart_listing_update :gestionnaires %>

View file

@ -1,17 +1,17 @@
- if smart_listing.present? - if smart_listing.present?
%table.table#liste-gestionnaire %table.table#liste-instructeur
%thead %thead
%th#libelle= smart_listing.sortable 'Email', 'email' %th#libelle= smart_listing.sortable 'Email', 'email'
%th %th
- @gestionnaires.each do |gestionnaire| - @instructeurs.each do |instructeur|
%tr %tr
%td{ style: 'padding-top: 11px; font-size: 15px;' }= gestionnaire.email %td{ style: 'padding-top: 11px; font-size: 15px;' }= instructeur.email
%td{ style: 'text-align: right;' } %td{ style: 'text-align: right;' }
.delete.btn.btn-sm.fa.fa-trash .delete.btn.btn-sm.fa.fa-trash
.confirm .confirm
= link_to 'Valider', admin_gestionnaire_path(id: gestionnaire.id), { method: :delete, class: 'btn btn-sm btn-success' } = link_to 'Valider', admin_instructeur_path(id: instructeur.id), { method: :delete, class: 'btn btn-sm btn-success' }
.cancel.btn.btn-sm.btn-danger.fa.fa-minus{ style: 'top: 0;' } .cancel.btn.btn-sm.btn-danger.fa.fa-minus{ style: 'top: 0;' }
= smart_listing.paginate = smart_listing.paginate

View file

@ -12,13 +12,13 @@
.row .row
.col-xs-4 .col-xs-4
= smart_listing_render :gestionnaires = smart_listing_render :instructeurs
.col-xs-1 .col-xs-1
&nbsp; &nbsp;
.col-xs-6 .col-xs-6
%h3 Ajouter un instructeur %h3 Ajouter un instructeur
#procedure_new.section.section-label #procedure_new.section.section-label
= form_for @gestionnaire, url: { controller: 'admin/gestionnaires', action: :create } do |f| = form_for @instructeur, url: { controller: 'admin/instructeurs', action: :create } do |f|
.row .row
.col-xs-5 .col-xs-5
= render partial: 'informations', locals: { f: f } = render partial: 'informations', locals: { f: f }

View file

@ -0,0 +1 @@
<%= smart_listing_update :instructeurs %>

View file

@ -5,9 +5,9 @@
= render partial: '/admin/procedures/modal_transfer' = render partial: '/admin/procedures/modal_transfer'
- if @procedure.brouillon? - if @procedure.brouillon?
- if @procedure.gestionnaires.empty? || @procedure.service.nil? - if @procedure.instructeurs.empty? || @procedure.service.nil?
- missing_elements = [] - missing_elements = []
- if @procedure.gestionnaires.empty? - if @procedure.instructeurs.empty?
- missing_elements << 'des instructeurs' - missing_elements << 'des instructeurs'
- if @procedure.service.nil? - if @procedure.service.nil?
- missing_elements << 'un service' - missing_elements << 'un service'
@ -59,7 +59,7 @@
%br %br
Attention, diffusez toujours le <strong>lien complet</strong> affiché ci-dessus, et non pas un lien générique vers demarches-simplifiees.fr. Ne dites pas non plus aux usagers de se rendre sur le site générique demarches-simplifiees.fr, donnez-leur toujours le lien complet. Attention, diffusez toujours le <strong>lien complet</strong> affiché ci-dessus, et non pas un lien générique vers demarches-simplifiees.fr. Ne dites pas non plus aux usagers de se rendre sur le site générique demarches-simplifiees.fr, donnez-leur toujours le lien complet.
- elsif @procedure.brouillon_avec_lien? - elsif @procedure.brouillon_avec_lien?
- if @procedure.gestionnaires.present? && @procedure.service.present? - if @procedure.instructeurs.present? && @procedure.service.present?
%p %p
Cette démarche est actuellement <strong>en test</strong>, Cette démarche est actuellement <strong>en test</strong>,
pour y accéder vous pouvez utiliser le lien : pour y accéder vous pouvez utiliser le lien :
@ -106,9 +106,9 @@
- else - else
.alert.alert-info .alert.alert-info
Pour pouvoir tester cette démarche, vous devez dabord lui affecter Pour pouvoir tester cette démarche, vous devez dabord lui affecter
- if @procedure.gestionnaires.empty? - if @procedure.instructeurs.empty?
= link_to("des instructeurs", admin_procedure_instructeurs_path(@procedure)) = link_to("des instructeurs", admin_procedure_assigns_path(@procedure))
- if @procedure.gestionnaires.empty? && @procedure.service.nil? - if @procedure.instructeurs.empty? && @procedure.service.nil?
et et
- if @procedure.service.nil? - if @procedure.service.nil?
= link_to("un service", services_path(procedure_id: @procedure)) = link_to("un service", services_path(procedure_id: @procedure))
@ -122,7 +122,7 @@
- if @procedure.missing_steps.include?(:instructeurs) - if @procedure.missing_steps.include?(:instructeurs)
%p.alert.alert-danger %p.alert.alert-danger
Vous devez affecter des instructeurs avant de pouvoir publier votre démarche. Vous devez affecter des instructeurs avant de pouvoir publier votre démarche.
= link_to 'Cliquez ici.', admin_procedure_instructeurs_path(@procedure) = link_to 'Cliquez ici.', admin_procedure_assigns_path(@procedure)
%p.alert.alert-info %p.alert.alert-info
Cette démarche na pas encore de lien, et nest pas accessible par le public. Cette démarche na pas encore de lien, et nest pas accessible par le public.

View file

@ -1,5 +0,0 @@
#strength-bar.password-strength{ class: "strength-#{score}" }
- if score < 4
Mot de passe pas assez complexe
- else
Mot de passe suffisamment complexe

View file

@ -10,20 +10,13 @@
%h1 %h1
Choix du mot de passe Choix du mot de passe
= f.hidden_field :reset_password_token, value: @token
= f.label :email, "Email" = f.label :email, "Email"
= f.text_field :email, disabled: true = f.text_field :email, disabled: true
= f.label :password do = f.label :password do
Mot de passe Mot de passe
= f.password_field :password, placeholder: 'Mot de passe', data: { remote: true, url: admin_activate_test_password_strength_path } = render partial: 'shared/password/edit_password', locals: { form: f, controller: 'administrateurs/passwords' }
#strength-bar.password-strength
&nbsp;
.explication
%strong Aide :
Une courte phrase peut être un mot de passe très sécurisé.
= f.hidden_field :reset_password_token, value: params[:token]
= f.submit 'Continuer', class: 'button large primary expand', id: "submit-password", data: { disable_with: "Envoi..." } = f.submit 'Continuer', class: 'button large primary expand', id: "submit-password", data: { disable_with: "Envoi..." }

View file

@ -1 +0,0 @@
<%= render_to_element('#strength-bar', partial: 'password_strength', outer: true, locals: { score: @score }) %>

View file

@ -0,0 +1,6 @@
- content_for(:title, 'Changement de mot de passe')
- content_for :footer do
= render partial: 'root/footer'
= render 'shared/password/edit', test_password_strength: administrateurs_password_test_strength_path

View file

@ -1,5 +1,5 @@
- content_for(:title, 'Invitation à donner votre avis') - content_for(:title, 'Invitation à donner votre avis')
- avis_link = @avis.gestionnaire.present? ? gestionnaire_avis_url(@avis) : sign_up_gestionnaire_avis_url(@avis.id, @avis.email) - avis_link = @avis.instructeur.present? ? instructeur_avis_url(@avis) : sign_up_instructeur_avis_url(@avis.id, @avis.email)
- content_for(:footer) do - content_for(:footer) do
Merci de ne pas répondre à cet email. Donnez votre avis Merci de ne pas répondre à cet email. Donnez votre avis
@ -23,7 +23,7 @@
%p{ style: "padding: 8px; color: #333333; background-color: #EEEEEE; font-size: 14px;" } %p{ style: "padding: 8px; color: #333333; background-color: #EEEEEE; font-size: 14px;" }
= @avis.introduction = @avis.introduction
- if @avis.gestionnaire.present? - if @avis.instructeur.present?
%p %p
= link_to "Connectez-vous pour donner votre avis", avis_link = link_to "Connectez-vous pour donner votre avis", avis_link
- else - else

View file

@ -1,6 +1,6 @@
:ruby :ruby
url = if field.resource.class.name == 'Gestionnaire' url = if field.resource.class.name == 'Instructeur'
enable_feature_manager_gestionnaire_path(field.resource.id) enable_feature_manager_instructeur_path(field.resource.id)
else else
enable_feature_manager_administrateur_path(field.resource.id) enable_feature_manager_administrateur_path(field.resource.id)
end end

View file

@ -1,3 +0,0 @@
= link_to "/gestionnaires/sign_out", method: :delete do
%span.fa.fa-sign-out
Se déconnecter

View file

@ -1,10 +0,0 @@
.sub-header
.container
%ul.breadcrumbs
%li= link_to('Avis', gestionnaire_avis_index_path)
%li= "#{dossier.procedure.libelle}, dossier nº #{dossier.id}"
%ul.tabs
= dynamic_tab_item('Demande', gestionnaire_avis_path(avis))
= dynamic_tab_item('Avis', instruction_gestionnaire_avis_path(avis), notification: avis.answer.blank?)
= dynamic_tab_item('Messagerie', messagerie_gestionnaire_avis_path(avis))

View file

@ -1,15 +0,0 @@
- content_for(:title, "Personnes impliquées · Dossier nº #{@dossier.id} (#{@dossier.owner_name})")
= render partial: "header", locals: { dossier: @dossier }
.personnes-impliquees.container
= render partial: 'gestionnaires/dossiers/envoyer_dossier_block', locals: { dossier: @dossier, potential_recipients: @potential_recipients }
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @following_instructeurs_emails, title: "Instructeurs qui suivent actuellement le dossier", blank: "Aucun instructeur ne suit ce dossier" }
- if @previous_following_instructeurs_emails.present?
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @previous_following_instructeurs_emails, title: "Instructeurs ayant précédemment suivi le dossier", blank: " " }
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @avis_emails, title: "Personnes à qui un avis a été demandé", blank: "Aucun avis n'a été demandé" }
= render partial: 'gestionnaires/dossiers/personnes_impliquees_block', locals: { emails_collection: @invites_emails, title: "Personnes invitées à consulter ce dossier", blank: "Aucune personne n'a été invitée à consulter ce dossier" }

View file

@ -7,8 +7,8 @@
Vous venez d'être nommé instructeur sur demarches-simplifiees.fr. Vous venez d'être nommé instructeur sur demarches-simplifiees.fr.
%p %p
Votre compte a été créé pour l'adresse email #{@gestionnaire.email}. Pour lactiver, je vous invite à cliquer sur le lien suivant :  Votre compte a été créé pour l'adresse email #{@instructeur.email}. Pour lactiver, je vous invite à cliquer sur le lien suivant : 
= link_to(gestionnaire_activate_url(token: @reset_password_token), gestionnaire_activate_url(token: @reset_password_token)) = link_to(instructeur_activate_url(token: @reset_password_token), instructeur_activate_url(token: @reset_password_token))
%p %p
Par ailleurs, nous vous invitons à prendre quelques minutes pour consulter notre tutoriel à destination des nouveaux instructeurs : Par ailleurs, nous vous invitons à prendre quelques minutes pour consulter notre tutoriel à destination des nouveaux instructeurs :

View file

@ -10,7 +10,7 @@
%h2{ style: 'font-size: 16px; font-weight: 300; margin: 25px 0 5px;' } %h2{ style: 'font-size: 16px; font-weight: 300; margin: 25px 0 5px;' }
#{procedure_overview.procedure.libelle} #{procedure_overview.procedure.libelle}
= link_to 'voir', gestionnaire_procedure_url(procedure_overview.procedure), style: 'color: #0069CC; font-size: 14px;' = link_to 'voir', instructeur_procedure_url(procedure_overview.procedure), style: 'color: #0069CC; font-size: 14px;'
%table{ cellpadding: '0', cellspacing: '0', style: 'width: 100%; padding-bottom: 20px;' } %table{ cellpadding: '0', cellspacing: '0', style: 'width: 100%; padding-bottom: 20px;' }
%tbody %tbody
@ -30,7 +30,7 @@
- if procedure_overview.old_dossiers_en_construction.count < 6 - if procedure_overview.old_dossiers_en_construction.count < 6
\: \:
- old_dossiers_en_construction = procedure_overview.old_dossiers_en_construction.map do |old_dossier| - old_dossiers_en_construction = procedure_overview.old_dossiers_en_construction.map do |old_dossier|
- link_to "nº #{old_dossier.id}", gestionnaire_dossier_url(procedure_overview.procedure, old_dossier), style: 'color: #0069CC;' - link_to "nº #{old_dossier.id}", instructeur_dossier_url(procedure_overview.procedure, old_dossier), style: 'color: #0069CC;'
- end.join(', ') - end.join(', ')
= sanitize(old_dossiers_en_construction, attributes: %w(href style)) = sanitize(old_dossiers_en_construction, attributes: %w(href style))
@ -44,7 +44,7 @@
- if procedure_overview.old_dossiers_en_instruction.count < 6 - if procedure_overview.old_dossiers_en_instruction.count < 6
\: \:
- old_dossiers_en_instruction = procedure_overview.old_dossiers_en_instruction.map do |old_dossier| - old_dossiers_en_instruction = procedure_overview.old_dossiers_en_instruction.map do |old_dossier|
- link_to "nº #{old_dossier.id}", gestionnaire_dossier_url(procedure_overview.procedure, old_dossier), style: 'color: #0069CC;' - link_to "nº #{old_dossier.id}", instructeur_dossier_url(procedure_overview.procedure, old_dossier), style: 'color: #0069CC;'
- end.join(', ') - end.join(', ')
= sanitize(old_dossiers_en_instruction, attributes: %w(href style)) = sanitize(old_dossiers_en_instruction, attributes: %w(href style))

View file

@ -3,6 +3,6 @@
%p %p
= "#{@sender.email} vous a envoyé le dossier nº #{@dossier.id}, cliquez sur le lien ci-dessous pour y accéder :" = "#{@sender.email} vous a envoyé le dossier nº #{@dossier.id}, cliquez sur le lien ci-dessous pour y accéder :"
= link_to(gestionnaire_dossier_url(@dossier.procedure, @dossier), gestionnaire_dossier_url(@dossier.procedure, @dossier)) = link_to(instructeur_dossier_url(@dossier.procedure, @dossier), instructeur_dossier_url(@dossier.procedure, @dossier))
= render partial: "layouts/mailers/signature" = render partial: "layouts/mailers/signature"

View file

@ -3,7 +3,7 @@
%p %p
Veuillez cliquer sur le lien suivant pour vous connecter sur le site demarches-simplifiees.fr :  Veuillez cliquer sur le lien suivant pour vous connecter sur le site demarches-simplifiees.fr : 
= link_to(sign_in_by_link_url(@gestionnaire_id, jeton: @login_token), sign_in_by_link_url(@gestionnaire_id, jeton: @login_token)) = link_to(sign_in_by_link_url(@instructeur_id, jeton: @login_token), sign_in_by_link_url(@instructeur_id, jeton: @login_token))
%p %p
Ce lien est Ce lien est

View file

@ -0,0 +1,3 @@
= link_to "/instructeurs/sign_out", method: :delete do
%span.fa.fa-sign-out
Se déconnecter

View file

@ -1,7 +1,7 @@
.container .container
= form_for @gestionnaire, url: { controller: 'gestionnaires/activate', action: :create }, html: { class: "form" } do |f| = form_for @instructeur, url: { controller: 'instructeurs/activate', action: :create }, html: { class: "form" } do |f|
%br %br
%h1= @gestionnaire.email %h1= @instructeur.email
= f.password_field :password, placeholder: 'Mot de passe' = f.password_field :password, placeholder: 'Mot de passe'
= f.hidden_field :reset_password_token, value: params[:token] = f.hidden_field :reset_password_token, value: params[:token]
= f.submit 'Définir le mot de passe', class: 'button large primary expand' = f.submit 'Définir le mot de passe', class: 'button large primary expand'

View file

@ -0,0 +1,10 @@
.sub-header
.container
%ul.breadcrumbs
%li= link_to('Avis', instructeur_avis_index_path)
%li= "#{dossier.procedure.libelle}, dossier nº #{dossier.id}"
%ul.tabs
= dynamic_tab_item('Demande', instructeur_avis_path(avis))
= dynamic_tab_item('Avis', instruction_instructeur_avis_path(avis), notification: avis.answer.blank?)
= dynamic_tab_item('Messagerie', messagerie_instructeur_avis_path(avis))

View file

@ -1,4 +1,4 @@
- avis_statut = (@statut == Gestionnaires::AvisController::A_DONNER_STATUS) ? 'à donner' : 'rendus' - avis_statut = (@statut == Instructeurs::AvisController::A_DONNER_STATUS) ? 'à donner' : 'rendus'
- content_for(:title, "Avis #{avis_statut}") - content_for(:title, "Avis #{avis_statut}")
.sub-header .sub-header
@ -7,14 +7,14 @@
%h1.tab-title Avis %h1.tab-title Avis
%ul.tabs %ul.tabs
= tab_item('avis à donner', = tab_item('avis à donner',
gestionnaire_avis_index_path(statut: Gestionnaires::AvisController::A_DONNER_STATUS), instructeur_avis_index_path(statut: Instructeurs::AvisController::A_DONNER_STATUS),
active: @statut == Gestionnaires::AvisController::A_DONNER_STATUS, active: @statut == Instructeurs::AvisController::A_DONNER_STATUS,
badge: @avis_a_donner.count, badge: @avis_a_donner.count,
notification: @avis_a_donner.any?) notification: @avis_a_donner.any?)
= tab_item("avis #{'donné'.pluralize(@avis_donnes.count)}", = tab_item("avis #{'donné'.pluralize(@avis_donnes.count)}",
gestionnaire_avis_index_path(statut: Gestionnaires::AvisController::DONNES_STATUS), instructeur_avis_index_path(statut: Instructeurs::AvisController::DONNES_STATUS),
active: @statut == Gestionnaires::AvisController::DONNES_STATUS, active: @statut == Instructeurs::AvisController::DONNES_STATUS,
badge: @avis_donnes.count) badge: @avis_donnes.count)
.container .container
@ -29,11 +29,11 @@
- @avis.each do |avis| - @avis.each do |avis|
%tr %tr
%td.number-col %td.number-col
= link_to(gestionnaire_avis_path(avis), class: 'cell-link') do = link_to(instructeur_avis_path(avis), class: 'cell-link') do
%span.icon.folder %span.icon.folder
#{avis.dossier.id} #{avis.dossier.id}
%td= link_to(avis.dossier.user.email, gestionnaire_avis_path(avis), class: 'cell-link') %td= link_to(avis.dossier.user.email, instructeur_avis_path(avis), class: 'cell-link')
%td= link_to(avis.dossier.procedure.libelle, gestionnaire_avis_path(avis), class: 'cell-link') %td= link_to(avis.dossier.procedure.libelle, instructeur_avis_path(avis), class: 'cell-link')
= paginate(@avis) = paginate(@avis)
- else - else
%h2.empty-text Aucun avis %h2.empty-text Aucun avis

View file

@ -11,7 +11,7 @@
%span.date Demande d'avis envoyée le #{l(@avis.created_at, format: '%d/%m/%y')} %span.date Demande d'avis envoyée le #{l(@avis.created_at, format: '%d/%m/%y')}
%p.introduction= @avis.introduction %p.introduction= @avis.introduction
= form_for @avis, url: gestionnaire_avis_path(@avis), html: { class: 'form' } do |f| = form_for @avis, url: instructeur_avis_path(@avis), html: { class: 'form' } do |f|
= f.text_area :answer, rows: 3, placeholder: 'Votre avis', required: true = f.text_area :answer, rows: 3, placeholder: 'Votre avis', required: true
= render partial: "shared/attachment/update", locals: { attachment: @avis.piece_justificative_file.attachment, user_can_destroy: true, form: f } = render partial: "shared/attachment/update", locals: { attachment: @avis.piece_justificative_file.attachment, user_can_destroy: true, form: f }
@ -28,7 +28,7 @@
= f.submit 'Envoyer votre avis', class: 'button send' = f.submit 'Envoyer votre avis', class: 'button send'
- if !@dossier.termine? - if !@dossier.termine?
= render partial: "gestionnaires/shared/avis/form", locals: { url: avis_gestionnaire_avis_path(@avis), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis } = render partial: "instructeurs/shared/avis/form", locals: { url: avis_instructeur_avis_path(@avis), must_be_confidentiel: @avis.confidentiel?, avis: @new_avis }
- if @dossier.avis_for(current_gestionnaire).present? - if @dossier.avis_for(current_instructeur).present?
= render partial: 'gestionnaires/shared/avis/list', locals: { avis: @dossier.avis_for(current_gestionnaire), avis_seen_at: nil } = render partial: 'instructeurs/shared/avis/list', locals: { avis: @dossier.avis_for(current_instructeur), avis_seen_at: nil }

Some files were not shown because too many files have changed in this diff Show more