rodauth 1.22.0 → 2.3.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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +190 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +210 -80
  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 +2 -3
  42. data/doc/jwt_refresh.rdoc +23 -8
  43. data/doc/lockout.rdoc +17 -15
  44. data/doc/login.rdoc +17 -2
  45. data/doc/login_password_requirements_base.rdoc +18 -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.23.0.txt +32 -0
  53. data/doc/release_notes/2.0.0.txt +361 -0
  54. data/doc/release_notes/2.1.0.txt +31 -0
  55. data/doc/release_notes/2.2.0.txt +39 -0
  56. data/doc/release_notes/2.3.0.txt +37 -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/close_account.rb +8 -6
  79. data/lib/rodauth/features/confirm_password.rb +40 -2
  80. data/lib/rodauth/features/create_account.rb +8 -13
  81. data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
  82. data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
  83. data/lib/rodauth/features/email_auth.rb +31 -30
  84. data/lib/rodauth/features/email_base.rb +9 -4
  85. data/lib/rodauth/features/http_basic_auth.rb +55 -35
  86. data/lib/rodauth/features/jwt.rb +63 -16
  87. data/lib/rodauth/features/jwt_cors.rb +15 -15
  88. data/lib/rodauth/features/jwt_refresh.rb +42 -13
  89. data/lib/rodauth/features/lockout.rb +12 -14
  90. data/lib/rodauth/features/login.rb +64 -15
  91. data/lib/rodauth/features/login_password_requirements_base.rb +13 -8
  92. data/lib/rodauth/features/otp.rb +77 -80
  93. data/lib/rodauth/features/password_complexity.rb +8 -13
  94. data/lib/rodauth/features/password_expiration.rb +2 -2
  95. data/lib/rodauth/features/password_grace_period.rb +17 -10
  96. data/lib/rodauth/features/recovery_codes.rb +49 -53
  97. data/lib/rodauth/features/remember.rb +11 -27
  98. data/lib/rodauth/features/reset_password.rb +26 -26
  99. data/lib/rodauth/features/session_expiration.rb +7 -10
  100. data/lib/rodauth/features/single_session.rb +8 -6
  101. data/lib/rodauth/features/sms_codes.rb +62 -72
  102. data/lib/rodauth/features/two_factor_base.rb +134 -30
  103. data/lib/rodauth/features/verify_account.rb +29 -21
  104. data/lib/rodauth/features/verify_account_grace_period.rb +18 -9
  105. data/lib/rodauth/features/verify_login_change.rb +12 -11
  106. data/lib/rodauth/features/webauthn.rb +505 -0
  107. data/lib/rodauth/features/webauthn_login.rb +70 -0
  108. data/lib/rodauth/features/webauthn_verify_account.rb +46 -0
  109. data/lib/rodauth/migrations.rb +16 -5
  110. data/lib/rodauth/version.rb +2 -2
  111. data/templates/button.str +1 -3
  112. data/templates/change-login.str +1 -2
  113. data/templates/change-password.str +3 -5
  114. data/templates/close-account.str +2 -2
  115. data/templates/confirm-password.str +1 -1
  116. data/templates/create-account.str +1 -1
  117. data/templates/email-auth-request-form.str +2 -3
  118. data/templates/email-auth.str +1 -1
  119. data/templates/global-logout-field.str +6 -0
  120. data/templates/login-confirm-field.str +2 -4
  121. data/templates/login-display.str +3 -2
  122. data/templates/login-field.str +2 -4
  123. data/templates/login-form-footer.str +6 -0
  124. data/templates/login-form.str +7 -0
  125. data/templates/login.str +1 -9
  126. data/templates/logout.str +1 -1
  127. data/templates/multi-phase-login.str +3 -0
  128. data/templates/otp-auth-code-field.str +5 -3
  129. data/templates/otp-auth.str +1 -1
  130. data/templates/otp-disable.str +1 -1
  131. data/templates/otp-setup.str +3 -3
  132. data/templates/password-confirm-field.str +2 -4
  133. data/templates/password-field.str +2 -4
  134. data/templates/recovery-auth.str +3 -6
  135. data/templates/recovery-codes.str +1 -1
  136. data/templates/remember.str +15 -20
  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-request.str +4 -4
  149. data/templates/unlock-account.str +1 -1
  150. data/templates/verify-account-resend.str +3 -3
  151. data/templates/verify-account.str +1 -2
  152. data/templates/verify-login-change.str +1 -1
  153. data/templates/webauthn-auth.str +11 -0
  154. data/templates/webauthn-remove.str +14 -0
  155. data/templates/webauthn-setup.str +12 -0
  156. metadata +94 -54
  157. data/Rakefile +0 -179
  158. data/doc/verify_change_login.rdoc +0 -11
  159. data/lib/rodauth/features/verify_change_login.rb +0 -20
  160. data/spec/account_expiration_spec.rb +0 -225
  161. data/spec/all.rb +0 -1
  162. data/spec/change_login_spec.rb +0 -156
  163. data/spec/change_password_notify_spec.rb +0 -33
  164. data/spec/change_password_spec.rb +0 -202
  165. data/spec/close_account_spec.rb +0 -162
  166. data/spec/confirm_password_spec.rb +0 -70
  167. data/spec/create_account_spec.rb +0 -127
  168. data/spec/disallow_common_passwords_spec.rb +0 -93
  169. data/spec/disallow_password_reuse_spec.rb +0 -179
  170. data/spec/email_auth_spec.rb +0 -285
  171. data/spec/http_basic_auth_spec.rb +0 -143
  172. data/spec/jwt_cors_spec.rb +0 -57
  173. data/spec/jwt_refresh_spec.rb +0 -256
  174. data/spec/jwt_spec.rb +0 -235
  175. data/spec/lockout_spec.rb +0 -250
  176. data/spec/login_spec.rb +0 -328
  177. data/spec/migrate/001_tables.rb +0 -184
  178. data/spec/migrate/002_account_password_hash_column.rb +0 -11
  179. data/spec/migrate_password/001_tables.rb +0 -73
  180. data/spec/migrate_travis/001_tables.rb +0 -141
  181. data/spec/password_complexity_spec.rb +0 -109
  182. data/spec/password_expiration_spec.rb +0 -244
  183. data/spec/password_grace_period_spec.rb +0 -93
  184. data/spec/remember_spec.rb +0 -451
  185. data/spec/reset_password_spec.rb +0 -229
  186. data/spec/rodauth_spec.rb +0 -343
  187. data/spec/session_expiration_spec.rb +0 -58
  188. data/spec/single_session_spec.rb +0 -127
  189. data/spec/spec_helper.rb +0 -327
  190. data/spec/two_factor_spec.rb +0 -1462
  191. data/spec/update_password_hash_spec.rb +0 -40
  192. data/spec/verify_account_grace_period_spec.rb +0 -171
  193. data/spec/verify_account_spec.rb +0 -240
  194. data/spec/verify_change_login_spec.rb +0 -46
  195. data/spec/verify_login_change_spec.rb +0 -232
  196. data/spec/views/layout-other.str +0 -11
  197. data/spec/views/layout.str +0 -11
  198. data/spec/views/login.str +0 -21
