From f878bc0a41c5aef3cafcc2533817c9946c1de207 Mon Sep 17 00:00:00 2001 From: Thomas Belliard Date: Thu, 16 Nov 2023 23:26:06 +0200 Subject: [PATCH] fixes abevoelker/devise-passwordless#42 Allow combined use of database authentication and magic link authentication with dynamic activation of each strategy. Disabling magic link for a given user should not invalidate a session opened with another strategy. --- .../hooks/magic_link_authenticatable.rb | 2 +- .../spec/system/combined_user/sign_in_spec.rb | 52 +++++++++++++------ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/lib/devise/hooks/magic_link_authenticatable.rb b/lib/devise/hooks/magic_link_authenticatable.rb index 5791767..269a84e 100644 --- a/lib/devise/hooks/magic_link_authenticatable.rb +++ b/lib/devise/hooks/magic_link_authenticatable.rb @@ -2,7 +2,7 @@ # Deny user access when magic link authentication is disabled Warden::Manager.after_set_user do |record, warden, options| - if record && record.respond_to?(:active_for_magic_link_authentication?) && !record.active_for_magic_link_authentication? + if record && record.respond_to?(:active_for_magic_link_authentication?) && !record.active_for_magic_link_authentication? && warden.winning_strategy.is_a?(Devise::Strategies::MagicLinkAuthenticatable) scope = options[:scope] warden.logout(scope) throw :warden, scope: scope, message: record.magic_link_inactive_message diff --git a/spec/dummy_app_config/shared_source/all/spec/system/combined_user/sign_in_spec.rb b/spec/dummy_app_config/shared_source/all/spec/system/combined_user/sign_in_spec.rb index 343df71..f2700bb 100644 --- a/spec/dummy_app_config/shared_source/all/spec/system/combined_user/sign_in_spec.rb +++ b/spec/dummy_app_config/shared_source/all/spec/system/combined_user/sign_in_spec.rb @@ -14,19 +14,41 @@ it "successfully logs in combined user using password" do visit "/combined_users/sign_in" - + expect(page.status_code).to be(200) expect(page).to have_css("h2", text: "Log in") - + fill_in "Email", with: user.email fill_in "Password", with: password click_button "Log in" - + # It successfully logs in expect(page).to have_css("h2", text: "Sign-in status") expect(page).to have_css("p.combined_user span.email", text: user.email) end + context "with magic-link authentication disabled" do + before do + allow_any_instance_of(CombinedUser).to receive(:active_for_magic_link_authentication?).and_return(false) + end + + it "successfully logs in combined user using password even with magic-link disabled" do + visit "/combined_users/sign_in" + + expect(page.status_code).to be(200) + expect(page).to have_css("h2", text: "Log in") + + fill_in "Email", with: user.email + fill_in "Password", with: password + click_button "Log in" + + # It successfully logs in + expect(page).to have_css("h2", text: "Sign-in status") + expect(page).to have_css("p.combined_user span.email", text: user.email) + end + end + + context "with password authentication disabled" do before do expect_any_instance_of(CombinedUser).to receive(:active_for_authentication?).and_return(false) @@ -47,14 +69,14 @@ it "fails password sign-in with custom error message" do visit sign_in_path - + expect(page.status_code).to be(200) expect(page).to have_css("h2", text: "Log in") - + fill_in "Email", with: user.email fill_in "Password", with: password click_button "Log in" - + # Sign in fails with custom error message expect(page).to have_css("h2", text: "Log in") expect(page).to have_css("p.alert", text: "Password logins have been disabled. Use magic links instead.") @@ -110,10 +132,10 @@ context "default error message" do it "sends magic link, but visiting magic link fails sign-in with default error message" do visit sign_in_path - + expect(page.status_code).to be(200) expect(page).to have_css("h2", text: "Log in") - + fill_in "Email", with: user.email click_button "Log in" @@ -130,7 +152,7 @@ html = Nokogiri::HTML(mail.body.decoded) magic_link = html.css("a")[0].values[0] visit magic_link - + # Sign in fails with custom error message expect(page).to have_css("h2", text: "Log in") expect(page).to have_css("p.alert", text: "Invalid or expired login link.") @@ -159,10 +181,10 @@ it "sends magic link, but visiting magic link fails sign-in with custom error message" do visit sign_in_path - + expect(page.status_code).to be(200) expect(page).to have_css("h2", text: "Log in") - + fill_in "Email", with: user.email click_button "Log in" @@ -179,7 +201,7 @@ html = Nokogiri::HTML(mail.body.decoded) magic_link = html.css("a")[0].values[0] visit magic_link - + # Sign in fails with custom error message expect(page).to have_css("h2", text: "Log in") expect(page).to have_css("p.alert", text: "Passwordless / magic link logins have been disabled. Use your password instead.") @@ -200,10 +222,10 @@ it "sends magic link, but visiting magic link fails sign-in with custom error message" do visit sign_in_path - + expect(page.status_code).to be(200) expect(page).to have_css("h2", text: "Log in") - + fill_in "Email", with: user.email click_button "Log in" @@ -220,7 +242,7 @@ html = Nokogiri::HTML(mail.body.decoded) magic_link = html.css("a")[0].values[0] visit magic_link - + # Sign in fails with custom error message expect(page).to have_css("h2", text: "Log in") expect(page).to have_css("p.alert", text: "Passwordless / magic link logins have been disabled. Use your password instead.")