signinable 2.0.17 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 523362dea01356b6cbdaf4b31dfcd466d4a27d45d968e754fa2d553794e1afd2
4
- data.tar.gz: d129d2e715ee9376fd6aa4de5904ffbb617518c46136d2d4801bb01b034a2fd6
3
+ metadata.gz: c4cb3c9ed394555e10d075ec1b4ef7dfc401e81b1914abaff0ac79a34ed8adb1
4
+ data.tar.gz: d5a98fbe31a1db70c9739eb444bca9f1e070596853a5ef26911839c18d00289f
5
5
  SHA512:
6
- metadata.gz: 5d53f8b61728737d073ee40251b0fda57275032df9bfd8a32a9e79c69702551955d781d9fcb16b49a617de244137beb6efa776a357f09c127a67a1da033ccd5c
7
- data.tar.gz: ea5ded123711f4be9d5587f2177bbe3dd48b8c1a3be4665a6e8fe37aff4c33576b0235dbf1cb64e7b3ab4509c62f63c1402fe003ccfd98f2b16fdd1210511a58
6
+ metadata.gz: a2922803d96c5617d587f7a695acc7a6bb902c73a218b0bbbf38f9f1859d9e86da00635a2cd6b6ab1eca6030ac2e46558921749a3204e3fc93ad9d68d5bb6ed0
7
+ data.tar.gz: aaeed33569ef9f0a6298671076a2aac3496874b02cd4a27f4e505d94d8a4859b9d0c23b5a99a289ceef6c7a9052e0947aaa434da4845aa82bc586b32755637b4
data/app/models/signin.rb CHANGED
@@ -13,33 +13,24 @@ class Signin < ActiveRecord::Base
13
13
  scope :active, -> { where('expiration_time IS NULL OR expiration_time > ?', Time.zone.now) }
14
14
 
15
15
  before_validation on: :create do
16
- self.token = generate_token
16
+ self.token = self.class.generate_token
17
17
  end
18
18
 
19
19
  serialize :custom_data if ActiveRecord::Base.connection.instance_values['config'][:adapter].match('mysql')
20
20
 
21
21
  def expire!
22
- renew!(period: 0, ip: ip, user_agent: user_agent)
22
+ update!(
23
+ ip: ip,
24
+ user_agent: user_agent,
25
+ expiration_time: Time.current
26
+ )
23
27
  end
24
28
 
25
29
  def expired?
26
- expireable? && expiration_time.past?
30
+ expiration_time.past?
27
31
  end
28
32
 
29
- def expireable?
30
- !expiration_time.nil?
31
- end
32
-
33
- def renew!(period:, ip:, user_agent:, refresh_token: false)
34
- update_hash = { ip: ip, user_agent: user_agent }
35
- update_hash[:expiration_time] = Time.zone.now + period if expireable?
36
- update_hash[:token] = generate_token if refresh_token
37
- update!(update_hash)
38
- end
39
-
40
- private
41
-
42
- def generate_token
33
+ def self.generate_token
43
34
  SecureRandom.urlsafe_base64(rand(50..100))
44
35
  end
45
36
  end
@@ -9,16 +9,14 @@ module Signinable
9
9
  DEFAULT_REFRESH_EXP = 7200
10
10
  DEFAULT_JWT_EXP = 900
11
11
 
12
- cattr_reader :refresh_exp
13
12
  cattr_reader :simultaneous_signings
14
- cattr_reader :signin_restrictions
15
13
  cattr_reader :jwt_secret
16
14
  cattr_reader :jwt_exp
15
+ cattr_reader :refresh_exp
17
16
 
18
17
  def signinable(options = {})
19
18
  self.refresh_exp = options.fetch(:refresh_exp, DEFAULT_REFRESH_EXP)
20
19
  self.simultaneous_signings = options.fetch(:simultaneous, true)
21
- self.signin_restrictions = options[:restrictions]
22
20
  self.jwt_secret = options.fetch(:jwt_secret)
23
21
  self.jwt_exp = options.fetch(:jwt_exp, DEFAULT_JWT_EXP)
24
22
 
@@ -27,21 +25,19 @@ module Signinable
27
25
  attr_accessor :jwt
28
26
  end
29
27
 
30
- def authenticate_with_token(jwt, ip, user_agent, skip_restrictions: [])
28
+ def authenticate_with_token(jwt, ip, user_agent)
31
29
  jwt_payload = extract_jwt_payload(jwt)
32
- return refresh_jwt(jwt, ip, user_agent, skip_restrictions: skip_restrictions) unless jwt_payload
30
+ return nil unless jwt_payload
33
31
 
34
- signinable = find_by(primary_key => jwt_payload['signinable_id'])
32
+ jwt = refresh_jwt(jwt_payload[:data], ip, user_agent) if jwt_payload[:expired]
33
+
34
+ signinable = find_by(primary_key => jwt_payload[:data]['signinable_id'])
35
35
  return nil unless signinable
36
36
 
37
37
  signinable.jwt = jwt
38
38
  signinable
39
39
  end
40
40
 
41
- def check_signin_permission(signin, restrictions_to_check, skip_restrictions)
42
- signin_permitted?(signin, restrictions_to_check, skip_restrictions)
43
- end
44
-
45
41
  def expiration_period
46
42
  return refresh_exp.call if refresh_exp.respond_to?(:call)
47
43
 
@@ -60,101 +56,78 @@ module Signinable
60
56
  )
61
57
  end
62
58
 
