devise 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +6 -0
- data/README.rdoc +2 -1
- data/TODO +0 -3
- data/generators/devise_install/templates/devise.rb +1 -1
- data/lib/devise.rb +4 -3
- data/lib/devise/hooks/timeoutable.rb +7 -10
- data/lib/devise/hooks/trackable.rb +18 -0
- data/lib/devise/models.rb +22 -0
- data/lib/devise/models/authenticatable.rb +30 -31
- data/lib/devise/models/confirmable.rb +4 -9
- data/lib/devise/models/recoverable.rb +5 -7
- data/lib/devise/models/rememberable.rb +1 -1
- data/lib/devise/models/timeoutable.rb +2 -2
- data/lib/devise/models/trackable.rb +16 -0
- data/lib/devise/models/validatable.rb +15 -0
- data/lib/devise/orm/data_mapper.rb +9 -5
- data/lib/devise/schema.rb +10 -0
- data/lib/devise/version.rb +1 -1
- data/test/integration/confirmable_test.rb +2 -1
- data/test/integration/timeoutable_test.rb +12 -17
- data/test/integration/trackable_test.rb +64 -0
- data/test/models/authenticatable_test.rb +21 -36
- data/test/models/confirmable_test.rb +25 -40
- data/test/models/recoverable_test.rb +17 -20
- data/test/models/rememberable_test.rb +27 -28
- data/test/models/timeoutable_test.rb +5 -4
- data/test/models/trackable_test.rb +5 -0
- data/test/models/validatable_test.rb +6 -0
- data/test/models_test.rb +14 -15
- data/test/rails_app/app/controllers/users_controller.rb +3 -8
- data/test/rails_app/app/models/admin.rb +1 -1
- data/test/rails_app/app/models/user.rb +1 -0
- data/test/rails_app/config/routes.rb +1 -1
- data/test/test_helper.rb +2 -0
- metadata +42 -39
data/CHANGELOG.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -7,13 +7,14 @@ Devise is a flexible authentication solution for Rails based on Warden. It:
|
|
7
7
|
* Allows you to have multiple roles (or models/scopes) signed in at the same time;
|
8
8
|
* Is based on a modularity concept: use just what you really need.
|
9
9
|
|
10
|
-
Right now it's composed of
|
10
|
+
Right now it's composed of seven mainly modules:
|
11
11
|
|
12
12
|
* Authenticatable: responsible for encrypting password and validating authenticity of a user while signing in.
|
13
13
|
* Confirmable: responsible for verifying whether an account is already confirmed to sign in, and to send emails with confirmation instructions.
|
14
14
|
* Recoverable: takes care of reseting the user password and send reset instructions.
|
15
15
|
* Rememberable: manages generating and clearing token for remember the user from a saved cookie.
|
16
16
|
* Timeoutable: expires sessions without activity in a certain period of time.
|
17
|
+
* Trackable: tracks sign in count, timestamps and ip.
|
17
18
|
* Validatable: creates all needed validations for email and password. It's totally optional, so you're able to to customize validations by yourself.
|
18
19
|
|
19
20
|
There's an example application using Devise at http://github.com/plataformatec/devise_example .
|
data/TODO
CHANGED
@@ -36,7 +36,7 @@ Devise.setup do |config|
|
|
36
36
|
|
37
37
|
# The time you want to timeout the user session without activity. After this
|
38
38
|
# time the user will be asked for credentials again.
|
39
|
-
# config.
|
39
|
+
# config.timeout_in = 10.minutes
|
40
40
|
|
41
41
|
# Configure the e-mail address which will be shown in DeviseMailer.
|
42
42
|
# config.mailer_sender = "foo.bar@yourapp.com"
|
data/lib/devise.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Devise
|
2
|
-
ALL = [:authenticatable, :confirmable, :recoverable, :rememberable,
|
2
|
+
ALL = [:authenticatable, :confirmable, :recoverable, :rememberable,
|
3
|
+
:timeoutable, :trackable, :validatable].freeze
|
3
4
|
|
4
5
|
# Maps controller names to devise modules
|
5
6
|
CONTROLLERS = {
|
@@ -46,8 +47,8 @@ module Devise
|
|
46
47
|
@@confirm_within = 0.days
|
47
48
|
|
48
49
|
# Time interval to timeout the user session without activity.
|
49
|
-
mattr_accessor :
|
50
|
-
@@
|
50
|
+
mattr_accessor :timeout_in
|
51
|
+
@@timeout_in = 30.minutes
|
51
52
|
|
52
53
|
# Used to define the password encryption algorithm.
|
53
54
|
mattr_accessor :encryptor
|
@@ -4,16 +4,13 @@
|
|
4
4
|
# record is set, we set the last request time inside it's scoped session to
|
5
5
|
# verify timeout in the following request.
|
6
6
|
Warden::Manager.after_set_user do |record, warden, options|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
if
|
11
|
-
|
12
|
-
|
13
|
-
warden.logout(scope)
|
14
|
-
throw :warden, :scope => scope, :message => :timeout
|
15
|
-
end
|
16
|
-
warden.session(scope)['last_request_at'] = Time.now.utc
|
7
|
+
scope = options[:scope]
|
8
|
+
if record && record.respond_to?(:timeout?) && warden.authenticated?(scope)
|
9
|
+
last_request_at = warden.session(scope)['last_request_at']
|
10
|
+
if record.timeout?(last_request_at)
|
11
|
+
warden.logout(scope)
|
12
|
+
throw :warden, :scope => scope, :message => :timeout
|
17
13
|
end
|
14
|
+
warden.session(scope)['last_request_at'] = Time.now.utc
|
18
15
|
end
|
19
16
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# After each sign in, update sign in time, sign in count and sign in IP.
|
2
|
+
Warden::Manager.after_authentication do |record, warden, options|
|
3
|
+
scope = options[:scope]
|
4
|
+
if Devise.mappings[scope].try(:trackable?) && warden.authenticated?(scope)
|
5
|
+
old_current, new_current = record.current_sign_in_at, Time.now
|
6
|
+
record.last_sign_in_at = old_current || new_current
|
7
|
+
record.current_sign_in_at = new_current
|
8
|
+
|
9
|
+
old_current, new_current = record.current_sign_in_ip, warden.request.remote_ip
|
10
|
+
record.last_sign_in_ip = old_current || new_current
|
11
|
+
record.current_sign_in_ip = new_current
|
12
|
+
|
13
|
+
record.sign_in_count ||= 0
|
14
|
+
record.sign_in_count += 1
|
15
|
+
|
16
|
+
record.save(false)
|
17
|
+
end
|
18
|
+
end
|
data/lib/devise/models.rb
CHANGED
@@ -75,6 +75,7 @@ module Devise
|
|
75
75
|
options = modules.extract_options!
|
76
76
|
modules = Devise.all if modules.include?(:all)
|
77
77
|
modules -= Array(options.delete(:except))
|
78
|
+
modules = Devise::ALL & modules
|
78
79
|
|
79
80
|
if !modules.include?(:authenticatable)
|
80
81
|
modules = [:authenticatable] | modules
|
@@ -96,5 +97,26 @@ module Devise
|
|
96
97
|
def devise_modules
|
97
98
|
@devise_modules ||= []
|
98
99
|
end
|
100
|
+
|
101
|
+
# Find an initialize a record setting an error if it can't be found
|
102
|
+
def find_or_initialize_with_error_by(attribute, value, error=:invalid)
|
103
|
+
if value.present?
|
104
|
+
conditions = { attribute => value }
|
105
|
+
record = find(:first, :conditions => conditions)
|
106
|
+
end
|
107
|
+
|
108
|
+
unless record
|
109
|
+
record = new
|
110
|
+
|
111
|
+
if value.present?
|
112
|
+
record.send(:"#{attribute}=", value)
|
113
|
+
record.errors.add(attribute, error, :default => error.to_s.gsub("_", " "))
|
114
|
+
else
|
115
|
+
record.errors.add(attribute, :blank)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
record
|
120
|
+
end
|
99
121
|
end
|
100
122
|
end
|
@@ -38,16 +38,17 @@ module Devise
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
# Regenerates password salt and encrypted password each time password is
|
42
|
-
# setted.
|
41
|
+
# Regenerates password salt and encrypted password each time password is set.
|
43
42
|
def password=(new_password)
|
44
43
|
@password = new_password
|
45
|
-
|
46
|
-
|
44
|
+
|
45
|
+
if @password.present?
|
46
|
+
self.password_salt = Devise.friendly_token
|
47
|
+
self.encrypted_password = password_digest(@password)
|
48
|
+
end
|
47
49
|
end
|
48
50
|
|
49
|
-
# Verifies whether an incoming_password (ie from login) is the user
|
50
|
-
# password.
|
51
|
+
# Verifies whether an incoming_password (ie from login) is the user password.
|
51
52
|
def valid_password?(incoming_password)
|
52
53
|
password_digest(incoming_password) == encrypted_password
|
53
54
|
end
|
@@ -66,31 +67,8 @@ module Devise
|
|
66
67
|
def authenticate(attributes={})
|
67
68
|
return unless authentication_keys.all? { |k| attributes[k].present? }
|
68
69
|
conditions = attributes.slice(*authentication_keys)
|
69
|
-
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
# Find first record based on conditions given (ie by the sign in form).
|
74
|
-
# Overwrite to add customized conditions, create a join, or maybe use a
|
75
|
-
# namedscope to filter records while authenticating.
|
76
|
-
# Example:
|
77
|
-
#
|
78
|
-
# def self.find_for_authentication(conditions={})
|
79
|
-
# conditions[:active] = true
|
80
|
-
# find(:first, :conditions => conditions)
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
def find_for_authentication(conditions)
|
84
|
-
find(:first, :conditions => conditions)
|
85
|
-
end
|
86
|
-
|
87
|
-
# Attempt to find a user by it's email. If not user is found, returns a
|
88
|
-
# new user with an email not found error.
|
89
|
-
def find_or_initialize_with_error_by_email(email)
|
90
|
-
attributes = { :email => email }
|
91
|
-
record = find(:first, :conditions => attributes) || new(attributes)
|
92
|
-
record.errors.add(:email, :not_found, :default => 'not found') if record.new_record?
|
93
|
-
record
|
70
|
+
resource = find_for_authentication(conditions)
|
71
|
+
valid_for_authentication(resource, attributes) if resource
|
94
72
|
end
|
95
73
|
|
96
74
|
# Hook to serialize user into session. Overwrite if you want.
|
@@ -110,6 +88,27 @@ module Devise
|
|
110
88
|
@encryptor_class ||= ::Devise::Encryptors.const_get(encryptor.to_s.classify)
|
111
89
|
end
|
112
90
|
|
91
|
+
protected
|
92
|
+
|
93
|
+
# Find first record based on conditions given (ie by the sign in form).
|
94
|
+
# Overwrite to add customized conditions, create a join, or maybe use a
|
95
|
+
# namedscope to filter records while authenticating.
|
96
|
+
# Example:
|
97
|
+
#
|
98
|
+
# def self.find_for_authentication(conditions={})
|
99
|
+
# conditions[:active] = true
|
100
|
+
# find(:first, :conditions => conditions)
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
def find_for_authentication(conditions)
|
104
|
+
find(:first, :conditions => conditions)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Contains the logic used in authentication. Overwritten by other devise modules.
|
108
|
+
def valid_for_authentication(resource, attributes)
|
109
|
+
resource if resource.valid_password?(attributes[:password])
|
110
|
+
end
|
111
|
+
|
113
112
|
Devise::Models.config(self, :pepper, :stretches, :encryptor, :authentication_keys)
|
114
113
|
end
|
115
114
|
end
|
@@ -100,8 +100,7 @@ module Devise
|
|
100
100
|
# confirmation_period_valid? # will always return false
|
101
101
|
#
|
102
102
|
def confirmation_period_valid?
|
103
|
-
confirmation_sent_at &&
|
104
|
-
((Time.now.utc - confirmation_sent_at.utc) < self.class.confirm_within)
|
103
|
+
confirmation_sent_at && confirmation_sent_at.utc >= self.class.confirm_within.ago
|
105
104
|
end
|
106
105
|
|
107
106
|
# Checks whether the record is confirmed or not, yielding to the block
|
@@ -129,7 +128,7 @@ module Devise
|
|
129
128
|
# with an email not found error.
|
130
129
|
# Options must contain the user email
|
131
130
|
def send_confirmation_instructions(attributes={})
|
132
|
-
confirmable =
|
131
|
+
confirmable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
|
133
132
|
confirmable.reset_confirmation! unless confirmable.new_record?
|
134
133
|
confirmable
|
135
134
|
end
|
@@ -139,12 +138,8 @@ module Devise
|
|
139
138
|
# If the user is already confirmed, create an error for the user
|
140
139
|
# Options must have the confirmation_token
|
141
140
|
def confirm!(attributes={})
|
142
|
-
confirmable =
|
143
|
-
|
144
|
-
confirmable.errors.add(:confirmation_token, :invalid)
|
145
|
-
else
|
146
|
-
confirmable.confirm!
|
147
|
-
end
|
141
|
+
confirmable = find_or_initialize_with_error_by(:confirmation_token, attributes[:confirmation_token])
|
142
|
+
confirmable.confirm! unless confirmable.new_record?
|
148
143
|
confirmable
|
149
144
|
end
|
150
145
|
|
@@ -6,9 +6,11 @@ module Devise
|
|
6
6
|
#
|
7
7
|
# # resets the user password and save the record, true if valid passwords are given, otherwise false
|
8
8
|
# User.find(1).reset_password!('password123', 'password123')
|
9
|
+
#
|
9
10
|
# # only resets the user password, without saving the record
|
10
11
|
# user = User.find(1)
|
11
12
|
# user.reset_password('password123', 'password123')
|
13
|
+
#
|
12
14
|
# # creates a new token and send it with instructions about how to reset the password
|
13
15
|
# User.find(1).send_reset_password_instructions
|
14
16
|
module Recoverable
|
@@ -62,7 +64,7 @@ module Devise
|
|
62
64
|
# with an email not found error.
|
63
65
|
# Attributes must contain the user email
|
64
66
|
def send_reset_password_instructions(attributes={})
|
65
|
-
recoverable =
|
67
|
+
recoverable = find_or_initialize_with_error_by(:email, attributes[:email], :not_found)
|
66
68
|
recoverable.send_reset_password_instructions unless recoverable.new_record?
|
67
69
|
recoverable
|
68
70
|
end
|
@@ -73,12 +75,8 @@ module Devise
|
|
73
75
|
# containing an error in reset_password_token attribute.
|
74
76
|
# Attributes must contain reset_password_token, password and confirmation
|
75
77
|
def reset_password!(attributes={})
|
76
|
-
recoverable =
|
77
|
-
|
78
|
-
recoverable.errors.add(:reset_password_token, :invalid)
|
79
|
-
else
|
80
|
-
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation])
|
81
|
-
end
|
78
|
+
recoverable = find_or_initialize_with_error_by(:reset_password_token, attributes[:reset_password_token])
|
79
|
+
recoverable.reset_password!(attributes[:password], attributes[:password_confirmation]) unless recoverable.new_record?
|
82
80
|
recoverable
|
83
81
|
end
|
84
82
|
end
|
@@ -82,7 +82,7 @@ module Devise
|
|
82
82
|
# Recreate the user based on the stored cookie
|
83
83
|
def serialize_from_cookie(cookie)
|
84
84
|
rememberable_id, remember_token = cookie.split('::')
|
85
|
-
rememberable =
|
85
|
+
rememberable = find(:first, :conditions => { :id => rememberable_id }) if rememberable_id
|
86
86
|
rememberable if rememberable.try(:valid_remember_token?, remember_token)
|
87
87
|
end
|
88
88
|
|
@@ -19,11 +19,11 @@ module Devise
|
|
19
19
|
|
20
20
|
# Checks whether the user session has expired based on configured time.
|
21
21
|
def timeout?(last_access)
|
22
|
-
last_access && last_access <= self.class.
|
22
|
+
last_access && last_access <= self.class.timeout_in.ago
|
23
23
|
end
|
24
24
|
|
25
25
|
module ClassMethods
|
26
|
-
Devise::Models.config(self, :
|
26
|
+
Devise::Models.config(self, :timeout_in)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'devise/hooks/trackable'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Models
|
5
|
+
# Track information about your user sign in. It tracks the following columns:
|
6
|
+
#
|
7
|
+
# * sign_in_count - Increased every time a sign in is made (by form, openid, oauth)
|
8
|
+
# * current_sign_in_at - A tiemstamp updated when the user signs in
|
9
|
+
# * last_sign_in_at - Holds the timestamp of the previous sign in
|
10
|
+
# * current_sign_in_ip - The remote ip updated when the user sign in
|
11
|
+
# * last_sign_in_at - Holds the remote ip of the previous sign in
|
12
|
+
#
|
13
|
+
module Trackable
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -10,7 +10,13 @@ module Devise
|
|
10
10
|
# Email regex used to validate email formats. Retrieved from authlogic.
|
11
11
|
EMAIL_REGEX = /\A[\w\.%\+\-]+@(?:[A-Z0-9\-]+\.)+(?:[A-Z]{2,4}|museum|travel)\z/i
|
12
12
|
|
13
|
+
# All validations used by this module.
|
14
|
+
VALIDATIONS = [ :validates_presence_of, :validates_uniqueness_of, :validates_format_of,
|
15
|
+
:validates_confirmation_of, :validates_length_of ].freeze
|
16
|
+
|
13
17
|
def self.included(base)
|
18
|
+
assert_validations_api!(base)
|
19
|
+
|
14
20
|
base.class_eval do
|
15
21
|
attribute = authentication_keys.first
|
16
22
|
|
@@ -27,6 +33,15 @@ module Devise
|
|
27
33
|
end
|
28
34
|
end
|
29
35
|
|
36
|
+
def self.assert_validations_api!(base) #:nodoc:
|
37
|
+
unavailable_validations = VALIDATIONS.select { |v| !base.respond_to?(v) }
|
38
|
+
|
39
|
+
unless unavailable_validations.empty?
|
40
|
+
raise "Could not use :validatable module since #{base} does not respond " <<
|
41
|
+
"to the following methods: #{unavailable_validations.to_sentence}."
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
30
45
|
protected
|
31
46
|
|
32
47
|
# Checks whether a password is needed or not. For validations only.
|
@@ -5,11 +5,6 @@ module Devise
|
|
5
5
|
klass.send :extend, self
|
6
6
|
yield
|
7
7
|
|
8
|
-
# DataMapper validations have a completely different API
|
9
|
-
if modules.include?(:validatable) && !klass.respond_to?(:validates_presence_of)
|
10
|
-
raise ":validatable is not supported in DataMapper, please craft your validations by hand"
|
11
|
-
end
|
12
|
-
|
13
8
|
modules.each do |mod|
|
14
9
|
klass.send(mod) if klass.respond_to?(mod)
|
15
10
|
end
|
@@ -44,6 +39,15 @@ module Devise
|
|
44
39
|
end
|
45
40
|
end
|
46
41
|
|
42
|
+
# In Datamapper, we need to call save! if we don't want to execute callbacks.
|
43
|
+
def save(flag=nil)
|
44
|
+
if flag == false
|
45
|
+
save!
|
46
|
+
else
|
47
|
+
super()
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
47
51
|
# Tell how to apply schema methods. This automatically maps :limit to
|
48
52
|
# :length and :null to :nullable.
|
49
53
|
def apply_schema(name, type, options={})
|
data/lib/devise/schema.rb
CHANGED
@@ -41,6 +41,16 @@ module Devise
|
|
41
41
|
apply_schema :remember_created_at, DateTime
|
42
42
|
end
|
43
43
|
|
44
|
+
# Creates sign_in_count, current_sign_in_at, last_sign_in_at,
|
45
|
+
# current_sign_in_ip, last_sign_in_ip.
|
46
|
+
def trackable
|
47
|
+
apply_schema :sign_in_count, Integer
|
48
|
+
apply_schema :current_sign_in_at, DateTime
|
49
|
+
apply_schema :last_sign_in_at, DateTime
|
50
|
+
apply_schema :current_sign_in_ip, String
|
51
|
+
apply_schema :last_sign_in_ip, String
|
52
|
+
end
|
53
|
+
|
44
54
|
# Overwrite with specific modification to create your own schema.
|
45
55
|
def apply_schema(name, type, options={})
|
46
56
|
raise NotImplementedError
|
data/lib/devise/version.rb
CHANGED
@@ -43,7 +43,8 @@ class ConfirmationTest < ActionController::IntegrationTest
|
|
43
43
|
end
|
44
44
|
|
45
45
|
test 'user already confirmed user should not be able to confirm the account again' do
|
46
|
-
user = create_user
|
46
|
+
user = create_user(:confirm => false)
|
47
|
+
user.update_attribute(:confirmed_at, Time.now)
|
47
48
|
visit_user_confirmation_with_token(user.confirmation_token)
|
48
49
|
|
49
50
|
assert_template 'confirmations/new'
|
@@ -10,17 +10,16 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
|
10
10
|
sign_in_as_user
|
11
11
|
old_last_request = last_request_at
|
12
12
|
assert_not_nil last_request_at
|
13
|
+
|
13
14
|
get users_path
|
14
15
|
assert_not_nil last_request_at
|
15
16
|
assert_not_equal old_last_request, last_request_at
|
16
17
|
end
|
17
18
|
|
18
19
|
test 'not time out user session before default limit time' do
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
get edit_user_path(user)
|
23
|
-
assert_not_nil last_request_at
|
20
|
+
sign_in_as_user
|
21
|
+
assert_response :success
|
22
|
+
assert warden.authenticated?(:user)
|
24
23
|
|
25
24
|
get users_path
|
26
25
|
assert_response :success
|
@@ -28,12 +27,8 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
|
28
27
|
end
|
29
28
|
|
30
29
|
test 'time out user session after default limit time' do
|
31
|
-
sign_in_as_user
|
32
|
-
|
33
|
-
assert warden.authenticated?(:user)
|
34
|
-
|
35
|
-
# Setup last_request_at to timeout
|
36
|
-
get new_user_path
|
30
|
+
user = sign_in_as_user
|
31
|
+
get expire_user_path(user)
|
37
32
|
assert_not_nil last_request_at
|
38
33
|
|
39
34
|
get users_path
|
@@ -42,15 +37,15 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
|
42
37
|
end
|
43
38
|
|
44
39
|
test 'user configured timeout limit' do
|
45
|
-
swap Devise, :
|
40
|
+
swap Devise, :timeout_in => 8.minutes do
|
46
41
|
user = sign_in_as_user
|
47
42
|
|
48
|
-
|
49
|
-
get edit_user_path(user)
|
43
|
+
get users_path
|
50
44
|
assert_not_nil last_request_at
|
51
45
|
assert_response :success
|
52
46
|
assert warden.authenticated?(:user)
|
53
47
|
|
48
|
+
get expire_user_path(user)
|
54
49
|
get users_path
|
55
50
|
assert_redirected_to new_user_session_path(:timeout => true)
|
56
51
|
assert_not warden.authenticated?(:user)
|
@@ -61,9 +56,9 @@ class SessionTimeoutTest < ActionController::IntegrationTest
|
|
61
56
|
store_translations :en, :devise => {
|
62
57
|
:sessions => { :user => { :timeout => 'Session expired!' } }
|
63
58
|
} do
|
64
|
-
sign_in_as_user
|
65
|
-
|
66
|
-
get
|
59
|
+
user = sign_in_as_user
|
60
|
+
|
61
|
+
get expire_user_path(user)
|
67
62
|
get users_path
|
68
63
|
follow_redirect!
|
69
64
|
assert_contain 'Session expired!'
|