rodauth 2.12.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +8 -0
  3. data/doc/base.rdoc +1 -0
  4. data/doc/error_reasons.rdoc +73 -0
  5. data/doc/release_notes/2.13.0.txt +19 -0
  6. data/lib/rodauth/features/active_sessions.rb +1 -1
  7. data/lib/rodauth/features/base.rb +15 -0
  8. data/lib/rodauth/features/change_login.rb +4 -4
  9. data/lib/rodauth/features/change_password.rb +3 -3
  10. data/lib/rodauth/features/close_account.rb +1 -1
  11. data/lib/rodauth/features/confirm_password.rb +2 -2
  12. data/lib/rodauth/features/create_account.rb +4 -4
  13. data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
  14. data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
  15. data/lib/rodauth/features/email_auth.rb +2 -0
  16. data/lib/rodauth/features/jwt_refresh.rb +3 -1
  17. data/lib/rodauth/features/lockout.rb +4 -2
  18. data/lib/rodauth/features/login.rb +3 -3
  19. data/lib/rodauth/features/login_password_requirements_base.rb +15 -6
  20. data/lib/rodauth/features/otp.rb +7 -6
  21. data/lib/rodauth/features/password_complexity.rb +4 -4
  22. data/lib/rodauth/features/recovery_codes.rb +2 -2
  23. data/lib/rodauth/features/remember.rb +1 -1
  24. data/lib/rodauth/features/reset_password.rb +5 -4
  25. data/lib/rodauth/features/session_expiration.rb +1 -0
  26. data/lib/rodauth/features/single_session.rb +1 -0
  27. data/lib/rodauth/features/sms_codes.rb +10 -5
  28. data/lib/rodauth/features/two_factor_base.rb +4 -1
  29. data/lib/rodauth/features/verify_account.rb +5 -1
  30. data/lib/rodauth/features/verify_login_change.rb +3 -2
  31. data/lib/rodauth/features/webauthn.rb +15 -14
  32. data/lib/rodauth/features/webauthn_login.rb +1 -1
  33. data/lib/rodauth/version.rb +1 -1
  34. data/templates/button.str +1 -1
  35. data/templates/change-password.str +2 -2
  36. data/templates/global-logout-field.str +1 -1
  37. data/templates/login-confirm-field.str +2 -2
  38. data/templates/login-display.str +2 -2
  39. data/templates/login-field.str +2 -2
  40. data/templates/otp-auth-code-field.str +2 -2
  41. data/templates/otp-setup.str +2 -2
  42. data/templates/password-confirm-field.str +2 -2
  43. data/templates/password-field.str +2 -2
  44. data/templates/recovery-auth.str +2 -2
  45. data/templates/remember.str +1 -1
  46. data/templates/sms-code-field.str +2 -2
  47. data/templates/sms-setup.str +2 -2
  48. data/templates/webauthn-remove.str +1 -1
  49. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 453992f6df1e1a41e30923334f53146ddd575015f57960dcdadb2b3d4bc496e9
4
- data.tar.gz: 29172b14c9a5c6d88e36c827c4fbc9e4f61fbadadf6b656734ef7058e9dd4a13
3
+ metadata.gz: f01d42c90dd22a88566f17b3e77b9495dc1431f004f2f54865cff45a3874ce43
4
+ data.tar.gz: b09c0a44b2b4f6ab1eb795b11a69ec7acd1d4ed5ac4abbe45d8bb4072cb61e0f
5
5
  SHA512:
