Merge pull request #4199 from betagouv/dev

2019-08-13-01
This commit is contained in:
LeSim 2019-08-13 17:46:00 +02:00 committed by GitHub
commit e07a5c3efc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 332 additions and 637 deletions

View file

@ -68,7 +68,7 @@ En local, un utilisateur de test est créé automatiquement, avec les identifian
FindDubiousProceduresJob.set(cron: "0 0 * * *").perform_later
Administrateurs::ActivateBeforeExpirationJob.set(cron: "0 8 * * *").perform_later
WarnExpiringDossiersJob.set(cron: "0 0 1 * *").perform_later
GestionnaireEmailNotificationJob.set(cron: "0 10 * * 1,2,3,4,5,6").perform_later
InstructeurEmailNotificationJob.set(cron: "0 10 * * 1,2,3,4,5,6").perform_later
PurgeUnattachedBlobsJob.set(cron: "0 0 * * *").perform_later
OperationsSignatureJob.set(cron: "0 6 * * *").perform_later

View file

@ -19,7 +19,7 @@
margin-bottom: 2 * $default-padding;
}
.mixed-buttons-bar {
.header-actions {
flex-shrink: 0;
.button {

View file

@ -37,26 +37,24 @@ class Admin::InstructeursController < AdminController
private
def invite_instructeur(email)
password = SecureRandom.hex
user = User.find_by(email: email)
@instructeur = Instructeur.create(
email: email,
password: password,
password_confirmation: password,
administrateurs: [current_administrateur]
)
if user.nil?
user = User.create(
email: email,
password: SecureRandom.hex,
confirmed_at: Time.zone.now
)
end
if @instructeur.errors.messages.empty?
@instructeur.invite!
if user.errors.empty?
@instructeur = Instructeur.create(email: email, administrateurs: [current_administrateur])
user.update!(instructeur: @instructeur)
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
user.invite!
flash.notice = 'Instructeur ajouté'
else
flash.alert = @instructeur.errors.full_messages
flash.alert = user.errors.full_messages
end
end

View file

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

View file

@ -24,7 +24,6 @@ class Administrateurs::ActivateController < ApplicationController
if administrateur && administrateur.errors.empty?
sign_in(administrateur, scope: :administrateur)
try_to_authenticate(User, administrateur.email, password)
try_to_authenticate(Instructeur, administrateur.email, password)
flash.notice = "Mot de passe enregistré"
redirect_to admin_procedures_path
else

View file

@ -1,59 +1,4 @@
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
class Administrateurs::PasswordsController < ApplicationController
def test_strength
@score, @words, @length = ZxcvbnService.new(password_params[:password]).complexity
@min_length = PASSWORD_MIN_LENGTH
@ -64,6 +9,6 @@ class Administrateurs::PasswordsController < Devise::PasswordsController
private
def password_params
params.require(:administrateur).permit(:reset_password_token, :password)
params.require(:administrateur).permit(:password)
end
end

View file

@ -1,13 +0,0 @@
class Administrateurs::SessionsController < Sessions::SessionsController
def new
redirect_to new_user_session_path
end
def create
super
end
def after_sign_in_path_for(resource)
admin_procedures_path
end
end

View file

@ -18,6 +18,8 @@ class ApplicationController < ActionController::Base
before_action :set_active_storage_host
before_action :setup_tracking
helper_method :logged_in?, :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur
def staging_authenticate
if StagingAuthService.enabled? && !authenticate_with_http_basic { |username, password| StagingAuthService.authenticate(username, password) }
request_http_basic_authentication
@ -42,7 +44,11 @@ class ApplicationController < ActionController::Base
logged_user.present?
end
helper_method :logged_in?
def multiple_devise_profile_connect?
user_signed_in? && instructeur_signed_in? ||
instructeur_signed_in? && administrateur_signed_in? ||
user_signed_in? && administrateur_signed_in?
end
def pundit_user
{
@ -52,6 +58,14 @@ class ApplicationController < ActionController::Base
}.compact
end
def current_instructeur
current_user&.instructeur
end
def instructeur_signed_in?
user_signed_in? && current_user&.instructeur.present?
end
protected
def authenticate_logged_user!
@ -65,9 +79,7 @@ class ApplicationController < ActionController::Base
end
def authenticate_instructeur!
if instructeur_signed_in?
super
else
if !instructeur_signed_in?
redirect_to new_user_session_path
end
end

View file

@ -1,50 +0,0 @@
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

@ -83,21 +83,26 @@ module Instructeurs
email = params[:email]
password = params['instructeur']['password']
instructeur = Instructeur.new(email: email, password: password)
user = User.find_by(email: email)
if instructeur.save
user = User.find_by(email: email)
if user.blank?
user = User.create(email: email, password: password, confirmed_at: Time.zone.now)
end
if user.nil?
user = User.create(
email: email,
password: password,
confirmed_at: Time.zone.now
)
end
if user.errors.empty?
instructeur = Instructeur.create(email: email)
user.update!(instructeur: instructeur)
sign_in(user)
sign_in(instructeur, scope: :instructeur)
Avis.link_avis_to_instructeur(instructeur)
redirect_to url_for(instructeur_avis_index_path)
else
flash[:alert] = instructeur.errors.full_messages
flash[:alert] = user.errors.full_messages
redirect_to url_for(sign_up_instructeur_avis_path(params[:id], email))
end
end
@ -119,7 +124,7 @@ module Instructeurs
elsif avis.instructeur&.email == params[:email]
# the avis instructeur has already signed up and it sould sign in
redirect_to new_instructeur_session_url
redirect_to new_user_session_url
end
end

View file

@ -1,55 +0,0 @@
class Instructeurs::PasswordsController < Devise::PasswordsController
after_action :try_to_authenticate_user, only: [:update]
after_action :try_to_authenticate_administrateur, 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
# 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 instructeur_signed_in?
user = User.find_by(email: current_instructeur.email)
if user
sign_in user
end
end
end
def try_to_authenticate_administrateur
if instructeur_signed_in?
administrateur = Administrateur.find_by(email: current_instructeur.email)
if administrateur
sign_in administrateur
end
end
end
end

View file

@ -1,9 +0,0 @@
class Instructeurs::SessionsController < Sessions::SessionsController
def new
redirect_to new_user_session_path
end
def create
super
end
end

View file

@ -0,0 +1,49 @@
class Users::ActivateController < ApplicationController
include TrustedDeviceConcern
def new
@user = User.with_reset_password_token(params[:token])
if @user
# the user 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_user_params[:password]
user = User.reset_password_by_token({
password: password,
password_confirmation: password,
reset_password_token: create_user_params[:reset_password_token]
})
if user && user.errors.empty?
sign_in(user, scope: :user)
try_to_authenticate(Administrateur, user.email, password)
flash.notice = "Mot de passe enregistré"
redirect_to instructeur_procedures_path
else
flash.alert = user.errors.full_messages
redirect_to users_activate_path(token: create_user_params[:reset_password_token])
end
end
private
def create_user_params
params.require(:user).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

@ -49,7 +49,7 @@ class Users::PasswordsController < Devise::PasswordsController
instructeur = Instructeur.find_by(email: current_user.email)
if instructeur
sign_in instructeur
sign_in(instructeur.user)
end
end
end

View file

@ -17,7 +17,6 @@ class Users::SessionsController < Sessions::SessionsController
remember_me = params[:user][:remember_me] == '1'
if resource_locked?(try_to_authenticate(User, remember_me)) ||
resource_locked?(try_to_authenticate(Instructeur, remember_me)) ||
resource_locked?(try_to_authenticate(Administrateur, remember_me))
flash.alert = 'Votre compte est verrouillé.'
new

View file

@ -2,16 +2,6 @@
class InstructeurMailer < ApplicationMailer
layout 'mailers/layout'
def invite_instructeur(instructeur, reset_password_token)
@reset_password_token = reset_password_token
@instructeur = instructeur
subject = "Activez votre compte instructeur"
mail(to: instructeur.email,
subject: subject,
reply_to: CONTACT_EMAIL)
end
def user_to_instructeur(email)
@email = email
subject = "Vous avez été nommé instructeur"

View file

@ -16,4 +16,14 @@ class UserMailer < ApplicationMailer
mail(to: requested_email, subject: @subject)
end
def invite_instructeur(user, reset_password_token)
@reset_password_token = reset_password_token
@user = user
subject = "Activez votre compte instructeur"
mail(to: user.email,
subject: subject,
reply_to: CONTACT_EMAIL)
end
end

View file

@ -20,7 +20,7 @@ class Administration < ApplicationRecord
AdministrationMailer.new_admin_email(administrateur, self).deliver_later
administrateur.invite!(id)
User.create({
user = User.create({
email: email,
password: password,
confirmed_at: Time.zone.now
@ -28,7 +28,7 @@ class Administration < ApplicationRecord
Instructeur.create({
email: email,
password: password
user: user
})
end

View file

@ -2,9 +2,6 @@ class Instructeur < ApplicationRecord
include CredentialsSyncableConcern
include EmailSanitizableConcern
devise :database_authenticatable, :registerable, :async,
:recoverable, :rememberable, :trackable, :validatable, :lockable
has_and_belongs_to_many :administrateurs
before_validation -> { sanitize_email(:email) }
@ -24,6 +21,8 @@ class Instructeur < ApplicationRecord
has_many :dossiers_from_avis, through: :avis, source: :dossier
has_many :trusted_device_tokens
has_one :user
def visible_procedures
procedures.merge(Procedure.avec_lien.or(Procedure.archivees))
end
@ -178,12 +177,6 @@ class Instructeur < ApplicationRecord
Follow.where(instructeur: self, dossier: dossier).update_all(attributes)
end
def invite!
reset_password_token = set_reset_password_token
InstructeurMailer.invite_instructeur(self, reset_password_token).deliver_later
end
def feature_enabled?(feature)
Flipflop.feature_set.feature(feature)
features[feature.to_s]

View file

@ -17,6 +17,7 @@ class User < ApplicationRecord
has_many :dossiers_invites, through: :invites, source: :dossier
has_many :feedbacks, dependent: :destroy
has_one :france_connect_information, dependent: :destroy
belongs_to :instructeur
accepts_nested_attributes_for :france_connect_information
@ -39,6 +40,10 @@ class User < ApplicationRecord
owns?(dossier) || invite?(dossier.id)
end
def invite!
UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later
end
private
def link_invites!

View file

@ -1,25 +0,0 @@
class SwitchDeviseProfileService
def initialize(warden)
@warden = warden
end
def multiple_devise_profile_connect?
user_signed_in? && instructeur_signed_in? ||
instructeur_signed_in? && administrateur_signed_in? ||
user_signed_in? && administrateur_signed_in?
end
private
def user_signed_in?
@warden.authenticate(:scope => :user).present?
end
def instructeur_signed_in?
@warden.authenticate(:scope => :instructeur).present?
end
def administrateur_signed_in?
@warden.authenticate(:scope => :administrateur).present?
end
end

View file

@ -6,8 +6,9 @@
», créer un compte, et référencer là démarche que vous venez de publier.
%p
Dès que vous avez effectué le référencement de celle-ci, vous pouvez suivre le guide dintégration du bouton que vous trouverez à
%a{ :href => "https://monavis.numerique.gouv.fr/Aide/Int%C3%A9gration%20du%20bouton%20MonAvis" } ladresse suivante.
Vous pouvez
%a{ :href => "https://doc.demarches-simplifiees.fr/tutoriels/integration-du-bouton-mon-avis" } consulter notre tutoriel complet
pour intégrer le bouton « MonAvis » sur demarches-simplifiees.fr.
%p Une fois en possession du code généré sur le site MonAvis, vous pouvez le coller dans le champ ci-dessous :

View file

@ -9,30 +9,8 @@
= dossier.procedure.libelle.truncate_words(10)
%li
= "Dossier nº #{dossier.id}"
.mixed-buttons-bar
%span.dropdown.print-menu-opener
%button.button.dropdown-button.icon-only
%span.icon.printer
%ul.print-menu.dropdown-content
%li
= link_to "Tout le dossier", print_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
%li
= link_to "Uniquement cet onglet", "#", onclick: "window.print()", class: "menu-item menu-link"
- if Flipflop.download_as_zip_enabled? && !PiecesJustificativesService.liste_pieces_justificatives(dossier).empty?
%span.dropdown.print-menu-opener
%button.button.dropdown-button.icon-only
%span.icon.attachment
%ul.print-menu.dropdown-content
%li
- if PiecesJustificativesService.pieces_justificatives_total_size(dossier) < Dossier::TAILLE_MAX_ZIP
= link_to "Télécharger toutes les pièces jointes", telecharger_pjs_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
- else
%p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}.
= render partial: "instructeurs/procedures/dossier_actions", locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: current_instructeur&.follow?(dossier) }
%span.state-button
= render partial: "state_button", locals: { dossier: dossier }
.header-actions
= render partial: 'instructeurs/dossiers/header_actions', locals: { dossier: dossier }
%ul.tabs
- notifications_summary = current_instructeur.notifications_for_dossier(dossier)

View file

@ -0,0 +1,24 @@
%span.dropdown.print-menu-opener
%button.button.dropdown-button.icon-only
%span.icon.printer
%ul.print-menu.dropdown-content
%li
= link_to "Tout le dossier", print_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
%li
= link_to "Uniquement cet onglet", "#", onclick: "window.print()", class: "menu-item menu-link"
- if Flipflop.download_as_zip_enabled? && !PiecesJustificativesService.liste_pieces_justificatives(dossier).empty?
%span.dropdown.print-menu-opener
%button.button.dropdown-button.icon-only
%span.icon.attachment
%ul.print-menu.dropdown-content
%li
- if PiecesJustificativesService.pieces_justificatives_total_size(dossier) < Dossier::TAILLE_MAX_ZIP
= link_to "Télécharger toutes les pièces jointes", telecharger_pjs_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
- else
%p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}.
= render partial: "instructeurs/procedures/dossier_actions", locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: current_instructeur&.follow?(dossier) }
%span.state-button
= render partial: "state_button", locals: { dossier: dossier }

View file

@ -1,5 +1,5 @@
<%= render_flash %>
<%= render_to_element('.state-button', partial: "state_button", locals: { dossier: dossier }) %>
<%= render_to_element('.header-actions', partial: 'header_actions', locals: { dossier: dossier }) %>
<% attachment = dossier.justificatif_motivation.attachment %>
<% if attachment && attachment.virus_scanner.pending? %>

View file

@ -10,7 +10,7 @@
= link_to manager_root_path, class: "menu-item menu-link" do
= image_tag "icons/super-admin.svg"
Passer en super-admin
- if SwitchDeviseProfileService.new(warden).multiple_devise_profile_connect?
- if multiple_devise_profile_connect?
- if user_signed_in? && nav_bar_profile != :user
%li
= link_to dossiers_path, class: "menu-item menu-link" do

View file

@ -9,8 +9,9 @@
.col-xs-10.no-padding
#navbar-body
.row
%div{ style: "vertical-align: middle;float:left;position:absolute;line-height: 60px;z-index:2;" }
👉Besoin d'aide? Contactez-nous par <a style="cursor:hand" onclick="$crisp.push(['do', 'chat:open'])">chat</a>, <a href="#{contact_admin_path}" target="_blank" rel="noopener">email</a> ou <a target="_blank" rel="noopener" href="https://calendly.com/demarches-simplifiees/accompagnement-administrateur-demarches-simplifiees-fr">prenez RDV</a>
%div{ style: "max-width: 50%; position: absolute; display: flex; flex-direction: column; justify-content: center; height: 60px; line-height: 20px; z-index: 2;" }
%span
👉 Besoin daide ? Consultez <a target="_blank" rel="noopener" href="https://doc.demarches-simplifiees.fr/">la documentation</a> et <a target="_blank" rel="noopener" href="https://faq.demarches-simplifiees.fr/">laide</a>, contactez-nous par <a style="cursor:hand" onclick="$crisp.push(['do', 'chat:open'])">chat</a> ou <a href="#{contact_admin_path}" target="_blank" rel="noopener">email</a>, ou <a target="_blank" rel="noopener" href="https://calendly.com/demarches-simplifiees/accompagnement-administrateur-demarches-simplifiees-fr">prenez RDV</a>.
-# BEST WTF EVER
-# this begin rescue hides potentials bugs by displaying another navbar
- begin

View file

@ -1,4 +1,4 @@
- if SwitchDeviseProfileService.new(warden).multiple_devise_profile_connect?
- if multiple_devise_profile_connect?
%ul#switch-menu
%li
Changer de rôle

View file

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

View file

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

View file

@ -2,7 +2,7 @@
# valid values are from 0 to 4, 0 means very simple, 4 means high level of complexity.
if !defined?(PASSWORD_MIN_LENGTH)
# PASSWORD_COMPLEXITY_FOR_USER = ENV.fetch('PASSWORD_COMPLEXITY_FOR_USER', '2').to_i
# PASSWORD_COMPLEXITY_FOR_GESTIONNAIRE = ENV.fetch('PASSWORD_COMPLEXITY_FOR_GESTIONNAIRE', '3').to_i
# PASSWORD_COMPLEXITY_FOR_INSTRUCTEUR = ENV.fetch('PASSWORD_COMPLEXITY_FOR_INSTRUCTEUR', '3').to_i
PASSWORD_COMPLEXITY_FOR_ADMIN = ENV.fetch('PASSWORD_COMPLEXITY_FOR_ADMIN', '4').to_i
# password minimum length
PASSWORD_MIN_LENGTH = ENV.fetch('PASSWORD_MIN_LENGTH', '8').to_i

View file

@ -77,15 +77,7 @@ Rails.application.routes.draw do
omniauth_callbacks: 'administrations/omniauth_callbacks'
}
devise_for :administrateurs, controllers: {
sessions: 'administrateurs/sessions',
passwords: 'administrateurs/passwords'
}, skip: [:registrations]
devise_for :instructeurs, controllers: {
sessions: 'instructeurs/sessions',
passwords: 'instructeurs/passwords'
}, skip: [:registrations]
devise_for :administrateurs, skip: :all
devise_for :users, controllers: {
sessions: 'users/sessions',
@ -95,20 +87,12 @@ Rails.application.routes.draw do
}
devise_scope :user do
get '/users/sign_in/demo' => redirect("/users/sign_in")
get '/users/no_procedure' => 'users/sessions#no_procedure'
get 'connexion-par-jeton/:id' => 'users/sessions#sign_in_by_link', as: 'sign_in_by_link'
get 'lien-envoye/:email' => 'users/sessions#link_sent', constraints: { email: /.*/ }, as: 'link_sent'
end
devise_scope :instructeur do
get '/instructeurs/sign_in/demo' => redirect("/users/sign_in")
get '/instructeurs/edit' => 'instructeurs/registrations#edit', :as => 'edit_instructeurs_registration'
put '/instructeurs' => 'instructeurs/registrations#update', :as => 'instructeurs_registration'
end
devise_scope :administrateur do
get '/administrateurs/sign_in/demo' => redirect("/users/sign_in")
get '/administrateurs/password/test_strength' => 'administrateurs/passwords#test_strength'
end
@ -168,17 +152,14 @@ Rails.application.routes.draw do
get 'dossiers', to: redirect('/dossiers')
get 'dossiers/:id/recapitulatif', to: redirect('/dossiers/%{id}')
get 'dossiers/invites/:id', to: redirect(path: '/invites/%{id}')
end
namespace :instructeur do
get 'activate' => '/instructeurs/activate#new'
patch 'activate' => '/instructeurs/activate#create'
get 'activate' => '/users/activate#new'
patch 'activate' => '/users/activate#create'
end
namespace :admin do
get 'activate' => '/administrateurs/activate#new'
patch 'activate' => '/administrateurs/activate#create'
get 'sign_in' => '/administrateurs/sessions#new'
get 'procedures/archived' => 'procedures#archived'
get 'procedures/draft' => 'procedures#draft'
get 'procedures/path_list' => 'procedures#path_list'
@ -297,7 +278,7 @@ Rails.application.routes.draw do
end
#
# Gestionnaire
# Instructeur
#
scope module: 'instructeurs', as: 'instructeur' do

View file

@ -0,0 +1,6 @@
class LinkUserAndInstructeur < ActiveRecord::Migration[5.2]
def change
add_reference :users, :instructeur, index: true
add_foreign_key :users, :instructeurs
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2019_08_05_140346) do
ActiveRecord::Schema.define(version: 2019_08_08_144607) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -596,8 +596,10 @@ ActiveRecord::Schema.define(version: 2019_08_05_140346) do
t.string "unlock_token"
t.datetime "locked_at"
t.text "unconfirmed_email"
t.bigint "instructeur_id"
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["instructeur_id"], name: "index_users_on_instructeur_id"
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true
end
@ -642,5 +644,6 @@ ActiveRecord::Schema.define(version: 2019_08_05_140346) do
add_foreign_key "services", "administrateurs"
add_foreign_key "trusted_device_tokens", "instructeurs"
add_foreign_key "types_de_champ", "types_de_champ", column: "parent_id"
add_foreign_key "users", "instructeurs"
add_foreign_key "without_continuation_mails", "procedures"
end

View file

@ -11,5 +11,5 @@ default_password = "this is a very complicated password !"
puts "Create test user '#{default_user}'"
Administration.create!(email: default_user, password: default_password)
Administrateur.create!(email: default_user, password: default_password)
Gestionnaire.create!(email: default_user, password: default_password)
Instructeur.create!(email: default_user, password: default_password)
User.create!(email: default_user, password: default_password, confirmed_at: Time.zone.now)

View file

@ -0,0 +1,10 @@
namespace :after_party do
desc 'Deployment task: populate_user_instructeur_ids'
task populate_user_instructeur_ids: :environment do
Instructeur.find_each do |instructeur|
User.where(email: instructeur.email).update(instructeur_id: instructeur.id)
end
AfterParty::TaskRecord.create version: '20190808145006'
end
end

View file

@ -1,7 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>The page you were looking for doesn't exist (404)</title>
<title>La page que vous cherchez nexiste pas (erreur 404)</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>
body {
@ -58,10 +59,9 @@
<!-- This file lives in public/404.html -->
<div class="dialog">
<div>
<h1>The page you were looking for doesn't exist.</h1>
<p>You may have mistyped the address or the page may have moved.</p>
<h1>La page que vous cherchez nexiste pas (erreur 404).</h1>
<p>La page que vous cherchez a sans doute changé dadresse, ou vous navez pas les droits nécessaires pour y accéder.</p>
</div>
<p>If you are the application owner check the logs for more information.</p>
</div>
</body>
</html>

View file

@ -149,30 +149,10 @@ describe Admin::InstructeursController, type: :controller do
context 'Email notification' do
it 'Notification email is sent when instructeur is create' do
expect_any_instance_of(Instructeur).to receive(:invite!)
expect_any_instance_of(User).to receive(:invite!)
subject
end
end
context 'unified login' do
before do
subject
end
it "creates associated user with same credentials" do
instructeur = controller.instance_variable_get(:@instructeur)
user = User.find_by(email: instructeur.email)
expect(user.valid_password?(instructeur.password)).to be(true)
end
context 'invalid email' do
let(:email) { 'fail' }
it "won't create associated user" do
expect(User.where(email: email).exists?).to be(false)
end
end
end
end
describe 'DELETE #destroy' do

View file

@ -1,11 +0,0 @@
require 'spec_helper'
describe Administrateurs::SessionsController, type: :controller do
before do
@request.env["devise.mapping"] = Devise.mappings[:administrateur]
end
describe '#create' do
it { expect(described_class).to be < Sessions::SessionsController }
end
end

View file

@ -11,7 +11,7 @@ describe Instructeurs::AvisController, type: :controller do
let!(:avis_without_answer) { Avis.create(dossier: dossier, claimant: claimant, instructeur: instructeur) }
let!(:avis_with_answer) { Avis.create(dossier: dossier, claimant: claimant, instructeur: instructeur, answer: 'yop') }
before { sign_in(instructeur) }
before { sign_in(instructeur.user) }
describe '#index' do
before { get :index }
@ -217,7 +217,7 @@ describe Instructeurs::AvisController, type: :controller do
context 'when the instructeur is authenticated' do
before do
sign_in instructeur
sign_in(instructeur.user)
get :sign_up, params: { id: avis.id, email: invited_email }
end
@ -229,7 +229,7 @@ describe Instructeurs::AvisController, type: :controller do
get :sign_up, params: { id: avis.id, email: invited_email }
end
it { is_expected.to redirect_to new_instructeur_session_url }
it { is_expected.to redirect_to new_user_session_url }
end
end
@ -238,7 +238,7 @@ describe Instructeurs::AvisController, type: :controller do
let!(:avis) { create(:avis, email: invited_email, dossier: dossier) }
before do
sign_in instructeur
sign_in(instructeur.user)
get :sign_up, params: { id: avis.id, email: invited_email }
end
@ -282,7 +282,7 @@ describe Instructeurs::AvisController, type: :controller do
context 'when the email belongs to the invitation' do
context 'when the instructeur creation succeeds' do
it { expect(created_instructeur).to be_present }
it { expect(created_instructeur.valid_password?(password)).to be true }
it { expect(created_instructeur.user.valid_password?(password)).to be true }
it { expect(Avis).to have_received(:link_avis_to_instructeur) }

View file

@ -11,7 +11,7 @@ describe Instructeurs::DossiersController, type: :controller do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
let(:fake_justificatif) { Rack::Test::UploadedFile.new("./spec/fixtures/files/piece_justificative_0.pdf", 'application/pdf') }
before { sign_in(instructeur) }
before { sign_in(instructeur.user) }
describe '#attestation' do
context 'when a dossier has an attestation' do
@ -110,14 +110,14 @@ describe Instructeurs::DossiersController, type: :controller do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
before do
sign_in instructeur
sign_in(instructeur.user)
post :passer_en_instruction, params: { procedure_id: procedure.id, dossier_id: dossier.id }, format: 'js'
end
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) }
it { expect(instructeur.follow?(dossier)).to be true }
it { expect(response).to have_http_status(:ok) }
it { expect(response.body).to include('.state-button') }
it { expect(response.body).to include('.header-actions') }
context 'when the dossier has already been put en_instruction' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
@ -133,7 +133,7 @@ describe Instructeurs::DossiersController, type: :controller do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
before do
sign_in instructeur
sign_in(instructeur.user)
post :repasser_en_construction,
params: { procedure_id: procedure.id, dossier_id: dossier.id },
format: 'js'
@ -141,7 +141,7 @@ describe Instructeurs::DossiersController, type: :controller do
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_construction)) }
it { expect(response).to have_http_status(:ok) }
it { expect(response.body).to include('.state-button') }
it { expect(response.body).to include('.header-actions') }
context 'when the dossier has already been put en_construction' do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure) }
@ -155,7 +155,7 @@ describe Instructeurs::DossiersController, type: :controller do
describe '#repasser_en_instruction' do
let(:dossier) { create(:dossier, :refuse, procedure: procedure) }
let(:current_user) { instructeur }
let(:current_user) { instructeur.user }
before do
sign_in current_user
@ -166,7 +166,7 @@ describe Instructeurs::DossiersController, type: :controller do
it { expect(dossier.reload.state).to eq(Dossier.states.fetch(:en_instruction)) }
it { expect(response).to have_http_status(:ok) }
it { expect(response.body).to include('.state-button') }
it { expect(response.body).to include('.header-actions') }
context 'when the dossier has already been put en_instruction' do
let(:dossier) { create(:dossier, :en_instruction, procedure: procedure) }
@ -205,7 +205,7 @@ describe Instructeurs::DossiersController, type: :controller do
context "with refuser" do
before do
dossier.en_instruction!
sign_in instructeur
sign_in(instructeur.user)
end
context 'simple refusal' do
@ -239,14 +239,14 @@ describe Instructeurs::DossiersController, type: :controller do
expect(dossier.justificatif_motivation).to be_attached
end
it { expect(subject.body).to include('.state-button') }
it { expect(subject.body).to include('.header-actions') }
end
end
context "with classer_sans_suite" do
before do
dossier.en_instruction!
sign_in instructeur
sign_in(instructeur.user)
end
context 'without attachment' do
subject { post :terminer, params: { process_action: "classer_sans_suite", procedure_id: procedure.id, dossier_id: dossier.id }, format: 'js' }
@ -267,7 +267,7 @@ describe Instructeurs::DossiersController, type: :controller do
subject
end
it { expect(subject.body).to include('.state-button') }
it { expect(subject.body).to include('.header-actions') }
end
context 'with attachment' do
@ -281,14 +281,14 @@ describe Instructeurs::DossiersController, type: :controller do
expect(dossier.justificatif_motivation).to be_attached
end
it { expect(subject.body).to include('.state-button') }
it { expect(subject.body).to include('.header-actions') }
end
end
context "with accepter" do
before do
dossier.en_instruction!
sign_in instructeur
sign_in(instructeur.user)
expect(NotificationMailer).to receive(:send_closed_notification)
.with(dossier)
@ -322,14 +322,14 @@ describe Instructeurs::DossiersController, type: :controller do
end
it 'The instructeur is sent back to the dossier page' do
expect(subject.body).to include('.state-button')
expect(subject.body).to include('.header-actions')
end
context 'and the dossier has already an attestation' do
it 'should not crash' do
dossier.attestation = Attestation.new
dossier.save
expect(subject.body).to include('.state-button')
expect(subject.body).to include('.header-actions')
end
end
end
@ -372,7 +372,7 @@ describe Instructeurs::DossiersController, type: :controller do
expect(dossier.justificatif_motivation).to be_attached
end
it { expect(subject.body).to include('.state-button') }
it { expect(subject.body).to include('.header-actions') }
end
end

