From 7ff66c32aee788847d8adf8f946ea529fbfd7260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Ferrandis?= Date: Mon, 29 Apr 2024 17:00:45 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9connecter=20les=20agents=20et=20usagers?= =?UTF-8?q?=20apr=C3=A8s=20un=20temps=20d'inactivit=C3=A9=20(#4241)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ne plus utiliser le module :rememberable de Devise * Déconnecter les agents soient 14 jours après la dernière visite * Prendre des exemples de test plus explicites * Déconnecter les usagers 30 minutes après la dernière visite * Utiliser un critère plus précis pour déterminer qu'on est déconnecté * Move spec to the right directory * Move specs to account/ subdirectory * Déplacer la méthode `timeout_in` près de `devise` * Correction d'un titre de spec où j'anticipais trop --- app/models/agent.rb | 12 +++---- app/models/user.rb | 12 +++---- app/views/common/_session_form.html.slim | 4 --- config/application.rb | 2 ++ config/locales/views/devise.fr.yml | 3 -- .../agent_can_reset_his_password_spec.rb | 0 .../account/agent_session_expires_spec.rb | 33 +++++++++++++++++++ .../agents/{ => account}/change_email_spec.rb | 0 .../{ => account}/change_password_spec.rb | 0 ...ser_can_login_using_france_connect_spec.rb | 0 .../user_can_reset_his_password_spec.rb | 0 .../user_can_update_their_information_spec.rb | 0 ...ser_is_redirected_back_after_login_spec.rb | 0 .../account/user_session_expires_spec.rb | 28 ++++++++++++++++ .../user_signs_up_and_signs_in_spec.rb | 0 15 files changed, 75 insertions(+), 19 deletions(-) rename spec/features/agents/{ => account}/agent_can_reset_his_password_spec.rb (100%) create mode 100644 spec/features/agents/account/agent_session_expires_spec.rb rename spec/features/agents/{ => account}/change_email_spec.rb (100%) rename spec/features/agents/{ => account}/change_password_spec.rb (100%) rename spec/features/users/{ => account}/user_can_login_using_france_connect_spec.rb (100%) rename spec/features/users/{ => account}/user_can_reset_his_password_spec.rb (100%) rename spec/features/users/{ => account}/user_can_update_their_information_spec.rb (100%) rename spec/features/users/{ => account}/user_is_redirected_back_after_login_spec.rb (100%) create mode 100644 spec/features/users/account/user_session_expires_spec.rb rename spec/features/users/{ => account}/user_signs_up_and_signs_in_spec.rb (100%) diff --git a/app/models/agent.rb b/app/models/agent.rb index f9d1c89d06..5eb732a095 100644 --- a/app/models/agent.rb +++ b/app/models/agent.rb @@ -1,6 +1,8 @@ class SoftDeleteError < StandardError; end class Agent < ApplicationRecord + self.ignored_columns = [:remember_created_at] + # Mixins has_paper_trail( only: %w[email first_name last_name starts_at invitation_sent_at invitation_accepted_at] @@ -26,8 +28,10 @@ def self.search_options } end - devise :invitable, :database_authenticatable, :trackable, - :recoverable, :rememberable, :validatable, :confirmable, :async, validate_on_invite: true + devise :invitable, :database_authenticatable, :trackable, :timeoutable, + :recoverable, :validatable, :confirmable, :async, validate_on_invite: true + + def timeout_in = 14.days # Used by Devise's :timeoutable # HACK : Ces accesseurs permettent d'utiliser Devise::Models::Trackable mais sans persister les valeurs en base attr_accessor :current_sign_in_ip, :last_sign_in_ip, :sign_in_count, :current_sign_in_at @@ -121,10 +125,6 @@ def confreres Agent.in_any_of_these_services(services) end - def remember_me # Override from Devise::rememberable to enable it by default - super.nil? ? true : super - end - def reverse_full_name_and_service services.present? ? "#{reverse_full_name} (#{services_short_names})" : full_name end diff --git a/app/models/user.rb b/app/models/user.rb index 2cab645520..858ef4eb8b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ApplicationRecord + self.ignored_columns = [:remember_created_at] + # Mixins has_paper_trail( only: %w[ @@ -8,8 +10,10 @@ class User < ApplicationRecord ] ) - devise :invitable, :database_authenticatable, :registerable, - :recoverable, :rememberable, :validatable, :confirmable, :async + devise :invitable, :database_authenticatable, :registerable, :timeoutable, + :recoverable, :validatable, :confirmable, :async + + def timeout_in = 30.minutes # Used by Devise's :timeoutable include PgSearch::Model include FullNameConcern @@ -81,10 +85,6 @@ def self.search_options ## - - def remember_me # Override from Devise::rememberable to enable it by default - super.nil? ? true : super - end - def to_s full_name end diff --git a/app/views/common/_session_form.html.slim b/app/views/common/_session_form.html.slim index 4f5681de7d..ac4d99f846 100644 --- a/app/views/common/_session_form.html.slim +++ b/app/views/common/_session_form.html.slim @@ -10,9 +10,5 @@ .mt-1.mb-3= link_to "Mot de passe oublié ?", new_password_path(resource_name) - .form-group.mb-3 - .custom-control.custom-checkbox - = f.check_box :remember_me, class: "custom-control-input" - = f.label :remember_me, t("devise.sessions.new.remember_me"),class: "custom-control-label" .form-group.mb-0.text-center = f.submit "Se connecter", class: "btn btn-primary" diff --git a/config/application.rb b/config/application.rb index 946ce0e845..9afb148906 100644 --- a/config/application.rb +++ b/config/application.rb @@ -58,6 +58,8 @@ class Application < Rails::Application config.x.redis_namespace = "app" + # Avec cette configuration, on crée un cookie sans date d'expiration. + # L'expiration est gérée avec le module Timeoutable de Devise. config.session_store :cookie_store, key: "_rdv_sp_session" # Devise layout diff --git a/config/locales/views/devise.fr.yml b/config/locales/views/devise.fr.yml index 453adab49a..c6129f40a9 100644 --- a/config/locales/views/devise.fr.yml +++ b/config/locales/views/devise.fr.yml @@ -4,6 +4,3 @@ fr: new: email: Email password: Mot de passe - sessions: - new: - remember_me: Se souvenir de moi diff --git a/spec/features/agents/agent_can_reset_his_password_spec.rb b/spec/features/agents/account/agent_can_reset_his_password_spec.rb similarity index 100% rename from spec/features/agents/agent_can_reset_his_password_spec.rb rename to spec/features/agents/account/agent_can_reset_his_password_spec.rb diff --git a/spec/features/agents/account/agent_session_expires_spec.rb b/spec/features/agents/account/agent_session_expires_spec.rb new file mode 100644 index 0000000000..01531cf241 --- /dev/null +++ b/spec/features/agents/account/agent_session_expires_spec.rb @@ -0,0 +1,33 @@ +RSpec.describe "Agent session expiration" do + let(:password) { Faker::Internet.password(min_length: 12) } + let!(:agent) { create(:agent, password: password, password_confirmation: password) } + + def expect_to_be_logged_in + visit agents_preferences_path + expect(page).to have_content("Préférences de notifications") + end + + def expect_to_be_logged_out + visit agents_preferences_path + expect(page).to have_content("Entrez votre email et votre mot de passe") + end + + it "is done 14 days after last visit" do + login_time = Time.zone.parse("2024-01-01 12:00") + travel_to(login_time) + visit new_agent_session_path + fill_in "Email", with: agent.email + fill_in "password", with: password + click_on "Se connecter" + expect_to_be_logged_in + + travel_to(Time.zone.parse("2024-01-10 12:00")) # 10 days after last visit + expect_to_be_logged_in + + travel_to(Time.zone.parse("2024-01-24 11:55")) # almost 14 days after last visit + expect_to_be_logged_in + + travel_to(Time.zone.parse("2024-02-07 12:00")) # 14 days and 5 minutes after last visit + expect_to_be_logged_out + end +end diff --git a/spec/features/agents/change_email_spec.rb b/spec/features/agents/account/change_email_spec.rb similarity index 100% rename from spec/features/agents/change_email_spec.rb rename to spec/features/agents/account/change_email_spec.rb diff --git a/spec/features/agents/change_password_spec.rb b/spec/features/agents/account/change_password_spec.rb similarity index 100% rename from spec/features/agents/change_password_spec.rb rename to spec/features/agents/account/change_password_spec.rb diff --git a/spec/features/users/user_can_login_using_france_connect_spec.rb b/spec/features/users/account/user_can_login_using_france_connect_spec.rb similarity index 100% rename from spec/features/users/user_can_login_using_france_connect_spec.rb rename to spec/features/users/account/user_can_login_using_france_connect_spec.rb diff --git a/spec/features/users/user_can_reset_his_password_spec.rb b/spec/features/users/account/user_can_reset_his_password_spec.rb similarity index 100% rename from spec/features/users/user_can_reset_his_password_spec.rb rename to spec/features/users/account/user_can_reset_his_password_spec.rb diff --git a/spec/features/users/user_can_update_their_information_spec.rb b/spec/features/users/account/user_can_update_their_information_spec.rb similarity index 100% rename from spec/features/users/user_can_update_their_information_spec.rb rename to spec/features/users/account/user_can_update_their_information_spec.rb diff --git a/spec/features/users/user_is_redirected_back_after_login_spec.rb b/spec/features/users/account/user_is_redirected_back_after_login_spec.rb similarity index 100% rename from spec/features/users/user_is_redirected_back_after_login_spec.rb rename to spec/features/users/account/user_is_redirected_back_after_login_spec.rb diff --git a/spec/features/users/account/user_session_expires_spec.rb b/spec/features/users/account/user_session_expires_spec.rb new file mode 100644 index 0000000000..eb10f5822d --- /dev/null +++ b/spec/features/users/account/user_session_expires_spec.rb @@ -0,0 +1,28 @@ +RSpec.describe "Agent session expiration" do + let(:password) { Faker::Internet.password(min_length: 12) } + let!(:user) { create(:user, password: password, password_confirmation: password) } + + def expect_to_be_logged_in + visit users_informations_path + expect(page).to have_content("Mes informations") + end + + def expect_to_be_logged_out + visit users_informations_path + expect(page).to have_content("Entrez votre email et votre mot de passe") + end + + it "is done 30 minutes after last visit" do + visit new_user_session_path + fill_in "Email", with: user.email + fill_in "password", with: password + click_on "Se connecter" + expect_to_be_logged_in + + travel_to(28.minutes.from_now) + expect_to_be_logged_in + + travel_to(31.minutes.from_now) + expect_to_be_logged_out + end +end diff --git a/spec/features/users/user_signs_up_and_signs_in_spec.rb b/spec/features/users/account/user_signs_up_and_signs_in_spec.rb similarity index 100% rename from spec/features/users/user_signs_up_and_signs_in_spec.rb rename to spec/features/users/account/user_signs_up_and_signs_in_spec.rb