6
- metadata.gz: 956d8809e6ba87044e5aeba7712cc4e907604a632d7113084cda074bf675952fb4e3081cca5adf19a191df6d073e2b9068a313d8d26e81534b70f9eaba20688e
7
- data.tar.gz: aaa0cde299ba115ea281bc18dfe5f02a0d2b35dd95231d9e69662ec340194569a288be916abb2fe0e258c50599c6ea6ef42791824f986d6dc2e295f5db67645a
6
+ metadata.gz: 2934f2824b7c805f6400fab52aad9c4aaca2f3bbfb4584688619b0b24b9e052a3cecc4b36b6eb7379e13f2a9bf2bc64e0efac077d932e390270401966223e2ae
7
+ data.tar.gz: c1dcf6d140117743baa62ba0715c99584bb80b8aa933f596424f242c2ffb6a31c7d25f0fdba65fed4b1bd93d63692502c7c63b36a1f2b793083b1972c5313304
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 2.13.0 (2021-05-22)
2
+
3
+ * Make jwt_refresh expired access token support work when using rodauth.check_active_sessions before calling r.rodauth (renchap) (#165)
4
+
5
+ * Update default templates to add classes for Bootstrap 5 compatibility (janko) (#164)
6
+
7
+ * Add set_error_reason configuration method to allow applications more finer grained error handling (renchap, jeremyevans) (#162)
8
+
1
9
  === 2.12.0 (2021-04-22)
2
10
 
3
11
  * Add configuration methods to active_sessions plugin to control the inserting and updating of rows (janko) (#159)
data/doc/base.rdoc CHANGED
@@ -105,6 +105,7 @@ random_key :: A randomly generated string, used for creating tokens.
105
105
  redirect(path) :: Redirect the request to the given path.
106
106
  session_value :: The value for session_key in the current session.
107
107
  set_error_flash(message) :: Set the current error flash to the given message.
108
+ set_error_reason(reason) :: You can override this method to customize handling of specific error types (does nothing by default). Each separate error type has a separate reason symbol, you can see the {list of error reason symbols}[rdoc-ref:doc/error_reasons.rdoc].
108
109
  set_notice_flash(message) :: Set the next notice flash to the given message.
109
110
  set_notice_now_flash(message) :: Set the current notice flash to the given message.
110
111
  set_redirect_error_flash(message) :: Set the next error flash to the given message.
@@ -0,0 +1,73 @@
1
+ = Error Reasons
2
+
3
+ Rodauth allows for customizing response status codes and error
4
+ messages for each type of error. However, in some cases, the
5
+ response status code is too coarse for desired error handling
6
+ by the application (since many error types use the same status
7
+ code), and using the error message is too fragile since it may
8
+ be translated.
9
+
10
+ For this reason, Rodauth associates a fine grained reason for
11
+ each type of error. If an error occurs in Rodauth, it will
12
+ call the +set_error_reason+ method with a symbol for the
13
+ specific type of error. By default, this method does not do
14
+ anything, but you can use the +set_error_reason+ configuration
15
+ method to customize the error handling.
16
+
17
+ These are the currently supported error type symbols that
18
+ Rodauth will call +set_error_reason+ with:
19
+
20
+ * :account_locked_out
21
+ * :already_an_account_with_this_login
22
+ * :already_an_unverified_account_with_this_login
23
+ * :duplicate_webauthn_id
24
+ * :inactive_session
25
+ * :invalid_email_auth_key
26
+ * :invalid_otp_auth_code
27
+ * :invalid_otp_secret
28
+ * :invalid_password
29
+ * :invalid_password_pattern
30
+ * :invalid_phone_number
31
+ * :invalid_previous_password
32
+ * :invalid_recovery_code
33
+ * :invalid_remember_param
34
+ * :invalid_reset_password_key
35
+ * :invalid_sms_code
36
+ * :invalid_sms_confirmation_code
37
+ * :invalid_unlock_account_key
38
+ * :invalid_verify_account_key
39
+ * :invalid_verify_login_change_key
40
+ * :invalid_webauthn_auth_param
41
+ * :invalid_webauthn_remove_param
42
+ * :invalid_webauthn_setup_param
43
+ * :invalid_webauthn_sign_count
44
+ * :login_not_valid_email
45
+ * :login_required
46
+ * :login_too_long
47
+ * :login_too_short
48
+ * :logins_do_not_match
49
+ * :no_current_sms_code
50
+ * :no_matching_login
51
+ * :not_enough_character_groups_in_password
52
+ * :otp_locked_out
53
+ * :password_authentication_required
54
+ * :password_contains_null_byte
55
+ * :password_does_not_meet_requirements
56
+ * :password_in_dictionary
57
+ * :password_is_one_of_the_most_common
58
+ * :password_same_as_previous_password
59
+ * :password_too_short
60
+ * :passwords_do_not_match
61
+ * :same_as_current_login
62
+ * :same_as_existing_password
63
+ * :session_expired
64
+ * :sms_already_setup
65
+ * :sms_locked_out
66
+ * :sms_needs_confirmation
67
+ * :sms_not_setup
68
+ * :too_many_repeating_characters_in_password
69
+ * :two_factor_already_authenticated
70
+ * :two_factor_need_authentication
71
+ * :two_factor_not_setup
72
+ * :unverified_account
73
+ * :webauthn_not_setup
@@ -0,0 +1,19 @@
1
+ = New Features
2
+
3
+ * A set_error_reason configuration method has been added. This method
4
+ is called whenever a error occurs in Rodauth, with a symbol
5
+ describing the error. The default implementation of this method does
6
+ nothing, it has been added to make it easier for Rodauth users to
7
+ implement custom handling for specific error types. See the Rodauth
8
+ documentation for this method to see the list of symbols this method
9
+ can be called with.
10
+
11
+ = Other Improvements
12
+
13
+ * When using active_sessions and jwt_refresh together, and allowing for
14
+ expired JWTs when refreshing, you can now call
15
+ rodauth.check_active_session before r.rodauth. Previously, this
16
+ did not work, and you had to call rodauth.check_active_session
17
+ after r.rodauth.
18
+
19
+ * The default templates now also support Bootstrap 5.
@@ -57,6 +57,7 @@ module Rodauth
57
57
  def no_longer_active_session
58
58
  clear_session
59
59
  set_redirect_error_status inactive_session_error_status
60
+ set_error_reason :inactive_session
60
61
  set_redirect_error_flash active_sessions_error_flash
61
62
  redirect active_sessions_redirect
62
63
  end
@@ -176,4 +177,3 @@ module Rodauth
176
177
  end
177
178
  end
178
179
  end
179
-
@@ -100,6 +100,7 @@ module Rodauth
100
100
  :set_notice_flash,
101
101
  :set_notice_now_flash,
102
102
  :set_redirect_error_flash,
103
+ :set_error_reason,
103
104
  :set_title,
104
105
  :translate,
105
106
  :update_session
@@ -294,6 +295,7 @@ module Rodauth
294
295
 
295
296
  def login_required
296
297
  set_redirect_error_status(login_required_error_status)
298
+ set_error_reason :login_required
297
299
  set_redirect_error_flash require_login_error_flash
298
300
  redirect require_login_redirect
299
301
  end
@@ -539,6 +541,11 @@ module Rodauth
539
541
  def set_response_error_status(status)
540
542
  response.status = status
541
543
  end
544
+
545
+ def set_response_error_reason_status(reason, status)
546
+ set_error_reason(reason)
547
+ set_response_error_status(status)
548
+ end
542
549
 
543
550
  def throw_error(field, error)
544
551
  set_field_error(field, error)
@@ -550,6 +557,14 @@ module Rodauth
550
557
  throw_error(field, error)
551
558
  end
552
559
 
560
+ def set_error_reason(reason)
561
+ end
562
+
563
+ def throw_error_reason(reason, status, field, message)
564
+ set_error_reason(reason)
565
+ throw_error_status(status, field, message)
566
+ end
567
+
553
568
  def use_date_arithmetic?
554
569
  set_deadline_values?
555
570
  end
@@ -30,7 +30,7 @@ module Rodauth
30
30
  r.post do
31
31
  catch_error do
32
32
  if change_login_requires_password? && !password_match?(param(password_param))
33
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
33
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
34
34
  end
35
35
 
36
36
  login = param(login_param)
@@ -39,7 +39,7 @@ module Rodauth
39
39
  end
40
40
 
41
41
  if require_login_confirmation? && login != param(login_confirm_param)
42
- throw_error_status(unmatched_field_error_status, login_param, logins_do_not_match_message)
42
+ throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message)
43
43
  end
44
44
 
45
45
  transaction do
@@ -65,7 +65,7 @@ module Rodauth
65
65
 
66
66
  def change_login(login)
67
67
  if account_ds.get(login_column).downcase == login.downcase
68
- @login_requirement_message = same_as_current_login_message
68
+ set_login_requirement_error_message(:same_as_current_login, same_as_current_login_message)
69
69
  return false
70
70
  end
71
71
 
@@ -82,7 +82,7 @@ module Rodauth
82
82
  updated = nil
83
83
  raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
84
84
  if raised
85
- @login_requirement_message = already_an_account_with_this_login_message
85
+ set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
86
86
  end
87
87
  updated && !raised
88
88
  end
@@ -33,16 +33,16 @@ module Rodauth
33
33
  r.post do
34
34
  catch_error do
35
35
  if change_password_requires_password? && !password_match?(param(password_param))
36
- throw_error_status(invalid_password_error_status, password_param, invalid_previous_password_message)
36
+ throw_error_reason(:invalid_previous_password, invalid_password_error_status, password_param, invalid_previous_password_message)
37
37
  end
38
38
 
39
39
  password = param(new_password_param)
40
40
  if require_password_confirmation? && password != param(password_confirm_param)
41
- throw_error_status(unmatched_field_error_status, new_password_param, passwords_do_not_match_message)
41
+ throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, new_password_param, passwords_do_not_match_message)
42
42
  end
43
43
 
44
44
  if password_match?(password)
45
- throw_error_status(invalid_field_error_status, new_password_param, same_as_existing_password_message)
45
+ throw_error_reason(:same_as_existing_password, invalid_field_error_status, new_password_param, same_as_existing_password_message)
46
46
  end
47
47
 
48
48
  unless password_meets_requirements?(password)
@@ -35,7 +35,7 @@ module Rodauth
35
35
  r.post do
36
36
  catch_error do
37
37
  if close_account_requires_password? && !password_match?(param(password_param))
38
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
38
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
39
39
  end
40
40
 
41
41
  transaction do
@@ -40,7 +40,7 @@ module Rodauth
40
40
  set_notice_flash confirm_password_notice_flash
41
41
  redirect confirm_password_redirect
42
42
  else
43
- set_response_error_status(invalid_password_error_status)
43
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
44
44
  set_field_error(password_param, invalid_password_message)
45
45
  set_error_flash confirm_password_error_flash
46
46
  confirm_password_view
@@ -53,6 +53,7 @@ module Rodauth
53
53
 
54
54
  if require_password_authentication? && has_password?
55
55
  set_redirect_error_status(password_authentication_required_error_status)
56
+ set_error_reason :password_authentication_required
56
57
  set_redirect_error_flash password_authentication_required_error_flash
57
58
  set_session_value(confirm_password_redirect_session_key, request.fullpath)
58
59
  redirect password_authentication_required_redirect
@@ -89,4 +90,3 @@ module Rodauth
89
90
  end
90
91
  end
91
92
  end
92
-
@@ -43,7 +43,7 @@ module Rodauth
43
43
 
44
44
  catch_error do
45
45
  if require_login_confirmation? && login != param(login_confirm_param)
46
- throw_error_status(unmatched_field_error_status, login_param, logins_do_not_match_message)
46
+ throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message)
47
47
  end
48
48
 
49
49
  unless login_meets_requirements?(login)
@@ -52,11 +52,11 @@ module Rodauth
52
52
 
53
53
  if create_account_set_password?
54
54
  if require_password_confirmation? && password != param(password_confirm_param)
55
- throw_error_status(unmatched_field_error_status, password_param, passwords_do_not_match_message)
55
+ throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
56
56
  end
57
57
 
58
58
  unless password_meets_requirements?(password)
59
- throw_error_status(invalid_field_error_status, password_param, password_does_not_meet_requirements_message)
59
+ throw_error_reason(:password_does_not_meet_requirements, invalid_field_error_status, password_param, password_does_not_meet_requirements_message)
60
60
  end
61
61
 
62
62
  if account_password_hash_column
@@ -100,7 +100,7 @@ module Rodauth
100
100
  raised = raises_uniqueness_violation?{id = db[accounts_table].insert(account)}
101
101
 
102
102
  if raised
103
- @login_requirement_message = already_an_account_with_this_login_message
103
+ set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
104
104
  end
105
105
 
106
106
  if id
@@ -32,7 +32,7 @@ module Rodauth
32
32
 
33
33
  def password_not_one_of_the_most_common?(password)
34
34
  return true unless password_one_of_most_common?(password)
35
- @password_requirement_message = password_is_one_of_the_most_common_message
35
+ set_password_requirement_error_message(:password_is_one_of_the_most_common, password_is_one_of_the_most_common_message)
36
36
  false
37
37
  end
38
38
  end
@@ -65,7 +65,7 @@ module Rodauth
65
65
  end
66
66
 
67
67
  return true unless match
68
- @password_requirement_message = password_same_as_previous_password_message
68
+ set_password_requirement_error_message(:password_same_as_previous_password, password_same_as_previous_password_message)
69
69
  false
70
70
  end
71
71
 
@@ -58,6 +58,7 @@ module Rodauth
58
58
  _email_auth_request
59
59
  else
60
60
  set_redirect_error_status(no_matching_login_error_status)
61
+ set_error_reason :no_matching_login
61
62
  set_redirect_error_flash email_auth_request_error_flash
62
63
  end
63
64
 
@@ -90,6 +91,7 @@ module Rodauth
90
91
  key = session[email_auth_session_key] || param(email_auth_key_param)
91
92
  unless account_from_email_auth_key(key)
92
93
  set_redirect_error_status(invalid_key_error_status)
94
+ set_error_reason :invalid_email_auth_key
93
95
  set_redirect_error_flash email_auth_error_flash
94
96
  redirect email_auth_email_sent_redirect
95
97
  end
@@ -32,6 +32,8 @@ module Rodauth
32
32
  )
