rodauth 1.22.0 → 1.23.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.
- checksums.yaml +4 -4
- data/CHANGELOG +12 -0
- data/README.rdoc +5 -3
- data/doc/email_base.rdoc +1 -0
- data/doc/release_notes/1.23.0.txt +32 -0
- data/lib/rodauth.rb +5 -2
- data/lib/rodauth/features/base.rb +8 -0
- data/lib/rodauth/features/change_password_notify.rb +1 -1
- data/lib/rodauth/features/create_account.rb +1 -1
- data/lib/rodauth/features/email_auth.rb +3 -4
- data/lib/rodauth/features/email_base.rb +7 -2
- data/lib/rodauth/features/lockout.rb +1 -1
- data/lib/rodauth/features/login.rb +6 -2
- data/lib/rodauth/features/otp.rb +6 -3
- data/lib/rodauth/features/password_expiration.rb +1 -1
- data/lib/rodauth/features/recovery_codes.rb +3 -3
- data/lib/rodauth/features/reset_password.rb +2 -2
- data/lib/rodauth/features/sms_codes.rb +5 -5
- data/lib/rodauth/features/verify_account.rb +2 -2
- data/lib/rodauth/features/verify_login_change.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/templates/email-auth-request-form.str +2 -2
- data/templates/reset-password-request.str +3 -3
- data/templates/unlock-account-request.str +3 -3
- data/templates/verify-account-resend.str +3 -3
- metadata +5 -43
- data/Rakefile +0 -179
- data/spec/account_expiration_spec.rb +0 -225
- data/spec/all.rb +0 -1
- data/spec/change_login_spec.rb +0 -156
- data/spec/change_password_notify_spec.rb +0 -33
- data/spec/change_password_spec.rb +0 -202
- data/spec/close_account_spec.rb +0 -162
- data/spec/confirm_password_spec.rb +0 -70
- data/spec/create_account_spec.rb +0 -127
- data/spec/disallow_common_passwords_spec.rb +0 -93
- data/spec/disallow_password_reuse_spec.rb +0 -179
- data/spec/email_auth_spec.rb +0 -285
- data/spec/http_basic_auth_spec.rb +0 -143
- data/spec/jwt_cors_spec.rb +0 -57
- data/spec/jwt_refresh_spec.rb +0 -256
- data/spec/jwt_spec.rb +0 -235
- data/spec/lockout_spec.rb +0 -250
- data/spec/login_spec.rb +0 -328
- data/spec/migrate/001_tables.rb +0 -184
- data/spec/migrate/002_account_password_hash_column.rb +0 -11
- data/spec/migrate_password/001_tables.rb +0 -73
- data/spec/migrate_travis/001_tables.rb +0 -141
- data/spec/password_complexity_spec.rb +0 -109
- data/spec/password_expiration_spec.rb +0 -244
- data/spec/password_grace_period_spec.rb +0 -93
- data/spec/remember_spec.rb +0 -451
- data/spec/reset_password_spec.rb +0 -229
- data/spec/rodauth_spec.rb +0 -343
- data/spec/session_expiration_spec.rb +0 -58
- data/spec/single_session_spec.rb +0 -127
- data/spec/spec_helper.rb +0 -327
- data/spec/two_factor_spec.rb +0 -1462
- data/spec/update_password_hash_spec.rb +0 -40
- data/spec/verify_account_grace_period_spec.rb +0 -171
- data/spec/verify_account_spec.rb +0 -240
- data/spec/verify_change_login_spec.rb +0 -46
- data/spec/verify_login_change_spec.rb +0 -232
- data/spec/views/layout-other.str +0 -11
- data/spec/views/layout.str +0 -11
- data/spec/views/login.str +0 -21
data/spec/login_spec.rb
DELETED
@@ -1,328 +0,0 @@
|
|
1
|
-
require File.expand_path("spec_helper", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
describe 'Rodauth login feature' do
|
4
|
-
it "should handle logins and logouts" do
|
5
|
-
rodauth{enable :login, :logout}
|
6
|
-
roda do |r|
|
7
|
-
r.rodauth
|
8
|
-
next unless rodauth.logged_in?
|
9
|
-
r.root{view :content=>"Logged In"}
|
10
|
-
end
|
11
|
-
|
12
|
-
visit '/login'
|
13
|
-
page.title.must_equal 'Login'
|
14
|
-
|
15
|
-
login(:login=>'foo@example2.com', :visit=>false)
|
16
|
-
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
17
|
-
page.html.must_include("no matching login")
|
18
|
-
page.all('[type=text]').first.value.must_equal 'foo@example2.com'
|
19
|
-
|
20
|
-
login(:pass=>'012345678', :visit=>false)
|
21
|
-
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
22
|
-
page.html.must_include("invalid password")
|
23
|
-
|
24
|
-
fill_in 'Password', :with=>'0123456789'
|
25
|
-
click_button 'Login'
|
26
|
-
page.current_path.must_equal '/'
|
27
|
-
page.find('#notice_flash').text.must_equal 'You have been logged in'
|
28
|
-
page.html.must_include("Logged In")
|
29
|
-
|
30
|
-
visit '/logout'
|
31
|
-
page.title.must_equal 'Logout'
|
32
|
-
|
33
|
-
click_button 'Logout'
|
34
|
-
page.find('#notice_flash').text.must_equal 'You have been logged out'
|
35
|
-
page.current_path.must_equal '/login'
|
36
|
-
end
|
37
|
-
|
38
|
-
it "should handle multi phase login (email first, then password)" do
|
39
|
-
rodauth do
|
40
|
-
enable :login, :logout
|
41
|
-
use_multi_phase_login? true
|
42
|
-
login_input_type 'email'
|
43
|
-
input_field_label_suffix ' (Required)'
|
44
|
-
input_field_error_class ' bad-input'
|
45
|
-
input_field_error_message_class 'err-msg'
|
46
|
-
mark_input_fields_as_required? true
|
47
|
-
field_attributes do |field|
|
48
|
-
if field == 'login'
|
49
|
-
'custom_field="custom_value"'
|
50
|
-
else
|
51
|
-
super(field)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
field_error_attributes do |field|
|
55
|
-
if field == 'login'
|
56
|
-
'custom_error_field="custom_error_value"'
|
57
|
-
else
|
58
|
-
super(field)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
formatted_field_error do |field, error|
|
62
|
-
if field == 'login'
|
63
|
-
super(field, error)
|
64
|
-
else
|
65
|
-
"<span class='err-msg2'>1#{error}2</span>"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
roda do |r|
|
70
|
-
r.rodauth
|
71
|
-
next unless rodauth.logged_in?
|
72
|
-
r.root{view :content=>"Logged In"}
|
73
|
-
end
|
74
|
-
|
75
|
-
visit '/login'
|
76
|
-
page.title.must_equal 'Login'
|
77
|
-
|
78
|
-
page.find('[custom_field=custom_value]').value.must_equal ''
|
79
|
-
page.all('[custom_error_field=custom_error_value]').must_be_empty
|
80
|
-
page.all('input[type=password]').must_be_empty
|
81
|
-
fill_in 'Login (Required)', :with=>'foo2@example.com'
|
82
|
-
click_button 'Login'
|
83
|
-
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
84
|
-
page.find('[custom_field=custom_value]').value.must_equal 'foo2@example.com'
|
85
|
-
page.find('[custom_error_field=custom_error_value]').value.must_equal 'foo2@example.com'
|
86
|
-
page.find('[type=email]').value.must_equal 'foo2@example.com'
|
87
|
-
page.find('.bad-input').value.must_equal 'foo2@example.com'
|
88
|
-
page.find('.err-msg').text.must_equal 'no matching login'
|
89
|
-
|
90
|
-
page.all('input[type=password]').must_be_empty
|
91
|
-
fill_in 'Login (Required)', :with=>'foo@example.com'
|
92
|
-
click_button 'Login'
|
93
|
-
page.find('#notice_flash').text.must_equal 'Login recognized, please enter your password'
|
94
|
-
|
95
|
-
page.all('[custom_field=custom_value]').must_be_empty
|
96
|
-
page.all('[custom_error_field=custom_error_value]').must_be_empty
|
97
|
-
page.all('[aria-invalid=true]').must_be_empty
|
98
|
-
page.all('[aria-describedby]').must_be_empty
|
99
|
-
page.find('[required=required]').value.to_s.must_equal ''
|
100
|
-
page.all('input[type=text]').must_be_empty
|
101
|
-
fill_in 'Password (Required)', :with=>'012345678'
|
102
|
-
click_button 'Login'
|
103
|
-
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
104
|
-
page.find('[aria-invalid=true]').value.to_s.must_equal ''
|
105
|
-
page.find('[aria-describedby=password_error_message]').value.to_s.must_equal ''
|
106
|
-
page.all('[custom_error_field=custom_error_value]').must_be_empty
|
107
|
-
page.find('.err-msg2').text.must_equal '1invalid password2'
|
108
|
-
|
109
|
-
page.all('input[type=text]').must_be_empty
|
110
|
-
fill_in 'Password (Required)', :with=>'0123456789'
|
111
|
-
click_button 'Login'
|
112
|
-
page.current_path.must_equal '/'
|
113
|
-
page.find('#notice_flash').text.must_equal 'You have been logged in'
|
114
|
-
page.html.must_include("Logged In")
|
115
|
-
|
116
|
-
visit '/logout'
|
117
|
-
page.title.must_equal 'Logout'
|
118
|
-
|
119
|
-
click_button 'Logout'
|
120
|
-
page.find('#notice_flash').text.must_equal 'You have been logged out'
|
121
|
-
page.current_path.must_equal '/login'
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should not allow login to unverified account" do
|
125
|
-
rodauth do
|
126
|
-
enable :login
|
127
|
-
skip_status_checks? false
|
128
|
-
end
|
129
|
-
roda do |r|
|
130
|
-
r.rodauth
|
131
|
-
next unless rodauth.logged_in?
|
132
|
-
r.root{view :content=>"Logged In"}
|
133
|
-
end
|
134
|
-
|
135
|
-
DB[:accounts].update(:status_id=>1)
|
136
|
-
login
|
137
|
-
page.find('#error_flash').text.must_equal 'There was an error logging in'
|
138
|
-
page.html.must_include("unverified account, please verify account before logging in")
|
139
|
-
end
|
140
|
-
|
141
|
-
it "should handle overriding login action" do
|
142
|
-
rodauth do
|
143
|
-
enable :login
|
144
|
-
end
|
145
|
-
roda do |r|
|
146
|
-
r.post 'login' do
|
147
|
-
if r.params['login'] == 'apple' && r.params['password'] == 'banana'
|
148
|
-
session['user_id'] = 'pear'
|
149
|
-
r.redirect '/'
|
150
|
-
end
|
151
|
-
r.redirect '/login'
|
152
|
-
end
|
153
|
-
r.rodauth
|
154
|
-
next unless session['user_id'] == 'pear'
|
155
|
-
r.root{"Logged In"}
|
156
|
-
end
|
157
|
-
|
158
|
-
login(:login=>'appl', :pass=>'banana')
|
159
|
-
page.html.wont_match(/Logged In/)
|
160
|
-
|
161
|
-
login(:login=>'apple', :pass=>'banan', :visit=>false)
|
162
|
-
page.html.wont_match(/Logged In/)
|
163
|
-
|
164
|
-
login(:login=>'apple', :pass=>'banana', :visit=>false)
|
165
|
-
page.current_path.must_equal '/'
|
166
|
-
page.html.must_include("Logged In")
|
167
|
-
end
|
168
|
-
|
169
|
-
it "should handle overriding some login attributes" do
|
170
|
-
rodauth do
|
171
|
-
enable :login
|
172
|
-
account_from_login do |login|
|
173
|
-
DB[:accounts].first if login == 'apple'
|
174
|
-
end
|
175
|
-
password_match? do |password|
|
176
|
-
password == 'banana'
|
177
|
-
end
|
178
|
-
update_session do
|
179
|
-
session['user_id'] = 'pear'
|
180
|
-
end
|
181
|
-
no_matching_login_message "no user"
|
182
|
-
invalid_password_message "bad password"
|
183
|
-
end
|
184
|
-
roda do |r|
|
185
|
-
r.rodauth
|
186
|
-
next unless session['user_id'] == 'pear'
|
187
|
-
r.root{"Logged In"}
|
188
|
-
end
|
189
|
-
|
190
|
-
login(:login=>'appl', :pass=>'banana')
|
191
|
-
page.html.must_include("no user")
|
192
|
-
|
193
|
-
login(:login=>'apple', :pass=>'banan', :visit=>false)
|
194
|
-
page.html.must_include("bad password")
|
195
|
-
|
196
|
-
fill_in 'Password', :with=>'banana'
|
197
|
-
click_button 'Login'
|
198
|
-
page.current_path.must_equal '/'
|
199
|
-
page.html.must_include("Logged In")
|
200
|
-
end
|
201
|
-
|
202
|
-
it "should handle a prefix and some other login options" do
|
203
|
-
rodauth do
|
204
|
-
enable :login, :logout
|
205
|
-
prefix '/auth'
|
206
|
-
session_key 'login_email'
|
207
|
-
account_from_session{DB[:accounts].first(:email=>session_value)}
|
208
|
-
account_session_value{account[:email]}
|
209
|
-
login_param{param('lp')}
|
210
|
-
login_additional_form_tags "<input type='hidden' name='lp' value='l' />"
|
211
|
-
password_param 'p'
|
212
|
-
login_redirect{"/foo/#{account[:email]}"}
|
213
|
-
logout_redirect '/auth/lin'
|
214
|
-
login_route 'lin'
|
215
|
-
logout_route 'lout'
|
216
|
-
end
|
217
|
-
no_freeze!
|
218
|
-
roda do |r|
|
219
|
-
r.on 'auth' do
|
220
|
-
r.rodauth
|
221
|
-
end
|
222
|
-
next unless session['login_email'] =~ /example/
|
223
|
-
r.get('foo', :email){|e| "Logged In: #{e}"}
|
224
|
-
end
|
225
|
-
app.plugin :render, :views=>'spec/views', :engine=>'str'
|
226
|
-
|
227
|
-
visit '/auth/lin?lp=l'
|
228
|
-
|
229
|
-
login(:login=>'foo@example2.com', :visit=>false)
|
230
|
-
page.html.must_include("no matching login")
|
231
|
-
|
232
|
-
login(:pass=>'012345678', :visit=>false)
|
233
|
-
page.html.must_include("invalid password")
|
234
|
-
|
235
|
-
login(:visit=>false)
|
236
|
-
page.current_path.must_equal '/foo/foo@example.com'
|
237
|
-
page.html.must_include("Logged In: foo@example.com")
|
238
|
-
|
239
|
-
visit '/auth/lout'
|
240
|
-
click_button 'Logout'
|
241
|
-
page.current_path.must_equal '/auth/lin'
|
242
|
-
end
|
243
|
-
|
244
|
-
it "should use correct redirect paths when using prefix" do
|
245
|
-
rodauth do
|
246
|
-
enable :login, :logout
|
247
|
-
prefix '/auth'
|
248
|
-
end
|
249
|
-
roda do |r|
|
250
|
-
r.on 'auth' do
|
251
|
-
r.rodauth
|
252
|
-
rodauth.require_login
|
253
|
-
end
|
254
|
-
rodauth.send("#{r.remaining_path[1..-1]}_redirect")
|
255
|
-
end
|
256
|
-
|
257
|
-
visit '/login'
|
258
|
-
page.html.must_equal '/'
|
259
|
-
visit '/logout'
|
260
|
-
page.html.must_equal '/auth/login'
|
261
|
-
visit '/require_login'
|
262
|
-
page.html.must_equal '/auth/login'
|
263
|
-
|
264
|
-
visit '/auth'
|
265
|
-
page.current_path.must_equal '/auth/login'
|
266
|
-
end
|
267
|
-
|
268
|
-
it "should login and logout via jwt" do
|
269
|
-
rodauth do
|
270
|
-
enable :login, :logout
|
271
|
-
json_response_custom_error_status? false
|
272
|
-
jwt_secret{proc{super()}.must_raise ArgumentError; "1"}
|
273
|
-
end
|
274
|
-
roda(:jwt) do |r|
|
275
|
-
r.rodauth
|
276
|
-
response['Content-Type'] = 'application/json'
|
277
|
-
rodauth.logged_in? ? '1' : '2'
|
278
|
-
end
|
279
|
-
|
280
|
-
json_request.must_equal [200, 2]
|
281
|
-
|
282
|
-
res = json_request("/login", :login=>'foo@example2.com', :password=>'0123456789')
|
283
|
-
res.must_equal [400, {'error'=>"There was an error logging in", "field-error"=>["login", "no matching login"]}]
|
284
|
-
|
285
|
-
res = json_request("/login", :login=>'foo@example.com', :password=>'012345678')
|
286
|
-
res.must_equal [400, {'error'=>"There was an error logging in", "field-error"=>["password", "invalid password"]}]
|
287
|
-
|
288
|
-
json_request("/login", :login=>'foo@example.com', :password=>'0123456789').must_equal [200, {"success"=>'You have been logged in'}]
|
289
|
-
json_request.must_equal [200, 1]
|
290
|
-
|
291
|
-
json_request("/logout").must_equal [200, {"success"=>'You have been logged out'}]
|
292
|
-
json_request.must_equal [200, 2]
|
293
|
-
end
|
294
|
-
|
295
|
-
it "should login and logout via jwt with custom error statuses" do
|
296
|
-
rodauth do
|
297
|
-
enable :login, :logout
|
298
|
-
end
|
299
|
-
roda(:jwt) do |r|
|
300
|
-
r.rodauth
|
301
|
-
response['Content-Type'] = 'application/json'
|
302
|
-
r.post('foo') do
|
303
|
-
rodauth.require_login
|
304
|
-
'3'
|
305
|
-
end
|
306
|
-
rodauth.logged_in? ? '1' : '2'
|
307
|
-
end
|
308
|
-
|
309
|
-
json_request.must_equal [200, 2]
|
310
|
-
|
311
|
-
res = json_request("/foo")
|
312
|
-
res.must_equal [401, {"error"=>"Please login to continue"}]
|
313
|
-
|
314
|
-
res = json_request("/login", :login=>'foo@example2.com', :password=>'0123456789')
|
315
|
-
res.must_equal [401, {'error'=>"There was an error logging in", "field-error"=>["login", "no matching login"]}]
|
316
|
-
|
317
|
-
res = json_request("/login", :login=>'foo@example.com', :password=>'012345678')
|
318
|
-
res.must_equal [401, {'error'=>"There was an error logging in", "field-error"=>["password", "invalid password"]}]
|
319
|
-
|
320
|
-
json_request("/login", :login=>'foo@example.com', :password=>'0123456789').must_equal [200, {"success"=>'You have been logged in'}]
|
321
|
-
json_request.must_equal [200, 1]
|
322
|
-
|
323
|
-
res = json_request("/foo").must_equal [200, 3]
|
324
|
-
|
325
|
-
json_request("/logout").must_equal [200, {"success"=>'You have been logged out'}]
|
326
|
-
json_request.must_equal [200, 2]
|
327
|
-
end
|
328
|
-
end
|
data/spec/migrate/001_tables.rb
DELETED
@@ -1,184 +0,0 @@
|
|
1
|
-
Sequel.migration do
|
2
|
-
up do
|
3
|
-
extension :date_arithmetic
|
4
|
-
|
5
|
-
# Used by the account verification and close account features
|
6
|
-
create_table(:account_statuses) do
|
7
|
-
Integer :id, :primary_key=>true
|
8
|
-
String :name, :null=>false, :unique=>true
|
9
|
-
end
|
10
|
-
from(:account_statuses).import([:id, :name], [[1, 'Unverified'], [2, 'Verified'], [3, 'Closed']])
|
11
|
-
|
12
|
-
db = self
|
13
|
-
create_table(:accounts) do
|
14
|
-
primary_key :id, :type=>:Bignum
|
15
|
-
foreign_key :status_id, :account_statuses, :null=>false, :default=>1
|
16
|
-
if db.database_type == :postgres
|
17
|
-
citext :email, :null=>false
|
18
|
-
constraint :valid_email, :email=>/^[^,;@ \r\n]+@[^,@; \r\n]+\.[^,@; \r\n]+$/
|
19
|
-
index :email, :unique=>true, :where=>{:status_id=>[1, 2]}
|
20
|
-
else
|
21
|
-
String :email, :null=>false
|
22
|
-
index :email, :unique=>true
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
deadline_opts = proc do |days|
|
27
|
-
if database_type == :mysql
|
28
|
-
{:null=>false}
|
29
|
-
else
|
30
|
-
{:null=>false, :default=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, :days=>days)}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# Used by the password reset feature
|
35
|
-
create_table(:account_password_reset_keys) do
|
36
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
37
|
-
String :key, :null=>false
|
38
|
-
DateTime :deadline, deadline_opts[1]
|
39
|
-
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
40
|
-
end
|
41
|
-
|
42
|
-
# Used by the refresh token feature
|
43
|
-
create_table(:account_jwt_refresh_keys) do
|
44
|
-
primary_key :id, :type=>:Bignum
|
45
|
-
foreign_key :account_id, :accounts, :type=>:Bignum
|
46
|
-
String :key, :null=>false
|
47
|
-
DateTime :deadline, deadline_opts[1]
|
48
|
-
end
|
49
|
-
|
50
|
-
# Used by the account verification feature
|
51
|
-
create_table(:account_verification_keys) do
|
52
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
53
|
-
String :key, :null=>false
|
54
|
-
DateTime :requested_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
55
|
-
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
56
|
-
end
|
57
|
-
|
58
|
-
# Used by the verify login change feature
|
59
|
-
create_table(:account_login_change_keys) do
|
60
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
61
|
-
String :key, :null=>false
|
62
|
-
String :login, :null=>false
|
63
|
-
DateTime :deadline, deadline_opts[1]
|
64
|
-
end
|
65
|
-
|
66
|
-
# Used by the remember me feature
|
67
|
-
create_table(:account_remember_keys) do
|
68
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
69
|
-
String :key, :null=>false
|
70
|
-
DateTime :deadline, deadline_opts[14]
|
71
|
-
end
|
72
|
-
|
73
|
-
# Used by the lockout feature
|
74
|
-
create_table(:account_login_failures) do
|
75
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
76
|
-
Integer :number, :null=>false, :default=>1
|
77
|
-
end
|
78
|
-
create_table(:account_lockouts) do
|
79
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
80
|
-
String :key, :null=>false
|
81
|
-
DateTime :deadline, deadline_opts[1]
|
82
|
-
DateTime :email_last_sent
|
83
|
-
end
|
84
|
-
|
85
|
-
# Used by the email auth feature
|
86
|
-
create_table(:account_email_auth_keys) do
|
87
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
88
|
-
String :key, :null=>false
|
89
|
-
DateTime :deadline, deadline_opts[1]
|
90
|
-
DateTime :email_last_sent, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
91
|
-
end
|
92
|
-
|
93
|
-
# Used by the password expiration feature
|
94
|
-
create_table(:account_password_change_times) do
|
95
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
96
|
-
DateTime :changed_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
97
|
-
end
|
98
|
-
|
99
|
-
# Used by the account expiration feature
|
100
|
-
create_table(:account_activity_times) do
|
101
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
102
|
-
DateTime :last_activity_at, :null=>false
|
103
|
-
DateTime :last_login_at, :null=>false
|
104
|
-
DateTime :expired_at
|
105
|
-
end
|
106
|
-
|
107
|
-
# Used by the single session feature
|
108
|
-
create_table(:account_session_keys) do
|
109
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
110
|
-
String :key, :null=>false
|
111
|
-
end
|
112
|
-
|
113
|
-
# Used by the otp feature
|
114
|
-
create_table(:account_otp_keys) do
|
115
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
116
|
-
String :key, :null=>false
|
117
|
-
Integer :num_failures, :null=>false, :default=>0
|
118
|
-
Time :last_use, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
119
|
-
end
|
120
|
-
|
121
|
-
# Used by the recovery codes feature
|
122
|
-
create_table(:account_recovery_codes) do
|
123
|
-
foreign_key :id, :accounts, :type=>:Bignum
|
124
|
-
String :code
|
125
|
-
primary_key [:id, :code]
|
126
|
-
end
|
127
|
-
|
128
|
-
# Used by the sms codes feature
|
129
|
-
create_table(:account_sms_codes) do
|
130
|
-
foreign_key :id, :accounts, :primary_key=>true, :type=>:Bignum
|
131
|
-
String :phone_number, :null=>false
|
132
|
-
Integer :num_failures
|
133
|
-
String :code
|
134
|
-
DateTime :code_issued_at, :null=>false, :default=>Sequel::CURRENT_TIMESTAMP
|
135
|
-
end
|
136
|
-
|
137
|
-
case database_type
|
138
|
-
when :postgres
|
139
|
-
user = get(Sequel.lit('current_user')) + '_password'
|
140
|
-
run "GRANT REFERENCES ON accounts TO #{user}"
|
141
|
-
when :mysql, :mssql
|
142
|
-
user = if database_type == :mysql
|
143
|
-
get(Sequel.lit('current_user')).sub(/_password@/, '@')
|
144
|
-
else
|
145
|
-
get(Sequel.function(:DB_NAME))
|
146
|
-
end
|
147
|
-
run "GRANT ALL ON account_statuses TO #{user}"
|
148
|
-
run "GRANT ALL ON accounts TO #{user}"
|
149
|
-
run "GRANT ALL ON account_password_reset_keys TO #{user}"
|
150
|
-
run "GRANT ALL ON account_jwt_refresh_keys TO #{user}"
|
151
|
-
run "GRANT ALL ON account_verification_keys TO #{user}"
|
152
|
-
run "GRANT ALL ON account_login_change_keys TO #{user}"
|
153
|
-
run "GRANT ALL ON account_remember_keys TO #{user}"
|
154
|
-
run "GRANT ALL ON account_login_failures TO #{user}"
|
155
|
-
run "GRANT ALL ON account_email_auth_keys TO #{user}"
|
156
|
-
run "GRANT ALL ON account_lockouts TO #{user}"
|
157
|
-
run "GRANT ALL ON account_password_change_times TO #{user}"
|
158
|
-
run "GRANT ALL ON account_activity_times TO #{user}"
|
159
|
-
run "GRANT ALL ON account_session_keys TO #{user}"
|
160
|
-
run "GRANT ALL ON account_otp_keys TO #{user}"
|
161
|
-
run "GRANT ALL ON account_recovery_codes TO #{user}"
|
162
|
-
run "GRANT ALL ON account_sms_codes TO #{user}"
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
down do
|
167
|
-
drop_table(:account_sms_codes,
|
168
|
-
:account_recovery_codes,
|
169
|
-
:account_otp_keys,
|
170
|
-
:account_session_keys,
|
171
|
-
:account_activity_times,
|
172
|
-
:account_password_change_times,
|
173
|
-
:account_email_auth_keys,
|
174
|
-
:account_lockouts,
|
175
|
-
:account_login_failures,
|
176
|
-
:account_remember_keys,
|
177
|
-
:account_login_change_keys,
|
178
|
-
:account_verification_keys,
|
179
|
-
:account_jwt_refresh_keys,
|
180
|
-
:account_password_reset_keys,
|
181
|
-
:accounts,
|
182
|
-
:account_statuses)
|
183
|
-
end
|
184
|
-
end
|