rodauth 1.21.0 → 2.2.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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +182 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +211 -79
  5. data/doc/account_expiration.rdoc +12 -26
  6. data/doc/active_sessions.rdoc +49 -0
  7. data/doc/audit_logging.rdoc +44 -0
  8. data/doc/base.rdoc +75 -128
  9. data/doc/change_login.rdoc +7 -14
  10. data/doc/change_password.rdoc +9 -13
  11. data/doc/change_password_notify.rdoc +2 -2
  12. data/doc/close_account.rdoc +9 -16
  13. data/doc/confirm_password.rdoc +12 -5
  14. data/doc/create_account.rdoc +11 -22
  15. data/doc/disallow_password_reuse.rdoc +6 -13
  16. data/doc/email_auth.rdoc +15 -14
  17. data/doc/email_base.rdoc +6 -15
  18. data/doc/guides/admin_activation.rdoc +46 -0
  19. data/doc/guides/already_authenticated.rdoc +10 -0
  20. data/doc/guides/alternative_login.rdoc +46 -0
  21. data/doc/guides/create_account_programmatically.rdoc +38 -0
  22. data/doc/guides/delay_password.rdoc +25 -0
  23. data/doc/guides/email_only.rdoc +16 -0
  24. data/doc/guides/i18n.rdoc +26 -0
  25. data/doc/{internals.rdoc → guides/internals.rdoc} +0 -0
  26. data/doc/guides/links.rdoc +12 -0
  27. data/doc/guides/login_return.rdoc +37 -0
  28. data/doc/guides/password_column.rdoc +25 -0
  29. data/doc/guides/password_confirmation.rdoc +37 -0
  30. data/doc/guides/password_requirements.rdoc +30 -0
  31. data/doc/guides/paths.rdoc +36 -0
  32. data/doc/guides/query_params.rdoc +9 -0
  33. data/doc/guides/redirects.rdoc +17 -0
  34. data/doc/guides/registration_field.rdoc +68 -0
  35. data/doc/guides/require_mfa.rdoc +30 -0
  36. data/doc/guides/reset_password_autologin.rdoc +21 -0
  37. data/doc/guides/status_column.rdoc +28 -0
  38. data/doc/guides/totp_or_recovery.rdoc +16 -0
  39. data/doc/http_basic_auth.rdoc +10 -1
  40. data/doc/jwt.rdoc +22 -22
  41. data/doc/jwt_cors.rdoc +22 -0
  42. data/doc/jwt_refresh.rdoc +18 -8
  43. data/doc/lockout.rdoc +17 -15
  44. data/doc/login.rdoc +10 -2
  45. data/doc/login_password_requirements_base.rdoc +15 -37
  46. data/doc/logout.rdoc +2 -2
  47. data/doc/otp.rdoc +25 -19
  48. data/doc/password_complexity.rdoc +10 -26
  49. data/doc/password_expiration.rdoc +11 -25
  50. data/doc/password_grace_period.rdoc +16 -2
  51. data/doc/recovery_codes.rdoc +18 -12
  52. data/doc/release_notes/1.22.0.txt +11 -0
  53. data/doc/release_notes/1.23.0.txt +32 -0
  54. data/doc/release_notes/2.0.0.txt +361 -0
  55. data/doc/release_notes/2.1.0.txt +31 -0
  56. data/doc/release_notes/2.2.0.txt +39 -0
  57. data/doc/remember.rdoc +40 -64
  58. data/doc/reset_password.rdoc +12 -9
  59. data/doc/session_expiration.rdoc +1 -0
  60. data/doc/single_session.rdoc +16 -25
  61. data/doc/sms_codes.rdoc +24 -14
  62. data/doc/two_factor_base.rdoc +60 -22
  63. data/doc/verify_account.rdoc +14 -12
  64. data/doc/verify_account_grace_period.rdoc +6 -2
  65. data/doc/verify_login_change.rdoc +9 -8
  66. data/doc/webauthn.rdoc +115 -0
  67. data/doc/webauthn_login.rdoc +15 -0
  68. data/doc/webauthn_verify_account.rdoc +9 -0
  69. data/javascript/webauthn_auth.js +45 -0
  70. data/javascript/webauthn_setup.js +35 -0
  71. data/lib/roda/plugins/rodauth.rb +1 -1
  72. data/lib/rodauth.rb +36 -28
  73. data/lib/rodauth/features/account_expiration.rb +5 -5
  74. data/lib/rodauth/features/active_sessions.rb +158 -0
  75. data/lib/rodauth/features/audit_logging.rb +98 -0
  76. data/lib/rodauth/features/base.rb +144 -43
  77. data/lib/rodauth/features/change_password_notify.rb +2 -2
  78. data/lib/rodauth/features/confirm_password.rb +40 -2
  79. data/lib/rodauth/features/create_account.rb +8 -13
  80. data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
  81. data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
  82. data/lib/rodauth/features/email_auth.rb +31 -30
  83. data/lib/rodauth/features/email_base.rb +9 -4
  84. data/lib/rodauth/features/http_basic_auth.rb +55 -35
  85. data/lib/rodauth/features/jwt.rb +63 -16
  86. data/lib/rodauth/features/jwt_cors.rb +53 -0
  87. data/lib/rodauth/features/jwt_refresh.rb +32 -9
  88. data/lib/rodauth/features/lockout.rb +12 -14
  89. data/lib/rodauth/features/login.rb +54 -10
  90. data/lib/rodauth/features/login_password_requirements_base.rb +4 -4
  91. data/lib/rodauth/features/otp.rb +77 -80
  92. data/lib/rodauth/features/password_complexity.rb +8 -13
  93. data/lib/rodauth/features/password_expiration.rb +2 -2
  94. data/lib/rodauth/features/password_grace_period.rb +17 -10
  95. data/lib/rodauth/features/recovery_codes.rb +49 -53
  96. data/lib/rodauth/features/remember.rb +11 -27
  97. data/lib/rodauth/features/reset_password.rb +26 -26
  98. data/lib/rodauth/features/session_expiration.rb +6 -4
  99. data/lib/rodauth/features/single_session.rb +8 -6
  100. data/lib/rodauth/features/sms_codes.rb +62 -72
  101. data/lib/rodauth/features/two_factor_base.rb +134 -30
  102. data/lib/rodauth/features/verify_account.rb +29 -21
  103. data/lib/rodauth/features/verify_account_grace_period.rb +18 -9
  104. data/lib/rodauth/features/verify_login_change.rb +12 -11
  105. data/lib/rodauth/features/webauthn.rb +505 -0
  106. data/lib/rodauth/features/webauthn_login.rb +70 -0
  107. data/lib/rodauth/features/webauthn_verify_account.rb +46 -0
  108. data/lib/rodauth/version.rb +2 -2
  109. data/templates/button.str +1 -3
  110. data/templates/change-login.str +1 -2
  111. data/templates/change-password.str +3 -5
  112. data/templates/close-account.str +2 -2
  113. data/templates/confirm-password.str +1 -1
  114. data/templates/create-account.str +1 -1
  115. data/templates/email-auth-email.str +1 -1
  116. data/templates/email-auth-request-form.str +2 -3
  117. data/templates/email-auth.str +1 -1
  118. data/templates/global-logout-field.str +6 -0
  119. data/templates/login-confirm-field.str +2 -4
  120. data/templates/login-display.str +3 -2
  121. data/templates/login-field.str +2 -4
  122. data/templates/login-form-footer.str +6 -0
  123. data/templates/login-form.str +7 -0
  124. data/templates/login.str +1 -9
  125. data/templates/logout.str +1 -1
  126. data/templates/multi-phase-login.str +3 -0
  127. data/templates/otp-auth-code-field.str +5 -3
  128. data/templates/otp-auth.str +1 -1
  129. data/templates/otp-disable.str +1 -1
  130. data/templates/otp-setup.str +3 -3
  131. data/templates/password-confirm-field.str +2 -4
  132. data/templates/password-field.str +2 -4
  133. data/templates/recovery-auth.str +3 -6
  134. data/templates/recovery-codes.str +1 -1
  135. data/templates/remember.str +15 -20
  136. data/templates/reset-password-email.str +1 -1
  137. data/templates/reset-password-request.str +3 -3
  138. data/templates/reset-password.str +1 -2
  139. data/templates/sms-auth.str +1 -1
  140. data/templates/sms-code-field.str +5 -3
  141. data/templates/sms-confirm.str +1 -2
  142. data/templates/sms-disable.str +1 -2
  143. data/templates/sms-request.str +1 -1
  144. data/templates/sms-setup.str +6 -4
  145. data/templates/two-factor-auth.str +5 -0
  146. data/templates/two-factor-disable.str +6 -0
  147. data/templates/two-factor-manage.str +16 -0
  148. data/templates/unlock-account-email.str +1 -1
  149. data/templates/unlock-account-request.str +4 -4
  150. data/templates/unlock-account.str +1 -1
  151. data/templates/verify-account-email.str +1 -1
  152. data/templates/verify-account-resend.str +3 -3
  153. data/templates/verify-account.str +1 -2
  154. data/templates/verify-login-change-email.str +2 -1
  155. data/templates/verify-login-change.str +1 -1
  156. data/templates/webauthn-auth.str +11 -0
  157. data/templates/webauthn-remove.str +14 -0
  158. data/templates/webauthn-setup.str +12 -0
  159. metadata +110 -52
  160. data/Rakefile +0 -179
  161. data/doc/verify_change_login.rdoc +0 -11
  162. data/lib/rodauth/features/verify_change_login.rb +0 -20
  163. data/spec/account_expiration_spec.rb +0 -225
  164. data/spec/all.rb +0 -1
  165. data/spec/change_login_spec.rb +0 -156
  166. data/spec/change_password_notify_spec.rb +0 -33
  167. data/spec/change_password_spec.rb +0 -202
  168. data/spec/close_account_spec.rb +0 -162
  169. data/spec/confirm_password_spec.rb +0 -70
  170. data/spec/create_account_spec.rb +0 -127
  171. data/spec/disallow_common_passwords_spec.rb +0 -93
  172. data/spec/disallow_password_reuse_spec.rb +0 -179
  173. data/spec/email_auth_spec.rb +0 -285
  174. data/spec/http_basic_auth_spec.rb +0 -143
  175. data/spec/jwt_refresh_spec.rb +0 -256
  176. data/spec/jwt_spec.rb +0 -235
  177. data/spec/lockout_spec.rb +0 -250
  178. data/spec/login_spec.rb +0 -328
  179. data/spec/migrate/001_tables.rb +0 -184
  180. data/spec/migrate/002_account_password_hash_column.rb +0 -11
  181. data/spec/migrate_password/001_tables.rb +0 -73
  182. data/spec/migrate_travis/001_tables.rb +0 -141
  183. data/spec/password_complexity_spec.rb +0 -109
  184. data/spec/password_expiration_spec.rb +0 -244
  185. data/spec/password_grace_period_spec.rb +0 -93
  186. data/spec/remember_spec.rb +0 -451
  187. data/spec/reset_password_spec.rb +0 -229
  188. data/spec/rodauth_spec.rb +0 -343
  189. data/spec/session_expiration_spec.rb +0 -58
  190. data/spec/single_session_spec.rb +0 -127
  191. data/spec/spec_helper.rb +0 -327
  192. data/spec/two_factor_spec.rb +0 -1462
  193. data/spec/update_password_hash_spec.rb +0 -40
  194. data/spec/verify_account_grace_period_spec.rb +0 -171
  195. data/spec/verify_account_spec.rb +0 -240
  196. data/spec/verify_change_login_spec.rb +0 -46
  197. data/spec/verify_login_change_spec.rb +0 -232
  198. data/spec/views/layout-other.str +0 -11
  199. data/spec/views/layout.str +0 -11
  200. data/spec/views/login.str +0 -21
@@ -0,0 +1,70 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Rodauth
4
+ Feature.define(:webauthn_login, :WebauthnLogin) do
5
+ depends :login, :webauthn
6
+
7
+ before
8
+
9
+ redirect(:webauthn_login_failure){require_login_redirect}
10
+
11
+ error_flash "There was an error authenticating via WebAuthn"
12
+
13
+ route(:webauthn_login) do |r|
14
+ check_already_logged_in
15
+ before_webauthn_login_route
16
+
17
+ r.post do
18
+ catch_error do
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)
21
+ end
22
+
23
+ webauthn_credential = webauthn_auth_credential_from_form_submission
24
+ before_webauthn_login
25
+ _login('webauthn') do
26
+ webauthn_update_session(webauthn_credential.id)
27
+ end
28
+ end
29
+
30
+ set_redirect_error_flash webauthn_login_error_flash
31
+ redirect webauthn_login_failure_redirect
32
+ end
33
+ end
34
+
35
+ def webauthn_auth_additional_form_tags
36
+ if @webauthn_login
37
+ super.to_s + login_hidden_field
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def webauthn_auth_form_path
44
+ if @webauthn_login
45
+ webauthn_login_path
46
+ else
47
+ super
48
+ end
49
+ end
50
+
51
+ def use_multi_phase_login?
52
+ true
53
+ end
54
+
55
+ private
56
+
57
+ def _multi_phase_login_forms
58
+ forms = super
59
+ if valid_login_entered? && webauthn_setup?
60
+ @webauthn_login = true
61
+ forms << [20, render('webauthn-auth'), nil]
62
+ end
63
+ forms
64
+ end
65
+
66
+ def webauthn_account_id
67
+ super || account_id
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,46 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Rodauth
4
+ Feature.define(:webauthn_verify_account, :WebauthnVerifyAccount) do
5
+ depends :verify_account, :webauthn
6
+
7
+ def verify_account_view
8
+ webauthn_setup_view
9
+ end
10
+
11
+ def create_account_set_password?
12
+ false
13
+ end
14
+
15
+ def verify_account_set_password?
16
+ false
17
+ end
18
+
19
+ def autologin_session(autologin_type)
20
+ super
21
+ if autologin_type == 'verify_account'
22
+ set_session_value(authenticated_by_session_key, ['webauthn'])
23
+ remove_session_value(autologin_type_session_key)
24
+ webauthn_update_session(@webauthn_credential.id)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def before_verify_account
31
+ super
32
+ if features.include?(:jwt) && use_jwt? && !param_or_nil(webauthn_setup_param)
33
+ cred = new_webauthn_credential
34
+ json_response[webauthn_setup_param] = cred.as_json
35
+ json_response[webauthn_setup_challenge_param] = cred.challenge
36
+ json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
37
+ end
38
+ @webauthn_credential = webauthn_setup_credential_from_form_submission
39
+ add_webauthn_credential(@webauthn_credential)
40
+ end
41
+
42
+ def webauthn_account_id
43
+ super || account_id
44
+ end
45
+ end
46
+ end
@@ -3,10 +3,10 @@
3
3
  module Rodauth
