devise 2.1.0.rc → 2.1.0.rc2

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.

Files changed (65) hide show
  1. data/CHANGELOG.rdoc +23 -1
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +4 -6
  4. data/MIT-LICENSE +1 -1
  5. data/README.md +7 -3
  6. data/Rakefile +1 -1
  7. data/app/controllers/devise/sessions_controller.rb +2 -4
  8. data/app/controllers/devise/unlocks_controller.rb +15 -2
  9. data/app/controllers/devise_controller.rb +24 -11
  10. data/devise.gemspec +1 -1
  11. data/gemfiles/Gemfile.rails-3.1.x +1 -1
  12. data/gemfiles/Gemfile.rails-3.1.x.lock +38 -40
  13. data/lib/devise.rb +13 -55
  14. data/lib/devise/controllers/helpers.rb +0 -5
  15. data/lib/devise/failure_app.rb +3 -1
  16. data/lib/devise/hooks/lockable.rb +7 -0
  17. data/lib/devise/hooks/timeoutable.rb +1 -0
  18. data/lib/devise/models.rb +9 -3
  19. data/lib/devise/models/authenticatable.rb +13 -3
  20. data/lib/devise/models/confirmable.rb +2 -5
  21. data/lib/devise/models/database_authenticatable.rb +4 -6
  22. data/lib/devise/models/lockable.rb +6 -6
  23. data/lib/devise/models/rememberable.rb +3 -3
  24. data/lib/devise/models/token_authenticatable.rb +4 -1
  25. data/lib/devise/modules.rb +0 -1
  26. data/lib/devise/orm/active_record.rb +1 -42
  27. data/lib/devise/orm/mongoid.rb +1 -29
  28. data/lib/devise/rails.rb +1 -58
  29. data/lib/devise/rails/routes.rb +1 -1
  30. data/lib/devise/rails/warden_compat.rb +10 -4
  31. data/lib/devise/strategies/rememberable.rb +1 -1
  32. data/lib/devise/test_helpers.rb +48 -9
  33. data/lib/devise/version.rb +1 -1
  34. data/lib/generators/active_record/devise_generator.rb +8 -4
  35. data/lib/generators/devise/orm_helpers.rb +2 -1
  36. data/lib/generators/mongoid/devise_generator.rb +0 -3
  37. data/lib/generators/templates/devise.rb +1 -8
  38. data/test/controllers/custom_strategy_test.rb +62 -0
  39. data/test/controllers/sessions_controller_test.rb +21 -1
  40. data/test/failure_app_test.rb +13 -3
  41. data/test/generators/active_record_generator_test.rb +32 -0
  42. data/test/integration/authenticatable_test.rb +2 -2
  43. data/test/integration/recoverable_test.rb +13 -0
  44. data/test/integration/token_authenticatable_test.rb +13 -0
  45. data/test/models/lockable_test.rb +0 -9
  46. data/test/models/rememberable_test.rb +1 -2
  47. data/test/models_test.rb +5 -5
  48. data/test/rails_app/app/mongoid/admin.rb +0 -3
  49. data/test/rails_app/app/mongoid/user.rb +0 -3
  50. data/test/rails_app/config/initializers/devise.rb +0 -15
  51. data/test/rails_app/config/routes.rb +1 -0
  52. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -6
  53. data/test/rails_app/lib/shared_admin.rb +1 -1
  54. metadata +17 -24
  55. data/lib/devise/encryptors/authlogic_sha512.rb +0 -19
  56. data/lib/devise/encryptors/base.rb +0 -24
  57. data/lib/devise/encryptors/bcrypt.rb +0 -14
  58. data/lib/devise/encryptors/clearance_sha1.rb +0 -17
  59. data/lib/devise/encryptors/restful_authentication_sha1.rb +0 -22
  60. data/lib/devise/encryptors/sha1.rb +0 -25
  61. data/lib/devise/encryptors/sha512.rb +0 -25
  62. data/lib/devise/models/encryptable.rb +0 -80
  63. data/lib/devise/schema.rb +0 -109
  64. data/test/encryptors_test.rb +0 -30
  65. data/test/models/encryptable_test.rb +0 -73
@@ -237,11 +237,6 @@ module Devise
237
237
  redirect_to after_sign_in_path_for(resource)
238
238
  end
239
239
 
240
- def redirect_location(scope, resource) #:nodoc:
241
- ActiveSupport::Deprecation.warn "redirect_location in Devise is deprecated. Please use after_sign_in_path_for instead.", caller
242
- after_sign_in_path_for(resource)
243
- end
244
-
245
240
  def expire_session_data_after_sign_in!