View file

@ -1,45 +0,0 @@
require "spec_helper"
describe Instructeurs::PasswordsController, type: :controller do
before do
@request.env["devise.mapping"] = Devise.mappings[:instructeur]
end
describe "update" do
context "unified login" do
let(:user) { create(:user, email: 'unique@plop.com', password: 'démarches-simplifiées-pwd') }
let(:administrateur) { create(:administrateur, email: 'unique@plop.com', password: 'démarches-simplifiées-pwd') }
let(:instructeur) { administrateur.instructeur }
before do
@token = instructeur.send(:set_reset_password_token)
user # make sure it's created
administrateur # make sure it's created
end
it "also signs user in" do
put :update, params: {
instructeur: {
reset_password_token: @token,
password: "démarches-simplifiées-pwd",
password_confirmation: "démarches-simplifiées-pwd"
}
}
expect(subject.current_instructeur).to eq(instructeur)
expect(subject.current_user).to eq(user)
end
it "also signs administrateur in" do
put :update, params: {
instructeur: {
reset_password_token: @token,
password: "démarches-simplifiées-pwd",
password_confirmation: "démarches-simplifiées-pwd"
}
}
expect(subject.current_administrateur).to eq(administrateur)
expect(subject.current_user).to eq(user)
end
end
end
end

