Merge branch 'dev'
This commit is contained in:
commit
aa93a4ff2c
17 changed files with 161 additions and 81 deletions
|
@ -1,38 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
class Users::ConfirmationsController < Devise::ConfirmationsController
|
|
||||||
# GET /resource/confirmation/new
|
|
||||||
# def new
|
|
||||||
# super
|
|
||||||
# end
|
|
||||||
|
|
||||||
# POST /resource/confirmation
|
|
||||||
# def create
|
|
||||||
# super
|
|
||||||
# end
|
|
||||||
|
|
||||||
# GET /resource/confirmation?confirmation_token=abcdef
|
|
||||||
# def show
|
|
||||||
# super
|
|
||||||
# end
|
|
||||||
|
|
||||||
protected
|
|
||||||
|
|
||||||
# The path used after resending confirmation instructions.
|
|
||||||
# def after_resending_confirmation_instructions_path_for(resource_name)
|
|
||||||
# super(resource_name)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# The path used after confirmation.
|
|
||||||
def after_confirmation_path_for(resource_name, resource)
|
|
||||||
check_invite!(resource)
|
|
||||||
|
|
||||||
super(resource_name, resource)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def check_invite!(user)
|
|
||||||
Invite.where(email: user.email).update_all user_id: user.id
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,7 +1,10 @@
|
||||||
class Users::Dossiers::InvitesController < UsersController
|
class Users::Dossiers::InvitesController < UsersController
|
||||||
def authenticate_user!
|
def authenticate_user!
|
||||||
session["user_return_to"] = request.fullpath
|
session["user_return_to"] = request.fullpath
|
||||||
return redirect_to new_user_registration_path(user_email: params[:email]) if params[:email].present? && User.find_by(email: params[:email]).nil?
|
|
||||||
|
if params[:email].present? && User.find_by(email: params[:email]).nil?
|
||||||
|
return redirect_to new_user_registration_path(user: { email: params[:email] })
|
||||||
|
end
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,9 +9,13 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
||||||
# end
|
# end
|
||||||
|
|
||||||
# GET /resource/sign_up
|
# GET /resource/sign_up
|
||||||
# def new
|
def new
|
||||||
# super
|
# Allow pre-filling the user email from a query parameter
|
||||||
# end
|
build_resource({ email: sign_up_params[:email] })
|
||||||
|
|
||||||
|
yield resource if block_given?
|
||||||
|
respond_with resource
|
||||||
|
end
|
||||||
|
|
||||||
# POST /resource
|
# POST /resource
|
||||||
def create
|
def create
|
||||||
|
|
|
@ -326,6 +326,18 @@ class Procedure < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mean_traitement_time
|
||||||
|
mean_time(:en_construction_at, :processed_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
def mean_verification_time
|
||||||
|
mean_time(:en_construction_at, :en_instruction_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
def mean_instruction_time
|
||||||
|
mean_time(:en_instruction_at, :processed_at)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def can_publish?(path)
|
def can_publish?(path)
|
||||||
|
@ -388,4 +400,15 @@ class Procedure < ApplicationRecord
|
||||||
self.durees_conservation_required ||= duree_conservation_dossiers_hors_ds.present? && duree_conservation_dossiers_dans_ds.present?
|
self.durees_conservation_required ||= duree_conservation_dossiers_hors_ds.present? && duree_conservation_dossiers_dans_ds.present?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mean_time(start_attribute, end_attribute)
|
||||||
|
times = dossiers
|
||||||
|
.state_termine
|
||||||
|
.pluck(start_attribute, end_attribute)
|
||||||
|
.map { |times| times[1] - times[0] }
|
||||||
|
|
||||||
|
if times.present?
|
||||||
|
times.sum.fdiv(times.size).ceil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,6 +24,11 @@ class User < ApplicationRecord
|
||||||
|
|
||||||
before_validation -> { sanitize_email(:email) }
|
before_validation -> { sanitize_email(:email) }
|
||||||
|
|
||||||
|
# Callback provided by Devise
|
||||||
|
def after_confirmation
|
||||||
|
link_invites!
|
||||||
|
end
|
||||||
|
|
||||||
def self.find_for_france_connect(email, siret)
|
def self.find_for_france_connect(email, siret)
|
||||||
user = User.find_by(email: email)
|
user = User.find_by(email: email)
|
||||||
if user.nil?
|
if user.nil?
|
||||||
|
@ -49,4 +54,10 @@ class User < ApplicationRecord
|
||||||
def owns_or_invite?(dossier)
|
def owns_or_invite?(dossier)
|
||||||
owns?(dossier) || invite?(dossier.id)
|
owns?(dossier) || invite?(dossier.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def link_invites!
|
||||||
|
Invite.where(email: email).update_all(user_id: id)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email
|
Afin de répondre à cette invitation, merci de vous inscrire avec l'adresse email
|
||||||
= @invite.email
|
= @invite.email
|
||||||
sur
|
sur
|
||||||
= "#{users_dossiers_invite_url(@invite.id)}?email=#{@invite.email}"
|
= users_dossiers_invite_url(@invite.id, params: { email: @invite.email })
|
||||||
|
|
||||||
%p
|
%p
|
||||||
Bonne journée,
|
Bonne journée,
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
= succeed '.' do
|
= succeed '.' do
|
||||||
%strong votre dossier passera directement en instruction
|
%strong votre dossier passera directement en instruction
|
||||||
|
|
||||||
|
- if dossier.procedure.mean_verification_time
|
||||||
|
- cache(dossier.procedure, expires_in: 1.week) do
|
||||||
|
%p
|
||||||
|
Le temps moyen de vérification pour cette démarche est de #{distance_of_time_in_words(dossier.procedure.mean_verification_time)}.
|
||||||
|
|
||||||
- elsif dossier.en_instruction?
|
- elsif dossier.en_instruction?
|
||||||
.en-instruction
|
.en-instruction
|
||||||
%p Votre dossier est complet. Il est en cours d’examen par les instructeur de l’administration.
|
%p Votre dossier est complet. Il est en cours d’examen par les instructeur de l’administration.
|
||||||
|
@ -34,6 +39,10 @@
|
||||||
%strong
|
%strong
|
||||||
vous recevrez un email
|
vous recevrez un email
|
||||||
avec le résultat.
|
avec le résultat.
|
||||||
|
- if dossier.procedure.mean_instruction_time
|
||||||
|
- cache(dossier.procedure, expires_in: 1.week) do
|
||||||
|
%p
|
||||||
|
Le temps moyen d’instruction pour cette démarche est de #{distance_of_time_in_words(dossier.procedure.mean_instruction_time)}.
|
||||||
|
|
||||||
- elsif dossier.accepte?
|
- elsif dossier.accepte?
|
||||||
.accepte
|
.accepte
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
.column.auth-form
|
.column.auth-form
|
||||||
= devise_error_messages!
|
= devise_error_messages!
|
||||||
= form_for User.new, url: user_registration_path, html: { class: "form" } do |f|
|
= form_for resource, url: user_registration_path, html: { class: "form" } do |f|
|
||||||
%h1 Créez-vous un compte
|
%h1 Créez-vous un compte
|
||||||
|
|
||||||
= f.label :email, "Email"
|
= f.label :email, "Email"
|
||||||
|
|
|
@ -47,7 +47,6 @@ fr:
|
||||||
submit:
|
submit:
|
||||||
publish: Publier
|
publish: Publier
|
||||||
reopen: Réactiver
|
reopen: Réactiver
|
||||||
|
|
||||||
support:
|
support:
|
||||||
info demarche: J'ai un problème lors du remplissage de mon dossier
|
info demarche: J'ai un problème lors du remplissage de mon dossier
|
||||||
info instruction: J'ai une question sur l'instruction de mon dossier
|
info instruction: J'ai une question sur l'instruction de mon dossier
|
||||||
|
|
|
@ -70,8 +70,7 @@ Rails.application.routes.draw do
|
||||||
devise_for :users, controllers: {
|
devise_for :users, controllers: {
|
||||||
sessions: 'users/sessions',
|
sessions: 'users/sessions',
|
||||||
registrations: 'users/registrations',
|
registrations: 'users/registrations',
|
||||||
passwords: 'users/passwords',
|
passwords: 'users/passwords'
|
||||||
confirmations: 'users/confirmations'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
devise_scope :user do
|
devise_scope :user do
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
describe Users::ConfirmationsController, type: :controller do
|
|
||||||
let(:email) { 'mail@beta.gouv.fr' }
|
|
||||||
let(:user) do
|
|
||||||
create(:user,
|
|
||||||
email: email,
|
|
||||||
password: 'a good password',
|
|
||||||
confirmation_token: '123',
|
|
||||||
confirmed_at: nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
before { @request.env["devise.mapping"] = Devise.mappings[:user] }
|
|
||||||
|
|
||||||
describe '#check_invite!' do
|
|
||||||
let!(:invite) { create(:invite, email: email) }
|
|
||||||
let!(:invite2) { create(:invite, email: email) }
|
|
||||||
|
|
||||||
before { get :show, params: { confirmation_token: user.confirmation_token } }
|
|
||||||
|
|
||||||
it 'the new user is connect at his two invite' do
|
|
||||||
expect(User.last.invites.size).to eq(2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -33,7 +33,7 @@ describe Users::Dossiers::InvitesController, type: :controller do
|
||||||
|
|
||||||
context 'when email is not affected at an user' do
|
context 'when email is not affected at an user' do
|
||||||
let(:email) { 'new_user@octo.com' }
|
let(:email) { 'new_user@octo.com' }
|
||||||
it { is_expected.to redirect_to new_user_registration_path(user_email: email) }
|
it { is_expected.to redirect_to new_user_registration_path(user: { email: email }) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,22 @@ describe Users::RegistrationsController, type: :controller do
|
||||||
@request.env["devise.mapping"] = Devise.mappings[:user]
|
@request.env["devise.mapping"] = Devise.mappings[:user]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#new' do
|
||||||
|
subject! { get :new }
|
||||||
|
|
||||||
|
it { expect(response).to have_http_status(:ok) }
|
||||||
|
it { expect(response).to render_template(:new) }
|
||||||
|
|
||||||
|
context 'when an email address is provided' do
|
||||||
|
render_views true
|
||||||
|
subject! { get :new, params: { user: { email: 'test@exemple.fr' } } }
|
||||||
|
|
||||||
|
it 'prefills the form with the email address' do
|
||||||
|
expect(response.body).to include('test@exemple.fr')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#create' do
|
describe '#create' do
|
||||||
subject do
|
subject do
|
||||||
post :create, params: { user: user }
|
post :create, params: { user: user }
|
||||||
|
|
|
@ -97,9 +97,9 @@ FactoryBot.define do
|
||||||
trait :accepte do
|
trait :accepte do
|
||||||
after(:create) do |dossier, _evaluator|
|
after(:create) do |dossier, _evaluator|
|
||||||
dossier.state = Dossier.states.fetch(:accepte)
|
dossier.state = Dossier.states.fetch(:accepte)
|
||||||
dossier.processed_at = dossier.created_at + 1.minute
|
dossier.processed_at ||= dossier.created_at + 1.minute
|
||||||
dossier.en_construction_at = dossier.created_at + 2.minutes
|
dossier.en_construction_at ||= dossier.created_at + 2.minutes
|
||||||
dossier.created_at = dossier.created_at + 3.minutes
|
dossier.created_at ||= dossier.created_at + 3.minutes
|
||||||
dossier.save!
|
dossier.save!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,6 +10,10 @@ describe 'Dossier details:' do
|
||||||
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, true)
|
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Flipflop::FeatureSet.current.test!.switch!(:new_dossier_details, false)
|
||||||
|
end
|
||||||
|
|
||||||
scenario 'the user can see the summary of the dossier status' do
|
scenario 'the user can see the summary of the dossier status' do
|
||||||
visit_dossier dossier
|
visit_dossier dossier
|
||||||
|
|
||||||
|
@ -19,6 +23,34 @@ describe 'Dossier details:' do
|
||||||
expect(page).to have_text(dossier.commentaires.last.body)
|
expect(page).to have_text(dossier.commentaires.last.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "the user can see the mean time they are expected to wait" do
|
||||||
|
context "the dossier is in construction" do
|
||||||
|
before do
|
||||||
|
other_dossier = create(:dossier, :accepte, :for_individual, procedure: simple_procedure, en_construction_at: 10.days.ago, en_instruction_at: Time.now)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "show the proper wait time" do
|
||||||
|
visit_dossier dossier
|
||||||
|
|
||||||
|
expect(page).to have_text("Le temps moyen de vérification pour cette démarche est de 10 jours.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "the dossier is in instruction" do
|
||||||
|
let(:dossier) { create(:dossier, :en_instruction, :for_individual, :with_commentaires, user: user, procedure: simple_procedure) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
other_dossier = create(:dossier, :accepte, :for_individual, procedure: simple_procedure, en_instruction_at: 2.months.ago, processed_at: Time.now)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "show the proper wait time" do
|
||||||
|
visit_dossier dossier
|
||||||
|
|
||||||
|
expect(page).to have_text("Le temps moyen d’instruction pour cette démarche est de 2 mois.")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario 'the user can see and edit dossier before instruction' do
|
scenario 'the user can see and edit dossier before instruction' do
|
||||||
visit_dossier dossier
|
visit_dossier dossier
|
||||||
click_on 'Demande'
|
click_on 'Demande'
|
||||||
|
|
|
@ -24,11 +24,37 @@ feature 'Invitations' do
|
||||||
expect(page).to have_field('Libelle du champ', with: 'Some edited value')
|
expect(page).to have_field('Libelle du champ', with: 'Some edited value')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when inviting someone without an existing account' do
|
||||||
|
let(:invite) { create(:invite_user, dossier: dossier, user: nil) }
|
||||||
|
let(:user_password) { 'l33tus3r' }
|
||||||
|
|
||||||
|
scenario 'an invited user can register using the registration link sent in the invitation email' do
|
||||||
|
# Click the invitation link
|
||||||
|
visit users_dossiers_invite_path(invite.id, params: { email: invite.email })
|
||||||
|
|
||||||
|
# Create the account
|
||||||
|
expect(page).to have_current_path(new_user_registration_path, ignore_query: true)
|
||||||
|
expect(page).to have_field('user_email', with: invite.email)
|
||||||
|
fill_in 'user_password', with: user_password
|
||||||
|
click_on 'Créer un compte'
|
||||||
|
|
||||||
|
expect(page).to have_content('lien de confirmation')
|
||||||
|
|
||||||
|
# Confirm the email
|
||||||
|
user = User.find_by(email: invite.email)
|
||||||
|
visit Rails.application.routes.url_helpers.user_confirmation_path(confirmation_token: user.confirmation_token)
|
||||||
|
submit_login_form(user.email, user_password)
|
||||||
|
|
||||||
|
# The user should be redirected to the dossier they was invited on
|
||||||
|
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scenario 'an invited user can see and edit the draft', js: true do
|
scenario 'an invited user can see and edit the draft', js: true do
|
||||||
visit users_dossiers_invite_path(invite)
|
visit users_dossiers_invite_path(invite)
|
||||||
expect(page).to have_current_path(new_user_session_path)
|
expect(page).to have_current_path(new_user_session_path)
|
||||||
|
|
||||||
submit_login_form(invited_user)
|
submit_login_form(invited_user.email, invited_user.password)
|
||||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||||
expect(page).to have_no_selector('.button.invite-user-action')
|
expect(page).to have_no_selector('.button.invite-user-action')
|
||||||
|
|
||||||
|
@ -42,7 +68,7 @@ feature 'Invitations' do
|
||||||
visit users_dossiers_invite_path(invite)
|
visit users_dossiers_invite_path(invite)
|
||||||
expect(page).to have_current_path(new_user_session_path)
|
expect(page).to have_current_path(new_user_session_path)
|
||||||
|
|
||||||
submit_login_form(invited_user)
|
submit_login_form(invited_user.email, invited_user.password)
|
||||||
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
expect(page).to have_current_path(brouillon_dossier_path(dossier))
|
||||||
|
|
||||||
expect(page).to have_button('Soumettre le dossier', disabled: true)
|
expect(page).to have_button('Soumettre le dossier', disabled: true)
|
||||||
|
@ -68,7 +94,7 @@ feature 'Invitations' do
|
||||||
visit users_dossiers_invite_path(invite)
|
visit users_dossiers_invite_path(invite)
|
||||||
expect(page).to have_current_path(new_user_session_path)
|
expect(page).to have_current_path(new_user_session_path)
|
||||||
|
|
||||||
submit_login_form(invited_user)
|
submit_login_form(invited_user.email, invited_user.password)
|
||||||
expect(page).to have_current_path(users_dossiers_invite_path(invite))
|
expect(page).to have_current_path(users_dossiers_invite_path(invite))
|
||||||
expect(page).to have_no_selector('.button.invite-user-action')
|
expect(page).to have_no_selector('.button.invite-user-action')
|
||||||
expect(page).to have_text("Dossier nº #{dossier.id}")
|
expect(page).to have_text("Dossier nº #{dossier.id}")
|
||||||
|
@ -92,13 +118,13 @@ feature 'Invitations' do
|
||||||
def log_in(user)
|
def log_in(user)
|
||||||
visit '/'
|
visit '/'
|
||||||
click_on 'Connexion'
|
click_on 'Connexion'
|
||||||
submit_login_form(user)
|
submit_login_form(user.email, user.password)
|
||||||
expect(page).to have_current_path(dossiers_path)
|
expect(page).to have_current_path(dossiers_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def submit_login_form(user)
|
def submit_login_form(email, password)
|
||||||
fill_in 'user_email', with: user.email
|
fill_in 'user_email', with: email
|
||||||
fill_in 'user_password', with: user.password
|
fill_in 'user_password', with: password
|
||||||
click_on 'Se connecter'
|
click_on 'Se connecter'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,25 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe User, type: :model do
|
describe User, type: :model do
|
||||||
|
describe '#after_confirmation' do
|
||||||
|
let(:email) { 'mail@beta.gouv.fr' }
|
||||||
|
let!(:invite) { create(:invite, email: email) }
|
||||||
|
let!(:invite2) { create(:invite, email: email) }
|
||||||
|
let(:user) do
|
||||||
|
create(:user,
|
||||||
|
email: email,
|
||||||
|
password: 'a good password',
|
||||||
|
confirmation_token: '123',
|
||||||
|
confirmed_at: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'when confirming a user, it links the pending invitations to this user' do
|
||||||
|
expect(user.invites.size).to eq(0)
|
||||||
|
user.confirm
|
||||||
|
expect(user.reload.invites.size).to eq(2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#find_for_france_connect' do
|
describe '#find_for_france_connect' do
|
||||||
let(:siret) { '00000000000000' }
|
let(:siret) { '00000000000000' }
|
||||||
context 'when user exist' do
|
context 'when user exist' do
|
||||||
|
|
Loading…
Reference in a new issue