signinable 2.0.17 → 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/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 +40 -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
|
@@ -154,6 +154,8 @@ files:
|
|
154
154
|
- spec/dummy/db/migrate/20140103165606_create_users.rb
|
155
155
|
- spec/dummy/db/schema.rb
|
156
156
|
- spec/dummy/db/test.sqlite3
|
157
|
+
- spec/dummy/db/test.sqlite3-shm
|
158
|
+
- spec/dummy/db/test.sqlite3-wal
|
157
159
|
- spec/dummy/log/development.log
|
158
160
|
- spec/dummy/log/test.log
|
159
161
|
- spec/dummy/public/404.html
|
@@ -179,55 +181,57 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
179
181
|
requirements:
|
180
182
|
- - ">="
|
181
183
|
- !ruby/object:Gem::Version
|
182
|
-
version: '
|
184
|
+
version: '3.0'
|
183
185
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
186
|
requirements:
|
185
187
|
- - ">="
|
186
188
|
- !ruby/object:Gem::Version
|
187
189
|
version: '0'
|
188
190
|
requirements: []
|
189
|
-
rubygems_version: 3.
|
191
|
+
rubygems_version: 3.3.26
|
190
192
|
signing_key:
|
191
193
|
specification_version: 4
|
192
194
|
summary: Token based signin
|
193
195
|
test_files:
|
194
|
-
- spec/dummy/config.ru
|
195
196
|
- spec/dummy/README.rdoc
|
196
|
-
- spec/dummy/
|
197
|
-
- spec/dummy/
|
198
|
-
- spec/dummy/
|
199
|
-
- spec/dummy/
|
200
|
-
- spec/dummy/
|
201
|
-
- spec/dummy/config/routes.rb
|
202
|
-
- 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
|
203
202
|
- spec/dummy/config/application.rb
|
204
|
-
- 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
|
205
209
|
- spec/dummy/config/initializers/backtrace_silencers.rb
|
206
|
-
- spec/dummy/config/initializers/wrap_parameters.rb
|
207
|
-
- spec/dummy/config/initializers/inflections.rb
|
208
210
|
- spec/dummy/config/initializers/filter_parameter_logging.rb
|
211
|
+
- spec/dummy/config/initializers/inflections.rb
|
212
|
+
- spec/dummy/config/initializers/mime_types.rb
|
209
213
|
- spec/dummy/config/initializers/secret_token.rb
|
210
214
|
- spec/dummy/config/initializers/session_store.rb
|
211
|
-
- spec/dummy/config/
|
212
|
-
- spec/dummy/config/environments/test.rb
|
213
|
-
- spec/dummy/config/environments/production.rb
|
214
|
-
- spec/dummy/config/environments/development.rb
|
215
|
+
- spec/dummy/config/initializers/wrap_parameters.rb
|
215
216
|
- spec/dummy/config/locales/en.yml
|
216
|
-
- spec/dummy/
|
217
|
-
- spec/dummy/
|
218
|
-
- spec/dummy/
|
219
|
-
- spec/dummy/
|
220
|
-
- spec/dummy/
|
221
|
-
- spec/dummy/
|
222
|
-
- 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
|
223
227
|
- spec/dummy/public/404.html
|
224
228
|
- spec/dummy/public/422.html
|
225
|
-
- spec/dummy/
|
226
|
-
- spec/dummy/
|
227
|
-
- spec/rails_helper.rb
|
228
|
-
- spec/support/utilities.rb
|
229
|
-
- spec/factories/users.rb
|
229
|
+
- spec/dummy/public/500.html
|
230
|
+
- spec/dummy/public/favicon.ico
|
230
231
|
- spec/factories/signins.rb
|
231
|
-
- spec/
|
232
|
+
- spec/factories/users.rb
|
232
233
|
- spec/models/signin_spec.rb
|
233
234
|
- spec/models/user_spec.rb
|
235
|
+
- spec/rails_helper.rb
|
236
|
+
- spec/spec_helper.rb
|
237
|
+
- spec/support/utilities.rb
|