rodauth 2.11.0 → 2.15.0

Sign up to get free protection for your applications and to get access to all the features.
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>