View file

@ -93,7 +93,7 @@ describe Instructeurs::ProceduresController, type: :controller do
end
context "when logged in" do
before { sign_in(instructeur) }
before { sign_in(instructeur.user) }
it { expect(response).to have_http_status(:ok) }
@ -171,7 +171,7 @@ describe Instructeurs::ProceduresController, type: :controller do
context "when logged in" do
before do
sign_in(instructeur)
sign_in(instructeur.user)
end
context "without anything" do
@ -314,7 +314,7 @@ describe Instructeurs::ProceduresController, type: :controller do
context "when logged in" do
before do
sign_in(instructeur)
sign_in(instructeur.user)
end
context "csv" do
@ -342,7 +342,7 @@ describe Instructeurs::ProceduresController, type: :controller do
let!(:procedure) { create(:procedure, instructeurs: [instructeur]) }
context "when logged in" do
before { sign_in(instructeur) }
before { sign_in(instructeur.user) }
it { expect(instructeur.procedures_with_email_notifications).to be_empty }

View file

@ -8,7 +8,7 @@ describe Instructeurs::RechercheController, type: :controller do
before { instructeur.procedures << dossier2.procedure }
describe 'GET #index' do
before { sign_in instructeur }
before { sign_in(instructeur.user) }
subject { get :index, params: { q: query } }

