Bring rememberable back.
This commit is contained in:
parent
f46d1b1d81
commit
2afad49a96
|
@ -27,8 +27,8 @@ module Devise
|
|||
autoload :MongoMapper, 'devise/orm/mongo_mapper'
|
||||
end
|
||||
|
||||
ALL = [:authenticatable, :activatable, :confirmable, :recoverable, :rememberable,
|
||||
:timeoutable, :trackable, :validatable, :lockable]
|
||||
ALL = [:authenticatable, :activatable, :confirmable, :recoverable,
|
||||
:rememberable, :validatable, :trackable, :timeoutable, :lockable]
|
||||
|
||||
# Maps controller names to devise modules
|
||||
CONTROLLERS = {
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
# Each time the user is set we verify if it is still able to really sign in.
|
||||
# This is done by checking the time frame the user is able to sign in without
|
||||
# confirming it's account. If the user has not confirmed it's account during
|
||||
# this time frame, he/she will not able to sign in anymore.
|
||||
# Deny user access whenever his account is not active yet.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
if record && record.respond_to?(:active?) && !record.active?
|
||||
scope = options[:scope]
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
# After authenticate hook to verify if the user in the given scope asked to be
|
||||
# remembered while he does not sign out. Generates a new remember token for
|
||||
# that specific user and adds a cookie with this user info to sign in this user
|
||||
# automatically without asking for credentials. Refer to rememberable strategy
|
||||
# for more info.
|
||||
Warden::Manager.after_authentication do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
remember_me = warden.params[scope].try(:fetch, :remember_me, nil)
|
||||
|
||||
if Devise::TRUE_VALUES.include?(remember_me) &&
|
||||
warden.authenticated?(scope) && record.respond_to?(:remember_me!)
|
||||
record.remember_me!
|
||||
|
||||
warden.response.set_cookie "remember_#{scope}_token", {
|
||||
:value => record.class.serialize_into_cookie(record),
|
||||
:expires => record.remember_expires_at,
|
||||
:path => "/"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Before logout hook to forget the user in the given scope, only if rememberable
|
||||
# is activated for this scope. Also clear remember token to ensure the user
|
||||
# won't be remembered again.
|
||||
Warden::Manager.before_logout do |record, warden, scope|
|
||||
if record.respond_to?(:forget_me!)
|
||||
record.forget_me!
|
||||
warden.response.delete_cookie "remember_#{scope}_token"
|
||||
end
|
||||
end
|
|
@ -5,12 +5,14 @@
|
|||
# verify timeout in the following request.
|
||||
Warden::Manager.after_set_user do |record, warden, options|
|
||||
scope = options[:scope]
|
||||
if record && record.respond_to?(:timeout?) && warden.authenticated?(scope)
|
||||
if record && record.respond_to?(:timedout?) && warden.authenticated?(scope)
|
||||
last_request_at = warden.session(scope)['last_request_at']
|
||||
if record.timeout?(last_request_at)
|
||||
|
||||
if record.timedout?(last_request_at)
|
||||
warden.logout(scope)
|
||||
throw :warden, :scope => scope, :message => :timeout
|
||||
end
|
||||
|
||||
warden.session(scope)['last_request_at'] = Time.now.utc
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
require 'devise/strategies/rememberable'
|
||||
require 'devise/hooks/rememberable'
|
||||
|
||||
module Devise
|
||||
module Models
|
||||
# Rememberable manages generating and clearing token for remember the user
|
||||
|
|
|
@ -16,7 +16,7 @@ module Devise
|
|||
end
|
||||
|
||||
# Checks whether the user session has expired based on configured time.
|
||||
def timeout?(last_access)
|
||||
def timedout?(last_access)
|
||||
last_access && last_access <= self.class.timeout_in.ago
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
# Taken from RailsWarden, thanks to Hassox. http://github.com/hassox/rails_warden
|
||||
module Warden::Mixins::Common
|
||||
def request
|
||||
return @request if @request
|
||||
if env['action_controller.rescue.request']
|
||||
@request = env['action_controller.rescue.request']
|
||||
else
|
||||
Rack::Request.new(env)
|
||||
end
|
||||
@request ||= env['action_controller.rescue.request']
|
||||
end
|
||||
|
||||
def reset_session!
|
||||
|
@ -15,22 +9,15 @@ module Warden::Mixins::Common
|
|||
end
|
||||
|
||||
def response
|
||||
return @response if @response
|
||||
if env['action_controller.rescue.response']
|
||||
@response = env['action_controller.rescue.response']
|
||||
else
|
||||
Rack::Response.new(env)
|
||||
end
|
||||
@response ||= env['action_controller.rescue.response']
|
||||
end
|
||||
end
|
||||
|
||||
class Warden::SessionSerializer
|
||||
# Hook to serialize user into session. Overwrite if you want.
|
||||
def serialize(record)
|
||||
[record.class, record.id]
|
||||
end
|
||||
|
||||
# Hook to serialize user from session. Overwrite if you want.
|
||||
def deserialize(keys)
|
||||
klass, id = keys
|
||||
klass.find(:first, :conditions => { :id => id })
|
||||
|
|
|
@ -4,9 +4,7 @@ module Devise
|
|||
module Strategies
|
||||
# Default strategy for signing in a user, based on his email and password.
|
||||
# Redirects to sign_in page if it's not authenticated
|
||||
class Authenticatable < Warden::Strategies::Base
|
||||
include Devise::Strategies::Base
|
||||
|
||||
class Authenticatable < Base
|
||||
def valid?
|
||||
super && params[scope] && params[scope][:password].present?
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Devise
|
||||
module Strategies
|
||||
# Base strategy for Devise. Responsible for verifying correct scope and mapping.
|
||||
module Base
|
||||
class Base < ::Warden::Strategies::Base
|
||||
# Validate strategy. By default will raise an error if no scope or an
|
||||
# invalid mapping is found.
|
||||
def valid?
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
require 'devise/strategies/base'
|
||||
|
||||
module Devise
|
||||
module Strategies
|
||||
# Remember the user through the remember token. This strategy is responsible
|
||||
# to verify whether there is a cookie with the remember token, and to
|
||||
# recreate the user from this cookie if it exists. Must be called *before*
|
||||
# authenticatable.
|
||||
class Rememberable < Devise::Strategies::Base
|
||||
|
||||
# A valid strategy for rememberable needs a remember token in the cookies.
|
||||
def valid?
|
||||
super && remember_me_cookie.present?
|
||||
end
|
||||
|
||||
# To authenticate a user we deserialize the cookie and attempt finding
|
||||
# the record in the database. If the attempt fails, we pass to another
|
||||
# strategy handle the authentication.
|
||||
def authenticate!
|
||||
if resource = mapping.to.serialize_from_cookie(remember_me_cookie)
|
||||
success!(resource)
|
||||
else
|
||||
pass
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Accessor for remember cookie
|
||||
def remember_me_cookie
|
||||
@remember_me_cookie ||= request.cookies["remember_#{mapping.name}_token"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Warden::Strategies.add(:rememberable, Devise::Strategies::Rememberable)
|
|
@ -1,63 +1,63 @@
|
|||
# require 'test/test_helper'
|
||||
#
|
||||
# class RememberMeTest < ActionController::IntegrationTest
|
||||
#
|
||||
# def create_user_and_remember(add_to_token='')
|
||||
# Devise.remember_for = 1
|
||||
# user = create_user
|
||||
# user.remember_me!
|
||||
# cookies['warden.user.user.key'] = User.serialize_into_cookie(user) + add_to_token
|
||||
# user
|
||||
# end
|
||||
#
|
||||
# test 'do not remember the user if he has not checked remember me option' do
|
||||
# user = sign_in_as_user
|
||||
# assert_nil user.reload.remember_token
|
||||
# end
|
||||
#
|
||||
# test 'generate remember token after sign in' do
|
||||
# user = sign_in_as_user :remember_me => true
|
||||
# assert_not_nil user.reload.remember_token
|
||||
# end
|
||||
#
|
||||
# test 'remember the user before sign in' do
|
||||
# user = create_user_and_remember
|
||||
# get users_path
|
||||
# assert_response :success
|
||||
# assert warden.authenticated?(:user)
|
||||
# assert warden.user(:user) == user
|
||||
# end
|
||||
#
|
||||
# test 'do not remember with invalid token' do
|
||||
# user = create_user_and_remember('add')
|
||||
# get users_path
|
||||
# assert_response :success
|
||||
# assert_not warden.authenticated?(:user)
|
||||
# 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
|
||||
# user = create_user_and_remember
|
||||
# get users_path
|
||||
# assert warden.authenticated?(:user)
|
||||
# get destroy_user_session_path
|
||||
# assert_not warden.authenticated?(:user)
|
||||
# assert_nil user.reload.remember_token
|
||||
# end
|
||||
#
|
||||
# test 'do not remember the user anymore after forget' do
|
||||
# user = create_user_and_remember
|
||||
# get users_path
|
||||
# assert warden.authenticated?(:user)
|
||||
# get destroy_user_session_path
|
||||
# get users_path
|
||||
# assert_not warden.authenticated?(:user)
|
||||
# end
|
||||
# end
|
||||
require 'test/test_helper'
|
||||
|
||||
class RememberMeTest < ActionController::IntegrationTest
|
||||
|
||||
def create_user_and_remember(add_to_token='')
|
||||
Devise.remember_for = 1
|
||||
user = create_user
|
||||
user.remember_me!
|
||||
cookies['remember_user_token'] = User.serialize_into_cookie(user) + add_to_token
|
||||
user
|
||||
end
|
||||
|
||||
test 'do not remember the user if he has not checked remember me option' do
|
||||
user = sign_in_as_user
|
||||
assert_nil user.reload.remember_token
|
||||
end
|
||||
|
||||
test 'generate remember token after sign in' do
|
||||
user = sign_in_as_user :remember_me => true
|
||||
assert_not_nil user.reload.remember_token
|
||||
end
|
||||
|
||||
test 'remember the user before sign in' do
|
||||
user = create_user_and_remember
|
||||
get users_path
|
||||
assert_response :success
|
||||
assert warden.authenticated?(:user)
|
||||
assert warden.user(:user) == user
|
||||
end
|
||||
|
||||
test 'do not remember with invalid token' do
|
||||
user = create_user_and_remember('add')
|
||||
get users_path
|
||||
assert_response :success
|
||||
assert_not warden.authenticated?(:user)
|
||||
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
|
||||
user = create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
get destroy_user_session_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
assert_nil user.reload.remember_token
|
||||
end
|
||||
|
||||
test 'do not remember the user anymore after forget' do
|
||||
user = create_user_and_remember
|
||||
get users_path
|
||||
assert warden.authenticated?(:user)
|
||||
get destroy_user_session_path
|
||||
get users_path
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,26 +3,26 @@ require 'test/test_helper'
|
|||
class TimeoutableTest < ActiveSupport::TestCase
|
||||
|
||||
test 'should be expired' do
|
||||
assert new_user.timeout?(31.minutes.ago)
|
||||
assert new_user.timedout?(31.minutes.ago)
|
||||
end
|
||||
|
||||
test 'should not be expired' do
|
||||
assert_not new_user.timeout?(29.minutes.ago)
|
||||
assert_not new_user.timedout?(29.minutes.ago)
|
||||
end
|
||||
|
||||
test 'should not be expired when params is nil' do
|
||||
assert_not new_user.timeout?(nil)
|
||||
assert_not new_user.timedout?(nil)
|
||||
end
|
||||
|
||||
test 'fallback to Devise config option' do
|
||||
swap Devise, :timeout_in => 1.minute do
|
||||
user = new_user
|
||||
assert user.timeout?(2.minutes.ago)
|
||||
assert_not user.timeout?(30.seconds.ago)
|
||||
assert user.timedout?(2.minutes.ago)
|
||||
assert_not user.timedout?(30.seconds.ago)
|
||||
|
||||
Devise.timeout_in = 5.minutes
|
||||
assert_not user.timeout?(2.minutes.ago)
|
||||
assert user.timeout?(6.minutes.ago)
|
||||
assert_not user.timedout?(2.minutes.ago)
|
||||
assert user.timedout?(6.minutes.ago)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue