devise 1.1.rc2 → 1.1.0
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 +22 -2
- data/Gemfile +7 -13
- data/Gemfile.lock +118 -0
- data/README.rdoc +15 -13
- data/app/controllers/devise/unlocks_controller.rb +0 -7
- data/app/mailers/devise/mailer.rb +7 -4
- data/app/views/devise/confirmations/new.html.erb +1 -1
- data/app/views/devise/passwords/new.html.erb +1 -1
- data/app/views/devise/unlocks/new.html.erb +1 -1
- data/lib/devise.rb +27 -9
- data/lib/devise/controllers/helpers.rb +19 -5
- data/lib/devise/controllers/internal_helpers.rb +2 -8
- data/lib/devise/encryptors/base.rb +1 -1
- data/lib/devise/encryptors/bcrypt.rb +2 -2
- data/lib/devise/failure_app.rb +6 -2
- data/lib/devise/hooks/rememberable.rb +9 -1
- data/lib/devise/mapping.rb +15 -50
- data/lib/devise/models/authenticatable.rb +8 -0
- data/lib/devise/models/confirmable.rb +10 -6
- data/lib/devise/models/database_authenticatable.rb +9 -1
- data/lib/devise/models/recoverable.rb +6 -1
- data/lib/devise/models/rememberable.rb +36 -7
- data/lib/devise/models/token_authenticatable.rb +5 -5
- data/lib/devise/models/validatable.rb +1 -1
- data/lib/devise/path_checker.rb +7 -2
- data/lib/devise/rails.rb +6 -1
- data/lib/devise/rails/routes.rb +137 -50
- data/lib/devise/rails/warden_compat.rb +16 -2
- data/lib/devise/strategies/authenticatable.rb +12 -0
- data/lib/devise/strategies/base.rb +0 -18
- data/lib/devise/strategies/rememberable.rb +9 -1
- data/lib/devise/test_helpers.rb +2 -0
- data/lib/devise/version.rb +1 -1
- data/lib/generators/active_record/devise_generator.rb +28 -0
- data/lib/generators/{devise/devise → active_record}/templates/migration.rb +4 -0
- data/lib/generators/devise/devise_generator.rb +17 -0
- data/lib/generators/devise/{install/install_generator.rb → install_generator.rb} +1 -1
- data/lib/generators/devise/orm_helpers.rb +23 -0
- data/lib/generators/devise/{install/templates → templates}/README +0 -0
- data/lib/generators/devise/{install/templates → templates}/devise.rb +20 -13
- data/lib/generators/devise/{views/views_generator.rb → views_generator.rb} +2 -2
- data/lib/generators/mongoid/devise_generator.rb +17 -0
- data/test/controllers/helpers_test.rb +9 -0
- data/test/controllers/internal_helpers_test.rb +7 -16
- data/test/controllers/url_helpers_test.rb +11 -0
- data/test/encryptors_test.rb +1 -1
- data/test/failure_app_test.rb +18 -5
- data/test/integration/authenticatable_test.rb +76 -11
- data/test/integration/confirmable_test.rb +16 -9
- data/test/integration/lockable_test.rb +11 -13
- data/test/integration/registerable_test.rb +4 -4
- data/test/integration/rememberable_test.rb +54 -1
- data/test/mapping_test.rb +10 -45
- data/test/models/confirmable_test.rb +1 -1
- data/test/models/rememberable_test.rb +108 -0
- data/test/models/validatable_test.rb +2 -4
- data/test/models_test.rb +4 -4
- data/test/rails_app/app/active_record/admin.rb +1 -1
- data/test/rails_app/app/controllers/publisher/registrations_controller.rb +2 -0
- data/test/rails_app/app/controllers/publisher/sessions_controller.rb +2 -0
- data/test/rails_app/app/controllers/users_controller.rb +5 -1
- data/test/rails_app/app/mongoid/admin.rb +1 -1
- data/test/rails_app/config/application.rb +2 -2
- data/test/rails_app/config/environments/test.rb +2 -0
- data/test/rails_app/config/initializers/devise.rb +95 -34
- data/test/rails_app/config/routes.rb +32 -14
- data/test/routes_test.rb +34 -2
- data/test/support/integration.rb +22 -6
- data/test/test_helpers_test.rb +16 -2
- metadata +24 -27
- data/lib/devise/orm/data_mapper.rb +0 -97
- data/lib/generators/devise/devise/devise_generator.rb +0 -86
- data/lib/generators/devise_generator.rb +0 -2
- data/test/orm/data_mapper.rb +0 -10
- data/test/rails_app/app/data_mapper/admin.rb +0 -12
- data/test/rails_app/app/data_mapper/shim.rb +0 -2
- data/test/rails_app/app/data_mapper/user.rb +0 -23
@@ -15,11 +15,25 @@ end
|
|
15
15
|
|
16
16
|
class Warden::SessionSerializer
|
17
17
|
def serialize(record)
|
18
|
-
[record.class, record.id]
|
18
|
+
[record.class.name, record.id]
|
19
19
|
end
|
20
20
|
|
21
21
|
def deserialize(keys)
|
22
22
|
klass, id = keys
|
23
|
-
|
23
|
+
|
24
|
+
if klass.is_a?(Class)
|
25
|
+
raise "Devise changed how it stores objects in session. If you are seeing this message, " <<
|
26
|
+
"you can fix it by changing one character in your cookie secret, forcing all previous " <<
|
27
|
+
"cookies to expire, or cleaning up your database sessions if you are using a db store."
|
28
|
+
end
|
29
|
+
|
30
|
+
klass.constantize.find(:first, :conditions => { :id => id })
|
31
|
+
rescue NameError => e
|
32
|
+
if e.message =~ /uninitialized constant/
|
33
|
+
Rails.logger.debug "Trying to deserialize invalid class #{klass}"
|
34
|
+
nil
|
35
|
+
else
|
36
|
+
raise
|
37
|
+
end
|
24
38
|
end
|
25
39
|
end
|
@@ -14,6 +14,18 @@ module Devise
|
|
14
14
|
|
15
15
|
private
|
16
16
|
|
17
|
+
# Simply invokes valid_for_authentication? with the given block and deal with the result.
|
18
|
+
def validate(resource, &block)
|
19
|
+
result = resource && resource.valid_for_authentication?(&block)
|
20
|
+
|
21
|
+
case result
|
22
|
+
when Symbol, String
|
23
|
+
fail!(result)
|
24
|
+
else
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
17
29
|
# Check if this is strategy is valid for http authentication by:
|
18
30
|
#
|
19
31
|
# * Validating if the model allows params authentication;
|
@@ -10,24 +10,6 @@ module Devise
|
|
10
10
|
mapping
|
11
11
|
end
|
12
12
|
end
|
13
|
-
|
14
|
-
protected
|
15
|
-
|
16
|
-
def succeeded?
|
17
|
-
@result == :success
|
18
|
-
end
|
19
|
-
|
20
|
-
# Simply invokes valid_for_authentication? with the given block and deal with the result.
|
21
|
-
def validate(resource, &block)
|
22
|
-
result = resource && resource.valid_for_authentication?(&block)
|
23
|
-
|
24
|
-
case result
|
25
|
-
when Symbol, String
|
26
|
-
fail!(result)
|
27
|
-
else
|
28
|
-
result
|
29
|
-
end
|
30
|
-
end
|
31
13
|
end
|
32
14
|
end
|
33
15
|
end
|
@@ -6,7 +6,7 @@ module Devise
|
|
6
6
|
# to verify whether there is a cookie with the remember token, and to
|
7
7
|
# recreate the user from this cookie if it exists. Must be called *before*
|
8
8
|
# authenticatable.
|
9
|
-
class Rememberable <
|
9
|
+
class Rememberable < Authenticatable
|
10
10
|
# A valid strategy for rememberable needs a remember token in the cookies.
|
11
11
|
def valid?
|
12
12
|
remember_cookie.present?
|
@@ -28,10 +28,18 @@ module Devise
|
|
28
28
|
|
29
29
|
private
|
30
30
|
|
31
|
+
def remember_me?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
31
35
|
def remember_key
|
32
36
|
"remember_#{scope}_token"
|
33
37
|
end
|
34
38
|
|
39
|
+
def extend_remember_period?
|
40
|
+
mapping.to.extend_remember_period
|
41
|
+
end
|
42
|
+
|
35
43
|
# Accessor for remember cookie
|
36
44
|
def remember_cookie
|
37
45
|
@remember_cookie ||= cookies.signed[remember_key]
|
data/lib/devise/test_helpers.rb
CHANGED
data/lib/devise/version.rb
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
require 'generators/devise/orm_helpers'
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
module Generators
|
6
|
+
class DeviseGenerator < ActiveRecord::Generators::Base
|
7
|
+
argument :attributes, :type => :array, :default => [], :banner => "field:type field:type"
|
8
|
+
|
9
|
+
include Devise::Generators::OrmHelpers
|
10
|
+
source_root File.expand_path("../templates", __FILE__)
|
11
|
+
|
12
|
+
def generate_model
|
13
|
+
invoke "active_record:model", [name], :migration => false unless model_exists?
|
14
|
+
end
|
15
|
+
|
16
|
+
def copy_devise_migration
|
17
|
+
migration_template "migration.rb", "db/migrate/devise_create_#{table_name}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def inject_devise_content
|
21
|
+
inject_into_class model_path, class_name, model_contents + <<-CONTENT
|
22
|
+
# Setup accessible (or protected) attributes for your model
|
23
|
+
attr_accessible :email, :password, :password_confirmation, :remember_me
|
24
|
+
CONTENT
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -10,6 +10,10 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
|
10
10
|
# t.lockable :lock_strategy => :<%= Devise.lock_strategy %>, :unlock_strategy => :<%= Devise.unlock_strategy %>
|
11
11
|
# t.token_authenticatable
|
12
12
|
|
13
|
+
<% for attribute in attributes -%>
|
14
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
15
|
+
<% end -%>
|
16
|
+
|
13
17
|
t.timestamps
|
14
18
|
end
|
15
19
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Devise
|
2
|
+
module Generators
|
3
|
+
class DeviseGenerator < Rails::Generators::NamedBase
|
4
|
+
namespace "devise"
|
5
|
+
source_root File.expand_path("../templates", __FILE__)
|
6
|
+
|
7
|
+
desc "Generates a model with the given NAME (if one does not exist) with devise " <<
|
8
|
+
"configuration plus a migration file and devise routes."
|
9
|
+
|
10
|
+
hook_for :orm
|
11
|
+
|
12
|
+
def add_devise_routes
|
13
|
+
route "devise_for :#{table_name}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Devise
|
2
|
+
module Generators
|
3
|
+
module OrmHelpers
|
4
|
+
def model_contents
|
5
|
+
<<-CONTENT
|
6
|
+
# Include default devise modules. Others available are:
|
7
|
+
# :token_authenticatable, :confirmable, :lockable and :timeoutable
|
8
|
+
devise :database_authenticatable, :registerable,
|
9
|
+
:recoverable, :rememberable, :trackable, :validatable
|
10
|
+
|
11
|
+
CONTENT
|
12
|
+
end
|
13
|
+
|
14
|
+
def model_exists?
|
15
|
+
File.exists?(File.join(destination_root, model_path))
|
16
|
+
end
|
17
|
+
|
18
|
+
def model_path
|
19
|
+
@model_path ||= File.join("app", "models", "#{file_path}.rb")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
File without changes
|
@@ -9,8 +9,9 @@ Devise.setup do |config|
|
|
9
9
|
# config.mailer = "Devise::Mailer"
|
10
10
|
|
11
11
|
# ==> ORM configuration
|
12
|
-
# Load and configure the ORM. Supports :active_record (default)
|
13
|
-
# (bson_ext recommended)
|
12
|
+
# Load and configure the ORM. Supports :active_record (default) and
|
13
|
+
# :mongoid (bson_ext recommended) by default. Other ORMs may be
|
14
|
+
# available as additional gems.
|
14
15
|
require 'devise/orm/<%= options[:orm] %>'
|
15
16
|
|
16
17
|
# ==> Configuration for any authentication mechanism
|
@@ -27,6 +28,9 @@ Devise.setup do |config|
|
|
27
28
|
# Tell if authentication through HTTP Basic Auth is enabled. True by default.
|
28
29
|
# config.http_authenticatable = true
|
29
30
|
|
31
|
+
# Set this to true to use Basic Auth for AJAX requests. True by default.
|
32
|
+
# config.http_authenticatable_on_xhr = true
|
33
|
+
|
30
34
|
# The realm used in Http Basic Authentication
|
31
35
|
# config.http_authentication_realm = "Application"
|
32
36
|
|
@@ -57,6 +61,12 @@ Devise.setup do |config|
|
|
57
61
|
# The time the user will be remembered without asking for credentials again.
|
58
62
|
# config.remember_for = 2.weeks
|
59
63
|
|
64
|
+
# If true, a valid remember token can be re-used between multiple browsers.
|
65
|
+
# config.remember_across_browsers = true
|
66
|
+
|
67
|
+
# If true, extends the user's remember period when remembered via cookie.
|
68
|
+
# config.extend_remember_period = false
|
69
|
+
|
60
70
|
# ==> Configuration for :validatable
|
61
71
|
# Range for password length
|
62
72
|
# config.password_length = 6..20
|
@@ -95,22 +105,19 @@ Devise.setup do |config|
|
|
95
105
|
|
96
106
|
# ==> Scopes configuration
|
97
107
|
# Turn scoped views on. Before rendering "sessions/new", it will first check for
|
98
|
-
# "sessions/
|
108
|
+
# "users/sessions/new". It's turned off by default because it's slower if you
|
99
109
|
# are using only default views.
|
100
110
|
# config.scoped_views = true
|
101
111
|
|
102
|
-
#
|
103
|
-
#
|
104
|
-
# routes as "/sign_in" not possible, unless you tell Devise to use the default
|
105
|
-
# scope, setting true below.
|
106
|
-
# Note that devise does not generate default routes. You also have to
|
107
|
-
# specify them in config/routes.rb
|
108
|
-
# config.use_default_scope = true
|
109
|
-
|
110
|
-
# Configure the default scope used by Devise. By default it's the first devise
|
111
|
-
# role declared in your routes.
|
112
|
+
# Configure the default scope given to Warden. By default it's the first
|
113
|
+
# devise role declared in your routes.
|
112
114
|
# config.default_scope = :user
|
113
115
|
|
116
|
+
# Configure sign_out behavior.
|
117
|
+
# By default sign_out is scoped (i.e. /users/sign_out affects only :user scope).
|
118
|
+
# In case of sign_out_all_scopes set to true any logout action will sign out all active scopes.
|
119
|
+
# config.sign_out_all_scopes = false
|
120
|
+
|
114
121
|
# ==> Navigation configuration
|
115
122
|
# Lists the formats that should be treated as navigational. Formats like
|
116
123
|
# :html, should redirect to the sign in page when the user does not have
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Devise
|
2
2
|
module Generators
|
3
3
|
class ViewsGenerator < Rails::Generators::Base
|
4
|
-
source_root File.expand_path("
|
4
|
+
source_root File.expand_path("../../../../app/views", __FILE__)
|
5
5
|
desc "Copies all Devise views to your application."
|
6
6
|
|
7
7
|
argument :scope, :required => false, :default => nil,
|
@@ -11,7 +11,7 @@ module Devise
|
|
11
11
|
:desc => "Template engine for the views. Available options are 'erb' and 'haml'."
|
12
12
|
|
13
13
|
def copy_views
|
14
|
-
case options[:template_engine]
|
14
|
+
case options[:template_engine].to_s
|
15
15
|
when "haml"
|
16
16
|
verify_haml_existence
|
17
17
|
verify_haml_version
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'generators/devise/orm_helpers'
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
module Generators
|
5
|
+
class DeviseGenerator < Rails::Generators::NamedBase
|
6
|
+
include Devise::Generators::OrmHelpers
|
7
|
+
|
8
|
+
def generate_model
|
9
|
+
invoke "mongoid:model", [name] unless model_exists?
|
10
|
+
end
|
11
|
+
|
12
|
+
def inject_devise_content
|
13
|
+
inject_into_file model_path, model_contents, :after => "include Mongoid::Document\n"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -126,6 +126,15 @@ class ControllerAuthenticableTest < ActionController::TestCase
|
|
126
126
|
@controller.sign_out(User.new)
|
127
127
|
end
|
128
128
|
|
129
|
+
test 'sign out everybody proxy to logout on warden' do
|
130
|
+
Devise.mappings.keys.each { |scope|
|
131
|
+
@mock_warden.expects(:user).with(scope).returns(true)
|
132
|
+
}
|
133
|
+
|
134
|
+
@mock_warden.expects(:logout).with(*Devise.mappings.keys).returns(true)
|
135
|
+
@controller.sign_out_all_scopes
|
136
|
+
end
|
137
|
+
|
129
138
|
test 'stored location for returns the location for a given scope' do
|
130
139
|
assert_nil @controller.stored_location_for(:user)
|
131
140
|
@controller.session[:"user_return_to"] = "/foo.bar"
|
@@ -10,37 +10,28 @@ class HelpersTest < ActionController::TestCase
|
|
10
10
|
def setup
|
11
11
|
@mock_warden = OpenStruct.new
|
12
12
|
@controller.request.env['warden'] = @mock_warden
|
13
|
+
@controller.request.env['devise.mapping'] = Devise.mappings[:user]
|
13
14
|
end
|
14
15
|
|
15
|
-
test 'get resource name from
|
16
|
-
@request.path = '/users/session'
|
16
|
+
test 'get resource name from env' do
|
17
17
|
assert_equal :user, @controller.resource_name
|
18
18
|
end
|
19
19
|
|
20
|
-
test 'get resource
|
21
|
-
@request.path = '/admin_area/session'
|
22
|
-
assert_equal :admin, @controller.resource_name
|
23
|
-
end
|
24
|
-
|
25
|
-
test 'get resource class from request path' do
|
26
|
-
@request.path = '/users/session'
|
20
|
+
test 'get resource class from env' do
|
27
21
|
assert_equal User, @controller.resource_class
|
28
22
|
end
|
29
23
|
|
30
|
-
test 'get resource instance variable from
|
31
|
-
@
|
32
|
-
@controller.instance_variable_set(:@admin, admin = Admin.new)
|
24
|
+
test 'get resource instance variable from env' do
|
25
|
+
@controller.instance_variable_set(:@user, admin = Admin.new)
|
33
26
|
assert_equal admin, @controller.resource
|
34
27
|
end
|
35
28
|
|
36
|
-
test 'set resource instance variable from
|
37
|
-
@request.path = '/admin_area/session'
|
38
|
-
|
29
|
+
test 'set resource instance variable from env' do
|
39
30
|
admin = @controller.send(:resource_class).new
|
40
31
|
@controller.send(:resource=, admin)
|
41
32
|
|
42
33
|
assert_equal admin, @controller.send(:resource)
|
43
|
-
assert_equal admin, @controller.instance_variable_get(:@
|
34
|
+
assert_equal admin, @controller.instance_variable_get(:@user)
|
44
35
|
end
|
45
36
|
|
46
37
|
test 'resources methods are not controller actions' do
|
@@ -44,4 +44,15 @@ class RoutesTest < ActionController::TestCase
|
|
44
44
|
assert_path_and_url :confirmation
|
45
45
|
assert_path_and_url :confirmation, :new
|
46
46
|
end
|
47
|
+
|
48
|
+
test 'should alias unlock to mapped user unlock' do
|
49
|
+
assert_path_and_url :unlock
|
50
|
+
assert_path_and_url :unlock, :new
|
51
|
+
end
|
52
|
+
|
53
|
+
test 'should alias registration to mapped user registration' do
|
54
|
+
assert_path_and_url :registration
|
55
|
+
assert_path_and_url :registration, :new
|
56
|
+
assert_path_and_url :registration, :edit
|
57
|
+
end
|
47
58
|
end
|
data/test/encryptors_test.rb
CHANGED
@@ -23,7 +23,7 @@ class Encryptors < ActiveSupport::TestCase
|
|
23
23
|
test "should have length #{value} for #{key.inspect}" do
|
24
24
|
swap Devise, :encryptor => key do
|
25
25
|
encryptor = Devise::Encryptors.const_get(key.to_s.classify)
|
26
|
-
assert_equal value, encryptor.digest('a', 4, encryptor.salt, nil).size
|
26
|
+
assert_equal value, encryptor.digest('a', 4, encryptor.salt(4), nil).size
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/test/failure_app_test.rb
CHANGED
@@ -77,6 +77,23 @@ class FailureTest < ActiveSupport::TestCase
|
|
77
77
|
assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
|
78
78
|
end
|
79
79
|
|
80
|
+
test 'dont return WWW-authenticate on ajax call if http_authenticatable_on_xhr false' do
|
81
|
+
swap Devise, :http_authenticatable_on_xhr => false do
|
82
|
+
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
83
|
+
assert_equal 302, @response.first
|
84
|
+
assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
|
85
|
+
assert_nil @response.second['WWW-Authenticate']
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
test 'return WWW-authenticate on ajax call if http_authenticatable_on_xhr true' do
|
90
|
+
swap Devise, :http_authenticatable_on_xhr => true do
|
91
|
+
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
92
|
+
assert_equal 401, @response.first
|
93
|
+
assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
80
97
|
test 'uses the proxy failure message as response body' do
|
81
98
|
call_failure('formats' => :xml, 'warden' => OpenStruct.new(:message => :invalid))
|
82
99
|
assert_match '<error>Invalid email or password.</error>', @response.third.body
|
@@ -88,11 +105,6 @@ class FailureTest < ActiveSupport::TestCase
|
|
88
105
|
assert_equal 401, @response.first
|
89
106
|
end
|
90
107
|
end
|
91
|
-
|
92
|
-
test 'works for xml http requests' do
|
93
|
-
call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
|
94
|
-
assert_equal 401, @response.first
|
95
|
-
end
|
96
108
|
end
|
97
109
|
|
98
110
|
context 'With recall' do
|
@@ -100,6 +112,7 @@ class FailureTest < ActiveSupport::TestCase
|
|
100
112
|
env = {
|
101
113
|
"action_dispatch.request.parameters" => { :controller => "devise/sessions" },
|
102
114
|
"warden.options" => { :recall => "new", :attempted_path => "/users/sign_in" },
|
115
|
+
"devise.mapping" => Devise.mappings[:user],
|
103
116
|
"warden" => stub_everything
|
104
117
|
}
|
105
118
|
call_failure(env)
|