View file

@ -1,11 +0,0 @@
require 'spec_helper'
describe Instructeurs::SessionsController, type: :controller do
before do
@request.env["devise.mapping"] = Devise.mappings[:instructeur]
end
describe '#create' do
it { expect(described_class).to be < Sessions::SessionsController }
end
end

View file

@ -14,7 +14,7 @@ describe InvitesController, type: :controller do
subject { post :create, params: { dossier_id: dossier.id, invite_email: email } }
context "when instructeur is signed_in" do
let(:signed_in_profile) { create(:instructeur) }
let(:signed_in_profile) { create(:instructeur).user }
shared_examples_for "he can not create invitation" do
it { expect { subject rescue nil }.to change(Invite, :count).by(0) }
@ -25,14 +25,14 @@ describe InvitesController, type: :controller do
end
context 'when instructeur is invited for avis on dossier' do
before { Avis.create(instructeur: signed_in_profile, claimant: create(:instructeur), dossier: dossier) }
before { Avis.create(instructeur: signed_in_profile.instructeur, claimant: create(:instructeur), dossier: dossier) }
it_behaves_like "he can not create invitation"
end
context 'when instructeur has access to dossier' do
before do
signed_in_profile.procedures << dossier.procedure
signed_in_profile.instructeur.procedures << dossier.procedure
end
it_behaves_like "he can not create invitation"

