devise 0.7.3 → 0.7.4
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 +4 -0
- data/README.rdoc +1 -0
- data/Rakefile +11 -3
- data/TODO +6 -3
- data/generators/devise_install/templates/devise.rb +7 -3
- data/lib/devise.rb +12 -7
- data/lib/devise/controllers/helpers.rb +1 -1
- data/lib/devise/hooks/{confirmable.rb → activatable.rb} +5 -4
- data/lib/devise/locales/en.yml +2 -0
- data/lib/devise/models.rb +20 -7
- data/lib/devise/models/activatable.rb +16 -0
- data/lib/devise/models/authenticatable.rb +14 -22
- data/lib/devise/models/confirmable.rb +12 -6
- data/lib/devise/models/cookie_serializer.rb +21 -0
- data/lib/devise/models/rememberable.rb +2 -20
- data/lib/devise/models/session_serializer.rb +19 -0
- data/lib/devise/models/validatable.rb +0 -4
- data/lib/devise/serializers/base.rb +2 -9
- data/lib/devise/serializers/cookie.rb +43 -0
- data/lib/devise/serializers/session.rb +22 -0
- data/lib/devise/version.rb +1 -1
- data/test/integration/confirmable_test.rb +3 -2
- data/test/integration/recoverable_test.rb +1 -1
- data/test/mapping_test.rb +9 -9
- data/test/models/authenticatable_test.rb +1 -1
- data/test/models/confirmable_test.rb +7 -5
- data/test/models/recoverable_test.rb +3 -3
- data/test/models/rememberable_test.rb +11 -5
- data/test/models/validatable_test.rb +1 -0
- data/test/models_test.rb +10 -10
- data/test/orm/active_record.rb +29 -0
- data/test/orm/mongo_mapper.rb +21 -0
- data/test/rails_app/app/{models → active_record}/account.rb +0 -0
- data/test/rails_app/app/{models → active_record}/admin.rb +1 -1
- data/test/rails_app/app/{models → active_record}/user.rb +1 -1
- data/test/rails_app/app/mongo_mapper/account.rb +9 -0
- data/test/rails_app/app/mongo_mapper/admin.rb +9 -0
- data/test/rails_app/app/mongo_mapper/user.rb +6 -0
- data/test/rails_app/config/environment.rb +3 -3
- data/test/rails_app/config/initializers/devise.rb +76 -0
- data/test/rails_app/config/routes.rb +2 -5
- data/test/routes_test.rb +4 -16
- data/test/support/assertions_helper.rb +15 -0
- data/test/support/integration_tests_helper.rb +1 -1
- data/test/support/model_tests_helper.rb +0 -15
- data/test/support/test_silencer.rb +5 -0
- data/test/test_helper.rb +7 -30
- data/test/test_helpers_test.rb +2 -6
- metadata +18 -9
- data/lib/devise/serializers/authenticatable.rb +0 -11
- data/lib/devise/serializers/rememberable.rb +0 -30
- data/test/rails_app/app/models/organizer.rb +0 -3
@@ -7,24 +7,17 @@ module Devise
|
|
7
7
|
attr_reader :scope
|
8
8
|
|
9
9
|
def serialize(record)
|
10
|
-
record.class.send(:"serialize_into_#{
|
10
|
+
record.class.send(:"serialize_into_#{klass_type}", record)
|
11
11
|
end
|
12
12
|
|
13
13
|
def deserialize(keys)
|
14
|
-
mapping.to.send(:"serialize_from_#{
|
14
|
+
mapping.to.send(:"serialize_from_#{klass_type}", keys)
|
15
15
|
end
|
16
16
|
|
17
17
|
def fetch(scope)
|
18
18
|
@scope = scope
|
19
19
|
super
|
20
20
|
end
|
21
|
-
|
22
|
-
def serialization_type
|
23
|
-
@serialization_type ||= begin
|
24
|
-
warden = self.class.ancestors.find{ |k| k < Warden::Serializers::Base && k != self.class }
|
25
|
-
warden.name.split("::").last.underscore
|
26
|
-
end
|
27
|
-
end
|
28
21
|
end
|
29
22
|
end
|
30
23
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'devise/serializers/base'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Serializers
|
5
|
+
# This is a cookie serializer which stores the information if a :remember_me
|
6
|
+
# is sent in the params and if the model responds to remember_me! as well.
|
7
|
+
# As in Session serializer, the invoked methods are:
|
8
|
+
#
|
9
|
+
# User.serialize_into_cookie(@user)
|
10
|
+
# User.serialize_from_cookie(*args)
|
11
|
+
#
|
12
|
+
# An implementation for such methods can be found at Devise::Models::Rememberable.
|
13
|
+
#
|
14
|
+
# Differently from session, this approach is based in a token which is stored in
|
15
|
+
# the database. So if you want to sign out all clients at once, you just need to
|
16
|
+
# clean up the token column.
|
17
|
+
#
|
18
|
+
class Cookie < Warden::Serializers::Cookie
|
19
|
+
include Devise::Serializers::Base
|
20
|
+
|
21
|
+
def store(record, scope)
|
22
|
+
remember_me = params[scope].try(:fetch, :remember_me, nil)
|
23
|
+
if Devise::TRUE_VALUES.include?(remember_me) && record.respond_to?(:remember_me!)
|
24
|
+
record.remember_me!
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def default_options(record)
|
30
|
+
super.merge!(:expires => record.remember_expires_at)
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(scope, record=nil)
|
34
|
+
if record && record.respond_to?(:forget_me!)
|
35
|
+
record.forget_me!
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Warden::Serializers.add(:cookie, Devise::Serializers::Cookie)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'devise/serializers/base'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Serializers
|
5
|
+
# This serializer stores sign in information in th client session. It just
|
6
|
+
# extends Warden own serializer to move all the serialization logic to a
|
7
|
+
# class. For example, if a @user resource is given, it will call the following
|
8
|
+
# two methods to serialize and deserialize a record:
|
9
|
+
#
|
10
|
+
# User.serialize_into_session(@user)
|
11
|
+
# User.serialize_from_session(*args)
|
12
|
+
#
|
13
|
+
# This can be used any strategy and the default implementation is available
|
14
|
+
# at Devise::Models::SessionSerializer.
|
15
|
+
#
|
16
|
+
class Session < Warden::Serializers::Session
|
17
|
+
include Devise::Serializers::Base
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Warden::Serializers.add(:session, Devise::Serializers::Session)
|
data/lib/devise/version.rb
CHANGED
@@ -27,7 +27,7 @@ class ConfirmationTest < ActionController::IntegrationTest
|
|
27
27
|
assert_response :success
|
28
28
|
assert_template 'confirmations/new'
|
29
29
|
assert_have_selector '#errorExplanation'
|
30
|
-
assert_contain
|
30
|
+
assert_contain /Confirmation token(.*)invalid/
|
31
31
|
end
|
32
32
|
|
33
33
|
test 'user with valid confirmation token should be able to confirm an account' do
|
@@ -44,7 +44,8 @@ class ConfirmationTest < ActionController::IntegrationTest
|
|
44
44
|
|
45
45
|
test 'user already confirmed user should not be able to confirm the account again' do
|
46
46
|
user = create_user(:confirm => false)
|
47
|
-
user.
|
47
|
+
user.confirmed_at = Time.now
|
48
|
+
user.save
|
48
49
|
visit_user_confirmation_with_token(user.confirmation_token)
|
49
50
|
|
50
51
|
assert_template 'confirmations/new'
|
@@ -78,7 +78,7 @@ class PasswordTest < ActionController::IntegrationTest
|
|
78
78
|
assert_response :success
|
79
79
|
assert_template 'passwords/edit'
|
80
80
|
assert_have_selector '#errorExplanation'
|
81
|
-
assert_contain
|
81
|
+
assert_contain /Reset password token(.*)invalid/
|
82
82
|
assert_not user.reload.valid_password?('987654321')
|
83
83
|
end
|
84
84
|
|
data/test/mapping_test.rb
CHANGED
@@ -14,8 +14,8 @@ class MappingTest < ActiveSupport::TestCase
|
|
14
14
|
assert_equal :admin_area, Devise.mappings[:admin].as
|
15
15
|
end
|
16
16
|
|
17
|
-
test 'allow custom
|
18
|
-
assert_equal :
|
17
|
+
test 'allow custom scope to be given' do
|
18
|
+
assert_equal :accounts, Devise.mappings[:manager].as
|
19
19
|
end
|
20
20
|
|
21
21
|
test 'allows a controller depending on the mapping' do
|
@@ -70,7 +70,7 @@ class MappingTest < ActiveSupport::TestCase
|
|
70
70
|
end
|
71
71
|
|
72
72
|
test 'allow custom path names to be given' do
|
73
|
-
mapping = Devise.mappings[:
|
73
|
+
mapping = Devise.mappings[:manager]
|
74
74
|
assert_equal 'login', mapping.path_names[:sign_in]
|
75
75
|
assert_equal 'logout', mapping.path_names[:sign_out]
|
76
76
|
assert_equal 'secret', mapping.path_names[:password]
|
@@ -78,7 +78,7 @@ class MappingTest < ActiveSupport::TestCase
|
|
78
78
|
end
|
79
79
|
|
80
80
|
test 'has an empty path as default path prefix' do
|
81
|
-
mapping = Devise.mappings[:
|
81
|
+
mapping = Devise.mappings[:user]
|
82
82
|
assert_equal '/', mapping.path_prefix
|
83
83
|
end
|
84
84
|
|
@@ -88,20 +88,20 @@ class MappingTest < ActiveSupport::TestCase
|
|
88
88
|
end
|
89
89
|
|
90
90
|
test 'retrieve as from the proper position' do
|
91
|
-
assert_equal 1, Devise.mappings[:
|
91
|
+
assert_equal 1, Devise.mappings[:user].as_position
|
92
92
|
assert_equal 2, Devise.mappings[:manager].as_position
|
93
93
|
end
|
94
94
|
|
95
95
|
test 'raw path is returned' do
|
96
|
-
assert_equal '/
|
97
|
-
assert_equal '/:locale/
|
96
|
+
assert_equal '/users', Devise.mappings[:user].raw_path
|
97
|
+
assert_equal '/:locale/accounts', Devise.mappings[:manager].raw_path
|
98
98
|
end
|
99
99
|
|
100
100
|
test 'parsed path is returned' do
|
101
101
|
begin
|
102
102
|
Devise.default_url_options {{ :locale => I18n.locale }}
|
103
|
-
assert_equal '/
|
104
|
-
assert_equal '/en/
|
103
|
+
assert_equal '/users', Devise.mappings[:user].parsed_path
|
104
|
+
assert_equal '/en/accounts', Devise.mappings[:manager].parsed_path
|
105
105
|
ensure
|
106
106
|
Devise.default_url_options {{ }}
|
107
107
|
end
|
@@ -168,8 +168,8 @@ class AuthenticatableTest < ActiveSupport::TestCase
|
|
168
168
|
user = create_user
|
169
169
|
assert_not user.update_with_password(:old_password => 'other',
|
170
170
|
:password => 'pass321', :password_confirmation => 'pass321')
|
171
|
-
assert_equal 'is invalid', user.errors[:old_password]
|
172
171
|
assert user.reload.valid_password?('123456')
|
172
|
+
assert_match /invalid/, user.errors[:old_password]
|
173
173
|
end
|
174
174
|
|
175
175
|
test 'should not update password with invalid confirmation' do
|
@@ -57,7 +57,7 @@ class ConfirmableTest < ActiveSupport::TestCase
|
|
57
57
|
assert_nil user.errors[:email]
|
58
58
|
|
59
59
|
assert_not user.confirm!
|
60
|
-
|
60
|
+
assert_match /already confirmed/, user.errors[:email]
|
61
61
|
end
|
62
62
|
|
63
63
|
test 'should find and confirm an user automatically' do
|
@@ -70,18 +70,19 @@ class ConfirmableTest < ActiveSupport::TestCase
|
|
70
70
|
test 'should return a new record with errors when a invalid token is given' do
|
71
71
|
confirmed_user = User.confirm!(:confirmation_token => 'invalid_confirmation_token')
|
72
72
|
assert confirmed_user.new_record?
|
73
|
-
|
73
|
+
assert_match /invalid/, confirmed_user.errors[:confirmation_token]
|
74
74
|
end
|
75
75
|
|
76
76
|
test 'should return a new record with errors when a blank token is given' do
|
77
77
|
confirmed_user = User.confirm!(:confirmation_token => '')
|
78
78
|
assert confirmed_user.new_record?
|
79
|
-
|
79
|
+
assert_match /blank/, confirmed_user.errors[:confirmation_token]
|
80
80
|
end
|
81
81
|
|
82
82
|
test 'should generate errors for a user email if user is already confirmed' do
|
83
83
|
user = create_user
|
84
|
-
user.
|
84
|
+
user.confirmed_at = Time.now
|
85
|
+
user.save
|
85
86
|
confirmed_user = User.confirm!(:confirmation_token => user.confirmation_token)
|
86
87
|
assert confirmed_user.confirmed?
|
87
88
|
assert confirmed_user.errors[:email]
|
@@ -220,7 +221,8 @@ class ConfirmableTest < ActiveSupport::TestCase
|
|
220
221
|
|
221
222
|
test 'should not be active without confirmation' do
|
222
223
|
user = create_user
|
223
|
-
user.
|
224
|
+
user.confirmation_sent_at = nil
|
225
|
+
user.save
|
224
226
|
assert_not user.reload.active?
|
225
227
|
end
|
226
228
|
end
|
@@ -83,7 +83,7 @@ class RecoverableTest < ActiveSupport::TestCase
|
|
83
83
|
test 'should return a new record with errors if user was not found by e-mail' do
|
84
84
|
reset_password_user = User.send_reset_password_instructions(:email => "invalid@email.com")
|
85
85
|
assert reset_password_user.new_record?
|
86
|
-
|
86
|
+
assert_match /not found/, reset_password_user.errors[:email]
|
87
87
|
end
|
88
88
|
|
89
89
|
test 'should reset reset_password_token before send the reset instructions email' do
|
@@ -111,13 +111,13 @@ class RecoverableTest < ActiveSupport::TestCase
|
|
111
111
|
test 'should a new record with errors if no reset_password_token is found' do
|
112
112
|
reset_password_user = User.reset_password!(:reset_password_token => 'invalid_token')
|
113
113
|
assert reset_password_user.new_record?
|
114
|
-
|
114
|
+
assert_match /invalid/, reset_password_user.errors[:reset_password_token]
|
115
115
|
end
|
116
116
|
|
117
117
|
test 'should a new record with errors if reset_password_token is blank' do
|
118
118
|
reset_password_user = User.reset_password!(:reset_password_token => '')
|
119
119
|
assert reset_password_user.new_record?
|
120
|
-
|
120
|
+
assert_match /blank/, reset_password_user.errors[:reset_password_token]
|
121
121
|
end
|
122
122
|
|
123
123
|
test 'should reset successfully user password given the new password and confirmation' do
|
@@ -56,7 +56,8 @@ class RememberableTest < ActiveSupport::TestCase
|
|
56
56
|
test 'valid remember token should also verify if remember is not expired' do
|
57
57
|
user = create_user
|
58
58
|
user.remember_me!
|
59
|
-
user.
|
59
|
+
user.remember_created_at = 3.days.ago
|
60
|
+
user.save
|
60
61
|
assert_not user.valid_remember_token?(user.remember_token)
|
61
62
|
end
|
62
63
|
|
@@ -72,8 +73,11 @@ class RememberableTest < ActiveSupport::TestCase
|
|
72
73
|
assert_equal user, User.serialize_from_cookie("#{user.id}::#{user.remember_token}")
|
73
74
|
end
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
# MongoMapper cries if an invalid ID is given, so this does not need to be tested
|
77
|
+
unless DEVISE_ORM == :mongo_mapper
|
78
|
+
test 'serialize should return nil if no user is found' do
|
79
|
+
assert_nil User.serialize_from_cookie('0::123')
|
80
|
+
end
|
77
81
|
end
|
78
82
|
|
79
83
|
test 'remember me return nil if is a valid user with invalid token' do
|
@@ -113,7 +117,8 @@ class RememberableTest < ActiveSupport::TestCase
|
|
113
117
|
swap Devise, :remember_for => 1.day do
|
114
118
|
user = create_user
|
115
119
|
user.remember_me!
|
116
|
-
user.
|
120
|
+
user.remember_created_at = 2.days.ago
|
121
|
+
user.save
|
117
122
|
assert user.remember_expired?
|
118
123
|
end
|
119
124
|
end
|
@@ -122,7 +127,8 @@ class RememberableTest < ActiveSupport::TestCase
|
|
122
127
|
swap Devise, :remember_for => 30.days do
|
123
128
|
user = create_user
|
124
129
|
user.remember_me!
|
125
|
-
user.
|
130
|
+
user.remember_created_at = (30.days.ago + 2.minutes)
|
131
|
+
user.save
|
126
132
|
assert_not user.remember_expired?
|
127
133
|
end
|
128
134
|
end
|
data/test/models_test.rb
CHANGED
@@ -24,7 +24,7 @@ class Timeoutable < User
|
|
24
24
|
devise :authenticatable, :timeoutable
|
25
25
|
end
|
26
26
|
|
27
|
-
class
|
27
|
+
class IsValidatable < User
|
28
28
|
devise :authenticatable, :validatable
|
29
29
|
end
|
30
30
|
|
@@ -37,11 +37,11 @@ class Exceptable < User
|
|
37
37
|
end
|
38
38
|
|
39
39
|
class Configurable < User
|
40
|
-
devise :all, :stretches => 15,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
devise :all, :timeoutable, :stretches => 15,
|
41
|
+
:pepper => 'abcdef',
|
42
|
+
:confirm_within => 5.days,
|
43
|
+
:remember_for => 7.days,
|
44
|
+
:timeout_in => 15.minutes
|
45
45
|
end
|
46
46
|
|
47
47
|
class ActiveRecordTest < ActiveSupport::TestCase
|
@@ -60,7 +60,7 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
test '
|
63
|
+
test 'add authenticatable module only' do
|
64
64
|
assert_include_modules Authenticatable, :authenticatable
|
65
65
|
end
|
66
66
|
|
@@ -85,16 +85,16 @@ class ActiveRecordTest < ActiveSupport::TestCase
|
|
85
85
|
end
|
86
86
|
|
87
87
|
test 'add validatable module only' do
|
88
|
-
assert_include_modules
|
88
|
+
assert_include_modules IsValidatable, :authenticatable, :validatable
|
89
89
|
end
|
90
90
|
|
91
91
|
test 'add all modules' do
|
92
92
|
assert_include_modules Devisable,
|
93
|
-
:authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :
|
93
|
+
:authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable
|
94
94
|
end
|
95
95
|
|
96
96
|
test 'configure modules with except option' do
|
97
|
-
assert_include_modules Exceptable, :authenticatable, :confirmable, :trackable
|
97
|
+
assert_include_modules Exceptable, :authenticatable, :confirmable, :trackable
|
98
98
|
end
|
99
99
|
|
100
100
|
test 'set a default value for stretches' do
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'rails_app', 'config', 'environment')
|
2
|
+
require 'test_help'
|
3
|
+
|
4
|
+
ActiveRecord::Migration.verbose = false
|
5
|
+
ActiveRecord::Base.logger = Logger.new(nil)
|
6
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
7
|
+
|
8
|
+
ActiveRecord::Schema.define(:version => 1) do
|
9
|
+
[:users, :admins, :accounts].each do |table|
|
10
|
+
create_table table do |t|
|
11
|
+
t.authenticatable :null => table == :admins
|
12
|
+
|
13
|
+
if table != :admin
|
14
|
+
t.string :username
|
15
|
+
t.confirmable
|
16
|
+
t.recoverable
|
17
|
+
t.rememberable
|
18
|
+
t.trackable
|
19
|
+
end
|
20
|
+
|
21
|
+
t.timestamps
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class ActiveSupport::TestCase
|
27
|
+
self.use_transactional_fixtures = true
|
28
|
+
self.use_instantiated_fixtures = false
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'mongo_mapper'
|
2
|
+
MongoMapper.database = "devise-test-suite"
|
3
|
+
MongoMapper.connection = Mongo::Connection.new('127.0.0.1', 27017)
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), '..', 'rails_app', 'config', 'environment')
|
6
|
+
require 'test_help'
|
7
|
+
|
8
|
+
module MongoMapper::Document
|
9
|
+
# TODO This should not be required
|
10
|
+
def invalid?
|
11
|
+
!valid?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class ActiveSupport::TestCase
|
16
|
+
setup do
|
17
|
+
User.delete_all
|
18
|
+
Admin.delete_all
|
19
|
+
Account.delete_all
|
20
|
+
end
|
21
|
+
end
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class Admin < ActiveRecord::Base
|
2
|
-
devise :all, :except => [:recoverable, :confirmable, :rememberable, :validatable, :trackable]
|
2
|
+
devise :all, :timeoutable, :except => [:recoverable, :confirmable, :rememberable, :validatable, :trackable]
|
3
3
|
|
4
4
|
def self.find_for_authentication(conditions)
|
5
5
|
last(:conditions => conditions)
|