33
33
 
34
34
  route do |r|
35
+ # For backward compatibility, unused in core Rodauth
36
+ # RODAUTH3: Remove
35
37
  @jwt_refresh_route = true
36
38
  before_jwt_refresh_route
37
39
 
@@ -135,7 +137,7 @@ module Rodauth
135
137
  end
136
138
 
137
139
  def _jwt_decode_opts
138
- if allow_refresh_with_expired_jwt_access_token? && @jwt_refresh_route
140
+ if allow_refresh_with_expired_jwt_access_token? && request.path == jwt_refresh_path
139
141
  Hash[super].merge!(:verify_expiration=>false)
140
142
  else
141
143
  super
@@ -84,6 +84,7 @@ module Rodauth
84
84
  set_notice_flash unlock_account_request_notice_flash
85
85
  else
86
86
  set_redirect_error_status(no_matching_login_error_status)
87
+ set_error_reason :no_matching_login
87
88
  set_redirect_error_flash no_matching_login_message.to_s.capitalize
88
89
  end
89
90
 
@@ -116,6 +117,7 @@ module Rodauth
116
117
  key = session[unlock_account_session_key] || param(unlock_account_key_param)
117
118
  unless account_from_unlock_key(key)
118
119
  set_redirect_error_status invalid_key_error_status
120
+ set_error_reason :invalid_unlock_account_key
119
121
  set_redirect_error_flash no_matching_unlock_account_key_error_flash
120
122
  redirect unlock_account_request_redirect
121
123
  end
@@ -134,7 +136,7 @@ module Rodauth
134
136
  set_notice_flash unlock_account_notice_flash
135
137
  redirect unlock_account_redirect
136
138
  else
137
- set_response_error_status(invalid_password_error_status)
139
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
138
140
  set_field_error(password_param, invalid_password_message)
139
141
  set_error_flash unlock_account_error_flash
140
142
  unlock_account_view
@@ -271,7 +273,7 @@ module Rodauth
271
273
  end
272
274
 
273
275
  def show_lockout_page
274
- set_response_error_status lockout_error_status
276
+ set_response_error_reason_status(:account_locked_out, lockout_error_status)
275
277
  set_error_flash login_lockout_error_flash
276
278
  response.write unlock_account_request_view
277
279
  request.halt
@@ -39,13 +39,13 @@ module Rodauth
39
39
 
40
40
  catch_error do
41
41
  unless account_from_login(param(login_param))