4
4
  # The major version of Rodauth, updated only for major changes that are
5
5
  # likely to require modification to apps using Rodauth.
6
- MAJOR = 1
6
+ MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 21
9
+ MINOR = 2
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
@@ -1,5 +1,3 @@
1
1
  <div class="form-group">
2
- <div class="col-sm-offset-2 col-sm-10">
3
- <input type="submit" #{"name=\"#{h opts[:name]}\"" if opts[:name]} class="#{h(opts[:class] || 'btn btn-primary')}" value="#{h value}"/>
4
- </div>
2
+ <input type="submit" #{"name=\"#{h opts[:name]}\"" if opts[:name]} class="#{h(opts[:class] || 'btn btn-primary')}" value="#{h value}"/>
5
3
  </div>
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="change-login-form">
1
+ <form method="post" class="rodauth" role="form" id="change-login-form">
2
2
  #{rodauth.change_login_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('login-field')}
@@ -6,4 +6,3 @@
6
6
  #{rodauth.render('password-field') if rodauth.change_login_requires_password?}
7
7
  #{rodauth.button(rodauth.change_login_button)}
8
8
  </form>
9
-
@@ -1,12 +1,10 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="change-password-form">
1
+ <form method="post" class="rodauth" role="form" id="change-password-form">
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
5
  <div class="form-group">
6
- <label class="col-sm-2 control-label" for="new-password">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
7
- <div class="col-sm-10">
8
- #{rodauth.input_field_string(rodauth.new_password_param, 'new-password', :type => 'password')}
9
- </div>
6
+ <label for="new-password">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
7
+ #{rodauth.input_field_string(rodauth.new_password_param, 'new-password', :type => 'password', :autocomplete=>"new-password")}
10
8
  </div>
11
9
  #{rodauth.render('password-confirm-field') if rodauth.require_password_confirmation?}
12
10
  #{rodauth.button(rodauth.change_password_button)}
@@ -1,6 +1,6 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="close-account-form">
1
+ <form method="post" class="rodauth" role="form" id="close-account-form">
2
2
  #{rodauth.close_account_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.close_account_requires_password?}
5
- #{rodauth.button(rodauth.close_account_button, :class=>'btn btn-warning')}
5
+ #{rodauth.button(rodauth.close_account_button, :class=>'btn btn-danger')}
6
6
  </form>
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="confirm-password-form">
1
+ <form method="post" class="rodauth" role="form" id="confirm-password-form">
2
2
  #{rodauth.confirm_password_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field')}
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="create-account-form">
1
+ <form method="post" class="rodauth" role="form" id="create-account-form">
2
2
  #{rodauth.create_account_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('login-field')}
@@ -1,5 +1,5 @@
1
1
  Someone has requested a login link for the account with this email
2
2
  address. If you did not request a login link, please ignore this
3
3
  message. If you requested a login link, please go to
4
- #{rodauth.email_auth_email_link}
4
+ #{rodauth.email_auth_email_link}
5
5
  to login to this account.
@@ -1,7 +1,6 @@
1
- <form action="#{rodauth.prefix}/#{rodauth.email_auth_request_route}" method="post" class="rodauth form-horizontal" role="form" id="email-auth-request-form">
1
+ <form action="#{rodauth.email_auth_request_path}" method="post" class="rodauth" role="form" id="email-auth-request-form">
2
2
  #{rodauth.email_auth_request_additional_form_tags}
3
- #{rodauth.csrf_tag("#{rodauth.prefix}/#{rodauth.email_auth_request_route}")}
3
+ #{rodauth.csrf_tag(rodauth.email_auth_request_path)}
4
4
  #{rodauth.login_hidden_field}
5
5
  #{rodauth.button(rodauth.email_auth_request_button)}
6
6
  </form>
7
-
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="email-auth-form">
1
+ <form method="post" class="rodauth" role="form" id="email-auth-form">
2
2
  #{rodauth.email_auth_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.button(rodauth.login_button)}
@@ -0,0 +1,6 @@
1
+ <div class="form-group">
2
+ <div class="form-check checkbox">
3
+ <input type="checkbox" name="#{rodauth.global_logout_param}" class="form-check-input" id="global-logout" value="t"/>
4
+ <label class="rodauth-global-logout-label form-check-label" for="global-logout">#{rodauth.global_logout_label}</label>
5
+ </div>
6
+ </div>
@@ -1,6 +1,4 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-2 control-label" for="login-confirm">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
- <div class="col-sm-10">
4
- #{rodauth.input_field_string(rodauth.login_confirm_param, 'login-confirm', :type=>rodauth.login_input_type)}
5
- </div>
2
+ <label for="login-confirm">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
+ #{rodauth.input_field_string(rodauth.login_confirm_param, 'login-confirm', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
6
4
  </div>
@@ -1,4 +1,5 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-2 control-label">#{rodauth.login_label}</label>
3
- <div class="col-sm-10">#{rodauth.login_hidden_field}#{h rodauth.param(rodauth.login_param)}</div>
2
+ #{rodauth.login_hidden_field}
3
+ <label for="login">#{rodauth.login_label}</label>
4
+ <div class="form-control-plaintext form-control-static">#{h rodauth.param(rodauth.login_param)}</div>
4
5
  </div>
@@ -1,6 +1,4 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-2 control-label" for="login">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
3
- <div class="col-sm-10">
4
- #{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type)}
5
- </div>
2
+ <label for="login">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
3
+ #{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
6
4
  </div>
@@ -0,0 +1,6 @@
1
+ #{rodauth.login_form_footer_links_heading}
2
+ <ul class="rodauth-links rodauth-login-footer-links">
3
+ #{rodauth.login_form_footer_links.sort.map do |_, link, text|
4
+ "<li><a href=\"#{h link}\">#{h text}</a></li>"
5
+ end.join("\n")}
6
+ </ul>
@@ -0,0 +1,7 @@
1
+ <form method="post" class="rodauth" role="form" id="login-form">
2
+ #{rodauth.login_additional_form_tags}
3
+ #{rodauth.csrf_tag}
4
+ #{rodauth.skip_login_field_on_login? ? rodauth.render('login-display') : rodauth.render('login-field')}
5
+ #{rodauth.render('password-field') unless rodauth.skip_password_field_on_login?}
6
+ #{rodauth.button(rodauth.login_button)}
7
+ </form>
@@ -1,11 +1,3 @@
1
1
  #{rodauth.login_form_header}
2
-
3
- <form method="post" class="rodauth form-horizontal" role="form" id="login-form">
4
- #{rodauth.login_additional_form_tags}
5
- #{rodauth.csrf_tag}
6
- #{rodauth.skip_login_field_on_login? ? rodauth.render('login-display') : rodauth.render('login-field')}
7
- #{rodauth.render('password-field') unless rodauth.skip_password_field_on_login?}
8
- #{rodauth.button(rodauth.login_button)}
9
- </form>
10
-
2
+ #{rodauth.render('login-form')}
11
3
  #{rodauth.login_form_footer}
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="logout-form">
1
+ <form method="post" class="rodauth" role="form" id="logout-form">
2
2
  #{rodauth.logout_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.button(rodauth.logout_button, :class=>'btn btn-warning')}
@@ -0,0 +1,3 @@
1
+ #{rodauth.login_form_header}
2
+ #{rodauth.render_multi_phase_login_forms}
3
+ #{rodauth.login_form_footer}
@@ -1,6 +1,8 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-4 control-label" for="otp-auth-code">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
3
- <div class="col-sm-3">
4
- #{rodauth.input_field_string(rodauth.otp_auth_param, 'otp-auth-code', :value=>'', :attr=>'autocomplete="off"' )}
2
+ <label for="otp-auth-code">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
3
+ <div class="row">
4
+ <div class="col-sm-3">
5
+ #{rodauth.input_field_string(rodauth.otp_auth_param, 'otp-auth-code', :value=>'', :autocomplete=>"off", :inputmode=>'numeric')}
6
+ </div>
5
7
  </div>
6
8
  </div>
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="otp-auth-form">
1
+ <form method="post" class="rodauth" role="form" id="otp-auth-form">
2
2
  #{rodauth.otp_auth_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('otp-auth-code-field')}
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="otp-disable-form">
1
+ <form method="post" class="rodauth" role="form" id="otp-disable-form">
2
2
  #{rodauth.otp_disable_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="otp-setup-form">
1
+ <form method="post" class="rodauth" role="form" id="otp-setup-form">
2
2
  #{rodauth.otp_setup_additional_form_tags}
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?}
@@ -9,13 +9,13 @@
9
9
  </div>
10
10
 
11
11
  <div class="row">
12
- <div class="col-sm-6 col-sm">
12
+ <div class="col-lg-6 col-lg">
13
13
  <div class="form-group">
14
14
  <p>#{rodauth.otp_qr_code}</p>
15
15
  </div>
16
16
  </div>
17
17
 
18
- <div class="col-sm-6 col-sm">
18
+ <div class="col-lg-6 col-lg">
19
19
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
20
20
  #{rodauth.render('otp-auth-code-field')}
21
21
  #{rodauth.button(rodauth.otp_setup_button)}
@@ -1,6 +1,4 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-2 control-label" for="password-confirm">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
- <div class="col-sm-10">
4
- #{rodauth.input_field_string(rodauth.password_confirm_param, 'password-confirm', :type => 'password')}
5
- </div>
2
+ <label for="password-confirm">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
3
+ #{rodauth.input_field_string(rodauth.password_confirm_param, 'password-confirm', :type => 'password', :autocomplete=>'new-password')}
6
4
  </div>
@@ -1,6 +1,4 @@
1
1
  <div class="form-group">
2
- <label class="col-sm-2 control-label" for="password">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
3
- <div class="col-sm-10">
4
- #{rodauth.input_field_string(rodauth.password_param, 'password', :type => 'password')}
5
- </div>
2
+ <label for="password">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
3
+ #{rodauth.input_field_string(rodauth.password_param, 'password', :type => 'password', :autocomplete=>rodauth.password_field_autocomplete_value)}
6
4
  </div>
@@ -1,12 +1,9 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="recovery-auth-form">
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
4
  <div class="form-group">
5
- <label class="col-sm-2 control-label" for="recovery_code">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
6
- <div class="col-sm-10">
7
- #{rodauth.input_field_string(rodauth.recovery_codes_param, 'recovery_code', :value => '')}
8
- </div>
5
+ <label for="recovery-code">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
6
+ #{rodauth.input_field_string(rodauth.recovery_codes_param, 'recovery-code', :value => '', :autocomplete=>'off')}
9
7
  </div>
