rodauth 2.11.0 → 2.15.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +28 -0
  3. data/README.rdoc +29 -7
  4. data/doc/active_sessions.rdoc +4 -0
  5. data/doc/base.rdoc +1 -0
  6. data/doc/error_reasons.rdoc +73 -0
  7. data/doc/internal_request.rdoc +463 -0
  8. data/doc/path_class_methods.rdoc +10 -0
  9. data/doc/release_notes/2.11.0.txt +1 -1
  10. data/doc/release_notes/2.12.0.txt +17 -0
  11. data/doc/release_notes/2.13.0.txt +19 -0
  12. data/doc/release_notes/2.14.0.txt +17 -0
  13. data/doc/release_notes/2.15.0.txt +48 -0
  14. data/doc/remember.rdoc +1 -0
  15. data/lib/rodauth.rb +9 -2
  16. data/lib/rodauth/features/active_sessions.rb +29 -8
  17. data/lib/rodauth/features/base.rb +26 -1
  18. data/lib/rodauth/features/change_login.rb +6 -4
  19. data/lib/rodauth/features/change_password.rb +5 -3
  20. data/lib/rodauth/features/close_account.rb +3 -1
  21. data/lib/rodauth/features/confirm_password.rb +2 -2
  22. data/lib/rodauth/features/create_account.rb +6 -4
  23. data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
  24. data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
  25. data/lib/rodauth/features/email_auth.rb +6 -0
  26. data/lib/rodauth/features/internal_request.rb +367 -0
  27. data/lib/rodauth/features/jwt_refresh.rb +1 -1
  28. data/lib/rodauth/features/lockout.rb +15 -4
  29. data/lib/rodauth/features/login.rb +6 -3
  30. data/lib/rodauth/features/login_password_requirements_base.rb +15 -6
  31. data/lib/rodauth/features/otp.rb +13 -6
  32. data/lib/rodauth/features/password_complexity.rb +4 -4
  33. data/lib/rodauth/features/path_class_methods.rb +22 -0
  34. data/lib/rodauth/features/recovery_codes.rb +6 -2
  35. data/lib/rodauth/features/remember.rb +25 -10
  36. data/lib/rodauth/features/reset_password.rb +8 -4
  37. data/lib/rodauth/features/session_expiration.rb +1 -0
  38. data/lib/rodauth/features/single_session.rb +1 -0
  39. data/lib/rodauth/features/sms_codes.rb +17 -5
  40. data/lib/rodauth/features/two_factor_base.rb +6 -1
  41. data/lib/rodauth/features/verify_account.rb +8 -1
  42. data/lib/rodauth/features/verify_account_grace_period.rb +1 -1
  43. data/lib/rodauth/features/verify_login_change.rb +5 -2
  44. data/lib/rodauth/features/webauthn.rb +15 -14
  45. data/lib/rodauth/features/webauthn_login.rb +1 -1
  46. data/lib/rodauth/version.rb +1 -1
  47. data/templates/button.str +1 -1
  48. data/templates/change-password.str +2 -2
  49. data/templates/global-logout-field.str +1 -1
  50. data/templates/login-confirm-field.str +2 -2
  51. data/templates/login-display.str +2 -2
  52. data/templates/login-field.str +2 -2
  53. data/templates/otp-auth-code-field.str +2 -2
  54. data/templates/otp-setup.str +2 -2
  55. data/templates/password-confirm-field.str +2 -2
  56. data/templates/password-field.str +2 -2
  57. data/templates/recovery-auth.str +2 -2
  58. data/templates/remember.str +1 -1
  59. data/templates/sms-code-field.str +2 -2
  60. data/templates/sms-setup.str +2 -2
  61. data/templates/unlock-account-email.str +1 -1
  62. data/templates/webauthn-remove.str +1 -1
  63. metadata +19 -3
@@ -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
@@ -112,6 +112,13 @@ module Rodauth
112
112
  :sms_valid_phone?
113
113
  )
114
114
 
115
+ internal_request_method :sms_setup
116
+ internal_request_method :sms_confirm
117
+ internal_request_method :sms_request
118
+ internal_request_method :sms_auth
119
+ internal_request_method :valid_sms_auth?
120
+ internal_request_method :sms_disable
121
+
115
122
  route(:sms_request) do |r|
116
123
  require_login
117
124
  require_account_session
@@ -146,7 +153,7 @@ module Rodauth
146
153
  sms_set_code(nil)
147
154
  end
148
155
 
149
- set_response_error_status(invalid_key_error_status)
156
+ set_response_error_reason_status(:no_current_sms_code, invalid_key_error_status)
150
157
  set_redirect_error_flash no_current_sms_code_error_flash
151
158
  redirect sms_request_redirect
152
159
  end
@@ -169,7 +176,7 @@ module Rodauth
169
176
  end
170
177
  end
171
178
 
