signinable 2.0.16 → 3.0.1
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/app/models/signin.rb +8 -17
- data/db/migrate/20220814152804_change_signinable_id_to_string.rb +12 -0
- data/lib/signinable/model_additions.rb +42 -69
- data/lib/signinable/version.rb +1 -1
- data/spec/dummy/config/application.rb +1 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3-shm +0 -0
- data/spec/dummy/db/test.sqlite3-wal +0 -0
- data/spec/dummy/log/test.log +9107 -0
- data/spec/models/signin_spec.rb +6 -76
- data/spec/models/user_spec.rb +32 -103
- data/spec/support/utilities.rb +2 -2
- metadata +41 -36
data/spec/models/signin_spec.rb
CHANGED
@@ -18,84 +18,14 @@ describe Signin do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
describe '#expireable?' do
|
22
|
-
it 'returns false when expireable' do
|
23
|
-
signin = create(:signin, expiration_time: nil)
|
24
|
-
expect(signin).to_not be_expireable
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'returns true when expireable' do
|
28
|
-
signin = create(:signin, expiration_time: Time.zone.now)
|
29
|
-
expect(signin).to be_expireable
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
21
|
describe '#expire!' do
|
34
22
|
it 'sets expiration_time to now' do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
describe '#renew!' do
|
43
|
-
let(:signin) { create(:signin) }
|
44
|
-
let(:attrs) do
|
45
|
-
{
|
46
|
-
period: 100,
|
47
|
-
ip: signin.ip,
|
48
|
-
user_agent: signin.user_agent,
|
49
|
-
refresh_token: false
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
before(:each) do
|
54
|
-
allow(signin).to receive(:update!)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'updates ip and user_agent' do
|
58
|
-
signin.renew!(**attrs)
|
59
|
-
expect(signin).to have_received(:update!).with(hash_including(ip: signin.ip, user_agent: signin.user_agent))
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'when expireable' do
|
63
|
-
before(:each) do
|
64
|
-
allow(signin).to receive(:expireable?).and_return(true)
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'updates expiration_time' do
|
68
|
-
Timecop.freeze do
|
69
|
-
signin.renew!(**attrs)
|
70
|
-
expect(signin).to have_received(:update!).with(hash_including(expiration_time: Time.zone.now + attrs[:period]))
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'when not expireable' do
|
76
|
-
before(:each) do
|
77
|
-
allow(signin).to receive(:expireable?).and_return(false)
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'does not update expiration_time' do
|
81
|
-
signin.renew!(**attrs)
|
82
|
-
expect(signin).to have_received(:update!).with(hash_excluding(expiration_time: Time.zone.now + attrs[:period]))
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'when need to refresh_token' do
|
87
|
-
it 'updates expiration_time' do
|
88
|
-
allow(SecureRandom).to receive(:urlsafe_base64).and_return('bla')
|
89
|
-
signin.renew!(**attrs.merge(refresh_token: true))
|
90
|
-
expect(signin).to have_received(:update!).with(hash_including(token: 'bla'))
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'when no need to refresh_token' do
|
95
|
-
it 'does not update expiration_time' do
|
96
|
-
allow(SecureRandom).to receive(:urlsafe_base64).and_return('bla')
|
97
|
-
signin.renew!(**attrs)
|
98
|
-
expect(signin).to have_received(:update!).with(hash_excluding(token: 'bla'))
|
23
|
+
time = Time.current
|
24
|
+
Timecop.freeze(time) do
|
25
|
+
signin = create(:signin, expiration_time: (Time.zone.now + 1.hour))
|
26
|
+
allow(signin).to receive(:update!)
|
27
|
+
signin.expire!
|
28
|
+
expect(signin).to have_received(:update!).with(ip: signin.ip, user_agent: signin.user_agent, expiration_time: time)
|
99
29
|
end
|
100
30
|
end
|
101
31
|
end
|
data/spec/models/user_spec.rb
CHANGED
@@ -4,7 +4,6 @@ require 'rails_helper'
|
|
4
4
|
|
5
5
|
describe User do
|
6
6
|
let(:credentials) { ['127.0.0.1', 'user_agent'] }
|
7
|
-
let(:other_credentials) { ['127.0.0.2', 'user_agent2'] }
|
8
7
|
let(:user) { create(:user) }
|
9
8
|
|
10
9
|
before :each do
|
@@ -29,8 +28,7 @@ describe User do
|
|
29
28
|
end
|
30
29
|
|
31
30
|
it 'should generate jwt with correct payload' do
|
32
|
-
sign_in_user(user, credentials)
|
33
|
-
signin = user.last_signin
|
31
|
+
signin = sign_in_user(user, credentials)
|
34
32
|
payload = JWT.decode(user.jwt, 'test', true, { algorithm: 'HS256' })[0]
|
35
33
|
expect(payload).to include(
|
36
34
|
'refresh_token' => signin.token,
|
@@ -39,18 +37,10 @@ describe User do
|
|
39
37
|
end
|
40
38
|
|
41
39
|
it 'should set expiration_time' do
|
42
|
-
sign_in_user(user, credentials)
|
43
|
-
signin = user.last_signin
|
40
|
+
signin = sign_in_user(user, credentials)
|
44
41
|
expect(signin.expiration_time.to_i).to eq((Time.zone.now + User.refresh_exp).to_i)
|
45
42
|
end
|
46
43
|
|
47
|
-
it 'should not set expiration_time' do
|
48
|
-
allow(described_class).to receive(:refresh_exp).and_return(0)
|
49
|
-
sign_in_user(user, credentials)
|
50
|
-
signin = user.last_signin
|
51
|
-
expect(signin.expiration_time).to be_nil
|
52
|
-
end
|
53
|
-
|
54
44
|
context 'when simultaneous signins enabled' do
|
55
45
|
before do
|
56
46
|
allow(described_class).to receive(:simultaneous_signings).and_return(true)
|
@@ -78,54 +68,17 @@ describe User do
|
|
78
68
|
|
79
69
|
describe '#signout' do
|
80
70
|
it 'ignores expired signin' do
|
81
|
-
sign_in_user(user, credentials)
|
82
|
-
signin = user.last_signin
|
71
|
+
signin = sign_in_user(user, credentials)
|
83
72
|
Timecop.travel(signin.expiration_time) do
|
84
|
-
expect(sign_out_user(user
|
73
|
+
expect(sign_out_user(user)).to be_falsey
|
85
74
|
end
|
86
75
|
end
|
87
76
|
|
88
77
|
it 'should expire signin' do
|
89
|
-
sign_in_user(user, credentials)
|
90
|
-
|
91
|
-
sign_out_user(user, credentials)
|
78
|
+
signin = sign_in_user(user, credentials)
|
79
|
+
sign_out_user(user)
|
92
80
|
expect(signin.reload).to be_expired
|
93
81
|
end
|
94
|
-
|
95
|
-
context 'when has no restrictions' do
|
96
|
-
%i[ip user_agent].each do |c|
|
97
|
-
it "allows signout when #{c} changes" do
|
98
|
-
sign_in_user(user, credentials)
|
99
|
-
expect(sign_out_user(user, credentials)).to be_truthy
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'when has restrictions' do
|
105
|
-
%i[ip user_agent].each do |c|
|
106
|
-
it "forbids signout when #{c} changes" do
|
107
|
-
allow(described_class).to receive(:signin_restrictions).and_return([c])
|
108
|
-
sign_in_user(user, credentials)
|
109
|
-
expect(sign_out_user(user, other_credentials)).to be_nil
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe '#last_signin' do
|
116
|
-
it 'retuns nil when no signins' do
|
117
|
-
expect(user.last_signin).to be_nil
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'returns last active signin' do
|
121
|
-
sign_in_user(user, credentials)
|
122
|
-
sign_in_user(user, credentials)
|
123
|
-
signin = user.signins.active.last
|
124
|
-
sign_in_user(user, credentials)
|
125
|
-
user.signins.last.expire!
|
126
|
-
|
127
|
-
expect(user.last_signin).to eq(signin)
|
128
|
-
end
|
129
82
|
end
|
130
83
|
|
131
84
|
describe '.generate_jwt' do
|
@@ -180,17 +133,18 @@ describe User do
|
|
180
133
|
Timecop.travel(Time.zone.now + described_class.jwt_exp)
|
181
134
|
end
|
182
135
|
|
183
|
-
it 'does not do user lookup' do
|
184
|
-
allow(described_class).to receive(:find_by)
|
185
|
-
described_class.authenticate_with_token(user.jwt, *credentials)
|
186
|
-
expect(described_class).not_to have_received(:find_by)
|
187
|
-
end
|
188
|
-
|
189
136
|
it 'calls for refresh token' do
|
190
137
|
allow(described_class).to receive(:refresh_jwt)
|
191
138
|
described_class.authenticate_with_token(user.jwt, *credentials)
|
192
139
|
expect(described_class).to have_received(:refresh_jwt)
|
193
140
|
end
|
141
|
+
|
142
|
+
it 'assigns new jwt' do
|
143
|
+
allow(User).to receive(:find_by).and_return(user)
|
144
|
+
allow(user).to receive(:jwt=)
|
145
|
+
described_class.authenticate_with_token(user.jwt, *credentials)
|
146
|
+
expect(user).to have_received(:jwt=)
|
147
|
+
end
|
194
148
|
end
|
195
149
|
end
|
196
150
|
|
@@ -207,60 +161,35 @@ describe User do
|
|
207
161
|
end
|
208
162
|
|
209
163
|
it 'returns nil when signin expired' do
|
210
|
-
sign_in_user(user, credentials)
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
context 'when has no restrictions' do
|
217
|
-
%i[ip user_agent].each do |c|
|
218
|
-
it "allows signin when #{c} changed" do
|
219
|
-
sign_in_user(user, credentials)
|
220
|
-
expect(described_class.refresh_jwt(user.jwt, *other_credentials)).to eq(user)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
context 'when has restrictions' do
|
226
|
-
%i[ip user_agent].each do |c|
|
227
|
-
it "forbids signin when #{c} changed" do
|
228
|
-
allow(User).to receive(:signin_restrictions).and_return([c])
|
229
|
-
sign_in_user(user, credentials)
|
230
|
-
expect(described_class.refresh_jwt(user.jwt, *other_credentials)).to be_nil
|
231
|
-
end
|
164
|
+
signin = sign_in_user(user, credentials)
|
165
|
+
Timecop.travel(Time.zone.now + described_class.refresh_exp) do
|
166
|
+
expect(described_class.refresh_jwt(
|
167
|
+
described_class.extract_jwt_payload(user.jwt)[:data],
|
168
|
+
*credentials
|
169
|
+
)).to be_nil
|
232
170
|
end
|
233
171
|
end
|
234
172
|
|
235
173
|
it 'renews signin' do
|
236
|
-
sign_in_user(user, credentials)
|
237
|
-
signin = user.last_signin
|
238
|
-
allow(signin).to receive(:renew!)
|
239
|
-
allow(Signin).to receive(:find_by).with(token: signin.token).and_return(signin)
|
240
|
-
|
241
|
-
described_class.refresh_jwt(user.jwt, *credentials)
|
242
|
-
expect(signin).to have_received(:renew!).with(period: described_class.expiration_period, ip: credentials[0],
|
243
|
-
user_agent: credentials[1], refresh_token: true)
|
244
|
-
end
|
245
|
-
|
246
|
-
it 'assigns new jwt' do
|
247
|
-
sign_in_user(user, credentials)
|
248
|
-
signin = user.last_signin
|
249
|
-
allow(user).to receive(:jwt=)
|
250
|
-
allow(signin).to receive(:signinable).and_return(user)
|
251
|
-
allow(Signin).to receive(:find_by).with(token: signin.token).and_return(signin)
|
252
|
-
allow(described_class).to receive(:generate_jwt).and_return('bla')
|
174
|
+
signin = sign_in_user(user, credentials)
|
253
175
|
|
254
|
-
|
255
|
-
|
176
|
+
expect {
|
177
|
+
described_class.refresh_jwt(
|
178
|
+
described_class.extract_jwt_payload(user.jwt)[:data],
|
179
|
+
*credentials
|
180
|
+
)
|
181
|
+
signin.reload
|
182
|
+
}.to change { signin.token }
|
256
183
|
end
|
257
184
|
|
258
185
|
it 'regenerates jwt' do
|
259
|
-
sign_in_user(user, credentials)
|
260
|
-
signin = user.last_signin
|
186
|
+
signin = sign_in_user(user, credentials)
|
261
187
|
allow(described_class).to receive(:generate_jwt)
|
262
188
|
|
263
|
-
described_class.refresh_jwt(
|
189
|
+
described_class.refresh_jwt(
|
190
|
+
described_class.extract_jwt_payload(user.jwt)[:data],
|
191
|
+
*credentials
|
192
|
+
)
|
264
193
|
signin.reload
|
265
194
|
expect(described_class).to have_received(:generate_jwt).with(signin.token, signin.signinable_id)
|
266
195
|
end
|
data/spec/support/utilities.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signinable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Novozhenets
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jwt
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 2.
|
19
|
+
version: 2.8.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 2.
|
26
|
+
version: 2.8.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rails
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 7.0.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 7.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: factory_bot_rails
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- config/routes.rb
|
123
123
|
- db/migrate/20140103165607_create_signins.rb
|
124
124
|
- db/migrate/20180530131006_add_custom_data_to_sigins.rb
|
125
|
+
- db/migrate/20220814152804_change_signinable_id_to_string.rb
|
125
126
|
- lib/signinable.rb
|
126
127
|
- lib/signinable/engine.rb
|
127
128
|
- lib/signinable/model_additions.rb
|
@@ -153,6 +154,8 @@ files:
|
|
153
154
|
- spec/dummy/db/migrate/20140103165606_create_users.rb
|
154
155
|
- spec/dummy/db/schema.rb
|
155
156
|
- spec/dummy/db/test.sqlite3
|
157
|
+
- spec/dummy/db/test.sqlite3-shm
|
158
|
+
- spec/dummy/db/test.sqlite3-wal
|
156
159
|
- spec/dummy/log/development.log
|
157
160
|
- spec/dummy/log/test.log
|
158
161
|
- spec/dummy/public/404.html
|
@@ -178,55 +181,57 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
178
181
|
requirements:
|
179
182
|
- - ">="
|
180
183
|
- !ruby/object:Gem::Version
|
181
|
-
version: '
|
184
|
+
version: '3.0'
|
182
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
186
|
requirements:
|
184
187
|
- - ">="
|
185
188
|
- !ruby/object:Gem::Version
|
186
189
|
version: '0'
|
187
190
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
191
|
+
rubygems_version: 3.3.26
|
189
192
|
signing_key:
|
190
193
|
specification_version: 4
|
191
194
|
summary: Token based signin
|
192
195
|
test_files:
|
193
|
-
- spec/dummy/config.ru
|
194
196
|
- spec/dummy/README.rdoc
|
195
|
-
- spec/dummy/
|
196
|
-
- spec/dummy/
|
197
|
-
- spec/dummy/
|
198
|
-
- spec/dummy/
|
199
|
-
- spec/dummy/
|
200
|
-
- spec/dummy/config/routes.rb
|
201
|
-
- spec/dummy/config/database.yml
|
197
|
+
- spec/dummy/Rakefile
|
198
|
+
- spec/dummy/app/models/user.rb
|
199
|
+
- spec/dummy/bin/bundle
|
200
|
+
- spec/dummy/bin/rails
|
201
|
+
- spec/dummy/bin/rake
|
202
202
|
- spec/dummy/config/application.rb
|
203
|
-
- spec/dummy/config/
|
203
|
+
- spec/dummy/config/boot.rb
|
204
|
+
- spec/dummy/config/database.yml
|
205
|
+
- spec/dummy/config/environment.rb
|
206
|
+
- spec/dummy/config/environments/development.rb
|
207
|
+
- spec/dummy/config/environments/production.rb
|
208
|
+
- spec/dummy/config/environments/test.rb
|
204
209
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
205
|
-
- spec/dummy/config/initializers/wrap_parameters.rb
|
206
|
-
- spec/dummy/config/initializers/inflections.rb
|
207
210
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
211
|
+
- spec/dummy/config/initializers/inflections.rb
|
212
|
+
- spec/dummy/config/initializers/mime_types.rb
|
208
213
|
- spec/dummy/config/initializers/secret_token.rb
|
209
214
|
- spec/dummy/config/initializers/session_store.rb
|
210
|
-
- spec/dummy/config/
|
211
|
-
- spec/dummy/config/environments/test.rb
|
212
|
-
- spec/dummy/config/environments/production.rb
|
213
|
-
- spec/dummy/config/environments/development.rb
|
215
|
+
- spec/dummy/config/initializers/wrap_parameters.rb
|
214
216
|
- spec/dummy/config/locales/en.yml
|
215
|
-
- spec/dummy/
|
216
|
-
- spec/dummy/
|
217
|
-
- spec/dummy/
|
218
|
-
- spec/dummy/
|
219
|
-
- spec/dummy/
|
220
|
-
- spec/dummy/
|
221
|
-
- spec/dummy/
|
217
|
+
- spec/dummy/config/routes.rb
|
218
|
+
- spec/dummy/config.ru
|
219
|
+
- spec/dummy/db/development.sqlite3
|
220
|
+
- spec/dummy/db/migrate/20140103165606_create_users.rb
|
221
|
+
- spec/dummy/db/schema.rb
|
222
|
+
- spec/dummy/db/test.sqlite3
|
223
|
+
- spec/dummy/db/test.sqlite3-shm
|
224
|
+
- spec/dummy/db/test.sqlite3-wal
|
225
|
+
- spec/dummy/log/development.log
|
226
|
+
- spec/dummy/log/test.log
|
222
227
|
- spec/dummy/public/404.html
|
223
228
|
- spec/dummy/public/422.html
|
224
|
-
- spec/dummy/
|
225
|
-
- spec/dummy/
|
226
|
-
- spec/rails_helper.rb
|
227
|
-
- spec/support/utilities.rb
|
228
|
-
- spec/factories/users.rb
|
229
|
+
- spec/dummy/public/500.html
|
230
|
+
- spec/dummy/public/favicon.ico
|
229
231
|
- spec/factories/signins.rb
|
230
|
-
- spec/
|
232
|
+
- spec/factories/users.rb
|
231
233
|
- spec/models/signin_spec.rb
|
232
234
|
- spec/models/user_spec.rb
|
235
|
+
- spec/rails_helper.rb
|
236
|
+
- spec/spec_helper.rb
|
237
|
+
- spec/support/utilities.rb
|