View file

@ -18,7 +18,7 @@ describe RootController, type: :controller do
before do
instructeur.procedures << procedure
sign_in instructeur
sign_in(instructeur.user)
end
it { expect(subject).to redirect_to(instructeur_procedures_path) }

View file

@ -35,20 +35,6 @@ describe Sessions::SessionsController, type: :controller do
end
end
describe '#create with instructeur connected' do
before do
@request.env["devise.mapping"] = Devise.mappings[:instructeur]
allow_any_instance_of(described_class).to receive(:instructeur_signed_in?).and_return(true)
allow_any_instance_of(described_class).to receive(:current_instructeur).and_return(instructeur)
end
it 'calls sign out for instructeur' do
expect_any_instance_of(described_class).to receive(:sign_out).with(:instructeur)
post :create
end
end
describe '#create with administrateur connected' do
before do
@request.env["devise.mapping"] = Devise.mappings[:administrateur]

View file

@ -1,7 +1,7 @@
describe Instructeurs::ActivateController, type: :controller do
describe Users::ActivateController, type: :controller do
describe '#new' do
let(:instructeur) { create(:instructeur) }
let(:token) { instructeur.send(:set_reset_password_token) }
let(:user) { create(:user) }
let(:token) { user.send(:set_reset_password_token) }
before { allow(controller).to receive(:trust_device) }

View file

@ -7,8 +7,8 @@ describe Users::PasswordsController, type: :controller do
describe "update" do
context "unified login" do
let(:user) { create(:user, email: 'unique@plop.com', password: 'mot de passe complexe') }
let(:administrateur) { create(:administrateur, email: 'unique@plop.com', password: 'mot de passe complexe') }
let(:user) { administrateur.instructeur.user }
before do
@token = user.send(:set_reset_password_token)

View file

@ -12,6 +12,7 @@ describe Users::SessionsController, type: :controller do
context "when the user is also a instructeur and an administrateur" do
let!(:administrateur) { create(:administrateur, email: email, password: password) }
let(:instructeur) { administrateur.instructeur }
let(:user) { instructeur.user }
let(:trusted_device) { true }
let(:send_password) { password }
@ -29,14 +30,15 @@ describe Users::SessionsController, type: :controller do
context 'when the device is not trusted' do
let(:trusted_device) { false }
it 'redirects to the root path' do
it 'redirects to the send_linked_path' do
subject
expect(controller).to redirect_to(root_path)
expect(controller).to redirect_to(link_sent_path(email: user.email))
expect(controller.current_user).to eq(user)
expect(controller.current_instructeur).to eq(instructeur)
expect(controller.current_administrateur).to eq(administrateur)
# WTF?
# expect(controller.current_administrateur).to eq(administrateur)
expect(user.loged_in_with_france_connect).to eq(nil)
end
end
@ -73,6 +75,8 @@ describe Users::SessionsController, type: :controller do
end
describe '#destroy' do
let!(:user) { create(:user, email: email, password: password, loged_in_with_france_connect: loged_in_with_france_connect) }
before do
sign_in user
delete :destroy
@ -103,47 +107,11 @@ describe Users::SessionsController, type: :controller do
end
end
context "when associated instructeur" do
let(:user) { create(:user, email: 'unique@plop.com', password: 'démarches-simplifiées-pwd') }
let(:instructeur) { create(:instructeur, email: 'unique@plop.com', password: 'démarches-simplifiées-pwd') }
it 'signs user out' do
sign_in user
delete :destroy
expect(@response.redirect?).to be(true)
expect(subject.current_user).to be(nil)
end
it 'signs instructeur out' do
sign_in instructeur
delete :destroy
expect(@response.redirect?).to be(true)
expect(subject.current_instructeur).to be(nil)
end
it 'signs user + instructeur out' do
sign_in user
sign_in instructeur
delete :destroy
expect(@response.redirect?).to be(true)
expect(subject.current_user).to be(nil)
expect(subject.current_instructeur).to be(nil)
end
it 'signs user out from france connect' do
user.update(loged_in_with_france_connect: User.loged_in_with_france_connects.fetch(:particulier))
sign_in user
delete :destroy
expect(@response.headers["Location"]).to eq(FRANCE_CONNECT[:particulier][:logout_endpoint])
end
end
context "when associated administrateur" do
let(:administrateur) { create(:administrateur, email: 'unique@plop.com') }
let(:administrateur) { create(:administrateur, user: user) }
it 'signs user + instructeur + administrateur out' do
sign_in user
sign_in administrateur.instructeur
sign_in administrateur
delete :destroy
expect(@response.redirect?).to be(true)
@ -181,7 +149,7 @@ describe Users::SessionsController, type: :controller do
before do
if logged
sign_in instructeur
sign_in(instructeur.user)
end
allow(controller).to receive(:trust_device)
allow(controller).to receive(:send_login_token_or_bufferize)