172
- set_response_error_status(invalid_key_error_status)
179
+ set_response_error_reason_status(:invalid_sms_code, invalid_key_error_status)
173
180
  set_field_error(sms_code_param, sms_invalid_code_message)
174
181
  set_error_flash sms_invalid_code_error_flash
175
182
  sms_auth_view
@@ -186,6 +193,7 @@ module Rodauth
186
193
 
187
194
  if sms_needs_confirmation?
188
195
  set_redirect_error_status(sms_needs_confirmation_error_status)
196
+ set_error_reason :sms_needs_confirmation
189
197
  set_redirect_error_flash sms_needs_confirmation_error_flash
190
198
  redirect sms_needs_confirmation_redirect
191
199
  end
@@ -199,13 +207,13 @@ module Rodauth
199
207
  r.post do
200
208
  catch_error do
201
209
  unless two_factor_password_match?(param(password_param))
202
- throw_error_status(invalid_password_error_status, password_param, invalid_password_message)
210
+ throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
203
211
  end
204
212
 
205
213
  phone = sms_normalize_phone(param(sms_phone_param))
206
214
 
207
215
  unless sms_valid_phone?(phone)
208
- throw_error_status(invalid_field_error_status, sms_phone_param, sms_invalid_phone_message)
216
+ throw_error_reason(:invalid_phone_number, invalid_field_error_status, sms_phone_param, sms_invalid_phone_message)
209
217
  end
210
218
 
211
219
  transaction do
@@ -254,6 +262,7 @@ module Rodauth
254
262
 
255
263
  sms_confirm_failure
256
264
  set_redirect_error_status(invalid_key_error_status)
265
+ set_error_reason :invalid_sms_confirmation_code
257
266
  set_redirect_error_flash sms_invalid_confirmation_code_error_flash
258
267
  redirect sms_needs_setup_redirect
259
268
  end
@@ -282,7 +291,7 @@ module Rodauth
282
291
  redirect sms_disable_redirect
283
292
  end
284
293
 
285
- set_response_error_status(invalid_password_error_status)
294
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
286
295
  set_field_error(password_param, invalid_password_message)
287
296
  set_error_flash sms_disable_error_flash
288
297
  sms_disable_view
@@ -302,6 +311,7 @@ module Rodauth
302
311
  def require_sms_setup
303
312
  unless sms_setup?
304
313
  set_redirect_error_status(two_factor_not_setup_error_status)
314
+ set_error_reason :sms_not_setup
305
315
  set_redirect_error_flash sms_not_setup_error_flash
306
316
  redirect sms_needs_setup_redirect
307
317
  end
@@ -310,6 +320,7 @@ module Rodauth
310
320
  def require_sms_not_setup
311
321
  if sms_setup?
312
322
  set_redirect_error_status(sms_already_setup_error_status)
323
+ set_error_reason :sms_already_setup
313
324
  set_redirect_error_flash sms_already_setup_error_flash
314
325
  redirect sms_already_setup_redirect
315
326
  end
@@ -320,6 +331,7 @@ module Rodauth
320
331
 
321
332
  if sms_locked_out?
322
333
  set_redirect_error_status(lockout_error_status)
334
+ set_error_reason :sms_locked_out
323
335
  set_redirect_error_flash sms_lockout_error_flash
324
336
  redirect sms_lockout_redirect
325
337
  end
@@ -57,6 +57,8 @@ module Rodauth
57
57
  :two_factor_update_session
58
58
  )
59
59
 
60
+ internal_request_method :two_factor_disable
61
+
60
62
  route(:two_factor_manage, 'multifactor-manage') do |r|
61
63
  require_account
62
64
  before_two_factor_manage_route
@@ -106,7 +108,7 @@ module Rodauth
106
108
  redirect two_factor_disable_redirect
107
109
  end
108
110
 
109
- set_response_error_status(invalid_password_error_status)
111
+ set_response_error_reason_status(:invalid_password, invalid_password_error_status)
110
112
  set_field_error(password_param, invalid_password_message)
111
113
  set_error_flash two_factor_disable_error_flash
112
114
  two_factor_disable_view
@@ -144,6 +146,7 @@ module Rodauth
144
146
  return if uses_two_factor_authentication?
145
147
 
146
148
  set_redirect_error_status(two_factor_not_setup_error_status)
149
+ set_error_reason :two_factor_not_setup
147
150
  set_redirect_error_flash two_factor_not_setup_error_flash
148
151
  redirect two_factor_need_setup_redirect
149
152
  end
@@ -151,6 +154,7 @@ module Rodauth
151
154
  def require_two_factor_not_authenticated(auth_type = nil)
152
155
  if two_factor_authenticated? || (auth_type && two_factor_login_type_match?(auth_type))
153
156
  set_redirect_error_status(two_factor_already_authenticated_error_status)
157
+ set_error_reason :two_factor_already_authenticated
154
158
  set_redirect_error_flash two_factor_already_authenticated_error_flash
155
159
  redirect two_factor_already_authenticated_redirect