@@ -1,46 +0,0 @@
1
- require File.expand_path("spec_helper", File.dirname(__FILE__))
2
-
3
- describe 'Rodauth verify_change_login feature' do
4
- it "should support reverifying accounts after changing logins" do
5
- rodauth do
6
- enable :login, :verify_change_login
7
- change_login_requires_password? false
8
- end
9
- roda do |r|
10
- r.rodauth
11
- r.root{view :content=>rodauth.logged_in? ? "Logged In#{rodauth.verified_account?}" : "Not Logged"}
12
- end
13
-
14
- visit '/create-account'
15
- fill_in 'Login', :with=>'foo@example2.com'
16
- fill_in 'Confirm Login', :with=>'foo@example2.com'
17
- fill_in 'Password', :with=>'0123456789'
18
- fill_in 'Confirm Password', :with=>'0123456789'
19
- click_button 'Create Account'
20
- link = email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com')
21
-
22
- visit '/change-login'
23
- page.find('#error_flash').text.must_equal "Cannot change login for unverified account. Please verify this account before changing the login."
24
- page.current_path.must_equal '/'
25
-
26
- visit link
27
- click_button 'Verify Account'
28
- page.find('#notice_flash').text.must_equal "Your account has been verified"
29
- page.body.must_include('Logged Intrue')
30
-
31
- visit '/change-login'
32
- fill_in 'Login', :with=>'foo3@example.com'
33
- fill_in 'Confirm Login', :with=>'foo3@example.com'
34
- click_button 'Change Login'
35
- page.find('#notice_flash').text.must_equal "Your login has been changed. An email has been sent to you with a link to verify your account"
36
- page.current_path.must_equal '/'
37
- page.body.must_include('Logged Infalse')
38
- link2 = email_link(/(\/verify-account\?key=.+)$/, 'foo3@example.com')
39
- link2.wont_equal link
40
-
41
- visit link2
42
- click_button 'Verify Account'
43
- page.find('#notice_flash').text.must_equal "Your account has been verified"
44
- page.body.must_include('Logged Intrue')
45
- end
46
- end
@@ -1,232 +0,0 @@
1
- require File.expand_path("spec_helper", File.dirname(__FILE__))
2
-
3
- describe 'Rodauth verify_login_change feature' do
4
- it "should support verifying login changes" do
5
- rodauth do
6
- enable :login, :logout, :verify_login_change
7
- change_login_requires_password? false
8
- end
9
- roda do |r|
10
- r.rodauth
11
- r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
12
- end
13
-
14
- login
15
-
16
- visit '/change-login'
17
- fill_in 'Login', :with=>'foo@example2.com'
18
- fill_in 'Confirm Login', :with=>'foo@example2.com'
19
- click_button 'Change Login'
20
- link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
21
- page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your login change"
22
-
23
- visit '/change-login'
24
- fill_in 'Login', :with=>'foo@example2.com'
25
- fill_in 'Confirm Login', :with=>'foo@example2.com'
26
- click_button 'Change Login'
27
- email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com').must_equal link
28
-
29
- visit '/change-login'
30
- fill_in 'Login', :with=>'foo@example3.com'
31
- fill_in 'Confirm Login', :with=>'foo@example3.com'
32
- click_button 'Change Login'
33
- new_link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example3.com')
34
- new_link.wont_equal link
35
-
36
- logout
37
-
38
- visit link
39
- page.find('#error_flash').text.must_equal "There was an error verifying your login change: invalid verify login change key"
40
-
41
- visit new_link
42
- page.title.must_equal 'Verify Login Change'
43
- click_button 'Verify Login Change'
44
- page.find('#notice_flash').text.must_equal "Your login change has been verified"
45
- page.body.must_include('Not Logged')
46
-
47
- login
48
- page.find('#error_flash').text.must_equal "There was an error logging in"
49
-
50
- login(:login=>'foo@example3.com')
51
- page.body.must_include('Logged In')
52
- end
53
-
54
- it "should support verifying login changes with autologin" do
55
- rodauth do
56
- enable :login, :logout, :verify_login_change
57
- verify_login_change_autologin? true
58
- change_login_requires_password? false
59
- end
60
- roda do |r|
61
- r.rodauth
62
- r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
63
- end
64
-
65
- login
66
-
67
- visit '/change-login'
68
- fill_in 'Login', :with=>'foo@example2.com'
69
- fill_in 'Confirm Login', :with=>'foo@example2.com'
70
- click_button 'Change Login'
71
- link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
72
-
73
- logout
74
-
75
- visit link
76
- click_button 'Verify Login Change'
77
- page.find('#notice_flash').text.must_equal "Your login change has been verified"
78
- page.body.must_include('Logged In')
79
- end
80
-
81
- it "should check for duplicate accounts before sending verify email and before updating login" do
82
- rodauth do
83
- enable :login, :logout, :verify_login_change, :create_account
84
- change_login_requires_password? false
85
- create_account_autologin? false
86
- end
87
- roda do |r|
88
- r.rodauth
89
- r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
90
- end
91
-
92
- visit '/create-account'
93
- fill_in 'Login', :with=>'foo@example2.com'
94
- fill_in 'Confirm Login', :with=>'foo@example2.com'
95
- fill_in 'Password', :with=>'0123456789'
96
- fill_in 'Confirm Password', :with=>'0123456789'
97
- click_button 'Create Account'
98
-
99
- login
100
-
101
- visit '/change-login'
102
- fill_in 'Login', :with=>'foo@example2.com'
103
- fill_in 'Confirm Login', :with=>'foo@example.com'
104
- click_button 'Change Login'
105
- page.find('#error_flash').text.must_equal "There was an error changing your login"
106
- page.body.must_include "logins do not match"
107
-
108
- visit '/change-login'
109
- fill_in 'Login', :with=>'foo@example2.com'
110
- fill_in 'Confirm Login', :with=>'foo@example2.com'
111
- click_button 'Change Login'
112
- page.find('#error_flash').text.must_equal "There was an error changing your login"
113
- page.body.must_include "invalid login, already an account with this login"
114
-
115
- visit '/change-login'
116
- fill_in 'Login', :with=>'foo@example3.com'
117
- fill_in 'Confirm Login', :with=>'foo@example3.com'
118
- click_button 'Change Login'
119
- link = email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example3.com')
120
-
121
- logout
122
-
123
- DB[:accounts].where(:email=>'foo@example2.com').update(:email=>'foo@example3.com')
124
-
125
- visit link
126
- click_button 'Verify Login Change'
127
- page.find('#error_flash').text.must_equal "Unable to change login as there is already an account with the new login"
128
- page.current_path.must_equal '/login'
129
-
130
- visit link
131
- page.find('#error_flash').text.must_equal "There was an error verifying your login change: invalid verify login change key"
132
- end
133
-
134
- it "should handle uniqueness errors raised when inserting verify login change entry" do
135
- unique = false
136
- rodauth do
137
- enable :login, :logout, :verify_login_change
138
- change_login_requires_password? false
139
-
140
- auth_class_eval do
141
- define_method(:raised_uniqueness_violation) do |*a, &block|
142
- unique.call if unique
143
- super(*a, &block)
144
- end
145
- end
146
- end
147
- roda do |r|
148
- r.rodauth
149
- r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
150
- end
151
-
152
- login
153
-
154
- visit '/change-login'
155
- fill_in 'Login', :with=>'foo@example2.com'
156
- fill_in 'Confirm Login', :with=>'foo@example2.com'
157
- click_button 'Change Login'
158
- email_link(/(\/verify-login-change\?key=.+)$/, 'foo@example2.com')
159
- page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your login change"
160
-
161
- unique = lambda{DB[:account_login_change_keys].update(:login=>'foo@example3.com'); true}
162
- visit '/change-login'
163
- fill_in 'Login', :with=>'foo@example2.com'
164
- fill_in 'Confirm Login', :with=>'foo@example2.com'
165
- proc{click_button 'Change Login'}.must_raise Sequel::ConstraintViolation
166
- end
167
-
168
- it "should clear verify login change token when closing account" do
169
- rodauth do
170
- enable :login, :verify_login_change, :close_account
171
- change_login_requires_password? false
172
- end
173
- roda do |r|
174
- r.rodauth
175
- r.root{view :content=>rodauth.logged_in? ? "Logged In" : "Not Logged"}
176
- end
177
-
178
- login
179
-
180
- visit '/change-login'
181
- fill_in 'Login', :with=>'foo@example2.com'
182
- fill_in 'Confirm Login', :with=>'foo@example2.com'
183
- click_button 'Change Login'
184
- email_link(/key=.+$/, 'foo@example2.com').wont_be_nil
185
-
186
- DB[:account_login_change_keys].count.must_equal 1
187
- visit '/close-account'
188
- fill_in 'Password', :with=>'0123456789'
189
- click_button 'Close Account'
190
- DB[:account_login_change_keys].count.must_equal 0
191
- end
192
-
193
- it "should support verifying login changes for accounts via jwt" do
194
- rodauth do
195
- enable :login, :verify_login_change
196
- change_login_requires_password? false
197
- verify_login_change_email_body{verify_login_change_email_link}
198
- end
199
- roda(:jwt) do |r|
200
- r.rodauth
201
- end
202
-
203
- json_login
204
-
205
- res = json_request('/change-login', :login=>'foo2@example.com', "login-confirm"=>'foo2@example.com')
206
- res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
207
- link = email_link(/key=.+$/, 'foo2@example.com')
208
-
209
- res = json_request('/change-login', :login=>'foo2@example.com', "login-confirm"=>'foo2@example.com')
210
- res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
211
- email_link(/key=.+$/, 'foo2@example.com').must_equal link
212
-
213
- res = json_request('/change-login', :login=>'foo3@example.com', "login-confirm"=>'foo3@example.com')
214
- res.must_equal [200, {'success'=>"An email has been sent to you with a link to verify your login change"}]
215
- new_link = email_link(/key=.+$/, 'foo3@example.com')
216
- new_link.wont_equal link
217
-
218
- res = json_request('/verify-login-change')
219
- res.must_equal [401, {"error"=>"Unable to verify login change"}]
220
-
221
- res = json_request('/verify-login-change', :key=>link[4..-1])
222
- res.must_equal [401, {"error"=>"Unable to verify login change"}]
223
-
224
- res = json_request('/verify-login-change', :key=>new_link[4..-1])
225
- res.must_equal [200, {"success"=>"Your login change has been verified"}]
226
-
227
- res = json_request("/login", :login=>'foo@example.com', :password=>'0123456789')
228
- res.must_equal [401, {'error'=>"There was an error logging in", "field-error"=>["login", "no matching login"]}]
229
-
230
- json_login(:login=>'foo3@example.com')
231
- end
232
- end
@@ -1,11 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>Foo #{@title}</title>
5
- </head>
6
- <body>
7
- #{"<div id='error_flash'>#{flash['error2']}</div>" if flash['error2']}
8
- #{"<div id='notice_flash'>#{flash['notice2']}</div>" if flash['notice2']}
9
- #{yield}
10
- </body>
11
- </html>
@@ -1,11 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <title>#{@title}</title>
5
- </head>
6
- <body>
7
- #{"<div id='error_flash'>#{opts[:sessions_convert_symbols] ? flash['error'] : flash[:error]}</div>" if opts[:sessions_convert_symbols] ? flash['error'] : flash[:error]}
8
- #{"<div id='notice_flash'>#{opts[:sessions_convert_symbols] ? flash['notice'] : flash[:notice]}</div>" if opts[:sessions_convert_symbols] ? flash['notice'] : flash[:notice]}
9
- #{yield}
10
- </body>
11
- </html>
@@ -1,21 +0,0 @@
1
- <form method="post" class="form-horizontal" role="form" id="login-form">
2
- #{csrf_tag if respond_to?(:csrf_tag)}
3
- <input type="hidden" name="lp" value="#{rodauth.param('lp')}"/>
4
- <div class="form-group">
5
- <label class="col-sm-2 control-label" for="login">Login</label>
6
- <div class="col-sm-10">
7
- <input type="text" class="form-control#{' error' if rodauth.field_error(rodauth.login_param)}" name="l" id="login"/> #{rodauth.field_error(rodauth.login_param)}
8
- </div>
9
- </div>
10
- <div class="form-group">
11
- <label class="col-sm-2 control-label" for="password">Password</label>
12
- <div class="col-sm-10">
13
- <input type="password" class="form-control#{' error' if rodauth.field_error(rodauth.password_param)}" name="p" id="password"/> #{rodauth.field_error(rodauth.password_param)}
14
- </div>
15
- </div>
16
- <div class="form-group">
17
- <div class="col-sm-offset-2 col-sm-10">
18
- <input type="submit" class="btn btn-default" value="Login"/>
19
- </div>
20
- </div>
21
- </form>