246
241
  session.keys.grep(/^devise\./).each { |k| session.delete(k) }
247
242
  end
@@ -88,7 +88,9 @@ module Devise
88
88
  opts = {}
89
89
  route = :"new_#{scope}_session_path"
90
90
  opts[:format] = request_format unless skip_format?
91
- opts[:script_name] = nil
91
+
92
+ config = Rails.application.config
93
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
92
94
 
93
95
  context = send(Devise.available_router_name)
94
96
 
@@ -0,0 +1,7 @@
1
+ # After each sign in, if resource responds to failed_attempts, sets it to 0
2
+ # This is only triggered when the user is explicitly set (with set_user)
3
+ Warden::Manager.after_set_user :except => :fetch do |record, warden, options|
4
+ if record.respond_to?(:failed_attempts) && warden.authenticated?(options[:scope])
5
+ record.update_attribute(:failed_attempts, 0)
6
+ end
7
+ end
@@ -11,6 +11,7 @@ Warden::Manager.after_set_user do |record, warden, options|
11
11
 
12
12
  if record.timedout?(last_request_at)
13
13
  warden.logout(scope)
14
+ record.reset_authentication_token! if record.respond_to?(:reset_authentication_token!) && record.expire_auth_token_on_timeout
14
15
  throw :warden, :scope => scope, :message => :timeout
15
16
  end
16
17
 
data/lib/devise/models.rb CHANGED
@@ -60,7 +60,9 @@ module Devise
60
60
  failed_attributes << field unless instance.respond_to?(field)
61
61
  end
62
62
  else
63
- ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). Devise uses required_fields to warn developers of any missing fields in their models. Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
63
+ ActiveSupport::Deprecation.warn "The module #{mod} doesn't implement self.required_fields(klass). " \
64
+ "Devise uses required_fields to warn developers of any missing fields in their models. " \
65
+ "Please implement #{mod}.required_fields(klass) that returns an array of symbols with the required fields."
64
66
  end
65
67
  end
66
68
 
@@ -87,6 +89,10 @@ module Devise
87
89
  devise_modules_hook! do
88
90
  include Devise::Models::Authenticatable
89
91
  selected_modules.each do |m|
92
+ if m == :encryptable && !(defined?(Devise::Models::Encryptable))
93
+ 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"
94
+ end
95
+
90
96
  mod = Devise::Models.const_get(m.to_s.classify)
91
97
 
92
98
  if mod.const_defined?("ClassMethods")
@@ -110,8 +116,8 @@ module Devise
110
116
  end
111
117
  end
112
118
 
113
- # The hook which is called inside devise. So your ORM can include devise
114
- # compatibility stuff.
119
+ # The hook which is called inside devise.
120
+ # So your ORM can include devise compatibility stuff.
115
121
  def devise_modules_hook!
116
122
  yield
117
123
  end
@@ -54,7 +54,7 @@ module Devise
54
54
  BLACKLIST_FOR_SERIALIZATION = [:encrypted_password, :reset_password_token, :reset_password_sent_at,
55
55
  :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip,
56
56
  :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at,
57
- :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]
57
+ :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at, :authentication_token]
58
58
 
59
59
  included do
60
60
  class_attribute :devise_modules, :instance_writer => false
@@ -102,11 +102,11 @@ module Devise
102
102
  end
103
103
 
104
104
  def downcase_keys
105
- (self.class.case_insensitive_keys || []).each { |k| self[k].try(:downcase!) }
105
+ self.class.case_insensitive_keys.each { |k| self[k].try(:downcase!) }
106
106
  end
107
107
 
108
108
  def strip_whitespace
109
- (self.class.strip_whitespace_keys || []).each { |k| self[k].try(:strip!) }
109
+ self.class.strip_whitespace_keys.each { |k| self[k].try(:strip!) }
110
110
  end
111
111
 
112
112
  array = %w(serializable_hash)
@@ -158,6 +158,12 @@ module Devise
158
158
  end
159
159
 
160
160
  # Find first record based on conditions given (ie by the sign in form).
161
+ # This method is always called during an authentication process but
162
+ # it may be wrapped as well. For instance, database authenticatable
163
+ # provides a `find_for_database_authentication` that wraps a call to
164
+ # this method. This allows you to customize both database authenticatable
165
+ # or the whole authenticate stack by customize `find_for_authentication.`
166
+ #
161
167
  # Overwrite to add customized conditions, create a join, or maybe use a
