Remember the user only if the remember token has not expired.
This commit is contained in:
parent
bbca9e830e
commit
5631b8dacd
|
@ -40,11 +40,11 @@ module Devise
|
||||||
string :reset_password_token, :limit => 20
|
string :reset_password_token, :limit => 20
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates remember_token and remember_expires_at.
|
# Creates remember_token and remember_created_at.
|
||||||
#
|
#
|
||||||
def rememberable
|
def rememberable
|
||||||
string :remember_token, :limit => 20
|
string :remember_token, :limit => 20
|
||||||
datetime :remember_expires_at
|
datetime :remember_created_at
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,6 +22,7 @@ module Devise
|
||||||
# # lookup the user based on the incoming cookie information
|
# # lookup the user based on the incoming cookie information
|
||||||
# User.serialize_from_cookie(cookie_string)
|
# User.serialize_from_cookie(cookie_string)
|
||||||
module Rememberable
|
module Rememberable
|
||||||
|
Devise.model_config(self, :remember_for, 0)
|
||||||
|
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.class_eval do
|
base.class_eval do
|
||||||
|
@ -36,6 +37,7 @@ module Devise
|
||||||
# Generate a new remember token and save the record without validations.
|
# Generate a new remember token and save the record without validations.
|
||||||
def remember_me!
|
def remember_me!
|
||||||
self.remember_token = friendly_token
|
self.remember_token = friendly_token
|
||||||
|
self.remember_created_at = Time.now
|
||||||
save(false)
|
save(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -44,27 +46,38 @@ module Devise
|
||||||
def forget_me!
|
def forget_me!
|
||||||
if remember_token?
|
if remember_token?
|
||||||
self.remember_token = nil
|
self.remember_token = nil
|
||||||
|
self.remember_created_at = nil
|
||||||
save(false)
|
save(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checks whether the incoming token matches or not with the record token.
|
# Checks whether the incoming token matches or not with the record token.
|
||||||
def valid_remember_token?(token)
|
def valid_remember_token?(token)
|
||||||
remember_token.present? && remember_token == token
|
!remember_expired? && remember_token == token
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remember token should be expired if expiration time not overpass now.
|
||||||
|
def remember_expired?
|
||||||
|
!remember_token? || remember_expires_at <= Time.now.utc
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remember token expires at created time + remember_for configuration
|
||||||
|
def remember_expires_at
|
||||||
|
remember_created_at + remember_for
|
||||||
end
|
end
|
||||||
|
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
|
||||||
# Create the cookie key using the record id and remember_token
|
# Create the cookie key using the record id and remember_token
|
||||||
def serialize_into_cookie(record)
|
def serialize_into_cookie(rememberable)
|
||||||
"#{record.id}::#{record.remember_token}"
|
"#{rememberable.id}::#{rememberable.remember_token}"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Recreate the user based on the stored cookie
|
# Recreate the user based on the stored cookie
|
||||||
def serialize_from_cookie(cookie)
|
def serialize_from_cookie(cookie)
|
||||||
record_id, remember_token = cookie.split('::')
|
rememberable_id, remember_token = cookie.split('::')
|
||||||
record = find_by_id(record_id)
|
rememberable = find_by_id(rememberable_id) if rememberable_id
|
||||||
record if record.try(:valid_remember_token?, remember_token)
|
rememberable if rememberable.try(:valid_remember_token?, remember_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,7 @@ require 'test/test_helper'
|
||||||
class RememberMeTest < ActionController::IntegrationTest
|
class RememberMeTest < ActionController::IntegrationTest
|
||||||
|
|
||||||
def create_user_and_remember(add_to_token='')
|
def create_user_and_remember(add_to_token='')
|
||||||
|
Devise.remember_for = 1
|
||||||
user = create_user
|
user = create_user
|
||||||
user.remember_me!
|
user.remember_me!
|
||||||
cookies['remember_token'] = User.serialize_into_cookie(user) + add_to_token
|
cookies['remember_token'] = User.serialize_into_cookie(user) + add_to_token
|
||||||
|
@ -36,6 +37,14 @@ class RememberMeTest < ActionController::IntegrationTest
|
||||||
assert_not warden.authenticated?(:user)
|
assert_not warden.authenticated?(:user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'do not remember with token expired' do
|
||||||
|
user = create_user_and_remember
|
||||||
|
Devise.remember_for = 0
|
||||||
|
get users_path
|
||||||
|
assert_response :success
|
||||||
|
assert_not warden.authenticated?(:user)
|
||||||
|
end
|
||||||
|
|
||||||
test 'forget the user before sign out' do
|
test 'forget the user before sign out' do
|
||||||
user = create_user_and_remember
|
user = create_user_and_remember
|
||||||
get users_path
|
get users_path
|
||||||
|
|
|
@ -209,7 +209,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
||||||
confirm_in = Devise.confirm_in
|
confirm_in = Devise.confirm_in
|
||||||
Devise.confirm_in = 1.day
|
Devise.confirm_in = 1.day
|
||||||
user = new_user
|
user = new_user
|
||||||
user.confirmation_sent_at = 2.day.ago
|
user.confirmation_sent_at = 2.days.ago
|
||||||
assert_not user.active?
|
assert_not user.active?
|
||||||
Devise.confirm_in = 3.days
|
Devise.confirm_in = 3.days
|
||||||
assert user.active?
|
assert user.active?
|
||||||
|
|
|
@ -2,6 +2,10 @@ require 'test/test_helper'
|
||||||
|
|
||||||
class RememberableTest < ActiveSupport::TestCase
|
class RememberableTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
|
def setup
|
||||||
|
Devise.remember_for = 1
|
||||||
|
end
|
||||||
|
|
||||||
test 'should respond to remember_me attribute' do
|
test 'should respond to remember_me attribute' do
|
||||||
user = new_user
|
user = new_user
|
||||||
assert user.respond_to?(:remember_me)
|
assert user.respond_to?(:remember_me)
|
||||||
|
@ -20,16 +24,32 @@ class RememberableTest < ActiveSupport::TestCase
|
||||||
assert_not user.changed?
|
assert_not user.changed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'remember_me should calculate expires_at based on remember_for setup' do
|
||||||
|
user = create_user
|
||||||
|
assert_not user.remember_created_at?
|
||||||
|
user.remember_me!
|
||||||
|
assert user.remember_created_at?
|
||||||
|
assert_equal Date.today, user.remember_created_at.to_date
|
||||||
|
end
|
||||||
|
|
||||||
test 'forget_me should clear remember token and save the record without validating' do
|
test 'forget_me should clear remember token and save the record without validating' do
|
||||||
user = create_user
|
user = create_user
|
||||||
user.remember_me!
|
user.remember_me!
|
||||||
assert_not_nil user.remember_token
|
assert user.remember_token?
|
||||||
user.expects(:valid?).never
|
user.expects(:valid?).never
|
||||||
user.forget_me!
|
user.forget_me!
|
||||||
assert_nil user.remember_token
|
assert_not user.remember_token?
|
||||||
assert_not user.changed?
|
assert_not user.changed?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'forget_me should clear remember_expires_at' do
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
assert user.remember_created_at?
|
||||||
|
user.forget_me!
|
||||||
|
assert_not user.remember_created_at?
|
||||||
|
end
|
||||||
|
|
||||||
test 'forget should do nothing if no remember token exists' do
|
test 'forget should do nothing if no remember token exists' do
|
||||||
user = create_user
|
user = create_user
|
||||||
user.expects(:save).never
|
user.expects(:save).never
|
||||||
|
@ -45,6 +65,13 @@ class RememberableTest < ActiveSupport::TestCase
|
||||||
assert_not user.valid_remember_token?(user.remember_token)
|
assert_not user.valid_remember_token?(user.remember_token)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'valid remember token should also verify if remember is not expired' do
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
user.update_attribute(:remember_created_at, 3.days.ago)
|
||||||
|
assert_not user.valid_remember_token?(user.remember_token)
|
||||||
|
end
|
||||||
|
|
||||||
test 'serialize into cookie' do
|
test 'serialize into cookie' do
|
||||||
user = create_user
|
user = create_user
|
||||||
user.remember_me!
|
user.remember_me!
|
||||||
|
@ -65,4 +92,56 @@ class RememberableTest < ActiveSupport::TestCase
|
||||||
user = create_user
|
user = create_user
|
||||||
assert_nil User.serialize_from_cookie("#{user.id}::#{user.remember_token}123")
|
assert_nil User.serialize_from_cookie("#{user.id}::#{user.remember_token}123")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'remember for should fallback to devise remember for default configuration' do
|
||||||
|
begin
|
||||||
|
remember_for = Devise.remember_for
|
||||||
|
user = create_user
|
||||||
|
Devise.remember_for = 1.day
|
||||||
|
user.remember_me!
|
||||||
|
assert_not user.remember_expired?
|
||||||
|
Devise.remember_for = 0.days
|
||||||
|
user.remember_me!
|
||||||
|
assert user.remember_expired?
|
||||||
|
ensure
|
||||||
|
Devise.remember_for = remember_for
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'remember should be expired without remember token' do
|
||||||
|
user = create_user
|
||||||
|
assert user.remember_expired?
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'remember expires at should sum date of creation with remember for configuration' do
|
||||||
|
Devise.remember_for = 3.days
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
assert_equal 3.days.from_now.to_date, user.remember_expires_at.to_date
|
||||||
|
Devise.remember_for = 5.days
|
||||||
|
assert_equal 5.days.from_now.to_date, user.remember_expires_at.to_date
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'remember should be expired if remember_for is zero' do
|
||||||
|
Devise.remember_for = 0.days
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
assert user.remember_expired?
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'remember should be expired if it was created before limit time' do
|
||||||
|
Devise.remember_for = 1.day
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
user.update_attribute(:remember_created_at, 2.days.ago)
|
||||||
|
assert user.remember_expired?
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'remember should not be expired if it was created whitin the limit time' do
|
||||||
|
Devise.remember_for = 30.days
|
||||||
|
user = create_user
|
||||||
|
user.remember_me!
|
||||||
|
user.update_attribute(:remember_created_at, 30.days.ago + 2.minutes)
|
||||||
|
assert_not user.remember_expired?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue