authenticate 0.1.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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +154 -0
- data/LICENSE +20 -0
- data/README.md +240 -0
- data/Rakefile +6 -0
- data/app/assets/config/authenticate_manifest.js +0 -0
- data/app/assets/images/authenticate/.keep +0 -0
- data/app/assets/javascripts/authenticate/.keep +0 -0
- data/app/assets/stylesheets/authenticate/.keep +0 -0
- data/app/controllers/.keep +0 -0
- data/app/helpers/.keep +0 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/views/.keep +0 -0
- data/authenticate.gemspec +38 -0
- data/bin/rails +12 -0
- data/config/routes.rb +2 -0
- data/lib/authenticate.rb +12 -0
- data/lib/authenticate/callbacks/authenticatable.rb +4 -0
- data/lib/authenticate/callbacks/brute_force.rb +31 -0
- data/lib/authenticate/callbacks/lifetimed.rb +5 -0
- data/lib/authenticate/callbacks/timeoutable.rb +15 -0
- data/lib/authenticate/callbacks/trackable.rb +8 -0
- data/lib/authenticate/configuration.rb +144 -0
- data/lib/authenticate/controller.rb +110 -0
- data/lib/authenticate/crypto/bcrypt.rb +30 -0
- data/lib/authenticate/debug.rb +10 -0
- data/lib/authenticate/engine.rb +21 -0
- data/lib/authenticate/lifecycle.rb +120 -0
- data/lib/authenticate/login_status.rb +27 -0
- data/lib/authenticate/model/brute_force.rb +51 -0
- data/lib/authenticate/model/db_password.rb +71 -0
- data/lib/authenticate/model/email.rb +76 -0
- data/lib/authenticate/model/lifetimed.rb +48 -0
- data/lib/authenticate/model/timeoutable.rb +47 -0
- data/lib/authenticate/model/trackable.rb +43 -0
- data/lib/authenticate/model/username.rb +45 -0
- data/lib/authenticate/modules.rb +61 -0
- data/lib/authenticate/session.rb +123 -0
- data/lib/authenticate/token.rb +7 -0
- data/lib/authenticate/user.rb +50 -0
- data/lib/authenticate/version.rb +3 -0
- data/lib/tasks/authenticate_tasks.rake +4 -0
- data/spec/configuration_spec.rb +60 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/models/user.rb +3 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/authenticate.rb +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20160120003910_create_users.rb +18 -0
- data/spec/dummy/db/schema.rb +31 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/users.rb +23 -0
- data/spec/model/session_spec.rb +86 -0
- data/spec/model/token_spec.rb +11 -0
- data/spec/model/user_spec.rb +12 -0
- data/spec/orm/active_record.rb +17 -0
- data/spec/spec_helper.rb +148 -0
- metadata +255 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module Authenticate
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
# config.generators do |g|
|
4
|
+
# g.test_framework :rspec
|
5
|
+
# g.fixture_replacement :factory_girl, dir: 'spec/factories'
|
6
|
+
# end
|
7
|
+
|
8
|
+
# viget
|
9
|
+
config.generators do |g|
|
10
|
+
g.test_framework :rspec
|
11
|
+
g.fixture_replacement :factory_girl, dir: 'spec/factories'
|
12
|
+
|
13
|
+
|
14
|
+
# g.test_framework :rspec, fixture: false
|
15
|
+
# g.fixture_replacement :factory_girl, dir: 'spec/factories'
|
16
|
+
# g.assets false
|
17
|
+
# g.helper false
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Authenticate
|
2
|
+
|
3
|
+
# Lifecycle stores and runs callbacks for authorization events.
|
4
|
+
#
|
5
|
+
# Heavily borrowed from warden (https://github.com/hassox/warden).
|
6
|
+
#
|
7
|
+
# = Events:
|
8
|
+
# :set_user - called after the user object is loaded, either through id/password or via session token.
|
9
|
+
# :authentication - called after the user authenticates with id & password
|
10
|
+
#
|
11
|
+
# Callbacks are added via after_set_user or after_authentication.
|
12
|
+
#
|
13
|
+
# Callbacks can throw(:failure,message) to signal an authentication/authorization failure, or perform
|
14
|
+
# actions on the user or session.
|
15
|
+
#
|
16
|
+
# = Options
|
17
|
+
#
|
18
|
+
# The callback options may optionally specify when to run the callback:
|
19
|
+
# only - executes the callback only if it matches the event(s) given
|
20
|
+
# except - executes the callback except if it matches the event(s) given
|
21
|
+
#
|
22
|
+
# The callback may also specify a 'name' key in options. This is for debugging purposes only.
|
23
|
+
#
|
24
|
+
# = Callback block parameters
|
25
|
+
#
|
26
|
+
# Callbacks are invoked with the following block parameters: |user, session, opts|
|
27
|
+
# user - the user object just loaded
|
28
|
+
# session - the Authenticate::Session
|
29
|
+
# opts - any options you want passed into the callback
|
30
|
+
#
|
31
|
+
# = Example
|
32
|
+
#
|
33
|
+
# # A callback to track the users successful logins:
|
34
|
+
# Authenticate.lifecycle.after_set_user do |user, session, opts|
|
35
|
+
# user.sign_in_count += 1
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
class Lifecycle
|
39
|
+
include Debug
|
40
|
+
@@conditions = [:only, :except, :event]
|
41
|
+
|
42
|
+
# This callback is triggered after the first time a user is set during per-hit authorization, or during login.
|
43
|
+
def after_set_user(options = {}, method = :push, &block)
|
44
|
+
raise BlockNotGiven unless block_given?
|
45
|
+
options = process_opts(options)
|
46
|
+
# puts "register after_set_user #{options.inspect}"
|
47
|
+
after_set_user_callbacks.send(method, [block, options])
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
# A callback to run after the user successfully authenticates, during the login process.
|
53
|
+
# Mechanically identical to [#after_set_user].
|
54
|
+
def after_authentication(options = {}, method = :push, &block)
|
55
|
+
raise BlockNotGiven unless block_given?
|
56
|
+
options = process_opts(options)
|
57
|
+
# puts "register after_authentication #{options}"
|
58
|
+
after_authentication_callbacks.send(method, [block, options])
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def run_callbacks(kind, *args) # args - |user, session, opts|
|
63
|
+
# Last callback arg MUST be a Hash
|
64
|
+
options = args.last
|
65
|
+
d "@@@@@@@@@@@@ run_callbacks kind:#{kind} options:#{options.inspect}"
|
66
|
+
|
67
|
+
# each callback has 'conditions' stored with it
|
68
|
+
send("#{kind}_callbacks").each do |callback, conditions|
|
69
|
+
conditions = conditions.dup # make a copy, we mutate it
|
70
|
+
d "running callback -- #{conditions.inspect}"
|
71
|
+
conditions.delete_if {|key, val| !@@conditions.include? key}
|
72
|
+
# d "conditions after filter:#{conditions.inspect}"
|
73
|
+
invalid = conditions.find do |key, value|
|
74
|
+
# d "!!!!!!! conditions key:#{key} value:#{value} options[key]:#{options[key].inspect}"
|
75
|
+
# d("!value.include?(options[key]):#{!value.include?(options[key])}") if value.is_a?(Array)
|
76
|
+
value.is_a?(Array) ? !value.include?(options[key]) : (value != options[key])
|
77
|
+
end
|
78
|
+
d "callback invalid? #{invalid.inspect}"
|
79
|
+
callback.call(*args) unless invalid
|
80
|
+
end
|
81
|
+
d "FINISHED run_callbacks #{kind}"
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def prepend_after_authentication(options = {}, &block)
|
87
|
+
after_authentication(options, :unshift, &block)
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# set event: to run callback on based on options
|
93
|
+
def process_opts(options)
|
94
|
+
if options.key?(:only)
|
95
|
+
options[:event] = options.delete(:only)
|
96
|
+
elsif options.key?(:except)
|
97
|
+
options[:event] = [:set_user, :authentication] - Array(options.delete(:except))
|
98
|
+
end
|
99
|
+
options
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
def after_set_user_callbacks
|
104
|
+
@after_set_user_callbacks ||= []
|
105
|
+
end
|
106
|
+
|
107
|
+
def after_authentication_callbacks
|
108
|
+
@after_authentication_callbacks ||= []
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def self.lifecycle
|
114
|
+
@lifecycle ||= Lifecycle.new
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.lifecycle=(lifecycle)
|
118
|
+
@lifecycle = lifecycle
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Authenticate
|
2
|
+
|
3
|
+
# Indicate login attempt was successful. Allows caller to supply a block to login() predicated on success?
|
4
|
+
class Success
|
5
|
+
def success?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Indicate login attempt was a failure, with a message.
|
11
|
+
# Allows caller to supply a block to login() predicated on success?
|
12
|
+
class Failure
|
13
|
+
# The reason the sign in failed.
|
14
|
+
attr_reader :message
|
15
|
+
|
16
|
+
# @param [String] message The reason the login failed.
|
17
|
+
def initialize(message)
|
18
|
+
@message = message
|
19
|
+
end
|
20
|
+
|
21
|
+
def success?
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'authenticate/callbacks/brute_force'
|
2
|
+
|
3
|
+
module Authenticate
|
4
|
+
module Model
|
5
|
+
|
6
|
+
|
7
|
+
# Protect from brute force attacks.
|
8
|
+
# Lock accounts that have too many failed consecutive logins.
|
9
|
+
# Todo: email user to allow faster unlocking via token.
|
10
|
+
module BruteForce
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
def self.required_fields(klass)
|
14
|
+
[:failed_logins_count, :lock_expires_at]
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def register_failed_login!
|
19
|
+
self.failed_logins_count ||= 0
|
20
|
+
self.failed_logins_count += 1
|
21
|
+
lock! if self.failed_logins_count >= max_bad_logins
|
22
|
+
end
|
23
|
+
|
24
|
+
def lock!
|
25
|
+
self.update_attribute(:lock_expires_at, Time.now.utc + lockout_period)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unlock!
|
29
|
+
self.update_attributes({failed_logins_count: 0, lock_expires_at: nil})
|
30
|
+
end
|
31
|
+
|
32
|
+
def locked?
|
33
|
+
!unlocked?
|
34
|
+
end
|
35
|
+
|
36
|
+
def unlocked?
|
37
|
+
self.lock_expires_at.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def max_bad_logins
|
43
|
+
Authenticate.configuration.max_consecutive_bad_logins_allowed
|
44
|
+
end
|
45
|
+
|
46
|
+
def lockout_period
|
47
|
+
Authenticate.configuration.bad_login_lockout_period
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'authenticate/crypto/bcrypt'
|
2
|
+
|
3
|
+
|
4
|
+
module Authenticate
|
5
|
+
module Model
|
6
|
+
|
7
|
+
# Encrypts and stores a password in the database to validate the authenticity of a user while signing in.
|
8
|
+
#
|
9
|
+
# Authenticate can plug in any crypto provider, but currently only features BCrypt.
|
10
|
+
#
|
11
|
+
# = Methods
|
12
|
+
#
|
13
|
+
# The following methods are added to your user model:
|
14
|
+
# - password_match?(password) - checks to see if the user's password matches the given password
|
15
|
+
# - password=(new_password) - encrypt and set the user password
|
16
|
+
#
|
17
|
+
# = Validations
|
18
|
+
#
|
19
|
+
# - :password validation, requiring the password is set
|
20
|
+
#
|
21
|
+
module DbPassword
|
22
|
+
extend ActiveSupport::Concern
|
23
|
+
|
24
|
+
def self.required_fields(klass)
|
25
|
+
[:encrypted_password]
|
26
|
+
end
|
27
|
+
|
28
|
+
included do
|
29
|
+
include crypto_provider
|
30
|
+
attr_reader :password
|
31
|
+
attr_accessor :password_changing
|
32
|
+
validates :password, presence: true, unless: :skip_password_validation?
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
|
39
|
+
# We only have one crypto provider at the moment, but this is a pluggable point
|
40
|
+
# to install different crypto.
|
41
|
+
def crypto_provider
|
42
|
+
Authenticate.configuration.crypto_provider || Authenticate::Crypto::BCrypt
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
def password_match?(password)
|
50
|
+
match?(password, self.encrypted_password)
|
51
|
+
end
|
52
|
+
|
53
|
+
def password=(new_password)
|
54
|
+
@password = new_password
|
55
|
+
|
56
|
+
if new_password.present?
|
57
|
+
self.encrypted_password = encrypt(new_password)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# If we already have an encrypted password and it's not changing, skip the validation.
|
64
|
+
def skip_password_validation?
|
65
|
+
encrypted_password.present? && !password_changing
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'email_validator'
|
2
|
+
|
3
|
+
module Authenticate
|
4
|
+
module Model
|
5
|
+
|
6
|
+
# Use :email as the identifier for the user. Must be unique to the system.
|
7
|
+
#
|
8
|
+
# = Columns
|
9
|
+
# - :email containing the email address of the user
|
10
|
+
#
|
11
|
+
# = Validations
|
12
|
+
# - :email requires email is set, validations the format, and ensure it is unique
|
13
|
+
#
|
14
|
+
# = Callbacks
|
15
|
+
# - :normalize_email - normalize the email, removing spaces etc, before saving
|
16
|
+
#
|
17
|
+
# = Methods
|
18
|
+
# - :email - require the email address is set and is a valid format
|
19
|
+
#
|
20
|
+
# = class methods
|
21
|
+
# - authenticate(email, password) - find user with given email, validate their password, return the user.
|
22
|
+
# - normalize_email(email) - clean up the given email and return it.
|
23
|
+
# - find_by_normalized_email(email) - normalize the given email, then look for the user with that email.
|
24
|
+
#
|
25
|
+
module Email
|
26
|
+
extend ActiveSupport::Concern
|
27
|
+
|
28
|
+
def self.required_fields(klass)
|
29
|
+
[:email]
|
30
|
+
end
|
31
|
+
|
32
|
+
included do
|
33
|
+
before_validation :normalize_email
|
34
|
+
validates :email,
|
35
|
+
email: { strict_mode: true },
|
36
|
+
presence: true,
|
37
|
+
uniqueness: { allow_blank: true }
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
|
43
|
+
def credentials(params)
|
44
|
+
# todo closure from configuration
|
45
|
+
[params[:session][:email], params[:session][:password]]
|
46
|
+
end
|
47
|
+
|
48
|
+
def authenticate(credentials)
|
49
|
+
user = find_by_credentials(credentials)
|
50
|
+
user && user.password_match?(credentials[1]) ? user : nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_by_credentials(credentials)
|
54
|
+
email = credentials[0]
|
55
|
+
puts "find_by_credentials email: #{email}"
|
56
|
+
find_by_email normalize_email(email)
|
57
|
+
end
|
58
|
+
|
59
|
+
def normalize_email(email)
|
60
|
+
email.to_s.downcase.gsub(/\s+/, '')
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
# Sets the email on this instance to the value returned by
|
66
|
+
# {.normalize_email}
|
67
|
+
#
|
68
|
+
# @return [String]
|
69
|
+
def normalize_email
|
70
|
+
self.email = self.class.normalize_email(email)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'authenticate/callbacks/lifetimed'
|
2
|
+
|
3
|
+
module Authenticate
|
4
|
+
module Model
|
5
|
+
|
6
|
+
# The user session has a maximum allowed lifespan, after which the session is expired and requires
|
7
|
+
# re-authentication.
|
8
|
+
#
|
9
|
+
# = configuration
|
10
|
+
#
|
11
|
+
# Set the maximum session lifetime in the initializer, giving a timestamp.
|
12
|
+
#
|
13
|
+
# Authenticate.configure do |config|
|
14
|
+
# config.max_session_lifetime = 8.hours
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# If the max_session_lifetime configuration parameter is nil, the :lifetimed module is not loaded.
|
18
|
+
#
|
19
|
+
# = columns
|
20
|
+
# Requires the `current_sign_in_at` column. This column is managed by the :trackable plugin.
|
21
|
+
#
|
22
|
+
# = methods
|
23
|
+
# - max_session_timedout? - true if the user's session is too old and must be reaped
|
24
|
+
#
|
25
|
+
#
|
26
|
+
module Lifetimed
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
def self.required_fields(klass)
|
30
|
+
[:current_sign_in_at]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Has the session reached its maximum allowed lifespan?
|
34
|
+
def max_session_timedout?
|
35
|
+
return false if max_session_lifetime.nil?
|
36
|
+
return false if current_sign_in_at.nil?
|
37
|
+
current_sign_in_at <= max_session_lifetime.ago
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def max_session_lifetime
|
43
|
+
Authenticate.configuration.max_session_lifetime
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'authenticate/callbacks/timeoutable'
|
2
|
+
|
3
|
+
module Authenticate
|
4
|
+
module Model
|
5
|
+
|
6
|
+
# Expire user sessions that have not been accessed within a certain period of time.
|
7
|
+
# Expired users will be asked for credentials again.
|
8
|
+
#
|
9
|
+
# == Columns
|
10
|
+
#
|
11
|
+
# This module expects and tracks this column on your user model:
|
12
|
+
# - last_access_at - timestamp of the last access by the user
|
13
|
+
#
|
14
|
+
# == Configuration
|
15
|
+
#
|
16
|
+
# Timeoutable is enabled and configured with the `timeout_in` configuration parameter.
|
17
|
+
# `timeout_in` expects a timestamp. Example:
|
18
|
+
#
|
19
|
+
# Authenticate.configure do |config|
|
20
|
+
# config.timeout_in = 15.minutes
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# You must specify a non-nil timeout_in in your initializer to enable Timeoutable.
|
24
|
+
#
|
25
|
+
module Timeoutable
|
26
|
+
extend ActiveSupport::Concern
|
27
|
+
|
28
|
+
def self.required_fields(klass)
|
29
|
+
[:last_access_at]
|
30
|
+
end
|
31
|
+
|
32
|
+
# Checks whether the user session has expired based on configured time.
|
33
|
+
def timedout?
|
34
|
+
Rails.logger.info "User.timedout? timeout_in:#{timeout_in} last_access_at:#{last_access_at}"
|
35
|
+
return false if timeout_in.nil?
|
36
|
+
return false if last_access_at.nil?
|
37
|
+
# result = Time.now.utc > (last_access_at + timeout_in)
|
38
|
+
Rails.logger.info "User.timedout? #{last_access_at >= timeout_in.ago} timeout_in.ago:#{timeout_in.ago} last_access_at:#{last_access_at}"
|
39
|
+
last_access_at <= timeout_in.ago
|
40
|
+
end
|
41
|
+
|
42
|
+
def timeout_in
|
43
|
+
Authenticate.configuration.timeout_in
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|