From b20a072223c0973c69c6e1a7b9073d8cb58ab2bb Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Wed, 11 Dec 2024 18:53:17 +0100 Subject: [PATCH 1/3] [#10952] If email is in mandatory list redirect to ProConnect --- app/controllers/users/sessions_controller.rb | 10 +++++ app/services/agent_connect_service.rb | 6 +++ app/views/agent_connect/agent/index.html.haml | 44 +++++++++---------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index e45f22ae026..f54becc534f 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -7,6 +7,7 @@ class Users::SessionsController < Devise::SessionsController layout 'login', only: [:new, :create] + before_action :redirect_to_agent_connect_if_mandatory, only: [:create] before_action :restore_procedure_context, only: [:new, :create] skip_before_action :redirect_if_untrusted, only: [:reset_link_sent] # POST /resource/sign_in @@ -117,4 +118,13 @@ def logout redirect_to root_path, notice: I18n.t('devise.sessions.signed_out') end + + def redirect_to_agent_connect_if_mandatory + return if !AgentConnectService.enabled? + + return if !AgentConnectService.email_domain_is_in_mandatory_list?(params[:user][:email]) + + flash[:alert] = "La connexion des agents passe à présent systématiquement par AgentConnect" + redirect_to agent_connect_path(force_agent_connect: true) + end end diff --git a/app/services/agent_connect_service.rb b/app/services/agent_connect_service.rb index 6b2dc6ba15f..f06749173bf 100644 --- a/app/services/agent_connect_service.rb +++ b/app/services/agent_connect_service.rb @@ -3,6 +3,8 @@ class AgentConnectService include OpenIDConnect + MANDATORY_EMAIL_DOMAINS = ['beta.gouv.fr', 'modernisation.gouv.fr'] + def self.enabled? ENV['AGENT_CONNECT_BASE_URL'].present? end @@ -45,6 +47,10 @@ def self.logout_url(id_token, host_with_port:) "#{AGENT_CONNECT[:end_session_endpoint]}?#{h.to_query}" end + def self.email_domain_is_in_mandatory_list?(email) + email.strip.split('@').last.in?(MANDATORY_EMAIL_DOMAINS) + end + private # TODO: remove this block when migration to new domain is done diff --git a/app/views/agent_connect/agent/index.html.haml b/app/views/agent_connect/agent/index.html.haml index d83c40f8c95..6187bf8deeb 100644 --- a/app/views/agent_connect/agent/index.html.haml +++ b/app/views/agent_connect/agent/index.html.haml @@ -26,36 +26,36 @@ %p = link_to t('.whats_agentconnect'), 'https://agentconnect.gouv.fr/', target: '_blank', rel: "noopener" + - if !params[:force_agent_connect] + %p.fr-hr-or= t('views.shared.france_connect_login.separator') - %p.fr-hr-or= t('views.shared.france_connect_login.separator') + %fieldset.fr-mb-0.fr-fieldset{ aria: { labelledby: 'new-account-legend' } } + %legend.fr-fieldset__legend#new-account-legend + %h2.fr-h6= I18n.t('views.users.sessions.new.subtitle') - %fieldset.fr-mb-0.fr-fieldset{ aria: { labelledby: 'new-account-legend' } } - %legend.fr-fieldset__legend#new-account-legend - %h2.fr-h6= I18n.t('views.users.sessions.new.subtitle') + = render Dsfr::AlertComponent.new(state: :info, size: :sm, extra_class_names: 'fr-mb-2w') do |c| + - c.with_body do + = t('views.users.sessions.new.for_tiers_alert') - = render Dsfr::AlertComponent.new(state: :info, size: :sm, extra_class_names: 'fr-mb-2w') do |c| - - c.with_body do - = t('views.users.sessions.new.for_tiers_alert') + .fr-fieldset__element + %p.fr-text--sm= t('utils.asterisk_html') - .fr-fieldset__element - %p.fr-text--sm= t('utils.asterisk_html') + .fr-fieldset__element + = render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email' }) do |c| + - c.with_label { t('.pro_email') } - .fr-fieldset__element - = render Dsfr::InputComponent.new(form: f, attribute: :email, input_type: :email_field, opts: { autocomplete: 'email' }) do |c| - - c.with_label { t('.pro_email') } + .fr-fieldset__element + = render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'current-password' }) - .fr-fieldset__element - = render Dsfr::InputComponent.new(form: f, attribute: :password, input_type: :password_field, opts: { autocomplete: 'current-password' }) + %p= link_to t('views.users.sessions.new.reset_password'), new_user_password_path, class: "fr-link" - %p= link_to t('views.users.sessions.new.reset_password'), new_user_password_path, class: "fr-link" - - .fr-fieldset__element - .auth-options - .flex-no-shrink - = f.check_box :remember_me - = f.label :remember_me, t('views.users.sessions.new.remember_me'), class: 'remember-me' + .fr-fieldset__element + .auth-options + .flex-no-shrink + = f.check_box :remember_me + = f.label :remember_me, t('views.users.sessions.new.remember_me'), class: 'remember-me' - .fr-btns-group= f.submit t('views.users.sessions.new.connection'), class: "fr-btn" + .fr-btns-group= f.submit t('views.users.sessions.new.connection'), class: "fr-btn" %hr From 6595b2a7c599b0eed7dfa4434f054fea2d3e018f Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 12 Dec 2024 12:01:32 +0100 Subject: [PATCH 2/3] [#10952] Fix small UI bug when a flash is present on this page --- app/views/agent_connect/agent/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/agent_connect/agent/index.html.haml b/app/views/agent_connect/agent/index.html.haml index 6187bf8deeb..8e96b0c4dfd 100644 --- a/app/views/agent_connect/agent/index.html.haml +++ b/app/views/agent_connect/agent/index.html.haml @@ -2,7 +2,7 @@ #agentconnect .fr-container - .fr-grid-row.fr-grid-row--gutters + .fr-grid-row.fr-grid-row--gutters.fr-mt-0 .fr-col-lg.fr-p-6w.fr-background-alt--blue-france From 9e03f940857eb01ab780d3951705b70a3cfe799c Mon Sep 17 00:00:00 2001 From: Mathieu Magnin Date: Thu, 12 Dec 2024 15:25:54 +0100 Subject: [PATCH 3/3] [#10952] Tests --- .../users/sessions_controller_spec.rb | 10 ++++++++ spec/services/agent_connect_service_spec.rb | 24 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/spec/controllers/users/sessions_controller_spec.rb b/spec/controllers/users/sessions_controller_spec.rb index 42c4e0f5807..5ed883879d8 100644 --- a/spec/controllers/users/sessions_controller_spec.rb +++ b/spec/controllers/users/sessions_controller_spec.rb @@ -96,6 +96,16 @@ expect(controller.current_user).to be(nil) end end + + context 'when email domain is in mandatory list' do + let(:email) { 'user@beta.gouv.fr' } + it 'redirects to agent connect with force parameter' do + expect(AgentConnectService).to receive(:enabled?).and_return(true) + subject + expect(response).to redirect_to(agent_connect_path(force_agent_connect: true)) + expect(flash[:alert]).to eq("La connexion des agents passe à présent systématiquement par AgentConnect") + end + end end describe '#destroy' do diff --git a/spec/services/agent_connect_service_spec.rb b/spec/services/agent_connect_service_spec.rb index f0aa30db7a0..5884eee1176 100644 --- a/spec/services/agent_connect_service_spec.rb +++ b/spec/services/agent_connect_service_spec.rb @@ -16,4 +16,28 @@ expect(subject).to eq("https://agent-connect.fr/logout?id_token_hint=id_token&post_logout_redirect_uri=http%3A%2F%2Ftest.host%2Flogout") end end + + describe '.email_domain_is_in_mandatory_list?' do + subject { described_class.email_domain_is_in_mandatory_list?(email) } + + context 'when email domain is beta.gouv.fr' do + let(:email) { 'user@beta.gouv.fr' } + it { is_expected.to be true } + end + + context 'when email domain is modernisation.gouv.fr' do + let(:email) { 'user@modernisation.gouv.fr' } + it { is_expected.to be true } + end + + context 'when email domain is not in the mandatory list' do + let(:email) { 'user@example.com' } + it { is_expected.to be false } + end + + context 'when email contains whitespace' do + let(:email) { ' user@beta.gouv.fr ' } + it { is_expected.to be true } + end + end end