From 6424ce7ead4cd51ea695d355ab6ea010296dbf82 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 16 Nov 2024 17:05:19 -0800 Subject: [PATCH] Perform a case-insensitive login confirmation by default Add login_confirmation_matches? configuration method to allow for case-sensitive login confirmation. --- CHANGELOG | 4 ++ doc/login_password_requirements_base.rdoc | 1 + lib/rodauth/features/change_login.rb | 2 +- lib/rodauth/features/create_account.rb | 2 +- .../login_password_requirements_base.rb | 13 ++++++ spec/create_account_spec.rb | 43 +++++++++++++++++++ 6 files changed, 63 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f30c25cb..ad744ac3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,9 @@ === master +* Add login_confirmation_matches? configuration method to allow for case-sensitive login confirmation (jeremyevans) (#451) + +* Perform a case-insensitive login confirmation by default (jeremyevans) (#451) + * Do not require CSRF tokens for json requests when using the json feature (janko) (#448, #449) * Make rodauth and r.rodauth call default_rodauth_name for the default configuration to use (jeremyevans) diff --git a/doc/login_password_requirements_base.rdoc b/doc/login_password_requirements_base.rdoc index 7a1e76ca..5cf23e69 100644 --- a/doc/login_password_requirements_base.rdoc +++ b/doc/login_password_requirements_base.rdoc @@ -37,6 +37,7 @@ same_as_existing_password_message :: The error message to display when a new pas == Auth Methods +login_confirmation_matches?(login, login_confirmation) :: Whether the login matches the login confirmation, does a case insensitive check using +casecmp+ by default. login_meets_requirements?(login) :: Whether the given login meets the requirements. By default, just checks that the login is a valid email address. login_valid_email?(login) :: Whether the login is a valid email address. password_hash(password) :: A hash of the given password. diff --git a/lib/rodauth/features/change_login.rb b/lib/rodauth/features/change_login.rb index 19a12f21..c07dafd1 100644 --- a/lib/rodauth/features/change_login.rb +++ b/lib/rodauth/features/change_login.rb @@ -41,7 +41,7 @@ module Rodauth throw_error_status(invalid_field_error_status, login_param, login_does_not_meet_requirements_message) end - if require_login_confirmation? && login != param(login_confirm_param) + if require_login_confirmation? && !login_confirmation_matches?(login, param(login_confirm_param)) throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message) end diff --git a/lib/rodauth/features/create_account.rb b/lib/rodauth/features/create_account.rb index f4e143ed..5236ba4b 100644 --- a/lib/rodauth/features/create_account.rb +++ b/lib/rodauth/features/create_account.rb @@ -45,7 +45,7 @@ module Rodauth new_account(login) catch_error do - if require_login_confirmation? && login != param(login_confirm_param) + if require_login_confirmation? && !login_confirmation_matches?(login, param(login_confirm_param)) throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message) end diff --git a/lib/rodauth/features/login_password_requirements_base.rb b/lib/rodauth/features/login_password_requirements_base.rb index 27fde353..d15053ea 100644 --- a/lib/rodauth/features/login_password_requirements_base.rb +++ b/lib/rodauth/features/login_password_requirements_base.rb @@ -36,6 +36,7 @@ module Rodauth ) auth_methods( + :login_confirmation_matches?, :login_meets_requirements?, :login_valid_email?, :password_hash, @@ -126,6 +127,18 @@ def set_login_requirement_error_message(reason, message) @login_requirement_message = message end + if RUBY_VERSION >= '2.4' + def login_confirmation_matches?(login, login_confirmation) + login.casecmp?(login_confirmation) + end + # :nocov: + else + def login_confirmation_matches?(login, login_confirmation) + login.casecmp(login_confirmation) == 0 + end + # :nocov: + end + def login_meets_length_requirements?(login) if login_minimum_length > login.length set_login_requirement_error_message(:login_too_short, login_too_short_message) diff --git a/spec/create_account_spec.rb b/spec/create_account_spec.rb index 776b4bf2..1d1172bd 100644 --- a/spec/create_account_spec.rb +++ b/spec/create_account_spec.rb @@ -99,6 +99,49 @@ page.html.must_include("Logged In: foo2@example.com") end + it "should do a case insensitive confirmation by default" do + rodauth do + enable :create_account + end + roda do |r| + r.rodauth + next unless rodauth.logged_in? + r.root{view :content=>"Logged In: #{DB[:accounts].where(:id=>rodauth.session_value).get(:email)}"} + end + + visit '/create-account' + fill_in 'Login', :with=>'foo2@example.com' + fill_in 'Confirm Login', :with=>'FOO2@example.com' + fill_in 'Password', :with=>'apple2' + fill_in 'Confirm Password', :with=>'apple2' + click_button 'Create Account' + page.html.must_include("Logged In: foo2@example.com") + end + + it "should support login_confirmation_matches? to allow for case sensitive confirmations" do + rodauth do + enable :create_account + login_confirmation_matches? do |l, lc| + l == lc + end + end + roda do |r| + r.rodauth + next unless rodauth.logged_in? + r.root{view :content=>"Logged In: #{DB[:accounts].where(:id=>rodauth.session_value).get(:email)}"} + end + + visit '/create-account' + fill_in 'Login', :with=>'foo2@example.com' + fill_in 'Confirm Login', :with=>'FOO2@example.com' + fill_in 'Password', :with=>'apple2' + fill_in 'Confirm Password', :with=>'apple2' + click_button 'Create Account' + page.html.must_include("logins do not match") + page.find('#error_flash').text.must_equal "There was an error creating your account" + page.current_path.must_equal '/create-account' + end + it "should not display create account link on login page if route is disabled" do route = 'create-account' rodauth do