162
168
  # namedscope to filter records while authenticating.
163
169
  # Example:
@@ -167,6 +173,10 @@ module Devise
167
173
  # super
168
174
  # end
169
175
  #
176
+ # Finally, notice that Devise also queries for users in other scenarios
177
+ # besides authentication, for example when retrieving an user to send
178
+ # an e-mail for password reset. In such cases, find_for_authentication
179
+ # is not called.
170
180
  def find_for_authentication(conditions)
171
181
  find_first_by_auth_conditions(conditions)
172
182
  end
@@ -33,15 +33,12 @@ module Devise
33
33
  before_create :generate_confirmation_token, :if => :confirmation_required?
34
34
  after_create :send_on_create_confirmation_instructions, :if => :confirmation_required?
35
35
  before_update :postpone_email_change_until_confirmation, :if => :postpone_email_change?
36
- after_update :send_confirmation_instructions, :if => :reconfirmation_required?
36
+ after_update :send_confirmation_instructions, :if => :reconfirmation_required?
37
37
  end
38
38
 
39
39
  def self.required_fields(klass)
40
40
  required_methods = [:confirmation_token, :confirmed_at, :confirmation_sent_at]
41
- if klass.reconfirmable
42
- required_methods << :unconfirmed_email
43
- end
44
-
41
+ required_methods << :unconfirmed_email if klass.reconfirmable
45
42
  required_methods
46
43
  end
47
44
 
@@ -40,7 +40,9 @@ module Devise
40
40
  # Verifies whether an password (ie from sign in) is the user password.
41
41
  def valid_password?(password)
42
42
  return false if encrypted_password.blank?
43
- encryptor_class.compare(encrypted_password, password, self.class.stretches, authenticatable_salt, self.class.pepper)
43
+ bcrypt = ::BCrypt::Password.new(encrypted_password)
44
+ password = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt.salt)
45
+ Devise.secure_compare(password, encrypted_password)
44
46
  end
45
47
 
46
48
  # Set password and password confirmation to nil
@@ -105,11 +107,7 @@ module Devise
105
107
 
106
108
  # Digests the password using bcrypt.
107
109
  def password_digest(password)
108
- encryptor_class.digest(password, self.class.stretches, ::BCrypt::Engine.generate_salt, self.class.pepper)
109
- end
110
-
111
- def encryptor_class
112
- Devise::Encryptors::BCrypt
110
+ ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
113
111
  end
114
112
 
115
113
  module ClassMethods
@@ -1,3 +1,5 @@
1
+ require "devise/hooks/lockable"
2
+
1
3
  module Devise
2
4
  module Models
3
5
  # Handles blocking a user access after a certain number of attempts.
@@ -43,7 +45,7 @@ module Devise
43
45
  save(:validate => false)
44
46
  end
45
47
 
46
- # Unlock a user by cleaning locket_at and failed_attempts.
48
+ # Unlock a user by cleaning locked_at and failed_attempts.
47
49
  def unlock_access!
48
50
  self.locked_at = nil
49
51
  self.failed_attempts = 0 if respond_to?(:failed_attempts=)
@@ -89,8 +91,6 @@ module Devise
89
91
  unlock_access! if lock_expired?
90
92
 
91
93
  if super && !access_locked?
92
- self.failed_attempts = 0
93
- save(:validate => false)
94
94
  true
95
95
  else
96
96
  self.failed_attempts ||= 0
@@ -149,9 +149,9 @@ module Devise
149
149
  # with an email not found error.
150
150
  # Options must contain the user email
151
151
  def send_unlock_instructions(attributes={})
152
- lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
153
- lockable.resend_unlock_token if lockable.persisted?
154
- lockable
152
+ lockable = find_or_initialize_with_errors(unlock_keys, attributes, :not_found)
153
+ lockable.resend_unlock_token if lockable.persisted?
154
+ lockable
155
155
  end
156
156
 
157
157
  # Find a user by its unlock token and try to unlock it.
@@ -42,7 +42,7 @@ module Devise
42
42
  attr_accessor :remember_me, :extend_remember_period
43
43
 
44
44
  def self.required_fields(klass)
45
- [:remember_created_at, :remember_token]
45
+ [:remember_created_at]
46
46
  end
47
47
 
48
48
  # Generate a new remember token and save the record without validations
@@ -91,7 +91,7 @@ module Devise
91
91
 
92
92
  protected
