FC ParticulierController: implement auto reconciliation based on user email

This commit is contained in:
simon lehericey 2018-01-16 12:08:50 +01:00 committed by Simon Lehericey
parent ecfb0f4ec2
commit 02dd1e209c
8 changed files with 11 additions and 269 deletions

View file

@ -12,51 +12,20 @@ class FranceConnect::ParticulierController < ApplicationController
.find_by(france_connect_particulier_id: fetched_fci[:france_connect_particulier_id]) ||
fetched_fci.tap { |object| object.save }
salt = FranceConnectSaltService.new(fci).salt
if fci.user.nil?
redirect_to france_connect_particulier_new_path(fci_id: fci.id, salt: salt)
else
connect_france_connect_particulier(fci.user)
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
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
private
def redirect_to_login_if_fc_aborted
@ -65,22 +34,6 @@ class FranceConnect::ParticulierController < ApplicationController
end
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
def connect_france_connect_particulier user
sign_out :user if user_signed_in?
sign_out :gestionnaire if gestionnaire_signed_in?
@ -98,9 +51,4 @@ class FranceConnect::ParticulierController < ApplicationController
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

View file

@ -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

View file

@ -1,23 +0,0 @@
%h2.text-info
= image_tag('logo_FC_02_small.png', style: 'height: 55px;')
&nbsp;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'

View file

@ -1,32 +0,0 @@
%h2.text-info
= image_tag('logo_FC_02_small.png', style: 'height: 55px;')
&nbsp;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'

View file

@ -65,9 +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/check_email' => 'particulier#check_email'
end
namespace :users do

View file

@ -9,7 +9,6 @@ describe FranceConnect::ParticulierController, type: :controller do
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 } }
@ -70,21 +69,16 @@ describe FranceConnect::ParticulierController, type: :controller do
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 {expect(response).to redirect_to(root_path)}
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} }
it { expect { subject }.to change { FranceConnectInformation.count }.by(1) }
@ -105,9 +99,7 @@ describe FranceConnect::ParticulierController, type: :controller do
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))
end
it { expect(subject).to redirect_to(root_path) }
end
end
@ -127,77 +119,4 @@ describe FranceConnect::ParticulierController, type: :controller do
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
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 }
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
end

View file

@ -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

View file

@ -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