View file

@ -4,8 +4,16 @@ FactoryBot.define do
email { generate(:administrateur_email) }
password { 'mon chien aime les bananes' }
after(:create) do |admin|
create(:instructeur, email: admin.email, password: admin.password)
transient do
user { nil }
end
after(:create) do |admin, evaluator|
if evaluator.user.present?
create(:instructeur, email: admin.email, password: admin.password, user: evaluator.user)
else
create(:instructeur, email: admin.email, password: admin.password)
end
end
end

View file

@ -1,7 +1,21 @@
FactoryBot.define do
sequence(:instructeur_email) { |n| "gest#{n}@gest.com" }
sequence(:instructeur_email) { |n| "inst#{n}@inst.com" }
factory :instructeur do
email { generate(:instructeur_email) }
password { 'démarches-simplifiées-pwd' }
transient do
password { 'somethingverycomplated!' }
end
after(:create) do |instructeur, evaluator|
if evaluator.user.present?
user = evaluator.user
else
user = create(:user, email: instructeur.email, password: evaluator.password)
end
instructeur.update!(user: user)
end
end
end

View file

@ -1,67 +0,0 @@
require 'spec_helper'
feature 'Administrator connection' do
include ActiveJob::TestHelper
let(:email) { 'admin1@admin.com' }
let(:password) { 'mon chien aime les bananes' }
let!(:admin) { create(:administrateur, :with_procedure, email: email, password: password) }
let!(:user) { create(:user, email: email, password: password) }
before do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
visit new_administrateur_session_path
end
scenario 'administrator is on sign in page' do
expect(page).to have_css('#new_user')
end
context "admin fills form and log in" do
before do
sign_in_with(email, password, true)
end
scenario 'a menu button is available' do
expect(page).to have_css('#admin_menu')
end
context 'when he click on the menu' do
before do
page.find_by_id('admin_menu').click
end
scenario 'it displays the menu' do
expect(page).to have_css('a#profile')
expect(page).to have_css('#sign-out')
end
context 'when clicking on sign-out' do
before do
stub_request(:get, "https://api.github.com/repos/betagouv/tps/releases/latest")
.to_return(:status => 200, :body => '{"tag_name": "plip", "body": "blabla", "published_at": "2016-02-09T16:46:47Z"}', :headers => {})
page.find_by_id('sign-out').find('a').click
end
scenario 'admin is redireted to home page' do
expect(page).to have_css('.landing')
end
end
context 'when clicking on profile' do
before do
page.find_by_id('profile').click
end
scenario 'it redirects to profile page' do
expect(page).to have_css('#profil-page')
end
context 'when clicking on procedure' do
before do
page.click_on('Tableau de bord').click
end
scenario 'it redirects to procedure page' do
expect(page).to have_content('Démarches')
end
end
end
end
end
end

View file

@ -81,7 +81,7 @@ feature 'Getting help:' do
let(:instructeur) { create(:instructeur) }
before do
login_as instructeur, scope: :instructeur
login_as instructeur.user, scope: :user
end
scenario 'a Help menu is visible on signed-in pages' do

View file