63
- def refresh_jwt(jwt, ip, user_agent, skip_restrictions: [])
64
- token = refresh_token_from_jwt(jwt)
65
- return nil unless token
59
+ def refresh_jwt(jwt_payload, ip, user_agent)
60
+ old_token = jwt_payload['refresh_token']
61
+ new_token = Signin.generate_token
66
62
 
67
- signin = Signin.find_by(token: token)
63
+ result = Signin.where(token: old_token)
64
+ .active
65
+ .update_all(
66
+ token: new_token,
67
+ expiration_time: expiration_period.seconds.from_now,
68
+ ip: ip,
69
+ user_agent: user_agent
70
+ )
68
71
 
69
- return unless signin
70
- return nil if signin.expired?
71
- return nil unless check_signin_permission(signin, { ip: ip, user_agent: user_agent }, skip_restrictions)
72
+ return if result.zero?
72
73
 
73
- signin.renew!(period: expiration_period, ip: ip, user_agent: user_agent, refresh_token: true)
74
- signin.signinable.jwt = generate_jwt(signin.token, signin.signinable_id)
75
- signin.signinable
74
+ generate_jwt(new_token, jwt_payload['signinable_id'])
76
75
  end
77
76
 
78
- def refresh_token_from_jwt(jwt)
79
- JWT.decode(jwt, jwt_secret, true, { verify_expiration: false, algorithm: 'HS256' })[0]['refresh_token']
77
+ def extract_jwt_payload(jwt)
78
+ {
79
+ data: JWT.decode(jwt, jwt_secret, true, { algorithm: 'HS256' })[0],
80
+ expired: false
81
+ }
80
82
  rescue JWT::DecodeError
81
- nil
83
+ begin
84
+ {
85
+ data: JWT.decode(jwt, jwt_secret, true, { verify_expiration: false, algorithm: 'HS256' })[0],
86
+ expired: true
87
+ }
88
+ rescue JWT::DecodeError
89
+ nil
90
+ end
82
91
  end
83
92
 
84
93
  private
85
94
 
86
95
  cattr_writer :refresh_exp
87
96
  cattr_writer :simultaneous_signings
88
- cattr_writer :signin_restrictions
89
97
  cattr_writer :jwt_secret
90
98
  cattr_writer :jwt_exp
91
-
92
- def extract_jwt_payload(jwt)
93
- JWT.decode(jwt, jwt_secret, true, { algorithm: 'HS256' })[0]
94
- rescue JWT::DecodeError
95
- nil
96
- end
97
-
98
- def signin_permitted?(signin, restrictions_to_check, skip_restrictions)
99
- restriction_fields = signin_restriction_fields(signin, skip_restrictions)
100
-
101
- restrictions_to_check.slice(*restriction_fields).each do |field, value|
102
- return false unless signin.send(field) == value
103
- end
104
-
105
- true
106
- end
107
-
108
- def signin_restriction_fields(signin, skip_restrictions)
109
- fields = if signin_restrictions.respond_to?(:call)
110
- signin_restrictions.call(signin.signinable)
111
- elsif signin_restrictions.is_a?(Array)
112
- signin_restrictions
113
- else
114
- []
115
- end
116
- (fields - skip_restrictions) & ALLOWED_RESTRICTIONS
117
- end
118
99
  end
119
100
 
120
- def signin(ip, user_agent, referer, permanent: false, custom_data: {})
121
- expires_in = self.class.expiration_period
122
- expiration_time = expires_in.zero? || permanent ? nil : expires_in.seconds.from_now
101
+ def signin(ip, user_agent, referer, custom_data: {})
123
102
  Signin.where(signinable: self).active.map(&:expire!) unless self.class.simultaneous_signings
103
+
124
104
  signin = Signin.create!(
125
105
  signinable: self,
126
106
  ip: ip,
127
107
  referer: referer,
128
108
  user_agent: user_agent,
129
- expiration_time: expiration_time,
109
+ expiration_time: self.class.expiration_period.seconds.from_now,
130
110
  custom_data: custom_data
131
111
  )
132
112
 
133
113
  self.jwt = self.class.generate_jwt(signin.token, signin.signinable_id)
134
- end
135
114
 
136
- def signout(jwt, ip, user_agent, skip_restrictions: [])
137
- token = self.class.refresh_token_from_jwt(jwt)
138
- return unless token
115
+ signin
116
+ end
139
117
 
140
- signin = Signin.find_by_token(token)
118
+ def signout(jwt)
119
+ jwt_payload = self.class.extract_jwt_payload(jwt)
120
+ return unless jwt_payload
121
+ return if jwt_payload[:expired]
141
122
 
123
+ signin = Signin.find_by(token: jwt_payload[:data]['refresh_token'])
142
124
  return unless signin
143
125
  return if signin.expired?
144
- return unless self.class.check_signin_permission(
145
- signin,
146
- { ip: ip, user_agent: user_agent },
147
- skip_restrictions
148
- )
149
126
 
150
127
  signin.expire!
151
128
 
152
129
  true
153
130
  end
154
-
155
- def last_signin
156
- signins.active.last
157
- end
158
131
  end
159
132
  end
160
133
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Signinable
4
- VERSION = '2.0.17'
4
+ VERSION = '3.0.1'
5
5
  end
@@ -9,5 +9,6 @@ require 'signinable'
9
9
 
10
10
  module Dummy
11
11
  class Application < Rails::Application
12
+ config.load_defaults 7.0
12
13
  end
13
14
  end
Binary file
Binary file
File without changes