93
93
 
94
- def generate_remember_token?
94
+ def generate_remember_token? #:nodoc:
95
95
  respond_to?(:remember_token) && remember_expired?
96
96
  end
97
97
 
@@ -114,7 +114,7 @@ module Devise
114
114
  end
115
115
 
116
116
  # Generate a token checking if one does not already exist in the database.
117
- def remember_token
117
+ def remember_token #:nodoc:
118
118
  generate_token(:remember_token)
119
119
  end
120
120
 
@@ -56,6 +56,9 @@ module Devise
56
56
  def after_token_authentication
57
57
  end
58
58
 
59
+ def expire_auth_token_on_timeout
60
+ self.class.expire_auth_token_on_timeout
61
+ end
59
62
 
60
63
  module ClassMethods
61
64
  def find_for_token_authentication(conditions)
@@ -67,7 +70,7 @@ module Devise
67
70
  generate_token(:authentication_token)
68
71
  end
69
72
 
70
- ::Devise::Models.config(self, :token_authentication_key)
73
+ Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)
71
74
  end
72
75
  end
73
76
  end
@@ -10,7 +10,6 @@ Devise.with_options :model => true do |d|
10
10
  end
11
11
 
12
12
  # Other authentications
13
- d.add_module :encryptable
14
13
  d.add_module :omniauthable, :controller => :omniauth_callbacks, :route => :omniauth_callback
15
14
 
16
15
  # Misc after
@@ -1,44 +1,3 @@
1
1
  require 'orm_adapter/adapters/active_record'
2
2
 
3
- module Devise
4
- module Orm
5
- # This module contains some helpers and handle schema (migrations):
6
- #
7
- # create_table :accounts do |t|
8
- # t.database_authenticatable
9
- # t.confirmable
10
- # t.recoverable
11
- # t.rememberable
12
- # t.trackable
13
- # t.lockable
14
- # t.timestamps
15
- # end
16
- #
17
- # However this method does not add indexes. If you need them, here is the declaration:
18
- #
19
- # add_index "accounts", ["email"], :name => "email", :unique => true
20
- # add_index "accounts", ["confirmation_token"], :name => "confirmation_token", :unique => true
21
- # add_index "accounts", ["reset_password_token"], :name => "reset_password_token", :unique => true
22
- #
23
- module ActiveRecord
24
- module Schema
25
- include Devise::Schema
26
-
27
- # Tell how to apply schema methods.
28
- def apply_devise_schema(name, type, options={})
29
- @__devise_warning_raised ||= begin
30
- $stderr.puts "\n[DEVISE] You are using t.database_authenticatable and others in your migration " \
31
- "and this feature is deprecated. Please simply use Rails helpers instead as mentioned here:\n" \
32
- "https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n\n"
33
- true
34
- end
35
- column name, type.to_s.downcase.to_sym, options
36
- end
37
- end
38
- end
39
- end
40
- end
41
-
42
- ActiveRecord::Base.extend Devise::Models
43
- ActiveRecord::ConnectionAdapters::Table.send :include, Devise::Orm::ActiveRecord::Schema
44
- ActiveRecord::ConnectionAdapters::TableDefinition.send :include, Devise::Orm::ActiveRecord::Schema
3
+ ActiveRecord::Base.extend Devise::Models
@@ -1,31 +1,3 @@
1
1
  require 'orm_adapter/adapters/mongoid'
2
2
 
3
- module Devise
4
- module Orm
5
- module Mongoid
6
- module Hook
7
- def devise_modules_hook!
8
- extend Schema
9
- yield
10
- return unless Devise.apply_schema
11
- devise_modules.each { |m| send(m) if respond_to?(m, true) }
12
- end
13
- end
14
-
15
- module Schema
16
- include Devise::Schema
17
-
18
- # Tell how to apply schema methods
19
- def apply_devise_schema(name, type, options={})
20
- type = Time if type == DateTime
21
- field name, { :type => type }.merge!(options)
22
- end
23
- end
24
- end
25
- end
26
- end
27
-
28
- Mongoid::Document::ClassMethods.class_eval do
29
- include Devise::Models
30
- include Devise::Orm::Mongoid::Hook
31
- end
3
+ Mongoid::Document::ClassMethods.send :include, Devise::Models
data/lib/devise/rails.rb CHANGED
@@ -43,69 +43,12 @@ module Devise
43
43
  end
44
44
 
45
45
  initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