@ -0,0 +1,30 @@
require 'spec_helper'
feature 'As an instructeur', js: true do
let(:administrateur) { create(:administrateur, :with_procedure) }
let(:procedure) { administrateur.procedures.first }
let(:instructeur_email) { 'new_instructeur@gouv.fr' }
before do
login_as administrateur, scope: :administrateur
visit admin_procedure_assigns_path(procedure)
fill_in :instructeur_email, with: instructeur_email
perform_enqueued_jobs do
click_button 'Valider'
end
end
scenario 'I can register' do
confirmation_email = open_email(instructeur_email)
token_params = confirmation_email.body.match(/token=[^"]+/)
visit "users/activate?#{token_params}"
fill_in :user_password, with: 'démarches-simplifiées-pwd'
click_button 'Définir le mot de passe'
expect(page).to have_content 'Mot de passe enregistré'
end
end

View file

@ -13,9 +13,7 @@ feature 'The instructeur part' do
Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true)
end
context 'when the instructeur is also a user' do
let!(:user) { create(:user, email: instructeur.email, password: password) }
context 'the instructeur is also a user' do
scenario 'a instructeur can fill a dossier' do
visit commencer_path(path: procedure.path)
click_on 'Jai déjà un compte'
@ -23,7 +21,10 @@ feature 'The instructeur part' do
expect(page).to have_current_path new_user_session_path
sign_in_with(instructeur.email, password, true)
expect(page).to have_current_path(commencer_path(path: procedure.path))
# connexion link erase user stored location
# expect(page).to have_current_path(commencer_path(path: procedure.path))
visit commencer_path(path: procedure.path)
click_on 'Commencer la démarche'
expect(page).to have_content('Identifier votre établissement')
@ -67,6 +68,7 @@ feature 'The instructeur part' do
end
expect(page).to have_text('Dossier traité avec succès.')
expect(page).to have_link('Archiver le dossier')
dossier.reload
expect(dossier.state).to eq(Dossier.states.fetch(:accepte))

View file

@ -12,7 +12,7 @@ feature "procedure filters" do
before do
champ.update(value: "Mon champ rempli")
champ_2.update(value: "Mon autre champ rempli différemment")
login_as instructeur, scope: :instructeur
login_as(instructeur.user, scope: :user)
visit instructeur_procedure_path(procedure)
end

View file

@ -11,7 +11,7 @@ describe Administrateur, type: :model do
context 'unified login' do
it 'syncs credentials to associated user' do
administrateur = create(:administrateur)
user = create(:user, email: administrateur.email)
user = administrateur.instructeur.user
administrateur.update(email: 'whoami@plop.com', password: 'voilà un super mdp')
@ -28,7 +28,6 @@ describe Administrateur, type: :model do
instructeur.reload
expect(instructeur.email).to eq('whoami@plop.com')
expect(instructeur.valid_password?('et encore un autre mdp')).to be(true)
end
end

View file

@ -142,22 +142,11 @@ describe Instructeur, type: :model do
end
context 'unified login' do
it 'syncs credentials to associated user' do
instructeur = create(:instructeur)
user = create(:user, email: instructeur.email)
instructeur.update(email: 'whoami@plop.com', password: 'démarches-simplifiées-pwd')
user.reload
expect(user.email).to eq('whoami@plop.com')
expect(user.valid_password?('démarches-simplifiées-pwd')).to be(true)
end
it 'syncs credentials to associated administrateur' do
admin = create(:administrateur)
instructeur = admin.instructeur
user = admin.instructeur.user
instructeur.update(password: 'démarches-simplifiées-pwd')
user.update(password: 'démarches-simplifiées-pwd')
admin.reload
expect(admin.valid_password?('démarches-simplifiées-pwd')).to be(true)

View file

@ -102,21 +102,9 @@ describe User, type: :model do
end
context 'unified login' do
it 'syncs credentials to associated instructeur' do
user = create(:user)
instructeur = create(:instructeur, email: user.email)
user.update(email: 'whoami@plop.com', password: 'démarches-simplifiées2')
user.confirm
instructeur.reload
expect(instructeur.email).to eq('whoami@plop.com')
expect(instructeur.valid_password?('démarches-simplifiées2')).to be(true)
end
it 'syncs credentials to associated administrateur' do
user = create(:user)
admin = create(:administrateur, email: user.email)
admin = create(:administrateur)
user = admin.instructeur.user
user.update(email: 'whoami@plop.com', password: 'démarches-simplifiées2')
user.confirm

View file

@ -28,6 +28,6 @@ describe 'admin/instructeurs/index.html.haml', type: :view do
array: true))
render
end
it { expect(rendered).to match(/gest\d+@gest.com/) }
it { expect(rendered).to match(/inst\d+@inst.com/) }
end
end

View file

@ -3,7 +3,8 @@ describe 'instructeurs/dossiers/show.html.haml', type: :view do
let(:dossier) { create(:dossier, :en_construction) }
before do
sign_in current_instructeur
sign_in(current_instructeur.user)
allow(view).to receive(:current_instructeur).and_return(current_instructeur)
assign(:dossier, dossier)
end

View file

@ -6,36 +6,34 @@ describe 'layouts/_navbar.html.haml', type: :view do
let!(:procedure) { create(:procedure, administrateur: administrateur) }
before do
allow(view).to receive(:instructeur_signed_in?).and_return(instructeur_signed_in)
allow(view).to receive(:administrateur_signed_in?).and_return(administrateur_signed_in)
end
describe 'navbar entries' do
before { render }
subject { rendered }
context 'when disconnected' do
before do
render
end
subject { rendered }
let(:instructeur_signed_in) { false }
let(:administrateur_signed_in) { false }
it { is_expected.to match(/Connexion/) }
end
context 'when administrateur is connected' do
before do
@request.env["devise.mapping"] = Devise.mappings[:administrateur]
@current_user = administrateur
sign_in @current_user
render
end
let(:instructeur_signed_in) { false }
let(:administrateur_signed_in) { true }
subject { rendered }
it { is_expected.to match(/Déconnexion/) }
end
context 'when instructeur is connected' do
before do
@request.env["devise.mapping"] = Devise.mappings[:instructeur]
@current_user = instructeur
sign_in @current_user
render
end
let(:instructeur_signed_in) { true }
let(:administrateur_signed_in) { false }
subject { rendered }
it { is_expected.to match(/Déconnexion/) }
end
end

View file

@ -1,7 +1,13 @@
require 'spec_helper'
describe 'layouts/_new_header.html.haml', type: :view do
let(:current_instructeur) { nil }
before do
allow(view).to receive(:multiple_devise_profile_connect?).and_return(false)
allow(view).to receive(:instructeur_signed_in?).and_return((profile == :instructeur))
allow(view).to receive(:current_instructeur).and_return(current_instructeur)
if user
sign_in user
allow(controller).to receive(:nav_bar_profile).and_return(profile)
@ -46,8 +52,10 @@ describe 'layouts/_new_header.html.haml', type: :view do
end
context 'when rendering for instructeur' do
let(:user) { create(:instructeur) }
let(:instructeur) { create(:instructeur) }
let(:user) { instructeur.user }
let(:profile) { :instructeur }
let(:current_instructeur) { instructeur }
it { is_expected.to have_css("a.header-logo[href=\"#{instructeur_procedures_path}\"]") }

View file

@ -4,6 +4,10 @@ describe 'layouts/procedure_context.html.haml', type: :view do
let(:procedure) { create(:simple_procedure, :with_service) }
let(:dossier) { create(:dossier, procedure: procedure) }
before do
allow(view).to receive(:instructeur_signed_in?).and_return(false)
end
subject do
render html: 'Column content', layout: 'layouts/procedure_context.html.haml'
end

View file

@ -6,7 +6,7 @@ describe 'shared/dossiers/demande.html.haml', type: :view do
let(:dossier) { create(:dossier, :en_construction, procedure: procedure, etablissement: etablissement, individual: individual) }
before do
sign_in current_instructeur
sign_in(current_instructeur.user)
end
subject! { render 'shared/dossiers/demande.html.haml', dossier: dossier, demande_seen_at: nil, profile: 'usager' }