156
160
  end
@@ -162,6 +166,7 @@ module Rodauth
162
166
  set_session_value(two_factor_auth_redirect_session_key, request.fullpath)
163
167
  end
164
168
  set_redirect_error_status(two_factor_need_authentication_error_status)
169
+ set_error_reason :two_factor_need_authentication
165
170
  set_redirect_error_flash two_factor_need_authentication_error_flash
166
171
  redirect two_factor_auth_required_redirect
167
172
  end
@@ -60,6 +60,9 @@ module Rodauth
60
60
  :account_from_verify_account_key
61
61
  )
62
62
 
63
+ internal_request_method(:verify_account_resend)
64
+ internal_request_method
65
+
63
66
  route(:verify_account_resend) do |r|
64
67
  verify_account_check_already_logged_in
65
68
  before_verify_account_resend_route
@@ -87,6 +90,7 @@ module Rodauth
87
90
  set_notice_flash verify_account_email_sent_notice_flash
88
91
  else
89
92
  set_redirect_error_status(no_matching_login_error_status)
93
+ set_error_reason :no_matching_login
90
94
  set_redirect_error_flash verify_account_resend_error_flash
91
95
  end
92
96
 
@@ -120,6 +124,7 @@ module Rodauth
120
124
  key = session[verify_account_session_key] || param(verify_account_key_param)
121
125
  unless account_from_verify_account_key(key)
122
126
  set_redirect_error_status(invalid_key_error_status)
127
+ set_error_reason :invalid_verify_account_key
123
128
  set_redirect_error_flash verify_account_error_flash
124
129
  redirect verify_account_redirect
125
130
  end
@@ -129,7 +134,7 @@ module Rodauth
129
134
  password = param(password_param)
130
135
 
131
136
  if require_password_confirmation? && password != param(password_confirm_param)
132
- throw_error_status(unmatched_field_error_status, password_param, passwords_do_not_match_message)
137
+ throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
133
138
  end
134
139
 
135
140
  unless password_meets_requirements?(password)
@@ -192,6 +197,7 @@ module Rodauth
192
197
  def new_account(login)
193
198
  if account_from_login(login) && allow_resending_verify_account_email?
194
199
  set_redirect_error_status(unopen_account_error_status)
200
+ set_error_reason :already_an_unverified_account_with_this_login
195
201
  set_error_flash attempt_to_create_unverified_account_error_flash
196
202
  response.write resend_verify_account_view
197
203
  request.halt
@@ -269,6 +275,7 @@ module Rodauth
269
275
  def before_login_attempt
270
276
  unless open_account?
271
277
  set_redirect_error_status(unopen_account_error_status)
278
+ set_error_reason :unverified_account
272
279
  set_error_flash attempt_to_login_to_unverified_account_error_flash
273
280
  response.write resend_verify_account_view
274
281
  request.halt
@@ -72,7 +72,7 @@ module Rodauth
72
72
  end
73
73
 
74
74
  def account_in_unverified_grace_period?
75
- account || account_from_session
75
+ return false unless account || (session_value && account_from_session)
76
76
  account[account_status_column] == account_unverified_status_value &&
77
77
  verify_account_grace_period &&
78
78
  !verify_account_ds.where(Sequel.date_add(verification_requested_at_column, :seconds=>verify_account_grace_period) > Sequel::CURRENT_TIMESTAMP).empty?
@@ -50,6 +50,8 @@ module Rodauth
50
50
  :account_from_verify_login_change_key
51
51
  )
52
52
 
53
+ internal_request_method
54
+
53
55
  route do |r|
54
56
  before_verify_login_change_route
55
57
 
@@ -74,6 +76,7 @@ module Rodauth
74
76
  key = session[verify_login_change_session_key] || param(verify_login_change_key_param)
75
77
  unless account_from_verify_login_change_key(key)
76
78
  set_redirect_error_status(invalid_key_error_status)
79
+ set_error_reason :invalid_verify_login_change_key
77
80
  set_redirect_error_flash verify_login_change_error_flash
78
81
  redirect verify_login_change_redirect
79
82
  end
@@ -82,6 +85,7 @@ module Rodauth
82
85
  before_verify_login_change
83
86
  unless verify_login_change
84
87
  set_redirect_error_status(invalid_key_error_status)
88
+ set_error_reason :already_an_account_with_this_login
85
89
  set_redirect_error_flash verify_login_change_duplicate_account_error_flash
86
90
  redirect verify_login_change_duplicate_account_redirect
87
91
  end
@@ -151,7 +155,7 @@ module Rodauth
151
155
 
152
156
  def update_login(login)
153
157
  if _account_from_login(login)
154
- @login_requirement_message = already_an_account_with_this_login_message
158
+ set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
155
159
  return false
156
160
  end
157
161
 
@@ -213,4 +217,3 @@ module Rodauth
213
217
  end
214
218
  end
215
219
  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 = 11
9
+ MINOR = 15
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>