42
- throw_error_status(no_matching_login_error_status, login_param, no_matching_login_message)
42
+ throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
43
43
  end
44
44
 
45
45
  before_login_attempt
46
46
 
47
47
  unless open_account?
48
- throw_error_status(unopen_account_error_status, login_param, unverified_account_message)
48
+ throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
49
49
  end
50
50
 
51
51
  if use_multi_phase_login?
@@ -61,7 +61,7 @@ module Rodauth
61
61
 
62
62
  unless password_match?(param(password_param))
63
63
  after_login_failure
64
- throw_error_status(login_error_status, password_param, invalid_password_message)
64
+ throw_error_reason(:invalid_password, login_error_status, password_param, invalid_password_message)
65
65
  end
66
66
 
67
67
  login('password')
@@ -81,6 +81,11 @@ module Rodauth
81
81
  def password_too_short_message
82
82
  "minimum #{password_minimum_length} characters"
83
83
  end
84
+
85
+ def set_password_requirement_error_message(reason, message)
86
+ set_error_reason(reason)
87
+ @password_requirement_message = message
88
+ end
84
89
 
85
90
  def login_does_not_meet_requirements_message
86
91
  "invalid login#{", #{login_requirement_message}" if login_requirement_message}"
@@ -93,13 +98,18 @@ module Rodauth
93
98
  def login_too_short_message
94
99
  "minimum #{login_minimum_length} characters"
95
100
  end
101
+
102
+ def set_login_requirement_error_message(reason, message)
103
+ set_error_reason(reason)
104
+ @login_requirement_message = message
105
+ end
96
106
 
97
107
  def login_meets_length_requirements?(login)
98
108
  if login_minimum_length > login.length
99
- @login_requirement_message = login_too_short_message
109
+ set_login_requirement_error_message(:login_too_short, login_too_short_message)
100
110
  false
101
111
  elsif login_maximum_length < login.length
102
- @login_requirement_message = login_too_long_message
112
+ set_login_requirement_error_message(:login_too_long, login_too_long_message)
103
113
  false
104
114
  else
105
115
  true
@@ -109,7 +119,7 @@ module Rodauth
109
119
  def login_meets_email_requirements?(login)
110
120
  return true unless require_email_address_logins?
111
121
  return true if login_valid_email?(login)
112
- @login_requirement_message = login_not_valid_email_message
122
+ set_login_requirement_error_message(:login_not_valid_email, login_not_valid_email_message)
113
123
  return false
114
124
  end
115
125
 
@@ -119,13 +129,13 @@ module Rodauth
119
129
 
120
130
  def password_meets_length_requirements?(password)
121
131
  return true if password_minimum_length <= password.length
122
- @password_requirement_message = password_too_short_message
132
+ set_password_requirement_error_message(:password_too_short, password_too_short_message)
123
133
  false
124
134
  end
125
135
 
126
136
  def password_does_not_contain_null_byte?(password)
127
137
  return true unless password.include?("\0")
128
- @password_requirement_message = contains_null_byte_message
138
+ set_password_requirement_error_message(:password_contains_null_byte, contains_null_byte_message)
129
139
  false
130
140
  end
131
141
 
@@ -150,4 +160,3 @@ module Rodauth
150
160
  end
151
161
  end
152
162
  end
153
-
@@ -103,7 +103,7 @@ module Rodauth
103
103
  require_otp_setup
104
104
 
105
105
  if otp_locked_out?
106
- set_response_error_status(lockout_error_status)
106
+ set_response_error_reason_status(:otp_locked_out, lockout_error_status)
107
107
  set_redirect_error_flash otp_lockout_error_flash
108
108
  redirect otp_lockout_redirect
109
109
  end
@@ -122,7 +122,7 @@ module Rodauth
122
122
 
123
123
  otp_record_authentication_failure
124
124
  after_otp_authentication_failure
125
- set_response_error_status(invalid_key_error_status)
125
+ set_response_error_reason_status(:invalid_otp_auth_code, invalid_key_error_status)
126
126
  set_field_error(otp_auth_param, otp_invalid_auth_code_message)
127
127
  set_error_flash otp_auth_error_flash
128
128
  otp_auth_view
@@ -149,7 +149,7 @@ module Rodauth
149
149
  catch_error do
150
150
  unless otp_valid_key?(secret)
151
151
  otp_tmp_key(otp_new_secret)
152
- throw_error_status(invalid_field_error_status, otp_setup_param, otp_invalid_secret_message)
152
+ throw_error_reason(:invalid_otp_secret, invalid_field_error_status, otp_setup_param, otp_invalid_secret_message)
153
153
  end
154
154
 
155
155
  if otp_keys_use_hmac?
@@ -159,11 +159,11 @@ module Rodauth
159
159
  end
160
160
 
161
161
  unless two_factor_password_match?(param(password_param))
162
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
162
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
163
163
  end
164
164
 
165
165
  unless otp_valid_code?(param(otp_auth_param))
166
- throw_error_status(invalid_key_error_status, otp_auth_param, otp_invalid_auth_code_message)
166
+ throw_error_reason(:invalid_otp_auth_code, invalid_key_error_status, otp_auth_param, otp_invalid_auth_code_message)
167
167
  end
168
168
 
169
169
  transaction do
@@ -206,7 +206,7 @@ module Rodauth
206
206
  redirect otp_disable_redirect
207
207
  end
208
208
 
209
- set_response_error_status(invalid_password_error_status)
209
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
210
210
  set_field_error(password_param, invalid_password_message)
211
211
  set_error_flash otp_disable_error_flash
212
212
  otp_disable_view
@@ -226,6 +226,7 @@ module Rodauth
226
226
  def require_otp_setup
227
227
  unless otp_exists?
228
228
  set_redirect_error_status(two_factor_not_setup_error_status)
229
+ set_error_reason :two_factor_not_setup
229
230
  set_redirect_error_flash two_factor_not_setup_error_flash
230
231
  redirect two_factor_need_setup_redirect
231
232
  end
@@ -54,21 +54,21 @@ module Rodauth
54
54
  def password_has_enough_character_groups?(password)
55
55
  return true if password.length > password_max_length_for_groups_check
56
56
  return true if password_character_groups.select{|re| password =~ re}.length >= password_min_groups
57
- @password_requirement_message = password_not_enough_character_groups_message
57
+ set_password_requirement_error_message(:not_enough_character_groups_in_password, password_not_enough_character_groups_message)
58
58
  false
59
59
  end
60
60
 
61
61
  def password_has_no_invalid_pattern?(password)
62
62
  return true unless password_invalid_pattern
63
63
  return true if password !~ password_invalid_pattern
64
- @password_requirement_message = password_invalid_pattern_message
64
+ set_password_requirement_error_message(:invalid_password_pattern, password_invalid_pattern_message)
65
65
  false
