Merge pull request #2944 from betagouv/autologin-after-confirm

Connecte automatiquement l'usager lorsqu'il confirme son compte
This commit is contained in:
Pierre de La Morinerie 2018-11-06 18:34:20 +01:00 committed by GitHub
commit c1d017193c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 157 additions and 29 deletions

View file

@ -145,6 +145,8 @@ group :test do
gem 'capybara-selenium'
# Save a dump of the page when an integration test fails
gem 'capybara-screenshot'
# Access emails during integration tests
gem 'capybara-email'
end
group :development do

View file

@ -120,6 +120,9 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
capybara-email (3.0.1)
capybara (>= 2.4, < 4.0)
mail
capybara-screenshot (1.0.21)
capybara (>= 1.0, < 4)
launchy
@ -812,6 +815,7 @@ DEPENDENCIES
browser
byebug
capybara
capybara-email
capybara-screenshot
capybara-selenium
carrierwave

View file

@ -25,8 +25,24 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
# super(resource_name)
# end
# If the user clicks the confirmation link before the maximum delay,
# they will be signed in directly.
def sign_in_after_confirmation?(resource)
# Avoid keeping auto-sign-in links in users inboxes for too long.
# 95% of users confirm their account within two hours.
auto_sign_in_timeout = 2.hours
resource.confirmation_sent_at + auto_sign_in_timeout > DateTime.current
end
# The path used after confirmation.
# def after_confirmation_path_for(resource_name, resource)
# super(resource_name, resource)
# end
def after_confirmation_path_for(resource_name, resource)
if sign_in_after_confirmation?(resource)
resource.remember_me = true
sign_in(resource)
resource.force_sync_credentials
after_sign_in_path_for(resource_name)
else
super(resource_name, resource)
end
end
end

View file

@ -39,7 +39,6 @@ Rails.application.configure do
# Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr
config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
Rails.application.routes.default_url_options = {
host: 'localhost:3000',

View file

@ -0,0 +1,57 @@
require 'spec_helper'
describe Users::ConfirmationsController, type: :controller do
let!(:user) { create(:user, :unconfirmed) }
let(:confirmation_token) { user.confirmation_token }
before do
@request.env["devise.mapping"] = Devise.mappings[:user]
end
describe '#show' do
context 'when confirming within the auto-sign-in delay' do
before do
Timecop.travel(1.hour.from_now) {
get :show, params: { confirmation_token: confirmation_token }
}
end
it 'confirms the user' do
expect(user.reload).to be_confirmed
end
it 'signs in the user after confirming its token' do
expect(controller.current_user).to eq(user)
expect(controller.current_gestionnaire).to be(nil)
expect(controller.current_administrateur).to be(nil)
end
it 'redirects the user to the root page' do
# NB: the root page may redirect the user again to the stored procedure path
expect(controller).to redirect_to(root_path)
end
end
context 'when the auto-sign-in delay has expired' do
before do
Timecop.travel(3.hours.from_now) {
get :show, params: { confirmation_token: confirmation_token }
}
end
it 'confirms the user' do
expect(user.reload).to be_confirmed
end
it 'doesnt sign in the user' do
expect(subject.current_user).to be(nil)
expect(subject.current_gestionnaire).to be(nil)
expect(subject.current_administrateur).to be(nil)
end
it 'redirects the user to the sign-in path' do
expect(subject).to redirect_to(new_user_session_path)
end
end
end
end

View file

@ -4,5 +4,9 @@ FactoryBot.define do
email { generate(:user_email) }
password { 'password' }
confirmed_at { Time.zone.now }
trait :unconfirmed do
confirmed_at { nil }
end
end
end

View file

@ -73,9 +73,6 @@ feature 'The gestionnaire part' do
end
scenario 'A gestionnaire can use avis' do
ActionMailer::Base.deliveries = []
ActiveJob::Base.queue_adapter = :test
log_in(gestionnaire.email, password)
click_on procedure.libelle

View file

@ -32,21 +32,17 @@ feature 'Invitations' do
scenario 'an invited user can register using the registration link sent in the invitation email' do
# Click the invitation link
visit users_dossiers_invite_path(invite.id, params: { email: invite.email })
# Create the account
expect(page).to have_current_path(new_user_registration_path, ignore_query: true)
expect(page).to have_field('user_email', with: invite.email)
fill_in 'user_password', with: user_password
click_on 'Créer un compte'
# Create the account
sign_up_with invite.email, user_password
expect(page).to have_content("lien d'activation")
# Confirm the email
user = User.find_by(email: invite.email)
visit Rails.application.routes.url_helpers.user_confirmation_path(confirmation_token: user.confirmation_token)
submit_login_form(user.email, user_password)
# The user should be redirected to the dossier they was invited on
# Confirm the account
# (The user should be redirected to the dossier they was invited on)
click_confirmation_link_for invite.email
expect(page).to have_content('Votre compte a été activé')
expect(page).to have_current_path(brouillon_dossier_path(dossier))
end
end
@ -102,16 +98,10 @@ feature 'Invitations' do
def log_in(user)
visit '/'
click_on 'Connexion'
submit_login_form(user.email, user.password)
sign_in_with(user.email, user.password)
expect(page).to have_current_path(dossiers_path)
end
def submit_login_form(email, password)
fill_in 'user_email', with: email
fill_in 'user_password', with: password
click_on 'Se connecter'
end
def navigate_to_brouillon(dossier)
expect(page).to have_current_path(dossiers_path)
click_on(dossier.id)
@ -127,7 +117,7 @@ feature 'Invitations' do
def navigate_to_invited_dossier(invite)
visit users_dossiers_invite_path(invite)
expect(page).to have_current_path(new_user_session_path)
submit_login_form(invited_user.email, invited_user.password)
sign_in_with(invited_user.email, invited_user.password)
end
def send_invite_to(invited_email)

View file

@ -0,0 +1,36 @@
require 'spec_helper'
feature 'Signin up:' do
scenario 'a new user can sign-up' do
visit root_path
click_on 'Connexion'
click_on 'Créer un compte'
sign_up_with 'testuser@exemple.fr'
expect(page).to have_content "Nous vous avons envoyé un email contenant un lien d'activation"
click_confirmation_link_for 'testuser@exemple.fr'
expect(page).to have_content 'Votre compte a été activé'
expect(page).to have_current_path dossiers_path
end
context 'when visiting a procedure' do
let(:procedure) { create :simple_procedure }
before do
visit commencer_path(path: procedure.path)
end
scenario 'a new user can sign-up and fill the procedure' do
expect(page).to have_current_path new_user_session_path
click_on 'Créer un compte'
sign_up_with 'testuser@exemple.fr'
expect(page).to have_content "Nous vous avons envoyé un email contenant un lien d'activation"
click_confirmation_link_for 'testuser@exemple.fr'
expect(page).to have_content 'Votre compte a été activé'
expect(page).to have_content procedure.libelle
end
end
end

View file

@ -600,10 +600,6 @@ describe Dossier do
let(:procedure) { create(:procedure) }
let(:user) { create(:user) }
before do
ActionMailer::Base.deliveries.clear
end
it "send an email when the dossier is created for the very first time" do
dossier = nil
ActiveJob::Base.queue_adapter = :test

View file

@ -23,6 +23,7 @@ require File.expand_path('../config/environment', __dir__)
require 'rspec/rails'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require 'capybara/email/rspec'
require 'database_cleaner'
require 'webmock/rspec'
require 'shoulda-matchers'
@ -137,6 +138,8 @@ RSpec.configure do |config|
Typhoeus::Expectation.clear
ActionMailer::Base.deliveries.clear
if Flipflop.remote_storage?
VCR.use_cassette("ovh_storage_init") do
CarrierWave.configure do |config|

View file

@ -1,4 +1,6 @@
module FeatureHelpers
include ActiveJob::TestHelper
def login_admin
user = create :user
login_as user, scope: :user
@ -14,6 +16,28 @@ module FeatureHelpers
dossier = FactoryBot.create(:dossier)
dossier
end
def sign_in_with(email, password)
fill_in :user_email, with: email
fill_in :user_password, with: password
click_on 'Se connecter'
end
def sign_up_with(email, password = 'testpassword')
fill_in :user_email, with: email
fill_in :user_password, with: password
perform_enqueued_jobs do
click_button 'Créer un compte'
end
end
def click_confirmation_link_for(email)
confirmation_email = open_email(email)
token_params = confirmation_email.body.match(/confirmation_token=[^"]+/)
visit "/users/confirmation?#{token_params}"
end
end
RSpec.configure do |config|