46
- # We can get rid of this once we support Rails > 3.2
46
+ # We can get rid of this once we support only Rails > 3.2
47
47
  ActionDispatch::Routing::RoutesProxy.class_eval do
48
48
  def respond_to?(method, include_private = false)
49
49
  super || routes.url_helpers.respond_to?(method)
50
50
  end
51
51
  end
52
52
  end
53
-
54
- initializer "devise.deprecations" do
55
- unless defined?(Rails::Generators)
56
- if Devise.case_insensitive_keys == false
57
- warn "\n[DEVISE] Devise.case_insensitive_keys is false which is no longer " \
58
- "supported. Recent Devise versions automatically downcase the e-mail before " \
59
- "saving it to the database but your app isn't using this feature. You can solve " \
60
- "this issue by either:\n\n" \
61
- "1) Setting config.case_insensitive_keys = [:email] in your Devise initializer and " \
62
- "running a migration that will downcase all emails already in the database;\n\n" \
63
- "2) Setting config.case_insensitive_keys = [] (so nothing will be downcased) and " \
64
- "making sure you are not using Devise :validatable (since validatable assumes case" \
65
- "insensitivity)\n"
66
- end
67
-
68
- if Devise.apply_schema && defined?(Mongoid)
69
- warn "\n[DEVISE] Devise.apply_schema is true. This means Devise was " \
70
- "automatically configuring your DB. This no longer happens. You should " \
71
- "set Devise.apply_schema to false and manually set the fields used by Devise as shown here: " \
72
- "https://github.com/plataformatec/devise/wiki/How-To:-Upgrade-to-Devise-2.0-migration-schema-style\n"
73
- end
74
-
75
- # TODO: Deprecate the true value of this option as well
76
- if Devise.use_salt_as_remember_token == false
77
- warn "\n[DEVISE] Devise.use_salt_as_remember_token is false which is no longer " \
78
- "supported. Devise now only uses the salt as remember token and the remember_token " \
79
- "column can be removed from your models.\n"
80
- end
81
-
82
- if Devise.reset_password_within.nil?
83
- warn "\n[DEVISE] Devise.reset_password_within is nil. Please set this value to " \
84
- "an interval (for example, 6.hours) and add a reset_password_sent_at field to " \
85
- "your Devise models (if they don't have one already).\n"
86
- end
87
- end
88
-
89
- config.after_initialize do
90
- example = <<-YAML
91
- en:
92
- devise:
93
- registrations:
94
- signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
95
- signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
96
- signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
97
- YAML
98
-
99
- if I18n.t(:"devise.registrations.reasons", :default => {}).present?
100
- warn "\n[DEVISE] devise.registrations.reasons in yml files is deprecated, " \
101
- "please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
102
- end
103
-
104
- if I18n.t(:"devise.registrations.inactive_signed_up", :default => "").present?
105
- warn "\n[DEVISE] devise.registrations.inactive_signed_up in yml files is deprecated, " \
106
- "please use devise.registrations.signed_up_but_REASON instead. The default values are:\n\n#{example}\n"
107
- end
108
- end
109
- end
110
53
  end
111
54
  end
@@ -136,7 +136,7 @@ module ActionDispatch::Routing
136
136
  #
137
137
  # devise_for :users, :format => false
138
138
  #
139
- # * :constraints => works the same as Rails' contraints
139
+ # * :constraints => works the same as Rails' constraints
140
140
  #
141
141
  # * :defaults => works the same as Rails' defaults
142
142
  #
@@ -21,17 +21,23 @@ class Warden::SessionSerializer
21
21
  end
22
22
 
23
23
  def deserialize(keys)
24
- klass, *args = keys
24
+ klass_name, *args = keys
25
25
 
26
26
  begin
27
- ActiveSupport::Inflector.constantize(klass).serialize_from_session(*args)
27
+ klass = ActiveSupport::Inflector.constantize(klass_name)
28
+ if klass.respond_to? :serialize_from_session
29
+ klass.serialize_from_session(*args)
30
+ else
31
+ Rails.logger.warn "[Devise] Stored serialized class #{klass_name} seems not to be Devise enabled anymore. Did you do that on purpose?"
32
+ nil
33
+ end
28
34
  rescue NameError => e
29
35
  if e.message =~ /uninitialized constant/
30
- Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass}"
36
+ Rails.logger.debug "[Devise] Trying to deserialize invalid class #{klass_name}"
31
37
  nil
32
38
  else
33
39
  raise
34
40
  end
35
41
  end
36
42
  end
37
- end
43
+ end