66
66
  end
67
67
 
68
68
  def password_not_too_many_repeating_characters?(password)
69
69
  return true if password_max_repeating_characters < 2
70
70
  return true if password !~ /(.)(\1){#{password_max_repeating_characters-1}}/
71
- @password_requirement_message = password_too_many_repeating_characters_message
71
+ set_password_requirement_error_message(:too_many_repeating_characters_in_password, password_too_many_repeating_characters_message)
72
72
  false
73
73
  end
74
74
 
@@ -77,7 +77,7 @@ module Rodauth
77
77
  return true unless password =~ /\A(?:\d*)([A-Za-z!@$+|][A-Za-z!@$+|0134578]+[A-Za-z!@$+|])(?:\d*)\z/
78
78
  word = $1.downcase.tr('!@$+|0134578', 'iastloleastb')
79
79
  return true if !dict.include?(word)
80
- @password_requirement_message = password_in_dictionary_message
80
+ set_password_requirement_error_message(:password_in_dictionary, password_in_dictionary_message)
81
81
  false
82
82
  end
83
83
  end
@@ -76,7 +76,7 @@ module Rodauth
76
76
  two_factor_authenticate('recovery_code')
77
77
  end
78
78
 
79
- set_response_error_status(invalid_key_error_status)
79
+ set_response_error_reason_status(:invalid_recovery_code, invalid_key_error_status)
80
80
  set_field_error(recovery_codes_param, invalid_recovery_code_message)
81
81
  set_error_flash invalid_recovery_code_error_flash
82
82
  recovery_auth_view
@@ -119,7 +119,7 @@ module Rodauth
119
119
  set_error_flash view_recovery_codes_error_flash
120
120
  end
121
121
 
122
- set_response_error_status(invalid_password_error_status)
122
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
123
123
  set_field_error(password_param, invalid_password_message)
124
124
  recovery_codes_view
125
125
  end
@@ -74,7 +74,7 @@ module Rodauth
74
74
  set_notice_flash remember_notice_flash
75
75
  redirect remember_redirect
76
76
  else
77
- set_response_error_status(invalid_field_error_status)
77
+ set_response_error_reason_status(:invalid_remember_param, invalid_field_error_status)
78
78
  set_error_flash remember_error_flash
79
79
  remember_view
80
80
  end
@@ -68,11 +68,11 @@ module Rodauth
68
68
  r.post do
69
69
  catch_error do
70
70
  unless account_from_login(param(login_param))
71
- throw_error_status(no_matching_login_error_status, login_param, no_matching_login_message)
71
+ throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
72
72
  end
73
73
 
74
74
  unless open_account?
75
- throw_error_status(unopen_account_error_status, login_param, unverified_account_message)
75
+ throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
76
76
  end
77
77
 
78
78
  if reset_password_email_recently_sent?
@@ -123,6 +123,7 @@ module Rodauth
123
123
  key = session[reset_password_session_key] || param(reset_password_key_param)
124
124
  unless account_from_reset_password_key(key)
125
125
  set_redirect_error_status(invalid_key_error_status)
126
+ set_error_reason :invalid_reset_password_key
126
127
  set_redirect_error_flash reset_password_error_flash
127
128
  redirect reset_password_email_sent_redirect
128
129
  end
@@ -130,11 +131,11 @@ module Rodauth
130
131
  password = param(password_param)
131
132
  catch_error do
132
133
  if password_match?(password)
133
- throw_error_status(invalid_field_error_status, password_param, same_as_existing_password_message)
134
+ throw_error_reason(:same_as_existing_password, invalid_field_error_status, password_param, same_as_existing_password_message)
134
135
  end
135
136
 
136
137
  if require_password_confirmation? && password != param(password_confirm_param)
137
- throw_error_status(unmatched_field_error_status, password_param, passwords_do_not_match_message)
138
+ throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
138
139
  end
139
140
 
140
141
  unless password_meets_requirements?(password)
@@ -38,6 +38,7 @@ module Rodauth
38
38
  def expire_session
39
39
  clear_session
40
40
  set_redirect_error_status session_expiration_error_status
41
+ set_error_reason :session_expired
41
42
  set_redirect_error_flash session_expiration_error_flash
42
43
  redirect session_expiration_redirect
43
44
  end
@@ -57,6 +57,7 @@ module Rodauth
57
57
  def no_longer_active_session
58
58
  clear_session
59
59
  set_redirect_error_status inactive_session_error_status
60
+ set_error_reason :inactive_session
60
61
  set_redirect_error_flash single_session_error_flash
61
62
  redirect single_session_redirect
62
63
  end
@@ -146,7 +146,7 @@ module Rodauth
146
146
  sms_set_code(nil)
147
147
  end
148
148
 
149
- set_response_error_status(invalid_key_error_status)
149
+ set_response_error_reason_status(:no_current_sms_code, invalid_key_error_status)
150
150
  set_redirect_error_flash no_current_sms_code_error_flash
151
151
  redirect sms_request_redirect
152
152
  end
@@ -169,7 +169,7 @@ module Rodauth
169
169
  end
170
170
  end
171
171
 
172
- set_response_error_status(invalid_key_error_status)
172
+ set_response_error_reason_status(:invalid_sms_code, invalid_key_error_status)
173
173
  set_field_error(sms_code_param, sms_invalid_code_message)
174
174
  set_error_flash sms_invalid_code_error_flash
175
175
  sms_auth_view
@@ -186,6 +186,7 @@ module Rodauth
186
186
 
187
187
  if sms_needs_confirmation?
188
188
  set_redirect_error_status(sms_needs_confirmation_error_status)
189
+ set_error_reason :sms_needs_confirmation
189
190
  set_redirect_error_flash sms_needs_confirmation_error_flash
190
191
  redirect sms_needs_confirmation_redirect
191
192
  end
@@ -199,13 +200,13 @@ module Rodauth
199
200
  r.post do
200
201
  catch_error do
201
202
  unless two_factor_password_match?(param(password_param))
202
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
203
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
203
204
  end
204
205
 
205
206
  phone = sms_normalize_phone(param(sms_phone_param))
206
207
 
207
208
  unless sms_valid_phone?(phone)
208
- throw_error_status(invalid_field_error_status, sms_phone_param, sms_invalid_phone_message)
209
+ throw_error_reason(:invalid_phone_number, invalid_field_error_status, sms_phone_param, sms_invalid_phone_message)
209
210
  end
210
211
 
211
212
  transaction do
@@ -254,6 +255,7 @@ module Rodauth
254
255
 
255
256
  sms_confirm_failure
256
257
  set_redirect_error_status(invalid_key_error_status)
258
+ set_error_reason :invalid_sms_confirmation_code
257
259
  set_redirect_error_flash sms_invalid_confirmation_code_error_flash
258
260
  redirect sms_needs_setup_redirect
259
261
  end
@@ -282,7 +284,7 @@ module Rodauth
282
284
  redirect sms_disable_redirect
283
285
  end
284
286
 
285
- set_response_error_status(invalid_password_error_status)
287
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
286
288
  set_field_error(password_param, invalid_password_message)
287
289
  set_error_flash sms_disable_error_flash
288
290
  sms_disable_view
@@ -302,6 +304,7 @@ module Rodauth
302
304
  def require_sms_setup
303
305
  unless sms_setup?
304
306
  set_redirect_error_status(two_factor_not_setup_error_status)
307
+ set_error_reason :sms_not_setup
305
308
  set_redirect_error_flash sms_not_setup_error_flash
306
309
  redirect sms_needs_setup_redirect
307
310
  end
@@ -310,6 +313,7 @@ module Rodauth
310
313
  def require_sms_not_setup
311
314
  if sms_setup?
312
315
  set_redirect_error_status(sms_already_setup_error_status)
316
+ set_error_reason :sms_already_setup
313
317
  set_redirect_error_flash sms_already_setup_error_flash
314
318
  redirect sms_already_setup_redirect
315
319
  end
@@ -320,6 +324,7 @@ module Rodauth
320
324
 
321
325
  if sms_locked_out?
322
326
  set_redirect_error_status(lockout_error_status)
327
+ set_error_reason :sms_locked_out
323
328
  set_redirect_error_flash sms_lockout_error_flash
324
329
  redirect sms_lockout_redirect
325
330
  end
@@ -106,7 +106,7 @@ module Rodauth
106
106
  redirect two_factor_disable_redirect
107
107
  end
108
108
 
109
- set_response_error_status(invalid_password_error_status)
109
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
110
110
  set_field_error(password_param, invalid_password_message)
111
111
  set_error_flash two_factor_disable_error_flash
112
112
  two_factor_disable_view
@@ -144,6 +144,7 @@ module Rodauth
144
144
  return if uses_two_factor_authentication?
145
145
 
146
146
  set_redirect_error_status(two_factor_not_setup_error_status)
147
+ set_error_reason :two_factor_not_setup
147
148
  set_redirect_error_flash two_factor_not_setup_error_flash
148
149
  redirect two_factor_need_setup_redirect
149
150
  end
@@ -151,6 +152,7 @@ module Rodauth
151
152
  def require_two_factor_not_authenticated(auth_type = nil)
152
153
  if two_factor_authenticated? || (auth_type && two_factor_login_type_match?(auth_type))
153
154
  set_redirect_error_status(two_factor_already_authenticated_error_status)
155
+ set_error_reason :two_factor_already_authenticated
154
156
  set_redirect_error_flash two_factor_already_authenticated_error_flash
155
157
  redirect two_factor_already_authenticated_redirect
156
158
  end
@@ -162,6 +164,7 @@ module Rodauth
162
164
  set_session_value(two_factor_auth_redirect_session_key, request.fullpath)
163
165
  end
164
166
  set_redirect_error_status(two_factor_need_authentication_error_status)
167
+ set_error_reason :two_factor_need_authentication
165
168
  set_redirect_error_flash two_factor_need_authentication_error_flash
166
169
  redirect two_factor_auth_required_redirect
167
170
  end
@@ -87,6 +87,7 @@ module Rodauth
87
87
  set_notice_flash verify_account_email_sent_notice_flash
88
88
  else
89
89
  set_redirect_error_status(no_matching_login_error_status)
90
+ set_error_reason :no_matching_login
90
91
  set_redirect_error_flash verify_account_resend_error_flash
91
92
  end
92
93
 
@@ -120,6 +121,7 @@ module Rodauth
120
121
  key = session[verify_account_session_key] || param(verify_account_key_param)
121
122
  unless account_from_verify_account_key(key)
122
123
  set_redirect_error_status(invalid_key_error_status)
124
+ set_error_reason :invalid_verify_account_key
123
125
  set_redirect_error_flash verify_account_error_flash
124
126
  redirect verify_account_redirect
125
127
  end
@@ -129,7 +131,7 @@ module Rodauth
129
131
  password = param(password_param)
130
132
 
131
133
  if require_password_confirmation? && password != param(password_confirm_param)
132
- throw_error_status(unmatched_field_error_status, password_param, passwords_do_not_match_message)
134
+ throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
133
135
  end
134
136
 
135
137
  unless password_meets_requirements?(password)
@@ -192,6 +194,7 @@ module Rodauth
192
194
  def new_account(login)
193
195
  if account_from_login(login) && allow_resending_verify_account_email?
194
196
  set_redirect_error_status(unopen_account_error_status)
197
+ set_error_reason :already_an_unverified_account_with_this_login
195
198
  set_error_flash attempt_to_create_unverified_account_error_flash
196
199
  response.write resend_verify_account_view
197
200
  request.halt
@@ -269,6 +272,7 @@ module Rodauth
269
272
  def before_login_attempt
270
273
  unless open_account?
271
274
  set_redirect_error_status(unopen_account_error_status)
275
+ set_error_reason :unverified_account
272
276
  set_error_flash attempt_to_login_to_unverified_account_error_flash
273
277
  response.write resend_verify_account_view
274
278
  request.halt
@@ -74,6 +74,7 @@ module Rodauth
74
74
  key = session[verify_login_change_session_key] || param(verify_login_change_key_param)
75
75
  unless account_from_verify_login_change_key(key)
76
76
  set_redirect_error_status(invalid_key_error_status)
77
+ set_error_reason :invalid_verify_login_change_key
77
78
  set_redirect_error_flash verify_login_change_error_flash
78
79
  redirect verify_login_change_redirect
79
80
  end
@@ -82,6 +83,7 @@ module Rodauth
82
83
  before_verify_login_change
83
84
  unless verify_login_change
84
85
  set_redirect_error_status(invalid_key_error_status)
86
+ set_error_reason :already_an_account_with_this_login
85
87
  set_redirect_error_flash verify_login_change_duplicate_account_error_flash
86
88
  redirect verify_login_change_duplicate_account_redirect
87
89
  end
@@ -151,7 +153,7 @@ module Rodauth
151
153
 
152
154
  def update_login(login)
153
155
  if _account_from_login(login)
154
- @login_requirement_message = already_an_account_with_this_login_message
156
+ set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
155
157
  return false
156
158
  end
157
159
 
@@ -213,4 +215,3 @@ module Rodauth
213
215
  end
214
216
  end
215
217
  end
216
-
@@ -182,7 +182,7 @@ module Rodauth
182
182
  end
183
183
 
184
184
  if throw_error
185
- throw_error_status(invalid_field_error_status, webauthn_setup_param, webauthn_duplicate_webauthn_id_message)
185
+ throw_error_reason(:duplicate_webauthn_id, invalid_field_error_status, webauthn_setup_param, webauthn_duplicate_webauthn_id_message)
186
186
  end
187
187
 
188
188
  set_notice_flash webauthn_setup_notice_flash
@@ -207,17 +207,17 @@ module Rodauth
207
207
  r.post do
208
208
  catch_error do
209
209
  unless webauthn_id = param_or_nil(webauthn_remove_param)
210
- throw_error_status(invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
210
+ throw_error_reason(:invalid_webauthn_remove_param, invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
211
211
  end
212
212
 
213
213
  unless two_factor_password_match?(param(password_param))
214
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
214
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
215
215
  end
216
216
 
217
217
  transaction do
218
218
  before_webauthn_remove
219
219
  unless remove_webauthn_key(webauthn_id)
220
- throw_error_status(invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
220
+ throw_error_reason(:invalid_webauthn_remove_param, invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
221
221
  end
222
222
  if authenticated_webauthn_id == webauthn_id && two_factor_login_type_match?('webauthn')
223
223
  webauthn_remove_authenticated_session
@@ -342,7 +342,7 @@ module Rodauth
342
342
  end
343
343
 
344
344
  def handle_webauthn_sign_count_verification_error
345
- throw_error_status(invalid_field_error_status, webauthn_auth_param, webauthn_invalid_sign_count_message)
345
+ throw_error_reason(:invalid_webauthn_sign_count, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_sign_count_message)
346
346
  end
347
347
 
348
348
  def add_webauthn_credential(webauthn_credential)
@@ -392,6 +392,7 @@ module Rodauth
392
392
  def require_webauthn_setup
393
393
  unless webauthn_setup?
394
394
  set_redirect_error_status(webauthn_not_setup_error_status)
395
+ set_error_reason :webauthn_not_setup
395
396
  set_redirect_error_flash webauthn_not_setup_error_flash
396
397
  redirect two_factor_need_setup_redirect
397
398
  end
@@ -450,23 +451,23 @@ module Rodauth
450
451
  begin
451
452
  auth_data = JSON.parse(auth_data)
452
453
  rescue
453
- throw_error_status(invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
454
+ throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
454
455
  end
455
456
  when Hash
456
457
  # nothing
457
458
  else
458
- throw_error_status(invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
459
+ throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
459
460
  end
460
461
 
461
462
  begin
462
463
  webauthn_credential = WebAuthn::Credential.from_get(auth_data)
463
464
  unless valid_webauthn_credential_auth?(webauthn_credential)
464
- throw_error_status(invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
465
+ throw_error_reason(:invalid_webauthn_auth_param, invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
465
466
  end
466
467
  rescue WebAuthn::SignCountVerificationError
467
468
  handle_webauthn_sign_count_verification_error
468
469
  rescue WebAuthn::Error, RuntimeError, NoMethodError
469
- throw_error_status(invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
470
+ throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
470
471
  end
471
472
 
472
473
  webauthn_credential
@@ -478,25 +479,25 @@ module Rodauth
478
479
  begin
479
480
  setup_data = JSON.parse(setup_data)
480
481
  rescue
481
- throw_error_status(invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
482
+ throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
482
483
  end
483
484
  when Hash
484
485
  # nothing
485
486
  else
486
- throw_error_status(invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
487
+ throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
487
488
  end
488
489
 
489
490
  unless two_factor_password_match?(param(password_param))
490
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
491
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
491
492
  end
492
493
 
493
494
  begin
494
495
  webauthn_credential = WebAuthn::Credential.from_create(setup_data)
495
496
  unless valid_new_webauthn_credential?(webauthn_credential)
496
- throw_error_status(invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
497
+ throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
497
498
  end
498
499
  rescue WebAuthn::Error, RuntimeError, NoMethodError
499
- throw_error_status(invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
500
+ throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
500
501
  end
501
502
 
502
503
  webauthn_credential
@@ -17,7 +17,7 @@ module Rodauth
17
17
  r.post do
18
18
  catch_error do
19
19
  unless account_from_login(param(login_param)) && open_account?
20
- throw_error_status(no_matching_login_error_status, login_param, no_matching_login_message)
20
+ throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
21
21
  end
22
22
 
23
23
  webauthn_credential = webauthn_auth_credential_from_form_submission
@@ -6,7 +6,7 @@ module Rodauth
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 12
9
+ MINOR = 13
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
data/templates/button.str CHANGED
@@ -1,3 +1,3 @@
1
- <div class="form-group">
1
+ <div class="form-group mb-3">
2
2
  <input type="submit" #{"name=\"#{h opts[:name]}\"" if opts[:name]} class="#{h(opts[:class] || 'btn btn-primary')}" value="#{h value}"/>
3
3
  </div>
@@ -2,8 +2,8 @@
2
2
  #{rodauth.change_password_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.change_password_requires_password?}
5
- <div class="form-group">
6
- <label for="new-password">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
5
+ <div class="form-group mb-3">
6
+ <label for="new-password" class="form-label">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
7
7
  #{rodauth.input_field_string(rodauth.new_password_param, 'new-password', :type => 'password', :autocomplete=>"new-password")}
8
8
  </div>
9
9
  #{rodauth.render('password-confirm-field') if rodauth.require_password_confirmation?}
@@ -1,4 +1,4 @@
1
- <div class="form-group">
1
+ <div class="form-group mb-3">
2
2
  <div class="form-check checkbox">
3
3
  <input type="checkbox" name="#{rodauth.global_logout_param}" class="form-check-input" id="global-logout" value="t"/>
4
4
  <label class="rodauth-global-logout-label form-check-label" for="global-logout">#{rodauth.global_logout_label}</label>
@@ -1,4 +1,4 @@
1
- <div class="form-group">
2
- <label for="login-confirm">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="login-confirm" class="form-label">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
3
  #{rodauth.input_field_string(rodauth.login_confirm_param, 'login-confirm', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
4
4
  </div>
@@ -1,5 +1,5 @@
1
- <div class="form-group">
1
+ <div class="form-group mb-3">
2
2
  #{rodauth.login_hidden_field}
3
- <label for="login">#{rodauth.login_label}</label>
3
+ <label for="login" class="form-label">#{rodauth.login_label}</label>
4
4
  <div class="form-control-plaintext form-control-static">#{h rodauth.param(rodauth.login_param)}</div>
5
5
  </div>
@@ -1,4 +1,4 @@
1
- <div class="form-group">
2
- <label for="login">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="login" class="form-label">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
3
3
  #{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
4
4
  </div>
@@ -1,5 +1,5 @@
1
- <div class="form-group">
2
- <label for="otp-auth-code">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="otp-auth-code" class="form-label">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
3
3
  <div class="row">
4
4
  <div class="col-sm-3">
5
5
  #{rodauth.input_field_string(rodauth.otp_auth_param, 'otp-auth-code', :value=>'', :autocomplete=>"off", :inputmode=>'numeric')}
@@ -3,14 +3,14 @@
3
3
  <input type="hidden" id="otp-key" name="#{rodauth.otp_setup_param}" value="#{rodauth.otp_user_key}" />
4
4
  #{"<input type=\"hidden\" id=\"otp-hmac-secret\" name=\"#{rodauth.otp_setup_raw_param}\" value=\"#{rodauth.otp_key}\" />" if rodauth.otp_keys_use_hmac?}
5
5
  #{rodauth.csrf_tag}
6
- <div class="form-group">
6
+ <div class="form-group mb-3">
7
7
  <p>#{rodauth.otp_secret_label}: #{rodauth.otp_user_key}</p>
8
8
  <p>#{rodauth.otp_provisioning_uri_label}: #{rodauth.otp_provisioning_uri}</p>
9
9
  </div>
10
10
 
11
11
  <div class="row">
12
12
  <div class="col-lg-6 col-lg">
13
- <div class="form-group">
13
+ <div class="form-group mb-3">
14
14
  <p>#{rodauth.otp_qr_code}</p>
15
15
  </div>
16
16
  </div>
@@ -1,4 +1,4 @@
1
- <div class="form-group">
2
- <label for="password-confirm">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="password-confirm" class="form-label">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
3
  #{rodauth.input_field_string(rodauth.password_confirm_param, 'password-confirm', :type => 'password', :autocomplete=>'new-password')}
4
4
  </div>
@@ -1,4 +1,4 @@
1
- <div class="form-group">
2
- <label for="password">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="password" class="form-label">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
3
3
  #{rodauth.input_field_string(rodauth.password_param, 'password', :type => 'password', :autocomplete=>rodauth.password_field_autocomplete_value)}
4
4
  </div>
@@ -1,8 +1,8 @@
1
1
  <form method="post" class="rodauth" role="form" id="recovery-auth-form">
2
2
  #{rodauth.recovery_auth_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
- <div class="form-group">
5
- <label for="recovery-code">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
4
+ <div class="form-group mb-3">
5
+ <label for="recovery-code" class="form-label">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
6
6
  #{rodauth.input_field_string(rodauth.recovery_codes_param, 'recovery-code', :value => '', :autocomplete=>'off')}
7
7
  </div>
8
8
  #{rodauth.button(rodauth.recovery_auth_button)}
@@ -1,7 +1,7 @@
1
1
  <form method="post" class="rodauth" role="form" id="remember-form">
2
2
  #{rodauth.remember_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
- <fieldset class="form-group">
4
+ <fieldset class="form-group mb-3">
5
5
  <div class="form-check radio">
6
6
  <input type="radio" name="#{rodauth.remember_param}" id="remember-remember" value="#{h rodauth.remember_remember_param_value}" class="form-check-input"/>
7
7
  <label class="form-check-label" for="remember-remember">#{rodauth.remember_remember_label}</label>
@@ -1,5 +1,5 @@
1
- <div class="form-group">
2
- <label for="sms-code">#{rodauth.sms_code_label}#{rodauth.input_field_label_suffix}</label>
1
+ <div class="form-group mb-3">
2
+ <label for="sms-code" class="form-label">#{rodauth.sms_code_label}#{rodauth.input_field_label_suffix}</label>
3
3
  <div class="row">
4
4
  <div class="col-sm-3">
5
5
  #{rodauth.input_field_string(rodauth.sms_code_param, 'sms-code', :value => '', :autocomplete=>'one-time-code', :inputmode=>'numeric')}
@@ -2,8 +2,8 @@
2
2
  #{rodauth.sms_setup_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
5
- <div class="form-group">
6
- <label for="sms-phone">#{rodauth.sms_phone_label}#{rodauth.input_field_label_suffix}</label>
5
+ <div class="form-group mb-3">
6
+ <label for="sms-phone" class="form-label">#{rodauth.sms_phone_label}#{rodauth.input_field_label_suffix}</label>
7
7
  <div class="row">
8
8
  <div class="col-sm-3">
9
9
  #{rodauth.input_field_string(rodauth.sms_phone_param, 'sms-phone', :type=>rodauth.sms_phone_input_type, :autocomplete=>'tel')}
@@ -2,7 +2,7 @@
2
2
  #{rodauth.webauthn_remove_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
5
- <fieldset class="form-group">
5
+ <fieldset class="form-group mb-3">
6
6
  #{(usage = rodauth.account_webauthn_usage; last_id = usage.keys.last; usage;).map do |id, last_use|
7
7
  input = rodauth.input_field_string(rodauth.webauthn_remove_param, "webauthn-remove-#{h id}", :type=>'radio', :class=>"form-check-input", :skip_error_message=>true, :value=>id, :required=>false)
8
8
  label = "<label class=\"rodauth-webauthn-id form-check-label\" for=\"webauthn-remove-#{h id}\">Last Use: #{last_use}</label>"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.12.0
4
+ version: 2.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-22 00:00:00.000000000 Z
11
+ date: 2021-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -266,6 +266,7 @@ extra_rdoc_files:
266
266
  - doc/disallow_password_reuse.rdoc
267
267
  - doc/email_auth.rdoc
268
268
  - doc/email_base.rdoc
269
+ - doc/error_reasons.rdoc
269
270
  - doc/http_basic_auth.rdoc
270
271
  - doc/json.rdoc
271
272
  - doc/jwt.rdoc
@@ -323,6 +324,7 @@ extra_rdoc_files:
323
324
  - doc/release_notes/2.10.0.txt
324
325
  - doc/release_notes/2.11.0.txt
325
326
  - doc/release_notes/2.12.0.txt
327
+ - doc/release_notes/2.13.0.txt
326
328
  - doc/release_notes/2.2.0.txt
327
329
  - doc/release_notes/2.3.0.txt
328
330
  - doc/release_notes/2.4.0.txt
@@ -351,6 +353,7 @@ files:
351
353
  - doc/disallow_password_reuse.rdoc
352
354
  - doc/email_auth.rdoc
353
355
  - doc/email_base.rdoc
356
+ - doc/error_reasons.rdoc
354
357
  - doc/guides/admin_activation.rdoc
355
358
  - doc/guides/already_authenticated.rdoc
356
359
  - doc/guides/alternative_login.rdoc
@@ -417,6 +420,7 @@ files:
417
420
  - doc/release_notes/2.10.0.txt
418
421
  - doc/release_notes/2.11.0.txt
419
422
  - doc/release_notes/2.12.0.txt
423
+ - doc/release_notes/2.13.0.txt
420
424
  - doc/release_notes/2.2.0.txt
421
425
  - doc/release_notes/2.3.0.txt
422
426
  - doc/release_notes/2.4.0.txt