2024-04-29 00:17:15 +02:00
# frozen_string_literal: true
2015-12-24 10:12:23 +01:00
describe FranceConnect :: ParticulierController , type : :controller do
let ( :birthdate ) { '20150821' }
2021-10-13 00:45:20 +02:00
let ( :email ) { 'EMAIL_from_fc@test.com' }
2015-12-24 10:12:23 +01:00
2018-01-16 15:29:37 +01:00
let ( :user_info ) do
{
france_connect_particulier_id : 'blablabla' ,
given_name : 'titi' ,
family_name : 'toto' ,
birthdate : birthdate ,
birthplace : '1234' ,
gender : 'M' ,
email_france_connect : email
}
end
2015-12-24 10:12:23 +01:00
2018-01-16 13:37:38 +01:00
describe '#auth' do
subject { get :login }
it { is_expected . to have_http_status ( :redirect ) }
2015-12-24 10:12:23 +01:00
end
2018-01-16 13:45:12 +01:00
describe '#callback' do
2018-01-16 15:29:37 +01:00
let ( :code ) { 'plop' }
2018-01-16 13:34:24 +01:00
subject { get :callback , params : { code : code } }
2018-01-16 13:45:12 +01:00
2019-05-09 13:54:50 +02:00
context 'when params are missing' do
subject { get :callback }
it { is_expected . to redirect_to ( new_user_session_path ) }
end
2018-01-16 14:11:17 +01:00
context 'when param code is missing' do
2018-01-16 13:45:12 +01:00
let ( :code ) { nil }
it { is_expected . to redirect_to ( new_user_session_path ) }
end
context 'when param code is empty' do
let ( :code ) { '' }
it { is_expected . to redirect_to ( new_user_session_path ) }
2015-12-24 10:12:23 +01:00
end
2018-01-16 13:52:44 +01:00
context 'when code is correct' do
before do
allow ( FranceConnectService ) . to receive ( :retrieve_user_informations_particulier )
. and_return ( FranceConnectInformation . new ( user_info ) )
end
2016-01-21 17:06:09 +01:00
2021-10-11 11:39:14 +02:00
context 'when france_connect_particulier_id exists in database' do
2021-10-13 00:45:20 +02:00
let! ( :fci ) { FranceConnectInformation . create! ( user_info . merge ( user_id : fc_user & . id ) ) }
2016-01-21 17:06:09 +01:00
2021-10-11 11:39:14 +02:00
context 'and is linked to an user' do
let ( :fc_user ) { create ( :user , email : 'associated_user@a.com' ) }
2016-01-21 17:06:09 +01:00
2021-10-11 11:39:14 +02:00
it { expect { subject } . not_to change { FranceConnectInformation . count } }
2023-11-17 11:21:01 +01:00
it { expect { subject } . to change { fc_user . reload . last_sign_in_at } }
2021-10-11 11:39:14 +02:00
it 'signs in with the fci associated user' do
subject
expect ( controller . current_user ) . to eq ( fc_user )
expect ( fc_user . reload . loged_in_with_france_connect ) . to eq ( User . loged_in_with_france_connects . fetch ( :particulier ) )
end
2015-12-24 10:12:23 +01:00
2021-10-11 11:39:14 +02:00
context 'and the user has a stored location' do
let ( :stored_location ) { '/plip/plop' }
before { controller . store_location_for ( :user , stored_location ) }
2016-01-21 17:06:09 +01:00
2021-10-11 11:39:14 +02:00
it { is_expected . to redirect_to ( stored_location ) }
end
2015-12-24 10:12:23 +01:00
end
2021-10-11 11:39:14 +02:00
context 'and is linked an instructeur' do
let ( :fc_user ) { create ( :instructeur , email : 'another_email@a.com' ) . user }
2021-04-26 16:27:28 +02:00
2021-10-11 11:39:14 +02:00
before { subject }
2021-04-26 16:27:28 +02:00
2021-10-11 11:39:14 +02:00
it do
expect ( response ) . to redirect_to ( new_user_session_path )
expect ( flash [ :alert ] ) . to be_present
end
2018-01-16 13:52:44 +01:00
end
2021-10-13 00:45:20 +02:00
context 'and is not linked to an user' do
let ( :fc_user ) { nil }
context 'and no user with the same email exists' do
2024-07-04 12:47:53 +02:00
it 'render the choose email template to select good email' do
expect { subject } . to change { User . count } . by ( 0 )
expect ( subject ) . to render_template ( :choose_email )
2023-12-26 15:00:15 +01:00
end
2021-10-13 00:45:20 +02:00
end
context 'and an user with the same email exists' do
let! ( :preexisting_user ) { create ( :user , email : email ) }
2024-07-31 17:50:14 +02:00
it 'renders the merge page' do
2021-10-13 00:45:20 +02:00
expect { subject } . not_to change { User . count }
2024-07-31 17:50:14 +02:00
expect ( response ) . to render_template ( :merge )
2021-10-13 00:45:20 +02:00
end
end
2021-11-23 10:44:38 +01:00
context 'and an instructeur with the same email exists' do
let! ( :preexisting_user ) { create ( :instructeur , email : email ) }
2024-07-31 17:50:14 +02:00
it 'redirects to the login path' do
2021-11-23 10:44:38 +01:00
expect { subject } . not_to change { User . count }
expect ( response ) . to redirect_to ( new_user_session_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'errors.messages.france_connect.forbidden_html' , reset_link : new_user_password_path ) )
end
end
2021-10-13 00:45:20 +02:00
end
2018-01-16 13:52:44 +01:00
end
2016-01-21 17:06:09 +01:00
2018-01-16 13:52:44 +01:00
context 'when france_connect_particulier_id does not exist in database' do
it { expect { subject } . to change { FranceConnectInformation . count } . by ( 1 ) }
2016-01-21 17:06:09 +01:00
2024-07-04 12:47:53 +02:00
it { is_expected . to render_template ( :choose_email ) }
2015-12-24 10:12:23 +01:00
end
2018-01-16 13:52:44 +01:00
end
2015-12-24 10:12:23 +01:00
2018-01-16 13:52:44 +01:00
context 'when code is not correct' do
before do
allow ( FranceConnectService ) . to receive ( :retrieve_user_informations_particulier ) { raise Rack :: OAuth2 :: Client :: Error . new ( 500 , error : 'Unknown' ) }
2018-01-16 15:16:51 +01:00
subject
2018-01-16 13:52:44 +01:00
end
2015-12-24 10:12:23 +01:00
2018-01-16 15:16:51 +01:00
it { expect ( response ) . to redirect_to ( new_user_session_path ) }
2015-12-24 10:12:23 +01:00
2018-01-16 15:16:51 +01:00
it { expect ( flash [ :alert ] ) . to be_present }
2015-12-24 10:12:23 +01:00
end
end
2021-10-13 09:23:14 +02:00
2024-07-31 17:50:14 +02:00
describe '#merge_using_fc_email' do
subject { post :merge_using_fc_email , params : { merge_token : merge_token } }
2024-07-04 12:47:53 +02:00
2024-07-31 17:50:14 +02:00
let! ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
2024-07-04 12:47:53 +02:00
before do
2024-07-31 17:50:14 +02:00
allow ( UserMailer ) . to receive_message_chain ( :custom_confirmation_instructions , :deliver_later )
2024-07-04 12:47:53 +02:00
end
2024-07-31 17:50:14 +02:00
context 'when the merge token is valid' do
it do
expect ( User . last . email ) . not_to eq ( email . downcase )
2024-07-04 12:47:53 +02:00
2024-07-31 17:50:14 +02:00
subject
2024-07-25 13:24:43 +02:00
2024-07-31 17:50:14 +02:00
user = User . last
2024-07-25 13:24:43 +02:00
2024-07-31 17:50:14 +02:00
expect ( user . email ) . to eq ( email . downcase )
expect ( UserMailer ) . to have_received ( :custom_confirmation_instructions ) . with ( user , user . confirmation_token )
expect ( user . email_verified_at ) . to be_nil
expect ( fci . reload . merge_token ) . to be_nil
expect ( response ) . to render_template ( :confirmation_sent )
2024-07-04 12:47:53 +02:00
end
end
2024-07-31 17:50:14 +02:00
context 'when the merge token is invalid' do
2024-07-04 12:47:53 +02:00
let ( :merge_token ) { 'invalid_token' }
it 'redirects to root_path with an alert' do
subject
expect ( response ) . to redirect_to ( root_path )
expect ( flash [ :alert ] ) . to eq ( " Le délai pour fusionner les comptes FranceConnect et demarches-simplifiees.fr est expiré. Veuillez recommencer la procédure pour vous fusionner les comptes. " )
end
end
context 'when @fci is not valid for merge' do
before do
2024-07-31 17:50:14 +02:00
merge_token
fci . update! ( merge_token_created_at : 2 . years . ago )
2024-07-04 12:47:53 +02:00
end
it 'redirects to root_path with an alert' do
subject
2024-07-31 17:50:14 +02:00
2024-07-04 12:47:53 +02:00
expect ( response ) . to redirect_to ( root_path )
expect ( flash [ :alert ] ) . to eq ( 'Le délai pour fusionner les comptes FranceConnect et demarches-simplifiees.fr est expiré. Veuillez recommencer la procédure pour vous fusionner les comptes.' )
end
end
end
describe '#confirm_email' do
let! ( :user ) { create ( :user ) }
let! ( :fci ) { create ( :france_connect_information , user : user ) }
2024-07-31 17:50:14 +02:00
before { fci . send_custom_confirmation_instructions }
2024-07-04 12:47:53 +02:00
context 'when the confirmation token is valid' do
before do
get :confirm_email , params : { token : user . confirmation_token }
user . reload
end
2024-07-31 17:50:14 +02:00
it do
2024-07-04 12:47:53 +02:00
expect ( user . email_verified_at ) . to be_present
expect ( user . confirmation_token ) . to be_nil
expect ( response ) . to redirect_to ( root_path ( user ) )
expect ( flash [ :notice ] ) . to eq ( 'Votre email est bien vérifié' )
end
end
context 'when invites are pending' do
let! ( :invite ) { create ( :invite , email : user . email , user : nil ) }
it 'links pending invites' do
get :confirm_email , params : { token : user . confirmation_token }
invite . reload
expect ( invite . user ) . to eq ( user )
end
end
context 'when the confirmation token is expired' do
2024-07-31 17:50:14 +02:00
let! ( :expired_user_confirmation ) do
2024-07-25 13:24:43 +02:00
create ( :user , confirmation_token : 'expired_token' , confirmation_sent_at : 3 . days . ago )
2024-07-04 12:47:53 +02:00
end
2024-07-25 13:24:43 +02:00
it 'redirects to root path with an alert when FranceConnectInformation is not found' do
get :confirm_email , params : { token : 'expired_token' }
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
expect ( response ) . to redirect_to ( root_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'france_connect.particulier.flash.confirmation_mail_resent_error' ) )
2024-07-04 12:47:53 +02:00
end
2024-07-25 13:24:43 +02:00
context 'when FranceConnectInformation exists' do
2024-07-31 17:50:14 +02:00
let! ( :france_connect_information ) do
create ( :france_connect_information , user : expired_user_confirmation )
end
2024-07-04 12:47:53 +02:00
before do
2024-07-31 17:50:14 +02:00
allow ( UserMailer ) . to receive_message_chain ( :custom_confirmation_instructions , :deliver_later )
2024-07-04 12:47:53 +02:00
end
2024-07-25 13:24:43 +02:00
it 'resends the confirmation email and redirects to root path with a notice' do
get :confirm_email , params : { token : 'expired_token' }
2024-07-04 12:47:53 +02:00
2024-07-31 17:50:14 +02:00
expect ( UserMailer ) . to have_received ( :custom_confirmation_instructions )
. with ( expired_user_confirmation , expired_user_confirmation . reload . confirmation_token )
2024-07-04 12:47:53 +02:00
expect ( response ) . to redirect_to ( root_path )
2024-07-25 13:24:43 +02:00
expect ( flash [ :notice ] ) . to eq ( I18n . t ( 'france_connect.particulier.flash.confirmation_mail_resent' ) )
2024-07-04 12:47:53 +02:00
end
end
2024-07-25 13:24:43 +02:00
end
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
context 'when a different user is signed in' do
2024-07-31 17:50:14 +02:00
let! ( :expired_user_confirmation ) do
2024-07-25 13:24:43 +02:00
create ( :user , confirmation_token : 'expired_token' , confirmation_sent_at : 3 . days . ago )
end
2024-07-04 12:47:53 +02:00
2024-07-31 17:50:14 +02:00
let ( :another_user ) { create ( :user ) }
before { sign_in ( another_user ) }
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
it 'signs out the current user and redirects to sign in path' do
2024-07-31 17:50:14 +02:00
expect_any_instance_of ( FranceConnectInformation ) . not_to receive ( :send_custom_confirmation_instructions )
expect ( controller ) . to receive ( :sign_out ) . with ( :user )
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
get :confirm_email , params : { token : 'expired_token' }
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
expect ( response ) . to redirect_to ( new_user_session_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'france_connect.particulier.flash.redirect_new_user_session' ) )
2024-07-04 12:47:53 +02:00
end
2024-07-25 13:24:43 +02:00
end
end
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
describe '#set_user_by_confirmation_token' do
let ( :current_user ) { create ( :user ) }
2024-07-31 17:50:14 +02:00
let! ( :confirmation_user ) { create ( :user , confirmation_token : 'valid_token' ) }
2024-07-04 12:47:53 +02:00
2024-07-31 17:50:14 +02:00
before { sign_in current_user }
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
it 'signs out current user and redirects to new session path when users do not match' do
2024-07-31 17:50:14 +02:00
expect ( controller ) . to receive ( :sign_out ) . with ( :user )
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
get :confirm_email , params : { token : 'valid_token' }
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
expect ( response ) . to redirect_to ( new_user_session_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'france_connect.particulier.flash.redirect_new_user_session' ) )
end
2024-07-04 12:47:53 +02:00
2024-07-25 13:24:43 +02:00
context 'when user is not found' do
it 'redirects to root path with user not found alert' do
get :confirm_email , params : { token : 'invalid_token' }
expect ( response ) . to redirect_to ( root_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'france_connect.particulier.flash.user_not_found' ) )
2024-07-04 12:47:53 +02:00
end
end
end
2021-10-13 09:23:40 +02:00
RSpec . shared_examples " a method that needs a valid merge token " do
context 'when the merge token is invalid' do
before do
2024-03-27 11:04:46 +01:00
allow ( Current ) . to receive ( :application_name ) . and_return ( 'demarches-simplifiees.fr' )
2021-10-13 09:23:40 +02:00
merge_token
fci . update ( merge_token_created_at : 2 . years . ago )
end
it do
if format == :js
subject
expect ( response . body ) . to eq ( " window.location.href='/' " )
else
expect ( subject ) . to redirect_to root_path
end
2024-03-27 11:04:46 +01:00
expect ( flash . alert ) . to eq ( 'Le délai pour fusionner les comptes FranceConnect et demarches-simplifiees.fr est expiré. Veuillez recommencer la procédure pour vous fusionner les comptes.' )
2021-10-13 09:23:40 +02:00
end
end
end
2024-07-31 17:50:14 +02:00
describe '#merge_using_password' do
2021-10-13 09:23:40 +02:00
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
let ( :email ) { 'EXISTING_account@a.com ' }
2023-03-03 14:16:15 +01:00
let ( :password ) { SECURE_PASSWORD }
2022-07-13 14:03:41 +02:00
let ( :format ) { :turbo_stream }
2021-10-13 09:23:14 +02:00
2024-07-31 17:50:14 +02:00
subject { post :merge_using_password , params : { merge_token : merge_token , password : password } , format : format }
2021-10-13 09:23:40 +02:00
it_behaves_like " a method that needs a valid merge token "
2021-10-19 11:21:24 +02:00
context 'when the user is not found' do
it 'does not log' do
subject
fci . reload
expect ( fci . user ) . to be_nil
expect ( fci . merge_token ) . not_to be_nil
expect ( controller . current_user ) . to be_nil
end
end
2021-10-13 09:23:40 +02:00
context 'when the credentials are ok' do
let! ( :user ) { create ( :user , email : email , password : password ) }
it 'merges the account, signs in, and delete the merge token' do
subject
fci . reload
expect ( fci . user ) . to eq ( user )
expect ( fci . merge_token ) . to be_nil
expect ( controller . current_user ) . to eq ( user )
end
context 'but the targeted user is an instructeur' do
let! ( :user ) { create ( :instructeur , email : email , password : password ) . user }
it 'redirects to the root page' do
subject
2024-07-31 17:50:14 +02:00
expect { fci . reload } . to raise_error ( ActiveRecord :: RecordNotFound )
2021-10-13 09:23:40 +02:00
expect ( fci . merge_token ) . not_to be_nil
expect ( controller . current_user ) . to be_nil
end
end
end
context 'when the credentials are not ok' do
let! ( :user ) { create ( :user , email : email , password : 'another password #$21$%%' ) }
it 'increases the failed attempts counter' do
subject
fci . reload
expect ( fci . user ) . to be_nil
expect ( fci . merge_token ) . not_to be_nil
expect ( controller . current_user ) . to be_nil
expect ( user . reload . failed_attempts ) . to eq ( 1 )
2021-10-13 09:23:14 +02:00
end
end
end
2021-10-13 09:26:54 +02:00
2024-07-31 17:50:14 +02:00
describe '#merge_using_email_link' do
2021-11-17 16:21:55 +01:00
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
2024-01-11 10:40:44 +01:00
let! ( :email_merge_token ) { fci . create_email_merge_token! }
2021-11-17 16:21:55 +01:00
context 'when the merge_token is ok and the user is found' do
2024-07-31 17:50:14 +02:00
subject do
post :merge_using_email_link , params : { email_merge_token : }
end
2021-11-17 16:21:55 +01:00
2024-03-27 11:04:46 +01:00
before do
allow ( Current ) . to receive ( :application_name ) . and_return ( 'demarches-simplifiees.fr' )
2024-07-31 17:50:14 +02:00
fci . update! ( requested_email : email . downcase )
2024-03-27 11:04:46 +01:00
end
2024-07-31 17:50:14 +02:00
let! ( :user ) { create ( :user , email : , password : 'abcdefgh' ) }
2021-11-17 16:21:55 +01:00
it 'merges the account, signs in, and delete the merge token' do
subject
fci . reload
expect ( fci . user ) . to eq ( user )
expect ( fci . merge_token ) . to be_nil
2024-01-11 10:44:19 +01:00
expect ( fci . email_merge_token ) . to be_nil
2021-11-17 16:21:55 +01:00
expect ( controller . current_user ) . to eq ( user )
2024-03-27 11:04:46 +01:00
expect ( flash [ :notice ] ) . to eq ( " Les comptes FranceConnect et #{ Current . application_name } sont à présent fusionnés " )
2021-11-17 16:21:55 +01:00
end
context 'but the targeted user is an instructeur' do
let! ( :user ) { create ( :instructeur , email : email , password : 'abcdefgh' ) . user }
it 'redirects to the new session' do
subject
expect ( FranceConnectInformation . exists? ( fci . id ) ) . to be_falsey
expect ( controller . current_user ) . to be_nil
expect ( response ) . to redirect_to ( new_user_session_path )
expect ( flash [ :alert ] ) . to eq ( I18n . t ( 'errors.messages.france_connect.forbidden_html' , reset_link : new_user_password_path ) )
end
end
end
end
2024-07-31 17:50:14 +02:00
describe '#send_email_merge_request' do
2021-10-13 09:26:54 +02:00
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
2024-07-31 17:50:14 +02:00
let ( :email ) { 'requested_email@.a.com' }
2021-10-13 09:26:54 +02:00
2024-07-31 17:50:14 +02:00
subject { post :send_email_merge_request , params : { merge_token : merge_token , email : } }
2021-10-13 09:26:54 +02:00
2024-07-31 17:50:14 +02:00
it 'renew token' do
allow ( UserMailer ) . to receive_message_chain ( :france_connect_merge_confirmation , :deliver_later )
subject
2024-01-10 21:09:57 +01:00
2024-07-31 17:50:14 +02:00
fci . reload
expect ( fci . requested_email ) . to eq ( email )
expect ( fci . email_merge_token ) . to be_present
2024-01-10 21:09:57 +01:00
2024-07-31 17:50:14 +02:00
expect ( UserMailer ) . to have_received ( :france_connect_merge_confirmation ) . with ( email , fci . email_merge_token , fci . email_merge_token_created_at )
2021-11-17 16:21:55 +01:00
2024-07-31 17:50:14 +02:00
expect ( response ) . to redirect_to ( root_path )
2021-11-17 16:21:55 +01:00
end
end
2015-12-24 10:12:23 +01:00
end