authie 3.3.2 → 4.0.0.rc3
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/db/migrate/20141012174250_create_authie_sessions.rb +4 -2
- data/db/migrate/20141013115205_add_indexes_to_authie_sessions.rb +4 -2
- data/db/migrate/20150109144120_add_parent_id_to_authie_sessions.rb +2 -0
- data/db/migrate/20150305135400_add_two_factor_auth_fields_to_authie.rb +3 -1
- data/db/migrate/20170417170000_add_token_hashes_to_authie_sessions.rb +2 -0
- data/db/migrate/20170421174100_add_index_to_token_hashes_on_authie_sessions.rb +3 -1
- data/db/migrate/20180215152200_add_host_to_authie_sessions.rb +2 -0
- data/lib/authie/config.rb +19 -35
- data/lib/authie/controller_delegate.rb +67 -40
- data/lib/authie/controller_extension.rb +14 -37
- data/lib/authie/engine.rb +3 -3
- data/lib/authie/error.rb +2 -0
- data/lib/authie/event_manager.rb +12 -8
- data/lib/authie/rack_controller.rb +6 -10
- data/lib/authie/session.rb +243 -290
- data/lib/authie/session_model.rb +141 -0
- data/lib/authie/user.rb +3 -3
- data/lib/authie/version.rb +8 -1
- data/lib/authie.rb +3 -3
- metadata +214 -5
data/lib/authie/session.rb
CHANGED
@@ -1,337 +1,290 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'authie/session_model'
|
4
|
+
require 'authie/error'
|
5
|
+
require 'authie/config'
|
6
|
+
require 'active_support/core_ext/module/delegation'
|
2
7
|
|
3
8
|
module Authie
|
4
|
-
class Session
|
9
|
+
class Session
|
10
|
+
# The underlying session model instance
|
11
|
+
#
|
12
|
+
# @return [Authie::SessionModel]
|
13
|
+
attr_reader :session
|
5
14
|
|
6
|
-
#
|
7
|
-
# validity in the request.
|
15
|
+
# A parent class that encapsulates all session validity errors.
|
8
16
|
class ValidityError < Error; end
|
9
|
-
class InactiveSession < ValidityError; end
|
10
|
-
class ExpiredSession < ValidityError; end
|
11
|
-
class BrowserMismatch < ValidityError; end
|
12
|
-
class HostMismatch < ValidityError; end
|
13
|
-
|
14
|
-
class NoParentSessionForRevert < Error; end
|
15
|
-
|
16
|
-
# Set table name
|
17
|
-
self.table_name = "authie_sessions"
|
18
|
-
|
19
|
-
# Relationships
|
20
|
-
parent_options = {:class_name => "Authie::Session"}
|
21
|
-
parent_options[:optional] = true if ActiveRecord::VERSION::MAJOR >= 5
|
22
|
-
belongs_to :parent, parent_options
|
23
|
-
|
24
|
-
# Scopes
|
25
|
-
scope :active, -> { where(:active => true) }
|
26
|
-
scope :asc, -> { order(:last_activity_at => :desc) }
|
27
|
-
scope :for_user, -> (user) { where(:user_type => user.class.name, :user_id => user.id) }
|
28
|
-
|
29
|
-
# Attributes
|
30
|
-
serialize :data, Hash
|
31
|
-
attr_accessor :controller
|
32
|
-
attr_accessor :temporary_token
|
33
17
|
|
34
|
-
|
35
|
-
|
36
|
-
self.user_agent = self.user_agent[0,255]
|
37
|
-
end
|
18
|
+
# Raised when a session is used but it is no longer active
|
19
|
+
class InactiveSession < ValidityError; end
|
38
20
|
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
21
|
+
# Raised when a session is used but it has expired
|
22
|
+
class ExpiredSession < ValidityError; end
|
43
23
|
|
44
|
-
|
45
|
-
|
46
|
-
self.token_hash = self.class.hash_token(self.temporary_token)
|
47
|
-
if controller
|
48
|
-
self.user_agent = controller.request.user_agent
|
49
|
-
set_cookie!
|
50
|
-
end
|
51
|
-
end
|
24
|
+
# Raised when a session is used but the browser ID does not match
|
25
|
+
class BrowserMismatch < ValidityError; end
|
52
26
|
|
53
|
-
|
54
|
-
|
55
|
-
end
|
27
|
+
# Raised when a session is used but the hostname does not match
|
28
|
+
# the session hostname
|
29
|
+
class HostMismatch < ValidityError; end
|
56
30
|
|
57
|
-
#
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
31
|
+
# Initialize a new session object
|
32
|
+
#
|
33
|
+
# @param controller [ActionController::Base] any controller
|
34
|
+
# @param session [Authie::SessionModel] an Authie session model instance
|
35
|
+
# @return [Authie::Session]
|
36
|
+
def initialize(controller, session)
|
37
|
+
@controller = controller
|
38
|
+
@session = session
|
39
|
+
end
|
40
|
+
|
41
|
+
# Validate that the session is valid and raise and error if not
|
42
|
+
#
|
43
|
+
# @raises [Authie::Session::BrowserMismatch]
|
44
|
+
# @raises [Authie::Session::InactiveSession]
|
45
|
+
# @raises [Authie::Session::ExpiredSession]
|
46
|
+
# @raises [Authie::Session::HostMismatch]
|
47
|
+
# @return [Authie::Session]
|
48
|
+
def validate
|
49
|
+
validate_browser_id
|
50
|
+
validate_active
|
51
|
+
validate_expiry
|
52
|
+
validate_inactivity
|
53
|
+
validate_host
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# Mark the current session as persistent. Will set the expiry time of the underlying
|
58
|
+
# session and update the cookie.
|
59
|
+
#
|
60
|
+
# @raises [ActiveRecord::RecordInvalid]
|
61
|
+
# @return [Authie::Session]
|
62
|
+
def persist
|
63
|
+
@session.expires_at = Authie.config.persistent_session_length.from_now
|
64
|
+
@session.save!
|
65
|
+
set_cookie
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# Invalidates the current session by marking it inactive and removing the current cookie.
|
70
|
+
#
|
71
|
+
# @raises [ActiveRecord::RecordInvalid]
|
72
|
+
# @return [Authie::Session]
|
73
|
+
def invalidate
|
74
|
+
@session.invalidate!
|
75
|
+
cookies.delete(:user_session)
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
# Touches the current session to ensure it is currently valid and to update attributes
|
80
|
+
# which should be updatd on each request. This will raise the same errors as the #validate
|
81
|
+
# method. It will set the last activity time, IP and path as well as incrementing
|
82
|
+
# the request counter.
|
83
|
+
#
|
84
|
+
# @raises [Authie::Session::BrowserMismatch]
|
85
|
+
# @raises [Authie::Session::InactiveSession]
|
86
|
+
# @raises [Authie::Session::ExpiredSession]
|
87
|
+
# @raises [Authie::Session::HostMismatch]
|
88
|
+
# @raises [ActiveRecord::RecordInvalid]
|
89
|
+
# @return [Authie::Session]
|
90
|
+
def touch
|
91
|
+
validate
|
92
|
+
@session.last_activity_at = Time.now
|
93
|
+
@session.last_activity_ip = @controller.request.ip
|
94
|
+
@session.last_activity_path = @controller.request.path
|
95
|
+
@session.requests += 1
|
96
|
+
@session.save!
|
97
|
+
Authie.config.events.dispatch(:session_touched, self)
|
98
|
+
self
|
63
99
|
end
|
64
100
|
|
65
|
-
#
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
101
|
+
# Mark the session's password as seen at the current time
|
102
|
+
#
|
103
|
+
# @raises [ActiveRecord::RecordInvalid]
|
104
|
+
# @return [Authie::Session]
|
105
|
+
def see_password
|
106
|
+
@session.password_seen_at = Time.now
|
107
|
+
@session.save!
|
108
|
+
Authie.config.events.dispatch(:seen_password, self)
|
109
|
+
self
|
110
|
+
end
|
111
|
+
|
112
|
+
# Mark this request as two factored by setting the time and the current
|
113
|
+
# IP address.
|
114
|
+
#
|
115
|
+
# @raises [ActiveRecord::RecordInvalid]
|
116
|
+
# @return [Authie::Session]
|
117
|
+
def mark_as_two_factored
|
118
|
+
@session.two_factored_at = Time.now
|
119
|
+
@session.two_factored_ip = @controller.request.ip
|
120
|
+
@session.save!
|
121
|
+
Authie.config.events.dispatch(:marked_as_two_factor, self)
|
122
|
+
self
|
123
|
+
end
|
124
|
+
|
125
|
+
# Starts a new session by setting the cookie. This should be invoked whenever
|
126
|
+
# a new session begins. It usually does not need to be called directly as it
|
127
|
+
# will be taken care of by the class-level start method.
|
128
|
+
#
|
129
|
+
# @return [Authie::Session]
|
130
|
+
def start
|
131
|
+
set_cookie
|
132
|
+
Authie.config.events.dispatch(:start_session, session)
|
133
|
+
self
|
74
134
|
end
|
75
135
|
|
76
|
-
|
77
|
-
# action while authenticated with this session.
|
78
|
-
def touch!
|
79
|
-
self.check_security!
|
80
|
-
self.last_activity_at = Time.now
|
81
|
-
self.last_activity_ip = controller.request.ip
|
82
|
-
self.last_activity_path = controller.request.path
|
83
|
-
self.requests += 1
|
84
|
-
self.save!
|
85
|
-
Authie.config.events.dispatch(:session_touched, self)
|
86
|
-
true
|
87
|
-
end
|
136
|
+
private
|
88
137
|
|
89
|
-
#
|
90
|
-
def set_cookie
|
138
|
+
# rubocop:disable Naming/AccessorMethodName
|
139
|
+
def set_cookie(value = @session.temporary_token)
|
91
140
|
cookies[:user_session] = {
|
92
|
-
:
|
93
|
-
:
|
94
|
-
:
|
95
|
-
:
|
141
|
+
value: value,
|
142
|
+
secure: @controller.request.ssl?,
|
143
|
+
httponly: true,
|
144
|
+
expires: @session.expires_at
|
96
145
|
}
|
97
146
|
Authie.config.events.dispatch(:session_cookie_updated, self)
|
98
147
|
true
|
99
148
|
end
|
149
|
+
# rubocop:enable Naming/AccessorMethodName
|
100
150
|
|
101
|
-
|
102
|
-
|
103
|
-
cookies[:parent_user_session] = {
|
104
|
-
:value => cookies[:user_session],
|
105
|
-
:secure => controller.request.ssl?,
|
106
|
-
:httponly => true,
|
107
|
-
:expires => self.expires_at
|
108
|
-
}
|
109
|
-
Authie.config.events.dispatch(:parent_session_cookie_updated, self)
|
110
|
-
true
|
151
|
+
def cookies
|
152
|
+
@controller.send(:cookies)
|
111
153
|
end
|
112
154
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
Authie.config.events.dispatch(:browser_id_mismatch_error, self)
|
119
|
-
raise BrowserMismatch, "Browser ID mismatch"
|
120
|
-
end
|
121
|
-
|
122
|
-
unless self.active?
|
123
|
-
invalidate!
|
124
|
-
Authie.config.events.dispatch(:invalid_session_error, self)
|
125
|
-
raise InactiveSession, "Session is no longer active"
|
126
|
-
end
|
127
|
-
|
128
|
-
if self.expired?
|
129
|
-
invalidate!
|
130
|
-
Authie.config.events.dispatch(:expired_session_error, self)
|
131
|
-
raise ExpiredSession, "Persistent session has expired"
|
132
|
-
end
|
133
|
-
|
134
|
-
if self.inactive?
|
135
|
-
invalidate!
|
136
|
-
Authie.config.events.dispatch(:inactive_session_error, self)
|
137
|
-
raise InactiveSession, "Non-persistent session has expired"
|
138
|
-
end
|
139
|
-
|
140
|
-
if self.host && self.host != controller.request.host
|
141
|
-
invalidate!
|
142
|
-
Authie.config.events.dispatch(:host_mismatch_error, self)
|
143
|
-
raise HostMismatch, "Session was created on #{self.host} but accessed using #{controller.request.host}"
|
144
|
-
end
|
155
|
+
def validate_browser_id
|
156
|
+
if cookies[:browser_id] != @session.browser_id
|
157
|
+
invalidate
|
158
|
+
Authie.config.events.dispatch(:browser_id_mismatch_error, self)
|
159
|
+
raise BrowserMismatch, 'Browser ID mismatch'
|
145
160
|
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Has this persistent session expired?
|
149
|
-
def expired?
|
150
|
-
self.expires_at &&
|
151
|
-
self.expires_at < Time.now
|
152
|
-
end
|
153
|
-
|
154
|
-
# Has a non-persistent session become inactive?
|
155
|
-
def inactive?
|
156
|
-
self.expires_at.nil? &&
|
157
|
-
self.last_activity_at &&
|
158
|
-
self.last_activity_at < Authie.config.session_inactivity_timeout.ago
|
159
|
-
end
|
160
|
-
|
161
|
-
# Allow this session to persist rather than expiring at the end of the
|
162
|
-
# current browser session
|
163
|
-
def persist!
|
164
|
-
self.expires_at = Authie.config.persistent_session_length.from_now
|
165
|
-
self.save!
|
166
|
-
set_cookie!
|
167
|
-
end
|
168
161
|
|
169
|
-
|
170
|
-
def persistent?
|
171
|
-
!!expires_at
|
162
|
+
self
|
172
163
|
end
|
173
164
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
# Mark this session as invalid
|
181
|
-
def invalidate!
|
182
|
-
self.active = false
|
183
|
-
self.save!
|
184
|
-
if controller
|
185
|
-
cookies.delete(:user_session)
|
165
|
+
def validate_active
|
166
|
+
unless @session.active?
|
167
|
+
invalidate
|
168
|
+
Authie.config.events.dispatch(:invalid_session_error, self)
|
169
|
+
raise InactiveSession, 'Session is no longer active'
|
186
170
|
end
|
187
|
-
Authie.config.events.dispatch(:session_invalidated, self)
|
188
|
-
true
|
189
|
-
end
|
190
|
-
|
191
|
-
# Set some additional data in this session
|
192
|
-
def set(key, value)
|
193
|
-
self.data ||= {}
|
194
|
-
self.data[key.to_s] = value
|
195
|
-
self.save!
|
196
|
-
end
|
197
171
|
|
198
|
-
|
199
|
-
def get(key)
|
200
|
-
(self.data ||= {})[key.to_s]
|
172
|
+
self
|
201
173
|
end
|
202
174
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
175
|
+
def validate_expiry
|
176
|
+
if @session.expired?
|
177
|
+
invalidate
|
178
|
+
Authie.config.events.dispatch(:expired_session_error, self)
|
179
|
+
raise ExpiredSession, 'Persistent session has expired'
|
207
180
|
end
|
208
|
-
end
|
209
181
|
|
210
|
-
|
211
|
-
def see_password!
|
212
|
-
self.password_seen_at = Time.now
|
213
|
-
self.save!
|
214
|
-
Authie.config.events.dispatch(:seen_password, self)
|
215
|
-
true
|
182
|
+
self
|
216
183
|
end
|
217
184
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
# Is two factor authentication required for this request?
|
224
|
-
def two_factored?
|
225
|
-
!!(two_factored_at || self.parent_id)
|
226
|
-
end
|
227
|
-
|
228
|
-
# Mark this request as two factor authoritsed
|
229
|
-
def mark_as_two_factored!
|
230
|
-
self.two_factored_at = Time.now
|
231
|
-
self.two_factored_ip = controller.request.ip
|
232
|
-
self.save!
|
233
|
-
Authie.config.events.dispatch(:marked_as_two_factored, self)
|
234
|
-
true
|
235
|
-
end
|
236
|
-
|
237
|
-
# Create a new session for impersonating for the given user
|
238
|
-
def impersonate!(user)
|
239
|
-
set_parent_cookie!
|
240
|
-
self.class.start(controller, :user => user, :parent => self)
|
241
|
-
end
|
242
|
-
|
243
|
-
# Revert back to the parent session
|
244
|
-
def revert_to_parent!
|
245
|
-
if self.parent && cookies[:parent_user_session]
|
246
|
-
self.invalidate!
|
247
|
-
self.parent.activate!
|
248
|
-
self.parent.controller = self.controller
|
249
|
-
self.parent.set_cookie!(cookies[:parent_user_session])
|
250
|
-
cookies.delete(:parent_user_session)
|
251
|
-
self.parent
|
252
|
-
else
|
253
|
-
raise NoParentSessionForRevert, "Session does not have a parent therefore cannot be reverted."
|
185
|
+
def validate_inactivity
|
186
|
+
if @session.inactive?
|
187
|
+
invalidate
|
188
|
+
Authie.config.events.dispatch(:inactive_session_error, self)
|
189
|
+
raise InactiveSession, 'Non-persistent session has expired'
|
254
190
|
end
|
255
|
-
end
|
256
191
|
|
257
|
-
|
258
|
-
def first_session_for_browser?
|
259
|
-
self.class.where("id < ?", self.id).for_user(self.user).where(:browser_id => self.browser_id).empty?
|
192
|
+
self
|
260
193
|
end
|
261
194
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
# Find a session from the database for the given controller instance.
|
268
|
-
# Returns a session object or :none if no session is found.
|
269
|
-
def self.get_session(controller)
|
270
|
-
cookies = controller.send(:cookies)
|
271
|
-
if cookies[:user_session] && session = self.find_session_by_token(cookies[:user_session])
|
272
|
-
session.temporary_token = cookies[:user_session]
|
273
|
-
session.controller = controller
|
274
|
-
session
|
275
|
-
else
|
276
|
-
:none
|
195
|
+
def validate_host
|
196
|
+
if @session.host && @session.host != @controller.request.host
|
197
|
+
invalidate
|
198
|
+
Authie.config.events.dispatch(:host_mismatch_error, self)
|
199
|
+
raise HostMismatch, "Session was created on #{@session.host} but accessed using #{@controller.request.host}"
|
277
200
|
end
|
278
|
-
end
|
279
201
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
205
|
+
class << self
|
206
|
+
# Create a new session within the given controller for the
|
207
|
+
#
|
208
|
+
# @param controller [ActionController::Base]
|
209
|
+
# @option params [ActiveRecord::Base] user
|
210
|
+
# @return [Authie::Session]
|
211
|
+
def start(controller, params = {})
|
212
|
+
cookies = controller.send(:cookies)
|
213
|
+
SessionModel.active.where(browser_id: cookies[:browser_id]).each(&:invalidate!)
|
214
|
+
user_object = params.delete(:user)
|
215
|
+
|
216
|
+
session = SessionModel.new(params)
|
217
|
+
session.user = user_object
|
218
|
+
session.browser_id = cookies[:browser_id]
|
219
|
+
session.login_at = Time.now
|
220
|
+
session.login_ip = controller.request.ip
|
221
|
+
session.host = controller.request.host
|
222
|
+
session.user_agent = controller.request.user_agent
|
223
|
+
session.save!
|
224
|
+
|
225
|
+
new(controller, session).start
|
226
|
+
end
|
285
227
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
session.user = user_object
|
295
|
-
session.controller = controller
|
296
|
-
session.browser_id = cookies[:browser_id]
|
297
|
-
session.login_at = Time.now
|
298
|
-
session.login_ip = controller.request.ip
|
299
|
-
session.host = controller.request.host
|
300
|
-
session.save!
|
301
|
-
Authie.config.events.dispatch(:start_session, session)
|
302
|
-
session
|
303
|
-
end
|
228
|
+
# Lookup a session for a given controller and return the session
|
229
|
+
# object.
|
230
|
+
#
|
231
|
+
# @param controller [ActionController::Base]
|
232
|
+
# @return [Authie::Session]
|
233
|
+
def get_session(controller)
|
234
|
+
cookies = controller.send(:cookies)
|
235
|
+
return nil if cookies[:user_session].blank?
|
304
236
|
|
305
|
-
|
306
|
-
|
307
|
-
Authie.config.events.dispatch(:before_cleanup)
|
308
|
-
# Invalidate transient sessions that haven't been used
|
309
|
-
self.active.where("expires_at IS NULL AND last_activity_at < ?", Authie.config.session_inactivity_timeout.ago).each(&:invalidate!)
|
310
|
-
# Invalidate persistent sessions that have expired
|
311
|
-
self.active.where("expires_at IS NOT NULL AND expires_at < ?", Time.now).each(&:invalidate!)
|
312
|
-
Authie.config.events.dispatch(:after_cleanup)
|
313
|
-
true
|
314
|
-
end
|
237
|
+
session = SessionModel.find_session_by_token(cookies[:user_session])
|
238
|
+
return nil if session.blank?
|
315
239
|
|
316
|
-
|
317
|
-
|
318
|
-
Digest::SHA256.hexdigest(token)
|
319
|
-
end
|
320
|
-
|
321
|
-
# Convert all existing active sessions to store their tokens in the database
|
322
|
-
def self.convert_tokens_to_hashes
|
323
|
-
active.where(:token_hash => nil).where("token is not null").each do |s|
|
324
|
-
hash = self.hash_token(s.token)
|
325
|
-
self.where(:id => s.id).update_all(:token_hash => hash, :token => nil)
|
240
|
+
session.temporary_token = cookies[:user_session]
|
241
|
+
new(controller, session)
|
326
242
|
end
|
327
|
-
end
|
328
|
-
|
329
|
-
private
|
330
|
-
|
331
|
-
# Return all cookies on the associated controller
|
332
|
-
def cookies
|
333
|
-
controller.send(:cookies)
|
334
|
-
end
|
335
243
|
|
244
|
+
delegate :hash_token, to: SessionModel
|
245
|
+
end
|
246
|
+
|
247
|
+
# Backwards compatibility with Authie < 4.0. These methods were all available on sessions
|
248
|
+
# in previous versions of Authie. They have been maintained for backwards-compatibility but
|
249
|
+
# will be removed entirely in Authie 5.0.
|
250
|
+
alias check_security! validate
|
251
|
+
alias persist! persist
|
252
|
+
alias invalidate! invalidate
|
253
|
+
alias touch! touch
|
254
|
+
alias set_cookie! set_cookie
|
255
|
+
alias see_password! see_password
|
256
|
+
alias mark_as_two_factored! mark_as_two_factored
|
257
|
+
|
258
|
+
# Delegate key methods back to the underlying session model. Previous behaviour in Authie
|
259
|
+
# exposed all methods on the session model. It is useful that these methods can be accessed
|
260
|
+
# easily from this session proxy model so these are maintained as delegated methods.
|
261
|
+
delegate :active?, to: :session
|
262
|
+
delegate :browser_id, to: :session
|
263
|
+
delegate :expired?, to: :session
|
264
|
+
delegate :first_session_for_browser?, to: :session
|
265
|
+
delegate :first_session_for_ip?, to: :session
|
266
|
+
delegate :get, to: :session
|
267
|
+
delegate :inactive?, to: :session
|
268
|
+
delegate :invalidate_others!, to: :session
|
269
|
+
delegate :last_activity_at, to: :session
|
270
|
+
delegate :last_activity_ip, to: :session
|
271
|
+
delegate :last_activity_path, to: :session
|
272
|
+
delegate :login_at, to: :session
|
273
|
+
delegate :login_ip, to: :session
|
274
|
+
delegate :password_seen_at, to: :session
|
275
|
+
delegate :persisted?, to: :session
|
276
|
+
delegate :persistent?, to: :session
|
277
|
+
delegate :recently_seen_password?, to: :session
|
278
|
+
delegate :requests, to: :session
|
279
|
+
delegate :set, to: :session
|
280
|
+
delegate :temporary_token, to: :session
|
281
|
+
delegate :token_hash, to: :session
|
282
|
+
delegate :two_factored_at, to: :session
|
283
|
+
delegate :two_factored_ip, to: :session
|
284
|
+
delegate :two_factored?, to: :session
|
285
|
+
delegate :update, to: :session
|
286
|
+
delegate :update!, to: :session
|
287
|
+
delegate :user_agent, to: :session
|
288
|
+
delegate :user, to: :session
|
336
289
|
end
|
337
290
|
end
|