Merge pull request #4184 from betagouv/remove_instructeur_devise_account

Remove instructeur devise account
This commit is contained in:
LeSim 2019-08-13 17:28:51 +02:00 committed by GitHub
commit c370b61abd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 275 additions and 304 deletions

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

@ -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

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

@ -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

@ -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

@ -79,8 +79,6 @@ Rails.application.routes.draw do
devise_for :administrateurs, skip: :all
devise_for :instructeurs, skip: :all
devise_for :users, controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
@ -154,11 +152,9 @@ 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

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

@ -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

@ -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

@ -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
@ -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,7 +110,7 @@ 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
@ -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'
@ -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
@ -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
@ -246,7 +246,7 @@ describe Instructeurs::DossiersController, type: :controller do
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' }
@ -288,7 +288,7 @@ describe Instructeurs::DossiersController, type: :controller do
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)

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

@ -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

@ -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')

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' }