devise 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of devise might be problematic. Click here for more details.
- data/{CHANGELOG.rdoc → CHANGELOG.md} +67 -25
- data/Gemfile.lock +13 -12
- data/README.md +19 -17
- data/app/controllers/devise/confirmations_controller.rb +11 -3
- data/app/controllers/devise/registrations_controller.rb +9 -3
- data/app/controllers/devise/sessions_controller.rb +1 -1
- data/app/mailers/devise/mailer.rb +6 -3
- data/app/views/devise/mailer/confirmation_instructions.html.erb +1 -1
- data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
- data/app/views/devise/mailer/unlock_instructions.html.erb +1 -1
- data/app/views/devise/shared/_links.erb +2 -2
- data/config/locales/en.yml +4 -3
- data/devise.gemspec +1 -0
- data/gemfiles/Gemfile.rails-3.2.x.lock +47 -44
- data/lib/devise/controllers/helpers.rb +1 -0
- data/lib/devise/controllers/rememberable.rb +1 -0
- data/lib/devise/hooks/csrf_cleaner.rb +5 -0
- data/lib/devise/hooks/lockable.rb +1 -1
- data/lib/devise/hooks/rememberable.rb +2 -1
- data/lib/devise/mailers/helpers.rb +0 -6
- data/lib/devise/models/authenticatable.rb +9 -16
- data/lib/devise/models/confirmable.rb +34 -43
- data/lib/devise/models/lockable.rb +15 -17
- data/lib/devise/models/recoverable.rb +21 -27
- data/lib/devise/models/rememberable.rb +6 -2
- data/lib/devise/models/timeoutable.rb +1 -1
- data/lib/devise/models/token_authenticatable.rb +4 -1
- data/lib/devise/models.rb +8 -12
- data/lib/devise/parameter_sanitizer.rb +49 -19
- data/lib/devise/rails/routes.rb +12 -9
- data/lib/devise/rails/warden_compat.rb +10 -2
- data/lib/devise/rails.rb +7 -11
- data/lib/devise/strategies/authenticatable.rb +0 -12
- data/lib/devise/token_generator.rb +70 -0
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +23 -12
- data/lib/generators/active_record/devise_generator.rb +2 -5
- data/lib/generators/active_record/templates/migration.rb +0 -1
- data/lib/generators/active_record/templates/migration_existing.rb +0 -1
- data/lib/generators/devise/orm_helpers.rb +25 -6
- data/lib/generators/mongoid/devise_generator.rb +2 -2
- data/lib/generators/templates/devise.rb +21 -9
- data/test/controllers/helpers_test.rb +1 -1
- data/test/controllers/passwords_controller_test.rb +4 -5
- data/test/failure_app_test.rb +1 -1
- data/test/generators/active_record_generator_test.rb +31 -1
- data/test/integration/authenticatable_test.rb +15 -1
- data/test/integration/confirmable_test.rb +29 -42
- data/test/integration/http_authenticatable_test.rb +1 -1
- data/test/integration/lockable_test.rb +11 -14
- data/test/integration/recoverable_test.rb +23 -24
- data/test/integration/rememberable_test.rb +15 -13
- data/test/mailers/confirmation_instructions_test.rb +6 -2
- data/test/mailers/reset_password_instructions_test.rb +6 -2
- data/test/mailers/unlock_instructions_test.rb +6 -2
- data/test/models/confirmable_test.rb +38 -27
- data/test/models/lockable_test.rb +15 -5
- data/test/models/recoverable_test.rb +20 -48
- data/test/models/rememberable_test.rb +8 -0
- data/test/models/timeoutable_test.rb +5 -0
- data/test/models_test.rb +0 -19
- data/test/parameter_sanitizer_test.rb +23 -9
- data/test/rails_app/config/initializers/devise.rb +3 -0
- data/test/rails_app/lib/shared_admin.rb +3 -0
- data/test/rails_app/lib/shared_user.rb +4 -0
- data/test/support/helpers.rb +0 -21
- metadata +42 -26
- data/app/views/devise/_links.erb +0 -3
data/lib/devise/models.rb
CHANGED
@@ -56,14 +56,8 @@ module Devise
|
|
56
56
|
klass.devise_modules.each do |mod|
|
57
57
|
constant = const_get(mod.to_s.classify)
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
failed_attributes << field unless instance.respond_to?(field)
|
62
|
-
end
|
63
|
-
else
|
64
|
-
ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
|
65
|
-
"Devise uses required_fields to warn developers of any missing fields in their models. " \
|
66
|
-
"Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
|
59
|
+
constant.required_fields(klass).each do |field|
|
60
|
+
failed_attributes << field unless instance.respond_to?(field)
|
67
61
|
end
|
68
62
|
end
|
69
63
|
|
@@ -89,11 +83,13 @@ module Devise
|
|
89
83
|
|
90
84
|
devise_modules_hook! do
|
91
85
|
include Devise::Models::Authenticatable
|
92
|
-
selected_modules.each do |m|
|
93
|
-
if m == :encryptable && !(defined?(Devise::Models::Encryptable))
|
94
|
-
warn "[DEVISE] You're trying to include :encryptable in your model but it is not bundled with the Devise gem anymore. Please add `devise-encryptable` to your Gemfile to proceed.\n"
|
95
|
-
end
|
96
86
|
|
87
|
+
if selected_modules.include?(:token_authenticatable)
|
88
|
+
ActiveSupport::Deprecation.warn "devise :token_authenticatable is deprecated. " \
|
89
|
+
"Please check Devise 3.1 release notes for more information on how to upgrade."
|
90
|
+
end
|
91
|
+
|
92
|
+
selected_modules.each do |m|
|
97
93
|
mod = Devise::Models.const_get(m.to_s.classify)
|
98
94
|
|
99
95
|
if mod.const_defined?("ClassMethods")
|
@@ -13,14 +13,25 @@ module Devise
|
|
13
13
|
if block_given?
|
14
14
|
@blocks[kind] = block
|
15
15
|
else
|
16
|
-
|
17
|
-
|
16
|
+
default_for(kind)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def sanitize(kind)
|
21
|
+
if block = @blocks[kind]
|
22
|
+
block.call(default_params)
|
23
|
+
else
|
24
|
+
default_sanitize(kind)
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
21
28
|
private
|
22
29
|
|
23
|
-
def
|
30
|
+
def default_for(kind)
|
31
|
+
raise ArgumentError, "a block is expected in Devise base sanitizer"
|
32
|
+
end
|
33
|
+
|
34
|
+
def default_sanitize(kind)
|
24
35
|
default_params
|
25
36
|
end
|
26
37
|
|
@@ -30,34 +41,53 @@ module Devise
|
|
30
41
|
end
|
31
42
|
|
32
43
|
class ParameterSanitizer < BaseSanitizer
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
if respond_to?(kind, true)
|
37
|
-
send(kind)
|
38
|
-
else
|
39
|
-
raise NotImplementedError, "Devise Parameter Sanitizer doesn't know how to sanitize parameters for #{kind}"
|
40
|
-
end
|
44
|
+
def initialize(*)
|
45
|
+
super
|
46
|
+
@permitted = Hash.new { |h,k| h[k] = attributes_for(k) }
|
41
47
|
end
|
42
48
|
|
43
|
-
# These are the params used to sign in a user so we don't need to
|
44
|
-
# mass-assign the password param in order to authenticate. Excluding it
|
45
|
-
# here allows us to construct a new user without sensitive information if
|
46
|
-
# authentication fails.
|
47
49
|
def sign_in
|
48
|
-
default_params.permit(
|
50
|
+
default_params.permit self.for(:sign_in)
|
49
51
|
end
|
50
52
|
|
51
53
|
def sign_up
|
52
|
-
default_params.permit(
|
54
|
+
default_params.permit self.for(:sign_up)
|
53
55
|
end
|
54
56
|
|
55
57
|
def account_update
|
56
|
-
default_params.permit(
|
58
|
+
default_params.permit self.for(:account_update)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Change for(kind) to return the values in the @permitted
|
64
|
+
# hash, allowing the developer to customize at runtime.
|
65
|
+
def default_for(kind)
|
66
|
+
@permitted[kind] || raise("No sanitizer provided for #{kind}")
|
67
|
+
end
|
68
|
+
|
69
|
+
def default_sanitize(kind)
|
70
|
+
if respond_to?(kind, true)
|
71
|
+
send(kind)
|
72
|
+
else
|
73
|
+
raise NotImplementedError, "Devise doesn't know how to sanitize parameters for #{kind}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def attributes_for(kind)
|
78
|
+
case kind
|
79
|
+
when :sign_in
|
80
|
+
auth_keys + [:password, :remember_me]
|
81
|
+
when :sign_up
|
82
|
+
auth_keys + [:password, :password_confirmation]
|
83
|
+
when :account_update
|
84
|
+
auth_keys + [:password, :password_confirmation, :current_password]
|
85
|
+
end
|
57
86
|
end
|
58
87
|
|
59
88
|
def auth_keys
|
60
|
-
resource_class.authentication_keys.respond_to?(:keys) ?
|
89
|
+
@auth_keys ||= @resource_class.authentication_keys.respond_to?(:keys) ?
|
90
|
+
@resource_class.authentication_keys.keys : @resource_class.authentication_keys
|
61
91
|
end
|
62
92
|
end
|
63
93
|
end
|
data/lib/devise/rails/routes.rb
CHANGED
@@ -80,7 +80,8 @@ module ActionDispatch::Routing
|
|
80
80
|
# * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
|
81
81
|
# :password, :confirmation, :unlock.
|
82
82
|
#
|
83
|
-
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout',
|
83
|
+
# devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout',
|
84
|
+
# :password => 'secret', :confirmation => 'verification', registration: 'register }
|
84
85
|
#
|
85
86
|
# * :controllers => the controller which should be used. All routes by default points to Devise controllers.
|
86
87
|
# However, if you want them to point to custom controller, you should do:
|
@@ -191,6 +192,7 @@ module ActionDispatch::Routing
|
|
191
192
|
#
|
192
193
|
def devise_for(*resources)
|
193
194
|
@devise_finalized = false
|
195
|
+
raise_no_secret_key unless Devise.secret_key
|
194
196
|
options = resources.extract_options!
|
195
197
|
|
196
198
|
options[:as] ||= @scope[:as] if @scope[:as].present?
|
@@ -222,14 +224,6 @@ module ActionDispatch::Routing
|
|
222
224
|
routes = mapping.used_routes
|
223
225
|
|
224
226
|
devise_scope mapping.name do
|
225
|
-
if block_given?
|
226
|
-
ActiveSupport::Deprecation.warn "Passing a block to devise_for is deprecated. " \
|
227
|
-
"Please remove the block from devise_for (only the block, the call to " \
|
228
|
-
"devise_for must still exist) and call devise_scope :#{mapping.name} do ... end " \
|
229
|
-
"with the block instead", caller
|
230
|
-
yield
|
231
|
-
end
|
232
|
-
|
233
227
|
with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
|
234
228
|
routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
|
235
229
|
end
|
@@ -442,6 +436,15 @@ module ActionDispatch::Routing
|
|
442
436
|
end
|
443
437
|
end
|
444
438
|
|
439
|
+
def raise_no_secret_key #:nodoc:
|
440
|
+
raise <<-ERROR
|
441
|
+
Devise.secret_key was not set. Please add the following to your Devise initializer:
|
442
|
+
|
443
|
+
config.secret_key = '#{SecureRandom.hex(64)}'
|
444
|
+
|
445
|
+
ERROR
|
446
|
+
end
|
447
|
+
|
445
448
|
def raise_no_devise_method_error!(klass) #:nodoc:
|
446
449
|
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " \
|
447
450
|
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " \
|
@@ -3,9 +3,17 @@ module Warden::Mixins::Common
|
|
3
3
|
@request ||= ActionDispatch::Request.new(env)
|
4
4
|
end
|
5
5
|
|
6
|
-
#
|
6
|
+
# Deprecate: Remove this check once we move to Rails 4 only.
|
7
|
+
NULL_STORE =
|
8
|
+
defined?(ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash) ?
|
9
|
+
ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash : nil
|
10
|
+
|
7
11
|
def reset_session!
|
8
|
-
|
12
|
+
# Calling reset_session on NULL_STORE causes it fail.
|
13
|
+
# This is a bug that needs to be fixed in Rails.
|
14
|
+
unless NULL_STORE && request.session.is_a?(NULL_STORE)
|
15
|
+
request.reset_session
|
16
|
+
end
|
9
17
|
end
|
10
18
|
|
11
19
|
def cookies
|
data/lib/devise/rails.rb
CHANGED
@@ -29,21 +29,17 @@ module Devise
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
initializer "devise.
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
"its usual uniqueness and format validations for the email field. It is recommended " \
|
39
|
-
"that you upgrade to Mongoid 2.1+ for this and other fixes, but if for some reason you " \
|
40
|
-
"are unable to do so, you should add these validations manually.\n"
|
32
|
+
initializer "devise.secret_key" do
|
33
|
+
Devise.token_generator ||=
|
34
|
+
if secret_key = Devise.secret_key
|
35
|
+
Devise::TokenGenerator.new(
|
36
|
+
Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
|
37
|
+
)
|
41
38
|
end
|
42
|
-
end
|
43
39
|
end
|
44
40
|
|
45
41
|
initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
|
46
|
-
#
|
42
|
+
# Deprecate: Remove once we move to Rails 4 only.
|
47
43
|
ActionDispatch::Routing::RoutesProxy.class_eval do
|
48
44
|
def respond_to?(method, include_private = false)
|
49
45
|
super || routes.url_helpers.respond_to?(method)
|
@@ -26,20 +26,8 @@ module Devise
|
|
26
26
|
# In case the resource can't be validated, it will fail with the given
|
27
27
|
# unauthenticated_message.
|
28
28
|
def validate(resource, &block)
|
29
|
-
unless resource
|
30
|
-
ActiveSupport::Deprecation.warn "an empty resource was given to #{self.class.name}#validate. " \
|
31
|
-
"Please ensure the resource is not nil", caller
|
32
|
-
end
|
33
|
-
|
34
29
|
result = resource && resource.valid_for_authentication?(&block)
|
35
30
|
|
36
|
-
case result
|
37
|
-
when Symbol, String
|
38
|
-
ActiveSupport::Deprecation.warn "valid_for_authentication? should return a boolean value"
|
39
|
-
fail!(result)
|
40
|
-
return false
|
41
|
-
end
|
42
|
-
|
43
31
|
if result
|
44
32
|
decorate(resource)
|
45
33
|
true
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Deprecate: Copied verbatim from Rails source, remove once we move to Rails 4 only.
|
2
|
+
require 'thread_safe'
|
3
|
+
require 'openssl'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Devise
|
7
|
+
class TokenGenerator
|
8
|
+
def initialize(key_generator, digest="SHA256")
|
9
|
+
@key_generator = key_generator
|
10
|
+
@digest = digest
|
11
|
+
end
|
12
|
+
|
13
|
+
def digest(klass, column, value)
|
14
|
+
value.present? && OpenSSL::HMAC.hexdigest(@digest, key_for(column), value.to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate(klass, column)
|
18
|
+
key = key_for(column)
|
19
|
+
|
20
|
+
loop do
|
21
|
+
raw = Devise.friendly_token
|
22
|
+
enc = OpenSSL::HMAC.hexdigest(@digest, key, raw)
|
23
|
+
break [raw, enc] unless klass.to_adapter.find_first({ column => enc })
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def key_for(column)
|
30
|
+
@key_generator.generate_key("Devise #{column}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# KeyGenerator is a simple wrapper around OpenSSL's implementation of PBKDF2
|
35
|
+
# It can be used to derive a number of keys for various purposes from a given secret.
|
36
|
+
# This lets Rails applications have a single secure secret, but avoid reusing that
|
37
|
+
# key in multiple incompatible contexts.
|
38
|
+
class KeyGenerator
|
39
|
+
def initialize(secret, options = {})
|
40
|
+
@secret = secret
|
41
|
+
# The default iterations are higher than required for our key derivation uses
|
42
|
+
# on the off chance someone uses this for password storage
|
43
|
+
@iterations = options[:iterations] || 2**16
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a derived key suitable for use. The default key_size is chosen
|
47
|
+
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
48
|
+
# i.e. OpenSSL::Digest::SHA1#block_length
|
49
|
+
def generate_key(salt, key_size=64)
|
50
|
+
OpenSSL::PKCS5.pbkdf2_hmac_sha1(@secret, salt, @iterations, key_size)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid
|
55
|
+
# re-executing the key generation process when it's called using the same salt and
|
56
|
+
# key_size
|
57
|
+
class CachingKeyGenerator
|
58
|
+
def initialize(key_generator)
|
59
|
+
@key_generator = key_generator
|
60
|
+
@cache_keys = ThreadSafe::Cache.new
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a derived key suitable for use. The default key_size is chosen
|
64
|
+
# to be compatible with the default settings of ActiveSupport::MessageVerifier.
|
65
|
+
# i.e. OpenSSL::Digest::SHA1#block_length
|
66
|
+
def generate_key(salt, key_size=64)
|
67
|
+
@cache_keys["#{salt}#{key_size}"] ||= @key_generator.generate_key(salt, key_size)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/devise/version.rb
CHANGED
data/lib/devise.rb
CHANGED
@@ -14,6 +14,7 @@ module Devise
|
|
14
14
|
autoload :ParameterSanitizer, 'devise/parameter_sanitizer'
|
15
15
|
autoload :TestHelpers, 'devise/test_helpers'
|
16
16
|
autoload :TimeInflector, 'devise/time_inflector'
|
17
|
+
autoload :TokenGenerator, 'devise/token_generator'
|
17
18
|
|
18
19
|
module Controllers
|
19
20
|
autoload :Helpers, 'devise/controllers/helpers'
|
@@ -45,6 +46,20 @@ module Devise
|
|
45
46
|
# True values used to check params
|
46
47
|
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE']
|
47
48
|
|
49
|
+
# Secret key used by the key generator
|
50
|
+
mattr_accessor :secret_key
|
51
|
+
@@secret_key = nil
|
52
|
+
|
53
|
+
# Allow insecure token lookup. Must be used
|
54
|
+
# temporarily just for migration.
|
55
|
+
mattr_accessor :allow_insecure_token_lookup
|
56
|
+
@@allow_insecure_tokens_lookup = false
|
57
|
+
|
58
|
+
# Allow insecure sign in after confirmation. Must be used
|
59
|
+
# temporarily just for migration.
|
60
|
+
mattr_accessor :allow_insecure_sign_in_after_confirmation
|
61
|
+
@@allow_insecure_sign_in_after_confirmation = false
|
62
|
+
|
48
63
|
# Custom domain or key for cookies. Not set by default
|
49
64
|
mattr_accessor :rememberable_options
|
50
65
|
@@rememberable_options = {}
|
@@ -223,17 +238,9 @@ module Devise
|
|
223
238
|
mattr_accessor :omniauth_path_prefix
|
224
239
|
@@omniauth_path_prefix = nil
|
225
240
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
def self.use_salt_as_remember_token=(value)
|
231
|
-
warn "\n[DEVISE] Devise.use_salt_as_remember_token is deprecated and has no effect. Please remove it.\n"
|
232
|
-
end
|
233
|
-
|
234
|
-
def self.apply_schema=(value)
|
235
|
-
warn "\n[DEVISE] Devise.apply_schema is deprecated and has no effect. Please remove it.\n"
|
236
|
-
end
|
241
|
+
# Set if we should clean up the CSRF Token on authentication
|
242
|
+
mattr_accessor :clean_up_csrf_token_on_authentication
|
243
|
+
@@clean_up_csrf_token_on_authentication = true
|
237
244
|
|
238
245
|
# PRIVATE CONFIGURATION
|
239
246
|
|
@@ -259,6 +266,10 @@ module Devise
|
|
259
266
|
mattr_accessor :paranoid
|
260
267
|
@@paranoid = false
|
261
268
|
|
269
|
+
# Stores the token generator
|
270
|
+
mattr_accessor :token_generator
|
271
|
+
@@token_generator = nil
|
272
|
+
|
262
273
|
# Default way to setup Devise. Run rails generate devise_install to create
|
263
274
|
# a fresh initializer with all configuration values.
|
264
275
|
def self.setup
|
@@ -447,7 +458,7 @@ module Devise
|
|
447
458
|
|
448
459
|
# Generate a friendly string randomly to be used as token.
|
449
460
|
def self.friendly_token
|
450
|
-
SecureRandom.
|
461
|
+
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
|
451
462
|
end
|
452
463
|
|
453
464
|
# constant-time comparison algorithm to prevent timing attacks
|
@@ -50,7 +50,7 @@ module ActiveRecord
|
|
50
50
|
t.datetime :remember_created_at
|
51
51
|
|
52
52
|
## Trackable
|
53
|
-
t.integer :sign_in_count, :default => 0
|
53
|
+
t.integer :sign_in_count, :default => 0, :null => false
|
54
54
|
t.datetime :current_sign_in_at
|
55
55
|
t.datetime :last_sign_in_at
|
56
56
|
t.string :current_sign_in_ip
|
@@ -63,12 +63,9 @@ module ActiveRecord
|
|
63
63
|
# t.string :unconfirmed_email # Only if using reconfirmable
|
64
64
|
|
65
65
|
## Lockable
|
66
|
-
# t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
|
66
|
+
# t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
|
67
67
|
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
68
68
|
# t.datetime :locked_at
|
69
|
-
|
70
|
-
## Token authenticatable
|
71
|
-
# t.string :authentication_token
|
72
69
|
RUBY
|
73
70
|
end
|
74
71
|
end
|
@@ -14,6 +14,5 @@ class DeviseCreate<%= table_name.camelize %> < ActiveRecord::Migration
|
|
14
14
|
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
15
15
|
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
16
16
|
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
17
|
-
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
18
17
|
end
|
19
18
|
end
|
@@ -15,7 +15,6 @@ class AddDeviseTo<%= table_name.camelize %> < ActiveRecord::Migration
|
|
15
15
|
add_index :<%= table_name %>, :reset_password_token, :unique => true
|
16
16
|
# add_index :<%= table_name %>, :confirmation_token, :unique => true
|
17
17
|
# add_index :<%= table_name %>, :unlock_token, :unique => true
|
18
|
-
# add_index :<%= table_name %>, :authentication_token, :unique => true
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.down
|
@@ -2,24 +2,43 @@ module Devise
|
|
2
2
|
module Generators
|
3
3
|
module OrmHelpers
|
4
4
|
def model_contents
|
5
|
-
<<-CONTENT
|
5
|
+
buffer = <<-CONTENT
|
6
6
|
# Include default devise modules. Others available are:
|
7
|
-
# :
|
8
|
-
# :lockable, :timeoutable and :omniauthable
|
7
|
+
# :confirmable, :lockable, :timeoutable and :omniauthable
|
9
8
|
devise :database_authenticatable, :registerable,
|
10
9
|
:recoverable, :rememberable, :trackable, :validatable
|
11
10
|
|
12
11
|
CONTENT
|
12
|
+
buffer += <<-CONTENT if needs_attr_accessible?
|
13
|
+
# Setup accessible (or protected) attributes for your model
|
14
|
+
attr_accessible :email, :password, :password_confirmation, :remember_me
|
15
|
+
|
16
|
+
CONTENT
|
17
|
+
buffer
|
18
|
+
end
|
19
|
+
|
20
|
+
def needs_attr_accessible?
|
21
|
+
rails_3? && !strong_parameters_enabled?
|
22
|
+
end
|
23
|
+
|
24
|
+
def rails_3?
|
25
|
+
Rails::VERSION::MAJOR == 3
|
13
26
|
end
|
14
27
|
|
28
|
+
def strong_parameters_enabled?
|
29
|
+
defined?(ActionController::StrongParameters)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
15
34
|
def model_exists?
|
16
35
|
File.exists?(File.join(destination_root, model_path))
|
17
36
|
end
|
18
|
-
|
37
|
+
|
19
38
|
def migration_exists?(table_name)
|
20
39
|
Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
|
21
40
|
end
|
22
|
-
|
41
|
+
|
23
42
|
def migration_path
|
24
43
|
@migration_path ||= File.join("db", "migrate")
|
25
44
|
end
|
@@ -29,4 +48,4 @@ CONTENT
|
|
29
48
|
end
|
30
49
|
end
|
31
50
|
end
|
32
|
-
end
|
51
|
+
end
|
@@ -22,7 +22,7 @@ module Mongoid
|
|
22
22
|
## Database authenticatable
|
23
23
|
field :email, :type => String, :default => ""
|
24
24
|
field :encrypted_password, :type => String, :default => ""
|
25
|
-
|
25
|
+
|
26
26
|
## Recoverable
|
27
27
|
field :reset_password_token, :type => String
|
28
28
|
field :reset_password_sent_at, :type => Time
|
@@ -54,4 +54,4 @@ RUBY
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
57
|
-
end
|
57
|
+
end
|
@@ -1,13 +1,19 @@
|
|
1
1
|
# Use this hook to configure devise mailer, warden hooks and so forth.
|
2
2
|
# Many of these configuration options can be set straight in your model.
|
3
3
|
Devise.setup do |config|
|
4
|
+
# The secret key used by Devise. Devise uses this key to generate
|
5
|
+
# random tokens. Changing this key will render invalid all existing
|
6
|
+
# confirmation, reset password and unlock tokens in the database.
|
7
|
+
config.secret_key = '<%= SecureRandom.hex(64) %>'
|
8
|
+
|
4
9
|
# ==> Mailer Configuration
|
5
10
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
6
|
-
# note that it will be overwritten if you use your own mailer class
|
7
|
-
|
11
|
+
# note that it will be overwritten if you use your own mailer class
|
12
|
+
# with default "from" parameter.
|
13
|
+
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
|
8
14
|
|
9
15
|
# Configure the class responsible to send e-mails.
|
10
|
-
# config.mailer =
|
16
|
+
# config.mailer = 'Devise::Mailer'
|
11
17
|
|
12
18
|
# ==> ORM configuration
|
13
19
|
# Load and configure the ORM. Supports :active_record (default) and
|
@@ -61,8 +67,8 @@ Devise.setup do |config|
|
|
61
67
|
# If http headers should be returned for AJAX requests. True by default.
|
62
68
|
# config.http_authenticatable_on_xhr = true
|
63
69
|
|
64
|
-
# The realm used in Http Basic Authentication.
|
65
|
-
# config.http_authentication_realm =
|
70
|
+
# The realm used in Http Basic Authentication. 'Application' by default.
|
71
|
+
# config.http_authentication_realm = 'Application'
|
66
72
|
|
67
73
|
# It will change confirmation, password recovery and other workflows
|
68
74
|
# to behave the same regardless if the e-mail provided was right or wrong.
|
@@ -76,6 +82,12 @@ Devise.setup do |config|
|
|
76
82
|
# passing :skip => :sessions to `devise_for` in your config/routes.rb
|
77
83
|
config.skip_session_storage = [:http_auth]
|
78
84
|
|
85
|
+
# By default, Devise cleans up the CSRF token on authentication to
|
86
|
+
# avoid CSRF token fixation attacks. This means that, when using AJAX
|
87
|
+
# requests for sign in and sign up, you need to get a new CSRF token
|
88
|
+
# from the server. You can disable this option at your own risk.
|
89
|
+
# config.clean_up_csrf_token_on_authentication = true
|
90
|
+
|
79
91
|
# ==> Configuration for :database_authenticatable
|
80
92
|
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
|
81
93
|
# using other encryptors, it sets how many times you want the password re-encrypted.
|
@@ -86,7 +98,7 @@ Devise.setup do |config|
|
|
86
98
|
config.stretches = Rails.env.test? ? 1 : 10
|
87
99
|
|
88
100
|
# Setup a pepper to generate the encrypted password.
|
89
|
-
# config.pepper = <%= SecureRandom.hex(64)
|
101
|
+
# config.pepper = '<%= SecureRandom.hex(64) %>'
|
90
102
|
|
91
103
|
# ==> Configuration for :confirmable
|
92
104
|
# A period that the user is allowed to access the website even without
|
@@ -211,7 +223,7 @@ Devise.setup do |config|
|
|
211
223
|
# should add them to the navigational formats lists.
|
212
224
|
#
|
213
225
|
# The "*/*" below is required to match Internet Explorer requests.
|
214
|
-
# config.navigational_formats = [
|
226
|
+
# config.navigational_formats = ['*/*', :html]
|
215
227
|
|
216
228
|
# The default HTTP method used to sign out a resource. Default is :delete.
|
217
229
|
config.sign_out_via = :delete
|
@@ -235,12 +247,12 @@ Devise.setup do |config|
|
|
235
247
|
# is mountable, there are some extra configurations to be taken into account.
|
236
248
|
# The following options are available, assuming the engine is mounted as:
|
237
249
|
#
|
238
|
-
# mount MyEngine, at:
|
250
|
+
# mount MyEngine, at: '/my_engine'
|
239
251
|
#
|
240
252
|
# The router that invoked `devise_for`, in the example above, would be:
|
241
253
|
# config.router_name = :my_engine
|
242
254
|
#
|
243
255
|
# When using omniauth, Devise cannot automatically set Omniauth path,
|
244
256
|
# so you need to do it manually. For the users scope, it would be:
|
245
|
-
# config.omniauth_path_prefix =
|
257
|
+
# config.omniauth_path_prefix = '/my_engine/users/auth'
|
246
258
|
end
|
@@ -202,7 +202,7 @@ class ControllerAuthenticatableTest < ActionController::TestCase
|
|
202
202
|
|
203
203
|
test 'sign in and redirect uses the stored location' do
|
204
204
|
user = User.new
|
205
|
-
@controller.session[:
|
205
|
+
@controller.session[:user_return_to] = "/foo.bar"
|
206
206
|
@mock_warden.expects(:user).with(:user).returns(nil)
|
207
207
|
@mock_warden.expects(:set_user).with(user, :scope => :user).returns(true)
|
208
208
|
@controller.expects(:redirect_to).with("/foo.bar")
|
@@ -4,16 +4,15 @@ class PasswordsControllerTest < ActionController::TestCase
|
|
4
4
|
tests Devise::PasswordsController
|
5
5
|
include Devise::TestHelpers
|
6
6
|
|
7
|
-
|
7
|
+
setup do
|
8
8
|
request.env["devise.mapping"] = Devise.mappings[:user]
|
9
|
-
|
10
|
-
@
|
11
|
-
@user.send_reset_password_instructions
|
9
|
+
@user = create_user.tap(&:confirm!)
|
10
|
+
@raw = @user.send_reset_password_instructions
|
12
11
|
end
|
13
12
|
|
14
13
|
def put_update_with_params
|
15
14
|
put :update, "user" => {
|
16
|
-
"reset_password_token" => @
|
15
|
+
"reset_password_token" => @raw, "password" => "123456", "password_confirmation" => "123456"
|
17
16
|
}
|
18
17
|
end
|
19
18
|
|
data/test/failure_app_test.rb
CHANGED
@@ -215,7 +215,7 @@ class FailureTest < ActiveSupport::TestCase
|
|
215
215
|
}
|
216
216
|
call_failure(env)
|
217
217
|
assert @response.third.body.include?('<h2>Sign in</h2>')
|
218
|
-
assert @response.third.body.include?('Your account
|
218
|
+
assert @response.third.body.include?('Your account is not activated yet.')
|
219
219
|
end
|
220
220
|
end
|
221
221
|
end
|