Merge pull request #1264 from betagouv/partially_clean_fc_part2
Partially clean fc part2
This commit is contained in:
commit
154181d793
8 changed files with 92 additions and 394 deletions
|
@ -1,87 +1,39 @@
|
|||
class FranceConnect::ParticulierController < ApplicationController
|
||||
before_action :redirect_to_login_if_fc_aborted, only: [:callback]
|
||||
|
||||
def login
|
||||
redirect_to FranceConnectService.authorization_uri
|
||||
end
|
||||
|
||||
def callback
|
||||
if params[:code].nil?
|
||||
return redirect_to new_user_session_path
|
||||
fetched_fci = FranceConnectService.retrieve_user_informations_particulier(params[:code])
|
||||
|
||||
fci = FranceConnectInformation
|
||||
.find_by(france_connect_particulier_id: fetched_fci[:france_connect_particulier_id]) ||
|
||||
fetched_fci.tap { |object| object.save }
|
||||
|
||||
if fci.user.nil?
|
||||
user = User.find_or_create_by(email: fci.email_france_connect) do |new_user|
|
||||
new_user.password = Devise.friendly_token[0, 20]
|
||||
end
|
||||
|
||||
fci.update_attribute('user_id', user.id)
|
||||
end
|
||||
|
||||
fetched_fc_information = FranceConnectService.retrieve_user_informations_particulier(params[:code])
|
||||
|
||||
france_connect_information = FranceConnectInformation
|
||||
.find_by(france_connect_particulier_id: fetched_fc_information[:france_connect_particulier_id])
|
||||
|
||||
if france_connect_information.nil?
|
||||
fetched_fc_information.save
|
||||
france_connect_information = fetched_fc_information
|
||||
end
|
||||
|
||||
user = france_connect_information.user
|
||||
salt = FranceConnectSaltService.new(france_connect_information).salt
|
||||
|
||||
if user.nil?
|
||||
redirect_to france_connect_particulier_new_path(fci_id: france_connect_information.id, salt: salt)
|
||||
else
|
||||
connect_france_connect_particulier(user)
|
||||
end
|
||||
connect_france_connect_particulier(fci.user)
|
||||
rescue Rack::OAuth2::Client::Error => e
|
||||
Rails.logger.error e.message
|
||||
redirect_france_connect_error_connection
|
||||
end
|
||||
|
||||
def new
|
||||
return redirect_france_connect_error_connection if !valid_salt_and_fci_id_params?
|
||||
|
||||
france_connect_information = FranceConnectInformation.find(params[:fci_id])
|
||||
@user = User.new(france_connect_information: france_connect_information).decorate
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
redirect_france_connect_error_connection
|
||||
end
|
||||
|
||||
def check_email
|
||||
return redirect_france_connect_error_connection if !valid_salt_and_fci_id_params?
|
||||
|
||||
user = User.find_by_email(params[:user][:email_france_connect])
|
||||
|
||||
return create if user.nil?
|
||||
|
||||
if params[:user][:password].present?
|
||||
|
||||
if user.valid_password?(params[:user][:password])
|
||||
user.france_connect_information = FranceConnectInformation.find(params[:fci_id])
|
||||
|
||||
return connect_france_connect_particulier user
|
||||
else
|
||||
flash.now.alert = 'Mot de passe invalide'
|
||||
end
|
||||
end
|
||||
|
||||
france_connect_information = FranceConnectInformation.find(params[:fci_id])
|
||||
france_connect_information.update_attribute(:email_france_connect, params[:user][:email_france_connect])
|
||||
|
||||
@user = User.new(france_connect_information: france_connect_information).decorate
|
||||
end
|
||||
|
||||
def create
|
||||
user = User.new email: params[:user][:email_france_connect]
|
||||
user.password = Devise.friendly_token[0, 20]
|
||||
|
||||
if !user.valid?
|
||||
flash.alert = 'Email non valide'
|
||||
|
||||
return redirect_to france_connect_particulier_new_path fci_id: params[:fci_id], salt: params[:salt], user: {email_france_connect: params[:user]['email_france_connect']}
|
||||
end
|
||||
|
||||
user.save
|
||||
FranceConnectInformation.find(params[:fci_id]).update_attribute(:user, user)
|
||||
|
||||
connect_france_connect_particulier user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def redirect_to_login_if_fc_aborted
|
||||
if params[:code].empty?
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
def connect_france_connect_particulier user
|
||||
sign_out :user if user_signed_in?
|
||||
sign_out :gestionnaire if gestionnaire_signed_in?
|
||||
|
@ -89,19 +41,13 @@ class FranceConnect::ParticulierController < ApplicationController
|
|||
|
||||
sign_in user
|
||||
|
||||
user.loged_in_with_france_connect = 'particulier'
|
||||
user.save
|
||||
user.update_attribute('loged_in_with_france_connect', 'particulier')
|
||||
|
||||
redirect_to stored_location_for(current_user) || signed_in_root_path(current_user)
|
||||
redirect_to stored_location_for(current_user) || root_path(current_user)
|
||||
end
|
||||
|
||||
def redirect_france_connect_error_connection
|
||||
flash.alert = t('errors.messages.france_connect.connexion')
|
||||
redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
def valid_salt_and_fci_id_params?
|
||||
france_connect_information = FranceConnectInformation.find(params[:fci_id])
|
||||
FranceConnectSaltService.new(france_connect_information).valid? params[:salt]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
class FranceConnectSaltService
|
||||
attr_reader :model
|
||||
|
||||
def initialize france_connect_information
|
||||
raise 'Not a FranceConnectInformation class' if france_connect_information.class != FranceConnectInformation
|
||||
@model = france_connect_information
|
||||
end
|
||||
|
||||
def valid? test_salt
|
||||
salt == test_salt
|
||||
end
|
||||
|
||||
def salt
|
||||
Digest::MD5.hexdigest(model.france_connect_particulier_id + model.given_name + model.family_name + FRANCE_CONNECT[:particulier][:secret] + DateTime.now.to_date.to_s)
|
||||
end
|
||||
end
|
|
@ -1,23 +0,0 @@
|
|||
%h2.text-info
|
||||
= image_tag('logo_FC_02_small.png', style: 'height: 55px;')
|
||||
France Connect - Particulier
|
||||
|
||||
%h3 Nouvelle connexion
|
||||
%h4.text-warning{ style: 'margin-left: 20px;' } Email déjà utilisé
|
||||
|
||||
%br
|
||||
%p
|
||||
%h4.center Nous avons trouvé un compte qui utilise déjà cette adresse email.
|
||||
%p.center
|
||||
Afin d'associer ce compte à votre identifiant France Connect, merci de saisir votre mot de passe TPS.
|
||||
%br
|
||||
.center
|
||||
#france-connect-particulier-email
|
||||
= form_for @user, url: { controller: 'france_connect/particulier', action: :check_email }, method: :post do |f|
|
||||
.form-group.form-group-lg
|
||||
= f.text_field :email_france_connect, class: "form-control", readonly: 'readonly'
|
||||
%br
|
||||
= f.password_field :password, class: "form-control", placeholder: "Entrez votre mot de passe"
|
||||
= hidden_field_tag :fci_id, params[:fci_id]
|
||||
= hidden_field_tag :salt, params[:salt]
|
||||
= f.submit 'Terminer', class: %w(btn btn-lg btn-success), style: 'margin-top: 20px;', id: 'valid_new_fcp'
|
|
@ -1,32 +0,0 @@
|
|||
%h2.text-info
|
||||
= image_tag('logo_FC_02_small.png', style: 'height: 55px;')
|
||||
France Connect - Particulier
|
||||
|
||||
%h3 Nouvelle connexion
|
||||
|
||||
%br
|
||||
%p
|
||||
Nous vous avons identifié comme étant
|
||||
|
||||
%h4.text-info.center
|
||||
%strong
|
||||
= @user.gender_fr
|
||||
= @user.given_name
|
||||
= @user.family_name
|
||||
né le
|
||||
%strong
|
||||
= @user.birthdate_fr
|
||||
|
||||
%br
|
||||
%h4
|
||||
Afin de finaliser votre première connexion à TPS, merci de saisir un email valide :
|
||||
%br
|
||||
|
||||
.center
|
||||
#france-connect-particulier-email
|
||||
= form_for @user, url: { controller: 'france_connect/particulier', action: :check_email }, method: :post do |f|
|
||||
.form-group.form-group-lg
|
||||
= f.text_field :email_france_connect, class: "form-control", placeholder: "Entrez votre email"
|
||||
= hidden_field_tag :fci_id, params[:fci_id]
|
||||
= hidden_field_tag :salt, params[:salt]
|
||||
= f.submit 'Terminer', class: %w(btn btn-lg btn-success), style: 'margin-top: 20px;', id: 'valid_new_fcp'
|
|
@ -65,10 +65,6 @@ Rails.application.routes.draw do
|
|||
namespace :france_connect do
|
||||
get 'particulier' => 'particulier#login'
|
||||
get 'particulier/callback' => 'particulier#callback'
|
||||
|
||||
get 'particulier/new' => 'particulier#new'
|
||||
post 'particulier/create' => 'particulier#create'
|
||||
post 'particulier/check_email' => 'particulier#check_email'
|
||||
end
|
||||
|
||||
namespace :users do
|
||||
|
|
|
@ -1,225 +1,103 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe FranceConnect::ParticulierController, type: :controller do
|
||||
let(:code) { 'plop' }
|
||||
let(:given_name) { 'titi' }
|
||||
let(:family_name) { 'toto' }
|
||||
let(:birthdate) { '20150821' }
|
||||
let(:gender) { 'M' }
|
||||
let(:birthplace) { '1234' }
|
||||
let(:france_connect_particulier_id) { 'blabla' }
|
||||
let(:email) { 'test@test.com' }
|
||||
let(:password) { '' }
|
||||
|
||||
let(:user_info) { { france_connect_particulier_id: france_connect_particulier_id, given_name: given_name, family_name: family_name, birthdate: birthdate, birthplace: birthplace, gender: gender, email_france_connect: email } }
|
||||
|
||||
describe '.auth' do
|
||||
it 'redirect to france connect serveur' do
|
||||
get :login
|
||||
expect(response.status).to eq(302)
|
||||
end
|
||||
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
|
||||
|
||||
describe '.callback' do
|
||||
describe '#auth' do
|
||||
subject { get :login }
|
||||
|
||||
it { is_expected.to have_http_status(:redirect) }
|
||||
end
|
||||
|
||||
describe '#callback' do
|
||||
let(:code) { 'plop' }
|
||||
|
||||
subject { get :callback, params: {code: code} }
|
||||
|
||||
context 'when param code is missing' do
|
||||
it 'redirect to login page' do
|
||||
get :callback
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
let(:code) { nil }
|
||||
|
||||
it { is_expected.to redirect_to(new_user_session_path) }
|
||||
end
|
||||
|
||||
context 'when params code is present' do
|
||||
context 'when code is correct' do
|
||||
before do
|
||||
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier)
|
||||
.and_return(FranceConnectInformation.new(user_info))
|
||||
end
|
||||
context 'when param code is empty' do
|
||||
let(:code) { '' }
|
||||
|
||||
context 'when france_connect_particulier_id exist in database' do
|
||||
let!(:france_connect_information) { create(:france_connect_information, france_connect_particulier_id: france_connect_particulier_id, given_name: given_name, family_name: family_name, birthdate: birthdate, gender: gender, birthplace: birthplace) }
|
||||
it { is_expected.to redirect_to(new_user_session_path) }
|
||||
end
|
||||
|
||||
context {
|
||||
subject { get :callback, params: {code: code} }
|
||||
context 'when code is correct' do
|
||||
before do
|
||||
allow(FranceConnectService).to receive(:retrieve_user_informations_particulier)
|
||||
.and_return(FranceConnectInformation.new(user_info))
|
||||
end
|
||||
|
||||
it 'does not create a new france_connect_information in database' do
|
||||
expect { subject }.not_to change { FranceConnectInformation.count }
|
||||
end
|
||||
}
|
||||
context 'when france_connect_particulier_id exist in database' do
|
||||
let!(:france_connect_information) { create(:france_connect_information, user_info) }
|
||||
|
||||
context 'when france_connect_particulier_id have an associate user' do
|
||||
before do
|
||||
create(:user, email: email, france_connect_information: france_connect_information)
|
||||
it { expect { subject }.not_to change { FranceConnectInformation.count } }
|
||||
|
||||
get :callback, params: {code: code}
|
||||
end
|
||||
context 'when france_connect_particulier_id have an associate user' do
|
||||
let!(:user) { create(:user, email: 'plop@plop.com', france_connect_information: france_connect_information) }
|
||||
|
||||
let(:email) { 'plop@plop.com' }
|
||||
let(:current_user) { User.find_by_email(email) }
|
||||
it do
|
||||
subject
|
||||
expect(user.reload.loged_in_with_france_connect).to eq('particulier')
|
||||
end
|
||||
|
||||
context 'and the user has a stored location' do
|
||||
let(:stored_location) { '/plip/plop' }
|
||||
before { controller.store_location_for(:user, stored_location) }
|
||||
|
||||
it 'current user have attribut loged_in_with_france_connect? at true' do
|
||||
expect(current_user.loged_in_with_france_connect?).to be_truthy
|
||||
end
|
||||
|
||||
it 'redirect to stored location' do
|
||||
subject.store_location_for(:user, stored_location)
|
||||
|
||||
get :callback, params: {code: code}
|
||||
expect(response).to redirect_to(stored_location)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when france_connect_particulier_id does not have an associate user' do
|
||||
let(:salt) { FranceConnectSaltService.new(france_connect_information).salt }
|
||||
|
||||
before do
|
||||
get :callback, params: {code: code}
|
||||
end
|
||||
|
||||
it 'redirects to check email FC page' do
|
||||
expect(response).to redirect_to(france_connect_particulier_new_path(fci_id: france_connect_information.id, salt: salt))
|
||||
end
|
||||
it { is_expected.to redirect_to(stored_location) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when france_connect_particulier_id does not exist in database' do
|
||||
let(:last_france_connect_information) { FranceConnectInformation.last }
|
||||
let(:salt) { FranceConnectSaltService.new(last_france_connect_information).salt }
|
||||
subject { get :callback, params: {code: code} }
|
||||
context 'when france_connect_particulier_id does not have an associate user' do
|
||||
it { is_expected.to redirect_to(root_path) }
|
||||
|
||||
it { expect { subject }.to change { FranceConnectInformation.count }.by(1) }
|
||||
|
||||
describe 'FranceConnectInformation attributs' do
|
||||
before do
|
||||
get :callback, params: {code: code}
|
||||
end
|
||||
|
||||
subject { last_france_connect_information }
|
||||
|
||||
it { expect(subject.gender).to eq gender }
|
||||
it { expect(subject.given_name).to eq given_name }
|
||||
it { expect(subject.family_name).to eq family_name }
|
||||
it { expect(subject.email_france_connect).to eq email }
|
||||
it { expect(subject.birthdate.to_time.to_i).to eq birthdate.to_time.to_i }
|
||||
it { expect(subject.birthplace).to eq birthplace }
|
||||
it { expect(subject.france_connect_particulier_id).to eq france_connect_particulier_id }
|
||||
end
|
||||
|
||||
it 'redirects to check email FC page' do
|
||||
expect(subject).to redirect_to(france_connect_particulier_new_path(fci_id: last_france_connect_information.id, salt: salt))
|
||||
it do
|
||||
subject
|
||||
expect(User.find_by(email: email)).not_to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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') }
|
||||
get :callback, params: {code: code}
|
||||
context 'when france_connect_particulier_id does not exist in database' do
|
||||
it { expect { subject }.to change { FranceConnectInformation.count }.by(1) }
|
||||
|
||||
describe 'FranceConnectInformation attributs' do
|
||||
let(:stored_fci) { FranceConnectInformation.last }
|
||||
|
||||
before { subject }
|
||||
|
||||
it { expect(stored_fci).to have_attributes(user_info.merge(birthdate: DateTime.parse(birthdate))) }
|
||||
end
|
||||
|
||||
it 'redirect to login page' do
|
||||
expect(response).to redirect_to(new_user_session_path)
|
||||
end
|
||||
|
||||
it 'display error message' do
|
||||
expect(flash[:alert]).to be_present
|
||||
end
|
||||
it { is_expected.to redirect_to(root_path) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #check_email' do
|
||||
let(:email) { 'plop@gmail.com' }
|
||||
|
||||
let!(:france_connect_information) { create(:france_connect_information) }
|
||||
let(:france_connect_information_id) { france_connect_information.id }
|
||||
let(:salt) { FranceConnectSaltService.new(france_connect_information).salt }
|
||||
|
||||
subject { post :check_email, params: {fci_id: france_connect_information_id, salt: salt, user: {email_france_connect: email}} }
|
||||
|
||||
context 'when salt and fci_id does not matches' do
|
||||
let(:france_connect_information_fake) { create(:france_connect_information, france_connect_particulier_id: 'iugfjh') }
|
||||
let(:france_connect_information_id) { france_connect_information_fake.id }
|
||||
|
||||
it { is_expected.to redirect_to new_user_session_path }
|
||||
end
|
||||
|
||||
context 'when salt and fci_id matches' do
|
||||
context 'when email is not used' do
|
||||
context 'when email is valid' do
|
||||
it { expect { subject }.to change { User.count }.by(1) }
|
||||
|
||||
describe 'New user attributs' do
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
let(:user) { User.last }
|
||||
|
||||
it { expect(user.email).to eq email }
|
||||
it { expect(user.france_connect_information).to eq france_connect_information }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email is not valid' do
|
||||
let(:email) { 'kdjizjflk' }
|
||||
|
||||
it { expect { subject }.not_to change { User.count } }
|
||||
it { is_expected.to redirect_to(france_connect_particulier_new_path fci_id: france_connect_information.id, salt: salt, user: {email_france_connect: email}) }
|
||||
end
|
||||
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') }
|
||||
subject
|
||||
end
|
||||
|
||||
context 'when email is used' do
|
||||
let!(:user) { create(:user, email: france_connect_information.email_france_connect) }
|
||||
let(:email) { france_connect_information.email_france_connect }
|
||||
let(:password) { user.password }
|
||||
it { expect(response).to redirect_to(new_user_session_path) }
|
||||
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
subject { post :check_email, params: {fci_id: france_connect_information_id, salt: salt, user: {email_france_connect: email, password: password}} }
|
||||
|
||||
context 'when email and password couple is valid' do
|
||||
it { expect { subject }.not_to change { User.count } }
|
||||
|
||||
describe 'Update user attributs' do
|
||||
before do
|
||||
subject
|
||||
end
|
||||
|
||||
it { expect(user.france_connect_information).to eq france_connect_information }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when email and password couple is not valid' do
|
||||
let(:password) { 'fake' }
|
||||
|
||||
it { expect(flash.alert).to eq 'Mot de passe invalide' }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
let!(:france_connect_information) { create(:france_connect_information, email_france_connect: email) }
|
||||
let(:france_connect_information_id) { france_connect_information.id }
|
||||
let(:salt) { FranceConnectSaltService.new(france_connect_information).salt }
|
||||
|
||||
subject { post :create, params: {fci_id: france_connect_information_id, salt: salt, user: {email_france_connect: france_connect_information.email_france_connect}} }
|
||||
|
||||
context 'when email is filled' do
|
||||
let(:email) { 'plop@gmail.com' }
|
||||
|
||||
it { expect { subject }.to change { User.count }.by(1) }
|
||||
it { expect(subject).to redirect_to(root_path) }
|
||||
end
|
||||
|
||||
context 'when email is incorrect' do
|
||||
let(:email) { '' }
|
||||
|
||||
it { expect { subject }.not_to change { User.count } }
|
||||
it { expect(subject).to redirect_to(france_connect_particulier_new_path(fci_id: france_connect_information_id, salt: salt, user: {email_france_connect: france_connect_information.email_france_connect})) }
|
||||
it { expect(flash[:alert]).to be_present }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -55,19 +55,9 @@ feature 'France Connect Particulier Connexion' do
|
|||
before do
|
||||
page.find('.login-with-fc').click
|
||||
end
|
||||
scenario 'he is redirected to france connect particulier page' do
|
||||
expect(page).to have_content('Nouvelle connexion')
|
||||
end
|
||||
|
||||
context 'when he fill an email and valid' do
|
||||
before do
|
||||
page.find_by_id('user_email_france_connect').set email
|
||||
page.find_by_id('valid_new_fcp').click
|
||||
end
|
||||
|
||||
scenario 'he is redirected to user dossiers page' do
|
||||
expect(page).to have_content('Dossiers')
|
||||
end
|
||||
scenario 'he is redirected to user dossiers page' do
|
||||
expect(page).to have_content('Dossiers')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe FranceConnectSaltService do
|
||||
describe '.initialize' do
|
||||
context 'when args is not a FranceConnectInformation class' do
|
||||
let(:args) { create(:dossier) }
|
||||
|
||||
subject { described_class.new args }
|
||||
|
||||
it { expect { subject }.to raise_error 'Not a FranceConnectInformation class' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.valid?' do
|
||||
let(:france_connect_information) { create(:france_connect_information) }
|
||||
let(:salt_service) { FranceConnectSaltService.new(france_connect_information) }
|
||||
let(:salt) { salt_service.salt }
|
||||
|
||||
context 'when france_connect_information_id is correct' do
|
||||
let(:france_connect_information_id) { france_connect_information.id }
|
||||
let(:france_connect_information_get_with_id) { FranceConnectInformation.find(france_connect_information_id) }
|
||||
let(:salt_service_compare) { FranceConnectSaltService.new france_connect_information_get_with_id }
|
||||
|
||||
subject { salt_service_compare.valid? salt }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when france_connect_information_id is not correct' do
|
||||
let(:france_connect_information_fake) { create(:france_connect_information, france_connect_particulier_id: '87515272') }
|
||||
|
||||
let(:france_connect_information_id) { france_connect_information_fake.id }
|
||||
let(:france_connect_information_get_with_id) { FranceConnectInformation.find(france_connect_information_id) }
|
||||
let(:salt_service_compare) { FranceConnectSaltService.new france_connect_information_get_with_id }
|
||||
|
||||
subject { salt_service_compare.valid? salt }
|
||||
|
||||
it { is_expected.to be_falsey }
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue