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
it 'creates an user with the same email and log in' do
expect { subject } . to change { User . count } . by ( 1 )
user = User . last
expect ( user . email ) . to eq ( email . downcase )
expect ( controller . current_user ) . to eq ( user )
expect ( response ) . to redirect_to ( root_path )
end
2023-12-26 15:00:15 +01:00
context 'when invites are pending' do
let! ( :invite ) { create ( :invite , email : email , user : nil ) }
it 'links pending invites' do
expect ( invite . reload . user ) . to eq ( nil )
subject
expect ( invite . reload . user ) . to eq ( User . last )
end
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 ) }
it 'redirects to the merge process' do
expect { subject } . not_to change { User . count }
expect ( response ) . to redirect_to ( france_connect_particulier_merge_path ( fci . reload . merge_token ) )
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 ) }
it 'redirects to the merge process' do
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
2018-01-16 13:52:44 +01:00
describe 'FranceConnectInformation attributs' do
2018-01-16 15:16:51 +01:00
let ( :stored_fci ) { FranceConnectInformation . last }
2016-01-21 17:06:09 +01:00
2018-01-16 15:16:51 +01:00
before { subject }
2018-01-16 13:52:44 +01:00
2019-11-25 14:39:42 +01:00
it { expect ( stored_fci ) . to have_attributes ( user_info . merge ( birthdate : Time . zone . parse ( birthdate ) . to_datetime ) ) }
2015-12-24 10:12:23 +01:00
end
2018-01-16 13:52:44 +01:00
2018-01-16 15:16:51 +01:00
it { is_expected . to redirect_to ( root_path ) }
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
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
2021-12-08 19:17:46 +01:00
stub_const ( " APPLICATION_NAME " , " 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
2021-11-17 16:21:55 +01:00
expect ( flash . alert ) . to eq ( 'Le délai pour fusionner les comptes FranceConnect et demarches-simplifiees.fr est expirée. Veuillez recommencer la procédure pour vous fusionner les comptes.' )
2021-10-13 09:23:40 +02:00
end
end
end
2021-10-13 09:23:14 +02:00
describe '#merge' do
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
2021-10-13 09:23:40 +02:00
let ( :format ) { :html }
2021-10-13 09:23:14 +02:00
subject { get :merge , params : { merge_token : merge_token } }
context 'when the merge token is valid' do
it { expect ( subject ) . to have_http_status ( :ok ) }
end
2021-10-13 09:23:40 +02:00
it_behaves_like " a method that needs a valid merge token "
context 'when the merge token does not exist' do
let ( :merge_token ) { 'i do not exist' }
2021-10-13 09:23:14 +02:00
2021-12-08 19:17:46 +01:00
before do
stub_const ( " APPLICATION_NAME " , " demarches-simplifiees.fr " )
end
2021-10-13 09:23:14 +02:00
it do
expect ( subject ) . to redirect_to root_path
2021-11-17 16:21:55 +01:00
expect ( flash . alert ) . to eq ( " Le délai pour fusionner les comptes FranceConnect et demarches-simplifiees.fr est expirée. Veuillez recommencer la procédure pour vous fusionner les comptes. " )
2021-10-13 09:23:14 +02:00
end
end
2021-10-13 09:23:40 +02:00
end
2021-10-13 09:23:14 +02:00
2021-10-13 09:23:40 +02:00
describe '#merge_with_existing_account' do
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
2021-10-13 09:23:40 +02:00
subject { post :merge_with_existing_account , params : { merge_token : merge_token , email : email , password : password } , format : format }
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
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
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
2021-11-17 16:21:55 +01:00
describe '#mail_merge_with_existing_account' do
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-01-11 10:40:44 +01:00
subject { post :mail_merge_with_existing_account , params : { email_merge_token : } }
2021-11-17 16:21:55 +01:00
let! ( :user ) { create ( :user , email : email , password : 'abcdefgh' ) }
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 )
2021-11-23 13:30:07 +01:00
expect ( flash [ :notice ] ) . to eq ( " Les comptes FranceConnect et #{ 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
2024-01-11 10:40:44 +01:00
context 'when the email_merge_token is not ok' do
subject { post :mail_merge_with_existing_account , params : { email_merge_token : 'ko' } }
2021-11-17 16:21:55 +01:00
let! ( :user ) { create ( :user , email : email ) }
it 'increases the failed attempts counter' do
subject
fci . reload
expect ( fci . user ) . to be_nil
2024-01-11 10:40:44 +01:00
expect ( fci . email_merge_token ) . not_to be_nil
2021-11-17 16:21:55 +01:00
expect ( controller . current_user ) . to be_nil
expect ( response ) . to redirect_to ( root_path )
end
end
end
2021-10-13 09:26:54 +02:00
describe '#merge_with_new_account' do
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
let ( :email ) { ' Account@a.com ' }
2022-07-13 14:03:41 +02:00
let ( :format ) { :turbo_stream }
2021-10-13 09:26:54 +02:00
subject { post :merge_with_new_account , params : { merge_token : merge_token , email : email } , format : format }
it_behaves_like " a method that needs a valid merge token "
context 'when the email does not belong to any user' do
it 'creates the account, signs in, and delete the merge token' do
subject
fci . reload
expect ( fci . user . email ) . to eq ( email . downcase . strip )
expect ( fci . merge_token ) . to be_nil
expect ( controller . current_user ) . to eq ( fci . user )
2022-07-13 14:03:41 +02:00
expect ( response ) . to redirect_to ( root_path )
2021-10-13 09:26:54 +02:00
end
end
2021-10-13 01:08:57 +02:00
context 'when an account with the same email exists' do
let! ( :user ) { create ( :user , email : email ) }
2024-01-10 21:09:57 +01:00
before { allow ( controller ) . to receive ( :sign_in ) . and_call_original }
2021-10-13 01:08:57 +02:00
render_views
it 'asks for the corresponding password' 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 ( response . body ) . to include ( 'entrez votre mot de passe' )
end
2024-01-10 21:09:57 +01:00
it 'cannot use the merge token in the email confirmation route' do
subject
fci . reload
2024-01-11 10:40:44 +01:00
get :mail_merge_with_existing_account , params : { email_merge_token : fci . merge_token }
2024-01-10 21:09:57 +01:00
expect ( controller ) . not_to have_received ( :sign_in )
expect ( flash [ :alert ] ) . to be_present
end
2021-10-13 01:08:57 +02:00
end
2021-10-13 09:26:54 +02:00
end
2021-11-17 16:21:55 +01:00
describe '#resend_and_renew_merge_confirmation' do
let ( :fci ) { FranceConnectInformation . create! ( user_info ) }
let ( :merge_token ) { fci . create_merge_token! }
it 'renew token' do
expect { post :resend_and_renew_merge_confirmation , params : { merge_token : merge_token } } . to change { fci . reload . merge_token }
2024-01-11 10:44:19 +01:00
expect ( fci . email_merge_token ) . to be_present
2021-11-17 16:21:55 +01:00
expect ( response ) . to redirect_to ( france_connect_particulier_merge_path ( fci . reload . merge_token ) )
end
end
2015-12-24 10:12:23 +01:00
end