10
8
  #{rodauth.button(rodauth.recovery_auth_button)}
11
9
  </form>
12
-
@@ -1,4 +1,4 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="recovery-codes-form">
1
+ <form method="post" class="rodauth" role="form" id="recovery-codes-form">
2
2
  #{rodauth.recovery_codes_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
4
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
@@ -1,24 +1,19 @@
1
- <form method="post" class="rodauth form-horizontal" role="form" id="remember-form">
1
+ <form method="post" class="rodauth" role="form" id="remember-form">
2
2
  #{rodauth.remember_additional_form_tags}
3
3
  #{rodauth.csrf_tag}
4
- <div class="radio">
5
- <label>
6
- <input type="radio" name="#{rodauth.remember_param}" id="remember_remember" value="#{rodauth.remember_remember_param_value}"/>
7
- #{rodauth.remember_remember_label}
8
- </label>
9
- </div>
10
- <div class="radio">
11
- <label>
12
- <input type="radio" name="#{rodauth.remember_param}" id="remember_forget" value="#{rodauth.remember_forget_param_value}"/>
13
- #{rodauth.remember_forget_label}
14
- </label>
15
- </div>
16
- <div class="radio">
17
- <label>
18
- <input type="radio" name="#{rodauth.remember_param}" id="remember_disable" value="#{rodauth.remember_disable_param_value}"/>
19
- #{rodauth.remember_disable_label}
20
- </label>
21
- </div>
4
+ <fieldset class="form-group">
5
+ <div class="form-check radio">
6
+ <input type="radio" name="#{rodauth.remember_param}" id="remember-remember" value="#{h rodauth.remember_remember_param_value}" class="form-check-input"/>
7
+ <label class="form-check-label" for="remember-remember">#{rodauth.remember_remember_label}</label>
8
+ </div>
9
+ <div class="form-check radio">
10
+ <input type="radio" name="#{rodauth.remember_param}" id="remember-forget" value="#{h rodauth.remember_forget_param_value}" class="form-check-input"/>
11
+ <label class="form-check-label" for="remember-forget">#{rodauth.remember_forget_label}</label>
12
+ </div>
13
+ <div class="form-check radio">
14
+ <input type="radio" name="#{rodauth.remember_param}" id="remember-disable" value="#{h rodauth.remember_disable_param_value}" class="form-check-input"/>
15
+ <label class="form-check-label" for="remember-disable">#{rodauth.remember_disable_label}</label>
16
+ </div>
17
+ </fieldset>
22
18
  #{rodauth.button(rodauth.remember_button)}
23
19
  </form>
24
-
@@ -1,5 +1,5 @@
1
1
  Someone has requested a password reset for the account with this email
2
2
  address. If you did not request a password reset, please ignore this
3
3
  message. If you requested a password reset, please go to
4
- #{rodauth.reset_password_email_link}
4
+ #{rodauth.reset_password_email_link}
5
5
  to reset the password for the account.
@@ -1,7 +1,7 @@
1
- <form action="#{rodauth.prefix}/#{rodauth.reset_password_request_route}" method="post" class="rodauth form-horizontal" role="form" id="reset-password-request-form">
1
+ <form action="#{rodauth.reset_password_request_path}" method="post" class="rodauth" role="form" id="reset-password-request-form">
2
2
  #{rodauth.reset_password_request_additional_form_tags}
3
- #{rodauth.csrf_tag("#{rodauth.prefix}/#{rodauth.reset_password_request_route}")}
3
+ #{rodauth.csrf_tag(rodauth.reset_password_request_path)}
4
4
  #{rodauth.reset_password_explanatory_text}
5
- #{(login = rodauth.param_or_nil(rodauth.login_param)) ? "<input type=\"hidden\" name=\"#{rodauth.login_param}\" value=\"#{h login}\"/>" : rodauth.render('login-field')}
5
+ #{rodauth.param_or_nil(rodauth.login_param) && !rodauth.field_error(rodauth.login_param) ? rodauth.login_hidden_field : rodauth.render('login-field')}
6
6
  #{rodauth.button(rodauth.reset_password_request_button)}
7
7
  </form>