From 86b9ed20791f2a98861316fc4d4364b0262b38bd Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 1 Aug 2019 15:22:37 +0200 Subject: [PATCH 01/21] Run load scripts after ujs responces --- app/javascript/new_design/champs/carte.js | 2 +- app/javascript/new_design/messagerie.js | 2 +- app/javascript/new_design/procedure-context.js | 2 +- app/javascript/new_design/select2.js | 2 +- app/javascript/new_design/support.js | 2 +- app/javascript/packs/application-old.js | 1 + app/javascript/packs/application.js | 1 + app/javascript/shared/autocomplete.js | 12 ++---------- app/javascript/shared/franceconnect.js | 3 +-- app/javascript/shared/page-update-event.js | 9 +++++++++ app/javascript/shared/react-ujs.js | 2 +- 11 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 app/javascript/shared/page-update-event.js diff --git a/app/javascript/new_design/champs/carte.js b/app/javascript/new_design/champs/carte.js index f91b3b0d5..c4f8a3cb8 100644 --- a/app/javascript/new_design/champs/carte.js +++ b/app/javascript/new_design/champs/carte.js @@ -39,7 +39,7 @@ function diplayMap(element, data, initial = false) { } } -addEventListener('turbolinks:load', initialize); +addEventListener('ds:page:update', initialize); addEventListener('carte:update', ({ detail: { selector, data } }) => { const element = document.querySelector(selector); diff --git a/app/javascript/new_design/messagerie.js b/app/javascript/new_design/messagerie.js index 91e9190db..d2e056feb 100644 --- a/app/javascript/new_design/messagerie.js +++ b/app/javascript/new_design/messagerie.js @@ -14,4 +14,4 @@ export function scrollMessagerie() { } } -addEventListener('turbolinks:load', scrollMessagerie); +addEventListener('ds:page:update', scrollMessagerie); diff --git a/app/javascript/new_design/procedure-context.js b/app/javascript/new_design/procedure-context.js index a6de9431d..4ec90a6f2 100644 --- a/app/javascript/new_design/procedure-context.js +++ b/app/javascript/new_design/procedure-context.js @@ -14,7 +14,7 @@ function expandProcedureDescription() { descBody.classList.remove('read-more-collapsed'); } -addEventListener('turbolinks:load', updateReadMoreVisibility); +addEventListener('ds:page:update', updateReadMoreVisibility); addEventListener('resize', updateReadMoreVisibility); delegate('click', '.read-more-button', expandProcedureDescription); diff --git a/app/javascript/new_design/select2.js b/app/javascript/new_design/select2.js index ccd14b117..bbc8cdb86 100644 --- a/app/javascript/new_design/select2.js +++ b/app/javascript/new_design/select2.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import 'select2'; -addEventListener('turbolinks:load', () => { +addEventListener('ds:page:update', () => { $('select.select2').select2({ language: 'fr', width: '100%' diff --git a/app/javascript/new_design/support.js b/app/javascript/new_design/support.js index 1e6485c30..1c637ed88 100644 --- a/app/javascript/new_design/support.js +++ b/app/javascript/new_design/support.js @@ -12,5 +12,5 @@ function updateContactElementsVisibility() { } } -addEventListener('turbolinks:load', updateContactElementsVisibility); +addEventListener('ds:page:update', updateContactElementsVisibility); delegate('change', '#contact-form #type', updateContactElementsVisibility); diff --git a/app/javascript/packs/application-old.js b/app/javascript/packs/application-old.js index 7f06ccb32..180698e4b 100644 --- a/app/javascript/packs/application-old.js +++ b/app/javascript/packs/application-old.js @@ -4,6 +4,7 @@ import Rails from '@rails/ujs'; import * as ActiveStorage from '@rails/activestorage'; import jQuery from 'jquery'; +import '../shared/page-update-event'; import '../shared/activestorage/ujs'; import '../shared/rails-ujs-fix'; import '../shared/safari-11-file-xhr-workaround'; diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 13014a91a..784ba4497 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -9,6 +9,7 @@ import Highcharts from 'highcharts'; import ReactUJS from '../shared/react-ujs'; import reactComponents from '../shared/react-components'; +import '../shared/page-update-event'; import '../shared/activestorage/ujs'; import '../shared/activestorage/attachment-checker'; import '../shared/rails-ujs-fix'; diff --git a/app/javascript/shared/autocomplete.js b/app/javascript/shared/autocomplete.js index db9db0180..4aefffd57 100644 --- a/app/javascript/shared/autocomplete.js +++ b/app/javascript/shared/autocomplete.js @@ -37,22 +37,14 @@ function source(url) { }; } -addEventListener('turbolinks:load', function() { - autocompleteSetup(); -}); - -addEventListener('ajax:success', function() { - autocompleteSetup(); -}); - -function autocompleteSetup() { +addEventListener('ds:page:update', function() { for (let { type, url } of sources) { for (let element of document.querySelectorAll(selector(type))) { element.removeAttribute('data-autocomplete'); autocompleteInitializeElement(element, url); } } -} +}); function autocompleteInitializeElement(element, url) { const select = autocomplete(element, options, [source(url)]); diff --git a/app/javascript/shared/franceconnect.js b/app/javascript/shared/franceconnect.js index 59b6aa9cc..c6d7653a7 100644 --- a/app/javascript/shared/franceconnect.js +++ b/app/javascript/shared/franceconnect.js @@ -20,8 +20,7 @@ function init() { } } -addEventListener('DOMContentLoaded', init); -addEventListener('turbolinks:load', init); +addEventListener('ds:page:update', init); function toggleElement(event) { event.preventDefault(); diff --git a/app/javascript/shared/page-update-event.js b/app/javascript/shared/page-update-event.js new file mode 100644 index 000000000..c5038f81d --- /dev/null +++ b/app/javascript/shared/page-update-event.js @@ -0,0 +1,9 @@ +import { fire } from '@utils'; + +addEventListener('turbolinks:load', function() { + fire(document, 'ds:page:update'); +}); + +addEventListener('ajax:success', function() { + fire(document, 'ds:page:update'); +}); diff --git a/app/javascript/shared/react-ujs.js b/app/javascript/shared/react-ujs.js index f42ccf132..c6e937984 100644 --- a/app/javascript/shared/react-ujs.js +++ b/app/javascript/shared/react-ujs.js @@ -56,6 +56,6 @@ export default class ReactUJS { } start() { - addEventListener('turbolinks:load', () => this.mountComponents()); + addEventListener('ds:page:update', () => this.mountComponents()); } } From 4e9895c11be4cd7fe8fc39feb9177efe4876fb20 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Tue, 13 Aug 2019 17:45:51 +0000 Subject: [PATCH 02/21] app: mark the contact forms as not sensitive to trusted tokens Instructeurs waiting for a confirmation token should be able to access the contact form (especially to ask for help). Fix #4198 --- app/controllers/application_controller.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6e91e50b1..e06547561 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -201,6 +201,8 @@ class ApplicationController < ActionController::Base if path == '/' || path == '/users/sign_out' || + path == '/contact' || + path == '/contact-admin' || path.start_with?('/connexion-par-jeton') || path.start_with?('/api/') || path.start_with?('/lien-envoye') From ef66defcd17d7077455947cbd11b76610b4d7b7e Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 13 Aug 2019 19:37:42 +0100 Subject: [PATCH 03/21] Fix invite instructeur from manager --- app/controllers/manager/instructeurs_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/manager/instructeurs_controller.rb b/app/controllers/manager/instructeurs_controller.rb index 44b85e5a3..89ed9bdc3 100644 --- a/app/controllers/manager/instructeurs_controller.rb +++ b/app/controllers/manager/instructeurs_controller.rb @@ -2,7 +2,7 @@ module Manager class InstructeursController < Manager::ApplicationController def reinvite instructeur = Instructeur.find(params[:id]) - instructeur.invite! + instructeur.user.invite! flash[:notice] = "Instructeur réinvité." redirect_to manager_instructeur_path(instructeur) end From 182a9a5df236868194c251468c06a492162f71ce Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Tue, 13 Aug 2019 14:22:20 +0200 Subject: [PATCH 04/21] service: remove the mandatory SIRET field --- app/views/new_administrateur/services/_form.html.haml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/app/views/new_administrateur/services/_form.html.haml b/app/views/new_administrateur/services/_form.html.haml index 9b92b49a3..b5d2010ae 100644 --- a/app/views/new_administrateur/services/_form.html.haml +++ b/app/views/new_administrateur/services/_form.html.haml @@ -10,16 +10,6 @@ %span.mandatory * = f.text_field :organisme, placeholder: "mairie de Mours, préfecture de l'Oise, ministère de la Culture", required: true - = f.label :siret do - SIRET - %span.mandatory * - %p - Pour trouver votre numéro SIRET, utilisez - %a{ href: 'https://entreprise.data.gouv.fr/', target: '_blank', rel: 'noopener' } - entreprise.data.gouv.fr - ou renseignez-vous auprès de votre service comptable - = f.number_field :siret, required: true - = f.label :type_organisme do Type d’organisme %span.mandatory * From 0969b1f85f5bd78dda948f73816709d5adea9614 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 31 Jul 2019 15:04:49 +0200 Subject: [PATCH 05/21] Enable email_login_token for all gestionnaires --- app/controllers/application_controller.rb | 2 +- config/features.rb | 6 +- ...11_08_activate_trusted_device_for_a-f.rake | 8 --- .../application_controller_spec.rb | 62 ++++++++----------- .../users/sessions_controller_spec.rb | 4 +- .../features/instructeurs/instructeur_spec.rb | 4 -- spec/models/instructeur_spec.rb | 4 -- spec/support/feature_helpers.rb | 4 ++ 8 files changed, 36 insertions(+), 58 deletions(-) delete mode 100644 lib/tasks/2018_11_08_activate_trusted_device_for_a-f.rake diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e06547561..6b01ca41e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -183,7 +183,7 @@ class ApplicationController < ActionController::Base def redirect_if_untrusted if instructeur_signed_in? && sensitive_path && - Flipflop.enable_email_login_token? && + !Flipflop.bypass_email_login_token? && !IPService.ip_trusted?(request.headers['X-Forwarded-For']) && !trusted_device? diff --git a/config/features.rb b/config/features.rb index 1fa9ba3ee..11c9b3717 100644 --- a/config/features.rb +++ b/config/features.rb @@ -14,12 +14,12 @@ Flipflop.configure do end feature :web_hook - feature :enable_email_login_token feature :procedure_export_v2_enabled feature :operation_log_serialize_subject - feature :download_as_zip_enabled, - default: false + feature :download_as_zip_enabled + feature :bypass_email_login_token, + default: Rails.env.test? group :development do feature :mini_profiler_enabled, diff --git a/lib/tasks/2018_11_08_activate_trusted_device_for_a-f.rake b/lib/tasks/2018_11_08_activate_trusted_device_for_a-f.rake deleted file mode 100644 index fe55cb3ee..000000000 --- a/lib/tasks/2018_11_08_activate_trusted_device_for_a-f.rake +++ /dev/null @@ -1,8 +0,0 @@ -namespace :'activate_trusted_device_for_a-f' do - task run: :environment do - letters_a_to_f = ('a'..'f').to_a - Gestionnaire - .where("substr(email, 1, 1) IN (?)", letters_a_to_f) - .update_all(features: { "enable_email_login_token" => true }) - end -end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 49a1fdea7..24929f43e 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -166,56 +166,44 @@ describe ApplicationController, type: :controller do context 'when the path is sensitive' do let(:sensitive_path) { true } + before do + Flipflop::FeatureSet.current.test!.switch!(:bypass_email_login_token, false) + end + context 'when the instructeur is signed_in' do let(:instructeur_signed_in) { true } - context 'when the feature is activated' do - before do - Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true) + context 'when the ip is not trusted' do + let(:ip_trusted) { false } + + context 'when the device is trusted' do + let(:trusted_device) { true } + + before { subject } + + it { expect(@controller).not_to have_received(:redirect_to) } end - context 'when the ip is not trusted' do - let(:ip_trusted) { false } + context 'when the device is not trusted' do + let(:trusted_device) { false } - context 'when the device is trusted' do - let(:trusted_device) { true } + before { subject } - before { subject } - - it { expect(@controller).not_to have_received(:redirect_to) } - end + it { expect(@controller).to have_received(:redirect_to) } + it { expect(@controller).to have_received(:send_login_token_or_bufferize) } + it { expect(@controller).to have_received(:store_location_for) } end end - context 'when the feature is activated' do - before do - Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true) - end + context 'when the ip is trusted' do + let(:ip_trusted) { true } - context 'when the ip is untrusted' do - let(:ip_trusted) { false } + context 'when the device is not trusted' do + let(:trusted_device) { false } - context 'when the device is not trusted' do - let(:trusted_device) { false } + before { subject } - before { subject } - - it { expect(@controller).to have_received(:redirect_to) } - it { expect(@controller).to have_received(:send_login_token_or_bufferize) } - it { expect(@controller).to have_received(:store_location_for) } - end - end - - context 'when the ip is trusted' do - let(:ip_trusted) { true } - - context 'when the device is not trusted' do - let(:trusted_device) { false } - - before { subject } - - it { expect(@controller).not_to have_received(:redirect_to) } - end + it { expect(@controller).not_to have_received(:redirect_to) } end end end diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index e72a81ecc..887febc97 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -17,7 +17,6 @@ describe Users::SessionsController, type: :controller do let(:send_password) { password } before do - Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true) allow(controller).to receive(:trusted_device?).and_return(trusted_device) allow(InstructeurMailer).to receive(:send_login_token).and_return(double(deliver_later: true)) end @@ -28,6 +27,9 @@ describe Users::SessionsController, type: :controller do end context 'when the device is not trusted' do + before do + Flipflop::FeatureSet.current.test!.switch!(:bypass_email_login_token, false) + end let(:trusted_device) { false } it 'redirects to the send_linked_path' do diff --git a/spec/features/instructeurs/instructeur_spec.rb b/spec/features/instructeurs/instructeur_spec.rb index 20f8e26bf..ddef26937 100644 --- a/spec/features/instructeurs/instructeur_spec.rb +++ b/spec/features/instructeurs/instructeur_spec.rb @@ -9,10 +9,6 @@ feature 'The instructeur part' do let!(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) } let!(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction), procedure: procedure) } - before do - Flipflop::FeatureSet.current.test!.switch!(:enable_email_login_token, true) - end - context 'the instructeur is also a user' do scenario 'a instructeur can fill a dossier' do visit commencer_path(path: procedure.path) diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index fd77c45dc..2a98e6336 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -12,10 +12,6 @@ describe Instructeur, type: :model do assign(procedure_2) end - describe 'default features' do - it { expect(instructeur.features).to eq({ "enable_email_login_token" => true }) } - end - describe '#visible_procedures' do let(:procedure_not_assigned) { create :procedure, administrateur: admin } let(:procedure_with_default_path) { create :procedure, administrateur: admin } diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 14d24442a..00240a295 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -21,6 +21,10 @@ module FeatureHelpers fill_in :user_email, with: email fill_in :user_password, with: password + if sign_in_by_link + Flipflop::FeatureSet.current.test!.switch!(:bypass_email_login_token, false) + end + perform_enqueued_jobs do click_on 'Se connecter' end From 9eaf14968fbe836886632780774f13e8c6754d2c Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 31 Jul 2019 15:09:03 +0200 Subject: [PATCH 06/21] Enable export v2 for all --- .../procedures/_download_dossiers.html.haml | 18 ++++++++---------- config/features.rb | 1 - 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/app/views/instructeurs/procedures/_download_dossiers.html.haml b/app/views/instructeurs/procedures/_download_dossiers.html.haml index 08e222aa7..074752555 100644 --- a/app/views/instructeurs/procedures/_download_dossiers.html.haml +++ b/app/views/instructeurs/procedures/_download_dossiers.html.haml @@ -4,18 +4,16 @@ Télécharger tous les dossiers - old_format_limit_date = Date.parse("Oct 31 2019") - export_v1_enabled = old_format_limit_date > Time.zone.today - - export_v2_enabled = Flipflop.procedure_export_v2_enabled? || !export_v1_enabled - - old_format_message = export_v1_enabled && export_v2_enabled ? "(ancien format, jusqu’au #{old_format_limit_date.strftime('%d/%m/%Y')})" : '' - .dropdown-content.fade-in-down{ style: export_v1_enabled && export_v2_enabled ? 'width: 330px' : '' } + .dropdown-content.fade-in-down{ style: !export_v1_enabled ? 'width: 330px' : '' } %ul.dropdown-items - - if export_v2_enabled - %li - = link_to "Au format .xlsx", procedure_dossiers_download_path(procedure, format: :xlsx, version: 'v2'), target: "_blank", rel: "noopener" - %li - = link_to "Au format .ods", procedure_dossiers_download_path(procedure, format: :ods, version: 'v2'), target: "_blank", rel: "noopener" - %li - = link_to "Au format .csv", procedure_dossiers_download_path(procedure, format: :csv, version: 'v2'), target: "_blank", rel: "noopener" + %li + = link_to "Au format .xlsx", procedure_dossiers_download_path(procedure, format: :xlsx, version: 'v2'), target: "_blank", rel: "noopener" + %li + = link_to "Au format .ods", procedure_dossiers_download_path(procedure, format: :ods, version: 'v2'), target: "_blank", rel: "noopener" + %li + = link_to "Au format .csv", procedure_dossiers_download_path(procedure, format: :csv, version: 'v2'), target: "_blank", rel: "noopener" - if export_v1_enabled + - old_format_message = "(ancien format, jusqu’au #{old_format_limit_date.strftime('%d/%m/%Y')})" %li = link_to "Au format .xlsx #{old_format_message}", procedure_dossiers_download_path(procedure, format: :xlsx, version: 'v1'), target: "_blank", rel: "noopener" %li diff --git a/config/features.rb b/config/features.rb index 11c9b3717..e650187ad 100644 --- a/config/features.rb +++ b/config/features.rb @@ -15,7 +15,6 @@ Flipflop.configure do feature :web_hook - feature :procedure_export_v2_enabled feature :operation_log_serialize_subject feature :download_as_zip_enabled feature :bypass_email_login_token, From e68d2cf5e2894e94d794b8422c57b6820f0a0f23 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 31 Jul 2019 15:10:54 +0200 Subject: [PATCH 07/21] Enable champ repetition for all --- app/helpers/procedure_helper.rb | 3 +-- config/features.rb | 2 -- spec/features/new_administrateur/types_de_champ_spec.rb | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/app/helpers/procedure_helper.rb b/app/helpers/procedure_helper.rb index 6eadece2f..92bae1271 100644 --- a/app/helpers/procedure_helper.rb +++ b/app/helpers/procedure_helper.rb @@ -64,8 +64,7 @@ module ProcedureHelper private TOGGLES = { - TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number?, - TypeDeChamp.type_champs.fetch(:repetition) => :champ_repetition? + TypeDeChamp.type_champs.fetch(:integer_number) => :champ_integer_number? } def types_de_champ_types diff --git a/config/features.rb b/config/features.rb index e650187ad..6e3dbf490 100644 --- a/config/features.rb +++ b/config/features.rb @@ -9,8 +9,6 @@ Flipflop.configure do group :champs do feature :champ_integer_number, title: "Champ nombre entier" - feature :champ_repetition, - title: "Bloc répétable" end feature :web_hook diff --git a/spec/features/new_administrateur/types_de_champ_spec.rb b/spec/features/new_administrateur/types_de_champ_spec.rb index 0fecd6759..be976ae47 100644 --- a/spec/features/new_administrateur/types_de_champ_spec.rb +++ b/spec/features/new_administrateur/types_de_champ_spec.rb @@ -5,7 +5,6 @@ feature 'As an administrateur I can edit types de champ', js: true do let(:procedure) { create(:procedure) } before do - Flipflop::FeatureSet.current.test!.switch!(:champ_repetition, true) login_as administrateur, scope: :administrateur visit champs_procedure_path(procedure) end From 81f44fa76b0147fcdb028ed93c35b134f64956ea Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 09:45:11 +0200 Subject: [PATCH 08/21] Link user and administrateur --- app/models/administrateur.rb | 2 ++ app/models/user.rb | 1 + db/migrate/20190809073736_link_user_and_administrateur.rb | 6 ++++++ db/schema.rb | 5 ++++- 4 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20190809073736_link_user_and_administrateur.rb diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index cc8ad21b2..399190165 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -12,6 +12,8 @@ class Administrateur < ApplicationRecord has_many :services has_many :dossiers, -> { state_not_brouillon }, through: :procedures + has_one :user + before_validation -> { sanitize_email(:email) } scope :inactive, -> { where(active: false) } diff --git a/app/models/user.rb b/app/models/user.rb index 7332dee3f..ff6673191 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -18,6 +18,7 @@ class User < ApplicationRecord has_many :feedbacks, dependent: :destroy has_one :france_connect_information, dependent: :destroy belongs_to :instructeur + belongs_to :administrateur accepts_nested_attributes_for :france_connect_information diff --git a/db/migrate/20190809073736_link_user_and_administrateur.rb b/db/migrate/20190809073736_link_user_and_administrateur.rb new file mode 100644 index 000000000..34ca446dd --- /dev/null +++ b/db/migrate/20190809073736_link_user_and_administrateur.rb @@ -0,0 +1,6 @@ +class LinkUserAndAdministrateur < ActiveRecord::Migration[5.2] + def change + add_reference :users, :administrateur, index: true + add_foreign_key :users, :administrateurs + end +end diff --git a/db/schema.rb b/db/schema.rb index 4b29d1dae..fdbf8f457 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_08_08_144607) do +ActiveRecord::Schema.define(version: 2019_08_09_073736) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -597,6 +597,8 @@ ActiveRecord::Schema.define(version: 2019_08_08_144607) do t.datetime "locked_at" t.text "unconfirmed_email" t.bigint "instructeur_id" + t.bigint "administrateur_id" + t.index ["administrateur_id"], name: "index_users_on_administrateur_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" @@ -644,6 +646,7 @@ ActiveRecord::Schema.define(version: 2019_08_08_144607) 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", "administrateurs" add_foreign_key "users", "instructeurs" add_foreign_key "without_continuation_mails", "procedures" end From 65d862b59d4f363ec4bf5fe81124f953b694f74d Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 09:50:55 +0200 Subject: [PATCH 09/21] Populate the column --- ...0190809074534_populate_user_administrateur_ids.rake | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lib/tasks/deployment/20190809074534_populate_user_administrateur_ids.rake diff --git a/lib/tasks/deployment/20190809074534_populate_user_administrateur_ids.rake b/lib/tasks/deployment/20190809074534_populate_user_administrateur_ids.rake new file mode 100644 index 000000000..ef6da498b --- /dev/null +++ b/lib/tasks/deployment/20190809074534_populate_user_administrateur_ids.rake @@ -0,0 +1,10 @@ +namespace :after_party do + desc 'Deployment task: populate_user_administrateur_ids' + task populate_user_administrateur_ids: :environment do + Administrateur.find_each do |administrateur| + User.where(email: administrateur.email).update(administrateur_id: administrateur.id) + end + + AfterParty::TaskRecord.create version: '20190809074534' + end +end From 840be2408e634fe16dab2a09456d317d07c664d8 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 10:38:27 +0200 Subject: [PATCH 10/21] Remove administrateur devise methods --- app/controllers/users/activate_controller.rb | 2 +- app/controllers/users/sessions_controller.rb | 3 +-- app/models/administrateur.rb | 3 --- config/routes.rb | 2 -- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/app/controllers/users/activate_controller.rb b/app/controllers/users/activate_controller.rb index c83cb026a..c8553c3a4 100644 --- a/app/controllers/users/activate_controller.rb +++ b/app/controllers/users/activate_controller.rb @@ -23,7 +23,7 @@ class Users::ActivateController < ApplicationController 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 diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index dbce76e0d..8aad112cb 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -16,8 +16,7 @@ class Users::SessionsController < Sessions::SessionsController def create remember_me = params[:user][:remember_me] == '1' - if resource_locked?(try_to_authenticate(User, remember_me)) || - resource_locked?(try_to_authenticate(Administrateur, remember_me)) + if resource_locked?(try_to_authenticate(User, remember_me)) flash.alert = 'Votre compte est verrouillé.' new return render :new, status: 401 diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 399190165..c1c1ffcd2 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -3,9 +3,6 @@ class Administrateur < ApplicationRecord include EmailSanitizableConcern include ActiveRecord::SecureToken - devise :database_authenticatable, :registerable, :async, - :recoverable, :rememberable, :trackable, :validatable, :lockable - has_and_belongs_to_many :instructeurs has_many :administrateurs_procedures has_many :procedures, through: :administrateurs_procedures diff --git a/config/routes.rb b/config/routes.rb index 678746d53..01301c3fb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -77,8 +77,6 @@ Rails.application.routes.draw do omniauth_callbacks: 'administrations/omniauth_callbacks' } - devise_for :administrateurs, skip: :all - devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations', From 4142acf8d3cf9058f437b76962b868a60cd82671 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 10:38:51 +0200 Subject: [PATCH 11/21] Replace administrateur devise methods in app --- app/controllers/application_controller.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6b01ca41e..8648c7b08 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -18,7 +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 + helper_method :logged_in?, :multiple_devise_profile_connect?, :instructeur_signed_in?, :current_instructeur, + :administrateur_signed_in?, :current_administrateur def staging_authenticate if StagingAuthService.enabled? && !authenticate_with_http_basic { |username, password| StagingAuthService.authenticate(username, password) } @@ -66,6 +67,14 @@ class ApplicationController < ActionController::Base user_signed_in? && current_user&.instructeur.present? end + def current_administrateur + current_user&.administrateur + end + + def administrateur_signed_in? + current_administrateur.present? + end + protected def authenticate_logged_user! @@ -85,9 +94,7 @@ class ApplicationController < ActionController::Base end def authenticate_administrateur! - if administrateur_signed_in? - super - else + if !administrateur_signed_in? redirect_to new_user_session_path end end From 27c81c19928c7eb299a252e060de27ff92187616 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 10:39:14 +0200 Subject: [PATCH 12/21] Update administrateur factory --- spec/factories/administrateur.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/factories/administrateur.rb b/spec/factories/administrateur.rb index c3da39bfe..5ab633aea 100644 --- a/spec/factories/administrateur.rb +++ b/spec/factories/administrateur.rb @@ -2,18 +2,20 @@ FactoryBot.define do sequence(:administrateur_email) { |n| "admin#{n}@admin.com" } factory :administrateur do email { generate(:administrateur_email) } - password { 'mon chien aime les bananes' } transient do user { nil } + password { 'mon chien aime les bananes' } end - after(:create) do |admin, evaluator| + after(:create) do |administrateur, evaluator| if evaluator.user.present? - create(:instructeur, email: admin.email, password: admin.password, user: evaluator.user) + user = evaluator.user else - create(:instructeur, email: admin.email, password: admin.password) + user = create(:user, email: administrateur.email, password: evaluator.password, administrateur: administrateur) end + + create(:instructeur, email: administrateur.email, user: user) end end From 1b38d4071d185482efdd0db37a6def13619a2613 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 10:41:10 +0200 Subject: [PATCH 13/21] temporary remove password complexity check --- app/models/administrateur.rb | 2 +- spec/models/administrateur_spec.rb | 44 +++++++++++++++--------------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index c1c1ffcd2..3c242a609 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -16,7 +16,7 @@ class Administrateur < ApplicationRecord scope :inactive, -> { where(active: false) } scope :with_publiees_ou_archivees, -> { joins(:procedures).where(procedures: { aasm_state: [:publiee, :archivee] }) } - validate :password_complexity, if: Proc.new { |a| Devise.password_length.include?(a.password.try(:size)) } + # validate :password_complexity, if: Proc.new { |a| Devise.password_length.include?(a.password.try(:size)) } def password_complexity if password.present? && ZxcvbnService.new(password).score < PASSWORD_COMPLEXITY_FOR_ADMIN diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb index fc016e971..6b8f83788 100644 --- a/spec/models/administrateur_spec.rb +++ b/spec/models/administrateur_spec.rb @@ -71,33 +71,33 @@ describe Administrateur, type: :model do it { expect(administrateur.feature_enabled?(:test_a)).to be_truthy } end - describe '#password_complexity' do - let(:email) { 'mail@beta.gouv.fr' } - let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] } - let(:administrateur) { build(:administrateur, email: email, password: password) } - let(:min_complexity) { PASSWORD_COMPLEXITY_FOR_ADMIN } + # describe '#password_complexity' do + # let(:email) { 'mail@beta.gouv.fr' } + # let(:passwords) { ['pass', '12pass23', 'démarches ', 'démarches-simple', 'démarches-simplifiées-pwd'] } + # let(:administrateur) { build(:administrateur, email: email, password: password) } + # let(:min_complexity) { PASSWORD_COMPLEXITY_FOR_ADMIN } - subject do - administrateur.save - administrateur.errors.full_messages - end + # subject do + # administrateur.save + # administrateur.errors.full_messages + # end - context 'when password is too short' do - let(:password) { 's' * (PASSWORD_MIN_LENGTH - 1) } + # context 'when password is too short' do + # let(:password) { 's' * (PASSWORD_MIN_LENGTH - 1) } - it { expect(subject).to eq(["Le mot de passe est trop court"]) } - end + # it { expect(subject).to eq(["Le mot de passe est trop court"]) } + # end - context 'when password is too simple' do - let(:password) { passwords[min_complexity - 1] } + # context 'when password is too simple' do + # let(:password) { passwords[min_complexity - 1] } - it { expect(subject).to eq(["Le mot de passe n'est pas assez complexe"]) } - end + # it { expect(subject).to eq(["Le mot de passe n'est pas assez complexe"]) } + # end - context 'when password is acceptable' do - let(:password) { passwords[min_complexity] } + # context 'when password is acceptable' do + # let(:password) { passwords[min_complexity] } - it { expect(subject).to eq([]) } - end - end + # it { expect(subject).to eq([]) } + # end + # end end From c380d807ab87d105d167247c538ee9d641cec613 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 10:46:39 +0200 Subject: [PATCH 14/21] Spec: sign_in with administrateur.user --- app/controllers/users/passwords_controller.rb | 2 +- .../admin/assigns_controller_spec.rb | 2 +- .../attestation_templates_controller_spec.rb | 2 +- .../admin/instructeurs_controller_spec.rb | 10 +++++----- .../admin/mail_templates_controller_spec.rb | 2 +- .../admin/procedures_controller_spec.rb | 20 +++++++++---------- .../mail_templates_controller_spec.rb | 2 +- .../procedures_controller_spec.rb | 2 +- .../services_controller_spec.rb | 10 +++++----- .../types_de_champ_controller_spec.rb | 2 +- spec/controllers/root_controller_spec.rb | 2 +- .../users/profil_controller_spec.rb | 2 +- .../users/sessions_controller_spec.rb | 2 +- spec/features/admin/procedure_cloning_spec.rb | 2 +- .../features/admin/procedure_creation_spec.rb | 2 +- spec/features/admin/procedure_update_spec.rb | 2 +- .../new_administrateur/types_de_champ_spec.rb | 2 +- 17 files changed, 34 insertions(+), 34 deletions(-) diff --git a/app/controllers/users/passwords_controller.rb b/app/controllers/users/passwords_controller.rb index ea7c705af..b3f174452 100644 --- a/app/controllers/users/passwords_controller.rb +++ b/app/controllers/users/passwords_controller.rb @@ -59,7 +59,7 @@ class Users::PasswordsController < Devise::PasswordsController administrateur = Administrateur.find_by(email: current_user.email) if administrateur - sign_in administrateur + sign_in(administrateur.user) end end end diff --git a/spec/controllers/admin/assigns_controller_spec.rb b/spec/controllers/admin/assigns_controller_spec.rb index 5b433976d..95fb4474a 100644 --- a/spec/controllers/admin/assigns_controller_spec.rb +++ b/spec/controllers/admin/assigns_controller_spec.rb @@ -6,7 +6,7 @@ describe Admin::AssignsController, type: :controller do let(:instructeur) { create :instructeur, administrateurs: [admin] } before do - sign_in admin + sign_in(admin.user) end describe 'GET #show' do diff --git a/spec/controllers/admin/attestation_templates_controller_spec.rb b/spec/controllers/admin/attestation_templates_controller_spec.rb index efae4d4af..27c43bac5 100644 --- a/spec/controllers/admin/attestation_templates_controller_spec.rb +++ b/spec/controllers/admin/attestation_templates_controller_spec.rb @@ -11,7 +11,7 @@ describe Admin::AttestationTemplatesController, type: :controller do let(:uninterlaced_logo) { fixture_file_upload('spec/fixtures/files/uninterlaced-black.png', 'image/png') } before do - sign_in admin + sign_in(admin.user) Timecop.freeze(Time.zone.now) end diff --git a/spec/controllers/admin/instructeurs_controller_spec.rb b/spec/controllers/admin/instructeurs_controller_spec.rb index dbb00621f..61cdf62c1 100644 --- a/spec/controllers/admin/instructeurs_controller_spec.rb +++ b/spec/controllers/admin/instructeurs_controller_spec.rb @@ -6,7 +6,7 @@ describe Admin::InstructeursController, type: :controller do let(:admin_2) { create :administrateur, email: email_2 } before do - sign_in admin + sign_in(admin.user) end describe 'GET #index' do @@ -117,8 +117,8 @@ describe Admin::InstructeursController, type: :controller do before do create :instructeur, email: email, administrateurs: [admin] - sign_out admin - sign_in admin_2 + sign_out(admin.user) + sign_in(admin_2.user) subject end @@ -138,8 +138,8 @@ describe Admin::InstructeursController, type: :controller do before do create :instructeur, email: email, administrateurs: [admin] - sign_out admin - sign_in admin_2 + sign_out(admin.user) + sign_in(admin_2.user) subject end diff --git a/spec/controllers/admin/mail_templates_controller_spec.rb b/spec/controllers/admin/mail_templates_controller_spec.rb index d34ef2684..a2eec599f 100644 --- a/spec/controllers/admin/mail_templates_controller_spec.rb +++ b/spec/controllers/admin/mail_templates_controller_spec.rb @@ -5,7 +5,7 @@ describe Admin::MailTemplatesController, type: :controller do let(:initiated_mail) { Mails::InitiatedMail.default_for_procedure(procedure) } before do - sign_in procedure.administrateurs.first + sign_in(procedure.administrateurs.first.user) end describe 'GET index' do diff --git a/spec/controllers/admin/procedures_controller_spec.rb b/spec/controllers/admin/procedures_controller_spec.rb index dbe4c104e..e32b5ab32 100644 --- a/spec/controllers/admin/procedures_controller_spec.rb +++ b/spec/controllers/admin/procedures_controller_spec.rb @@ -33,7 +33,7 @@ describe Admin::ProceduresController, type: :controller do } before do - sign_in admin + sign_in(admin.user) end describe 'GET #index' do @@ -155,7 +155,7 @@ describe Admin::ProceduresController, type: :controller do context 'when user is not connected' do before do - sign_out admin + sign_out(admin.user) end it { is_expected.to redirect_to new_user_session_path } @@ -252,7 +252,7 @@ describe Admin::ProceduresController, type: :controller do context 'when administrateur is not connected' do before do - sign_out admin + sign_out(admin.user) end subject { put :update, params: { id: procedure.id } } @@ -411,8 +411,8 @@ describe Admin::ProceduresController, type: :controller do let(:admin_2) { create(:administrateur) } before do - sign_out admin - sign_in admin_2 + sign_out(admin.user) + sign_in(admin_2.user) put :publish, params: { procedure_id: procedure.id, path: 'fake_path' } procedure.reload @@ -471,8 +471,8 @@ describe Admin::ProceduresController, type: :controller do let(:admin_2) { create(:administrateur) } before do - sign_out admin - sign_in admin_2 + sign_out(admin.user) + sign_in(admin_2.user) put :archive, params: { procedure_id: procedure.id } procedure.reload @@ -517,8 +517,8 @@ describe Admin::ProceduresController, type: :controller do let(:admin_2) { create(:administrateur) } before do - sign_out admin - sign_in admin_2 + sign_out(admin.user) + sign_in(admin_2.user) subject end @@ -783,7 +783,7 @@ describe Admin::ProceduresController, type: :controller do context 'when administrateur is not connected' do before do - sign_out admin + sign_out(admin.user) end subject { patch :update_monavis, params: { procedure_id: procedure.id } } diff --git a/spec/controllers/new_administrateur/mail_templates_controller_spec.rb b/spec/controllers/new_administrateur/mail_templates_controller_spec.rb index 365abe78b..11ed74f81 100644 --- a/spec/controllers/new_administrateur/mail_templates_controller_spec.rb +++ b/spec/controllers/new_administrateur/mail_templates_controller_spec.rb @@ -7,7 +7,7 @@ describe NewAdministrateur::MailTemplatesController, type: :controller do let(:procedure) { create(:procedure, :with_logo, :with_service, administrateur: admin) } before do - sign_in admin + sign_in(admin.user) get :preview, params: { id: "initiated_mail", procedure_id: procedure.id } end diff --git a/spec/controllers/new_administrateur/procedures_controller_spec.rb b/spec/controllers/new_administrateur/procedures_controller_spec.rb index 45a48d6e4..1dc6753bb 100644 --- a/spec/controllers/new_administrateur/procedures_controller_spec.rb +++ b/spec/controllers/new_administrateur/procedures_controller_spec.rb @@ -5,7 +5,7 @@ describe NewAdministrateur::ProceduresController, type: :controller do let(:procedure) { create(:procedure) } before do - sign_in admin + sign_in(admin.user) get :apercu, params: { id: procedure.id } end diff --git a/spec/controllers/new_administrateur/services_controller_spec.rb b/spec/controllers/new_administrateur/services_controller_spec.rb index e020d9751..71984efba 100644 --- a/spec/controllers/new_administrateur/services_controller_spec.rb +++ b/spec/controllers/new_administrateur/services_controller_spec.rb @@ -4,7 +4,7 @@ describe NewAdministrateur::ServicesController, type: :controller do describe '#create' do before do - sign_in admin + sign_in(admin.user) post :create, params: params end @@ -52,7 +52,7 @@ describe NewAdministrateur::ServicesController, type: :controller do let(:service_params) { { nom: 'nom', type_organisme: Service.type_organismes.fetch(:association) } } before do - sign_in admin + sign_in(admin.user) params = { id: service.id, service: service_params, @@ -82,7 +82,7 @@ describe NewAdministrateur::ServicesController, type: :controller do let!(:service) { create(:service, administrateur: admin) } def post_add_to_procedure - sign_in admin + sign_in(admin.user) params = { procedure: { id: procedure.id, @@ -114,7 +114,7 @@ describe NewAdministrateur::ServicesController, type: :controller do context 'when a service has no related procedure' do before do - sign_in admin + sign_in(admin.user) delete :destroy, params: { id: service.id, procedure_id: 12 } end @@ -128,7 +128,7 @@ describe NewAdministrateur::ServicesController, type: :controller do let!(:procedure) { create(:procedure, service: service) } before do - sign_in admin + sign_in(admin.user) delete :destroy, params: { id: service.id, procedure_id: 12 } end diff --git a/spec/controllers/new_administrateur/types_de_champ_controller_spec.rb b/spec/controllers/new_administrateur/types_de_champ_controller_spec.rb index 3722ed60b..dcae29934 100644 --- a/spec/controllers/new_administrateur/types_de_champ_controller_spec.rb +++ b/spec/controllers/new_administrateur/types_de_champ_controller_spec.rb @@ -6,7 +6,7 @@ describe NewAdministrateur::TypesDeChampController, type: :controller do before do admin.procedures << procedure - sign_in admin + sign_in(admin.user) end let(:type_champ) { TypeDeChamp.type_champs.fetch(:text) } diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb index ca7da499c..cfaf12a94 100644 --- a/spec/controllers/root_controller_spec.rb +++ b/spec/controllers/root_controller_spec.rb @@ -26,7 +26,7 @@ describe RootController, type: :controller do context 'when Administrateur is connected' do before do - sign_in create(:administrateur) + sign_in(create(:administrateur).user) end it { expect(subject).to redirect_to(admin_procedures_path) } diff --git a/spec/controllers/users/profil_controller_spec.rb b/spec/controllers/users/profil_controller_spec.rb index 38f46f2dd..aad9bc371 100644 --- a/spec/controllers/users/profil_controller_spec.rb +++ b/spec/controllers/users/profil_controller_spec.rb @@ -10,7 +10,7 @@ describe Users::ProfilController, type: :controller do describe 'POST #renew_api_token' do let(:administrateur) { create(:administrateur) } - before { sign_in(administrateur) } + before { sign_in(administrateur.user) } before do allow(administrateur).to receive(:renew_api_token) diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 887febc97..6a8adde5f 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -114,7 +114,7 @@ describe Users::SessionsController, type: :controller do it 'signs user + instructeur + administrateur out' do sign_in user - sign_in administrateur + sign_in(administrateur.user) delete :destroy expect(@response.redirect?).to be(true) expect(subject.current_user).to be(nil) diff --git a/spec/features/admin/procedure_cloning_spec.rb b/spec/features/admin/procedure_cloning_spec.rb index 72a7b9727..eb908a012 100644 --- a/spec/features/admin/procedure_cloning_spec.rb +++ b/spec/features/admin/procedure_cloning_spec.rb @@ -7,7 +7,7 @@ feature 'As an administrateur I wanna clone a procedure', js: true do let(:administrateur) { create(:administrateur) } before do - login_as administrateur, scope: :administrateur + login_as administrateur.user, scope: :user visit new_from_existing_admin_procedures_path end diff --git a/spec/features/admin/procedure_creation_spec.rb b/spec/features/admin/procedure_creation_spec.rb index 7c58b20b0..afd26564c 100644 --- a/spec/features/admin/procedure_creation_spec.rb +++ b/spec/features/admin/procedure_creation_spec.rb @@ -7,7 +7,7 @@ feature 'As an administrateur I wanna create a new procedure', js: true do let(:administrateur) { create(:administrateur, :with_procedure) } before do - login_as administrateur, scope: :administrateur + login_as administrateur.user, scope: :user visit root_path end diff --git a/spec/features/admin/procedure_update_spec.rb b/spec/features/admin/procedure_update_spec.rb index 3986fb9ab..23101549b 100644 --- a/spec/features/admin/procedure_update_spec.rb +++ b/spec/features/admin/procedure_update_spec.rb @@ -14,7 +14,7 @@ feature 'Administrateurs can edit procedures', js: true do end before do - login_as administrateur, scope: :administrateur + login_as administrateur.user, scope: :user end context 'when the procedure is in draft' do diff --git a/spec/features/new_administrateur/types_de_champ_spec.rb b/spec/features/new_administrateur/types_de_champ_spec.rb index be976ae47..e8fdabd50 100644 --- a/spec/features/new_administrateur/types_de_champ_spec.rb +++ b/spec/features/new_administrateur/types_de_champ_spec.rb @@ -5,7 +5,7 @@ feature 'As an administrateur I can edit types de champ', js: true do let(:procedure) { create(:procedure) } before do - login_as administrateur, scope: :administrateur + login_as administrateur.user, scope: :user visit champs_procedure_path(procedure) end From c08e356367758a3f14cac80943d83bc9145d1545 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 14 Aug 2019 12:15:13 +0200 Subject: [PATCH 15/21] Remove or fix nonsense code --- .../instructeurs/dossiers_controller_spec.rb | 8 +--- .../sessions/sessions_controller_spec.rb | 15 ------- .../users/sessions_controller_spec.rb | 14 ------- .../instructeurs/instructeur_creation_spec.rb | 2 +- spec/models/administrateur_spec.rb | 39 ------------------- spec/models/instructeur_spec.rb | 12 ------ spec/models/user_spec.rb | 14 ------- 7 files changed, 2 insertions(+), 102 deletions(-) diff --git a/spec/controllers/instructeurs/dossiers_controller_spec.rb b/spec/controllers/instructeurs/dossiers_controller_spec.rb index 4ca80d21e..379b77d9e 100644 --- a/spec/controllers/instructeurs/dossiers_controller_spec.rb +++ b/spec/controllers/instructeurs/dossiers_controller_spec.rb @@ -184,13 +184,7 @@ describe Instructeurs::DossiersController, type: :controller do expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte)) expect(response).to have_http_status(:ok) end - context 'as administrateur' do - let (:current_user) { administrateur } - it 'it is not possible to go back to en_instruction' do - expect(dossier.reload.state).to eq(Dossier.states.fetch(:accepte)) - expect(response).to have_http_status(:ok) - end - end + context 'as superadmin' do let (:current_user) { administration } it 'it is not possible to go back to en_instruction' do diff --git a/spec/controllers/sessions/sessions_controller_spec.rb b/spec/controllers/sessions/sessions_controller_spec.rb index ad1834671..06b4ec51c 100644 --- a/spec/controllers/sessions/sessions_controller_spec.rb +++ b/spec/controllers/sessions/sessions_controller_spec.rb @@ -8,8 +8,6 @@ describe Sessions::SessionsController, type: :controller do end let(:user) { create(:user) } - let(:instructeur) { create(:instructeur) } - let(:administrateur) { create(:administrateur) } describe '#create' do before do @@ -34,17 +32,4 @@ describe Sessions::SessionsController, type: :controller do post :create end end - - describe '#create with administrateur connected' do - before do - @request.env["devise.mapping"] = Devise.mappings[:administrateur] - - allow_any_instance_of(described_class).to receive(:administrateur_signed_in?).and_return(true) - end - - it 'calls sign out for administrateur' do - expect_any_instance_of(described_class).to receive(:sign_out).with(:administrateur) - post :create - end - end end diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 6a8adde5f..0a42fc26a 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -108,20 +108,6 @@ describe Users::SessionsController, type: :controller do expect(response).to redirect_to(root_path) end end - - context "when associated administrateur" do - let(:administrateur) { create(:administrateur, user: user) } - - it 'signs user + instructeur + administrateur out' do - sign_in user - sign_in(administrateur.user) - delete :destroy - expect(@response.redirect?).to be(true) - expect(subject.current_user).to be(nil) - expect(subject.current_instructeur).to be(nil) - expect(subject.current_administrateur).to be(nil) - end - end end describe '#new' do diff --git a/spec/features/instructeurs/instructeur_creation_spec.rb b/spec/features/instructeurs/instructeur_creation_spec.rb index 5ffb3488c..50d284e96 100644 --- a/spec/features/instructeurs/instructeur_creation_spec.rb +++ b/spec/features/instructeurs/instructeur_creation_spec.rb @@ -6,7 +6,7 @@ feature 'As an instructeur', js: true do let(:instructeur_email) { 'new_instructeur@gouv.fr' } before do - login_as administrateur, scope: :administrateur + login_as administrateur.user, scope: :user visit admin_procedure_assigns_path(procedure) fill_in :instructeur_email, with: instructeur_email diff --git a/spec/models/administrateur_spec.rb b/spec/models/administrateur_spec.rb index 6b8f83788..a4e679441 100644 --- a/spec/models/administrateur_spec.rb +++ b/spec/models/administrateur_spec.rb @@ -8,29 +8,6 @@ describe Administrateur, type: :model do it { is_expected.to have_many(:procedures) } end - context 'unified login' do - it 'syncs credentials to associated user' do - administrateur = create(:administrateur) - user = administrateur.instructeur.user - - administrateur.update(email: 'whoami@plop.com', password: 'voilà un super mdp') - - user.reload - expect(user.email).to eq('whoami@plop.com') - expect(user.valid_password?('voilà un super mdp')).to be(true) - end - - it 'syncs credentials to associated administrateur' do - administrateur = create(:administrateur) - instructeur = administrateur.instructeur - - administrateur.update(email: 'whoami@plop.com', password: 'et encore un autre mdp') - - instructeur.reload - expect(instructeur.email).to eq('whoami@plop.com') - end - end - describe "#renew_api_token" do let!(:administrateur) { create(:administrateur) } let!(:token) { administrateur.renew_api_token } @@ -44,22 +21,6 @@ describe Administrateur, type: :model do end end - describe '#find_inactive_by_token' do - let(:administrateur) { create(:administration).invite_admin('paul@tps.fr') } - let(:reset_password_token) { administrateur.invite!(administration.id) } - - it { expect(Administrateur.find_inactive_by_token(reset_password_token)).not_to be_nil } - end - - describe '#reset_password' do - let(:administrateur) { create(:administration).invite_admin('paul@tps.fr') } - let(:reset_password_token) { administrateur.invite!(administration.id) } - - it { expect(Administrateur.reset_password(reset_password_token, "j'aime manger des radis").errors).to be_empty } - it { expect(Administrateur.reset_password('123', "j'aime manger des radis").errors).not_to be_empty } - it { expect(Administrateur.reset_password(reset_password_token, '').errors).not_to be_empty } - end - describe '#feature_enabled?' do let(:administrateur) { create(:administrateur) } diff --git a/spec/models/instructeur_spec.rb b/spec/models/instructeur_spec.rb index 2a98e6336..5cc374a86 100644 --- a/spec/models/instructeur_spec.rb +++ b/spec/models/instructeur_spec.rb @@ -137,18 +137,6 @@ describe Instructeur, type: :model do end end - context 'unified login' do - it 'syncs credentials to associated administrateur' do - admin = create(:administrateur) - user = admin.instructeur.user - - user.update(password: 'démarches-simplifiées-pwd') - - admin.reload - expect(admin.valid_password?('démarches-simplifiées-pwd')).to be(true) - end - end - describe 'last_week_overview' do let!(:instructeur2) { create(:instructeur) } subject { instructeur2.last_week_overview } diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 08346f1f2..1b817db8a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -100,18 +100,4 @@ describe User, type: :model do it { is_expected.to be_falsey } end end - - context 'unified login' do - it 'syncs credentials to associated administrateur' do - admin = create(:administrateur) - user = admin.instructeur.user - - user.update(email: 'whoami@plop.com', password: 'démarches-simplifiées2') - user.confirm - - admin.reload - expect(admin.email).to eq('whoami@plop.com') - expect(admin.valid_password?('démarches-simplifiées2')).to be(true) - end - end end From d0ac1c33017f1130966d8ae87cb8fbb04b12a722 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 11:41:36 +0200 Subject: [PATCH 16/21] Fix manager invite administrateur --- .../administrateurs/activate_controller.rb | 20 ++++++---- app/models/administrateur.rb | 12 ------ app/models/administration.rb | 38 ++++++++++--------- app/models/user.rb | 12 ++++++ .../activate_controller_spec.rb | 2 +- spec/models/administration_spec.rb | 8 ++-- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/app/controllers/administrateurs/activate_controller.rb b/app/controllers/administrateurs/activate_controller.rb index 9d4a438bd..2d45c0da1 100644 --- a/app/controllers/administrateurs/activate_controller.rb +++ b/app/controllers/administrateurs/activate_controller.rb @@ -3,7 +3,9 @@ class Administrateurs::ActivateController < ApplicationController def new @token = params[:token] - @administrateur = Administrateur.find_inactive_by_token(@token) + + user = User.with_reset_password_token(@token) + @administrateur = user&.administrateur if @administrateur # the administrateur activates its account from an email @@ -16,14 +18,16 @@ class Administrateurs::ActivateController < ApplicationController def create password = update_administrateur_params[:password] - administrateur = Administrateur.reset_password( - update_administrateur_params[:reset_password_token], - password - ) - if administrateur && administrateur.errors.empty? - sign_in(administrateur, scope: :administrateur) - try_to_authenticate(User, administrateur.email, password) + user = User.reset_password_by_token({ + password: password, + password_confirmation: password, + reset_password_token: update_administrateur_params[:reset_password_token] + }) + + if user&.administrateur&.errors&.empty? + sign_in(user, scope: :user) + flash.notice = "Mot de passe enregistré" redirect_to admin_procedures_path else diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 3c242a609..e1292f6c9 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -55,18 +55,6 @@ class Administrateur < ApplicationRecord end end - def invite!(administration_id) - if active? - raise "Impossible d'inviter un utilisateur déjà actif !" - end - - reset_password_token = set_reset_password_token - - AdministrationMailer.invite_admin(self, reset_password_token, administration_id).deliver_later - - reset_password_token - end - def remind_invitation! if active? raise "Impossible d'envoyer un rappel d'invitation à un utilisateur déjà actif !" diff --git a/app/models/administration.rb b/app/models/administration.rb index f72a16936..7073779d7 100644 --- a/app/models/administration.rb +++ b/app/models/administration.rb @@ -9,29 +9,33 @@ class Administration < ApplicationRecord def invite_admin(email) password = SecureRandom.hex - administrateur = Administrateur.new({ - email: email, - active: false, - password: password, - password_confirmation: password - }) - if administrateur.save - AdministrationMailer.new_admin_email(administrateur, self).deliver_later - administrateur.invite!(id) + user = User.find_by(email: email) - user = User.create({ + if user.nil? + # set confirmed_at otherwise admin confirmation doesnt work + # we somehow mess up using reset_password logic instead of + # confirmation_logic + # FIXME + user = User.create( email: email, password: password, confirmed_at: Time.zone.now - }) - - Instructeur.create({ - email: email, - user: user - }) + ) end - administrateur + if user.errors.empty? + if user.instructeur.nil? + Instructeur.create!(email: email, user: user) + end + + if user.administrateur.nil? + administrateur = Administrateur.create!(email: email, active: false, user: user) + AdministrationMailer.new_admin_email(administrateur, self).deliver_later + user.invite_administrateur!(id) + end + end + + user end end diff --git a/app/models/user.rb b/app/models/user.rb index ff6673191..9a00bf4cf 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -45,6 +45,18 @@ class User < ApplicationRecord UserMailer.invite_instructeur(self, set_reset_password_token).deliver_later end + def invite_administrateur!(administration_id) + if administrateur.active? + raise "Impossible d'inviter un utilisateur déjà actif !" + end + + reset_password_token = set_reset_password_token + AdministrationMailer.invite_admin(self, reset_password_token, administration_id).deliver_later + + reset_password_token + end + + private def link_invites! diff --git a/spec/controllers/administrateur/activate_controller_spec.rb b/spec/controllers/administrateur/activate_controller_spec.rb index a6e99f851..6b97bfe4a 100644 --- a/spec/controllers/administrateur/activate_controller_spec.rb +++ b/spec/controllers/administrateur/activate_controller_spec.rb @@ -1,7 +1,7 @@ describe Administrateurs::ActivateController, type: :controller do describe '#new' do let(:admin) { create(:administrateur) } - let(:token) { admin.send(:set_reset_password_token) } + let(:token) { admin.user.send(:set_reset_password_token) } before { allow(controller).to receive(:trust_device) } diff --git a/spec/models/administration_spec.rb b/spec/models/administration_spec.rb index 40a65fa83..374b60c16 100644 --- a/spec/models/administration_spec.rb +++ b/spec/models/administration_spec.rb @@ -4,13 +4,15 @@ describe Administration, type: :model do describe '#invite_admin' do let(:administration) { create :administration } let(:valid_email) { 'paul@tps.fr' } + subject { administration.invite_admin(valid_email) } it { - expect(subject.errors).to be_empty - expect(subject).to be_persisted - expect(administration.invite_admin(valid_email).errors).not_to be_empty + user = subject + expect(user.errors).to be_empty + expect(user).to be_persisted } + it { expect(administration.invite_admin(nil).errors).not_to be_empty } it { expect(administration.invite_admin('toto').errors).not_to be_empty } From dc816472e94737f41650b9d4ab5e8234fb7e0fcc Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 15:34:53 +0200 Subject: [PATCH 17/21] Stub administrateur devise methods in spec --- spec/views/layouts/procedure_context.html.haml_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/views/layouts/procedure_context.html.haml_spec.rb b/spec/views/layouts/procedure_context.html.haml_spec.rb index 91445340c..617654577 100644 --- a/spec/views/layouts/procedure_context.html.haml_spec.rb +++ b/spec/views/layouts/procedure_context.html.haml_spec.rb @@ -6,6 +6,7 @@ describe 'layouts/procedure_context.html.haml', type: :view do before do allow(view).to receive(:instructeur_signed_in?).and_return(false) + allow(view).to receive(:administrateur_signed_in?).and_return(false) end subject do From e3e6bc7689203fef07e0027226c48ac0eee8d391 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Fri, 9 Aug 2019 16:04:28 +0200 Subject: [PATCH 18/21] ! NEED JOB REBOOT Move remind activation logic to user --- .../administrateurs/activate_before_expiration_job.rb | 6 +++++- app/mailers/administrateur_mailer.rb | 8 ++++---- app/models/administrateur.rb | 10 ---------- app/models/user.rb | 5 +++++ .../activate_before_expiration.haml | 2 +- .../activate_before_expiration_job_spec.rb | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/jobs/administrateurs/activate_before_expiration_job.rb b/app/jobs/administrateurs/activate_before_expiration_job.rb index 889875d78..9c6058666 100644 --- a/app/jobs/administrateurs/activate_before_expiration_job.rb +++ b/app/jobs/administrateurs/activate_before_expiration_job.rb @@ -2,6 +2,10 @@ class Administrateurs::ActivateBeforeExpirationJob < ApplicationJob queue_as :cron def perform(*args) - Administrateur.inactive.where(created_at: 3.days.ago.all_day).each(&:remind_invitation!) + Administrateur + .includes(:user) + .inactive + .where(created_at: 3.days.ago.all_day) + .each { |a| a.user.remind_invitation! } end end diff --git a/app/mailers/administrateur_mailer.rb b/app/mailers/administrateur_mailer.rb index 55855db14..07050ccc1 100644 --- a/app/mailers/administrateur_mailer.rb +++ b/app/mailers/administrateur_mailer.rb @@ -2,13 +2,13 @@ class AdministrateurMailer < ApplicationMailer layout 'mailers/layout' - def activate_before_expiration(administrateur, reset_password_token) - @administrateur = administrateur + def activate_before_expiration(user, reset_password_token) + @user = user @reset_password_token = reset_password_token - @expiration_date = @administrateur.reset_password_sent_at + Devise.reset_password_within + @expiration_date = @user.reset_password_sent_at + Devise.reset_password_within @subject = "N'oubliez pas d'activer votre compte administrateur" - mail(to: administrateur.email, + mail(to: user.email, subject: @subject, reply_to: CONTACT_EMAIL) end diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index e1292f6c9..0a3007694 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -55,16 +55,6 @@ class Administrateur < ApplicationRecord end end - def remind_invitation! - if active? - raise "Impossible d'envoyer un rappel d'invitation à un utilisateur déjà actif !" - end - - reset_password_token = set_reset_password_token - - AdministrateurMailer.activate_before_expiration(self, reset_password_token).deliver_later - end - def invitation_expired? !active && !reset_password_period_valid? end diff --git a/app/models/user.rb b/app/models/user.rb index 9a00bf4cf..42f7ceaa1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -56,6 +56,11 @@ class User < ApplicationRecord reset_password_token end + def remind_invitation! + reset_password_token = set_reset_password_token + + AdministrateurMailer.activate_before_expiration(self, reset_password_token).deliver_later + end private diff --git a/app/views/administrateur_mailer/activate_before_expiration.haml b/app/views/administrateur_mailer/activate_before_expiration.haml index a0331b59a..e60ae8d5d 100644 --- a/app/views/administrateur_mailer/activate_before_expiration.haml +++ b/app/views/administrateur_mailer/activate_before_expiration.haml @@ -9,7 +9,7 @@ %p Afin d’activer votre compte, veuillez cliquer sur le lien ci-dessous : - = link_to(admin_activate_url(token: @reset_password_token), admin_activate_url(token: @reset_password_token)) + = link_to(users_activate_url(token: @reset_password_token), users_activate_url(token: @reset_password_token)) %p Nous restons à votre disposition si vous avez besoin d’accompagnement. diff --git a/spec/jobs/administrateurs/activate_before_expiration_job_spec.rb b/spec/jobs/administrateurs/activate_before_expiration_job_spec.rb index a7e450f7e..15ac2f711 100644 --- a/spec/jobs/administrateurs/activate_before_expiration_job_spec.rb +++ b/spec/jobs/administrateurs/activate_before_expiration_job_spec.rb @@ -38,7 +38,7 @@ RSpec.describe Administrateurs::ActivateBeforeExpirationJob, type: :job do subject end - it { expect(AdministrateurMailer).to have_received(:activate_before_expiration).with(administrateur, kind_of(String)) } + it { expect(AdministrateurMailer).to have_received(:activate_before_expiration).with(administrateur.user, kind_of(String)) } end end From 9fc63d923f8c80cb93bce3d13afe39f9284b1bc9 Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 14 Aug 2019 15:20:08 +0200 Subject: [PATCH 19/21] Fix seeds.rb --- db/seeds.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index 51971e6c1..9598aebcf 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -10,6 +10,12 @@ 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) -Instructeur.create!(email: default_user, password: default_password) -User.create!(email: default_user, password: default_password, confirmed_at: Time.zone.now) +administrateur = Administrateur.create!(email: default_user) +instructeur = Instructeur.create!(email: default_user) +User.create!( + email: default_user, + password: default_password, + confirmed_at: Time.zone.now, + administrateur: administrateur, + instructeur: instructeur +) From 149b0b579780598ef33cc0a242139e09e79a44bb Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 14 Aug 2019 16:58:50 +0200 Subject: [PATCH 20/21] Fix Sign out --- app/controllers/users/sessions_controller.rb | 8 -------- spec/features/users/sign_out_spec.rb | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 spec/features/users/sign_out_spec.rb diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 8aad112cb..e3b3f9536 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -42,14 +42,6 @@ class Users::SessionsController < Sessions::SessionsController # DELETE /resource/sign_out def destroy - if instructeur_signed_in? - sign_out :instructeur - end - - if administrateur_signed_in? - sign_out :administrateur - end - if user_signed_in? connected_with_france_connect = current_user.loged_in_with_france_connect current_user.update(loged_in_with_france_connect: '') diff --git a/spec/features/users/sign_out_spec.rb b/spec/features/users/sign_out_spec.rb new file mode 100644 index 000000000..b77edb604 --- /dev/null +++ b/spec/features/users/sign_out_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +feature 'Sign out' do + context 'when a user is logged in' do + let(:user) { create(:administrateur).user } + + before { login_as user, scope: :user } + + scenario 'he can sign out' do + visit dossiers_path + + click_on 'Se déconnecter' + + expect(page).to have_current_path(root_path) + end + end +end From 7fbedb78fb0a38c20634af635fc8094e71b35c1f Mon Sep 17 00:00:00 2001 From: simon lehericey Date: Wed, 14 Aug 2019 17:26:47 +0200 Subject: [PATCH 21/21] Add feature spec about managing passwords (with the courtesy of kemenaran) --- spec/features/users/managing_password_spec.rb | 57 +++++++++++++++++++ spec/support/feature_helpers.rb | 7 +++ 2 files changed, 64 insertions(+) create mode 100644 spec/features/users/managing_password_spec.rb diff --git a/spec/features/users/managing_password_spec.rb b/spec/features/users/managing_password_spec.rb new file mode 100644 index 000000000..3d0393f1d --- /dev/null +++ b/spec/features/users/managing_password_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +feature 'Managing password:' do + context 'for simple users' do + let(:user) { create(:user) } + let(:new_password) { 'a simple password' } + + scenario 'a simple user can reset their password' do + visit root_path + click_on 'Connexion' + click_on 'Mot de passe oublié ?' + expect(page).to have_current_path(new_user_password_path) + + fill_in 'Email', with: user.email + perform_enqueued_jobs do + click_on 'Réinitialiser' + end + expect(page).to have_content 'vous allez recevoir un lien de réinitialisation par email' + + click_reset_password_link_for user.email + expect(page).to have_content 'Changement de mot de passe' + + fill_in 'user_password', with: new_password + fill_in 'user_password_confirmation', with: new_password + click_on 'Changer le mot de passe' + expect(page).to have_content('Votre mot de passe a été changé avec succès') + end + end + + context 'for admins' do + let(:user) { create(:user) } + let(:administrateur) { create(:administrateur, user: user) } + let(:new_password) { 'a new, long, and complicated password!' } + + scenario 'an admin can reset their password' do + visit root_path + click_on 'Connexion' + click_on 'Mot de passe oublié ?' + expect(page).to have_current_path(new_user_password_path) + + fill_in 'Email', with: user.email + perform_enqueued_jobs do + click_on 'Réinitialiser' + end + expect(page).to have_content 'vous allez recevoir un lien de réinitialisation par email' + + click_reset_password_link_for user.email + + expect(page).to have_content 'Changement de mot de passe' + + fill_in 'user_password', with: new_password + fill_in 'user_password_confirmation', with: new_password + click_on 'Changer le mot de passe' + expect(page).to have_content('Votre mot de passe a été changé avec succès') + end + end +end diff --git a/spec/support/feature_helpers.rb b/spec/support/feature_helpers.rb index 00240a295..545406561 100644 --- a/spec/support/feature_helpers.rb +++ b/spec/support/feature_helpers.rb @@ -78,6 +78,13 @@ module FeatureHelpers value end end + + def click_reset_password_link_for(email) + reset_password_email = open_email(email) + token_params = reset_password_email.body.match(/reset_password_token=[^"]+/) + + visit "/users/password/edit?#{token_params}" + end end RSpec.configure do |config|