devise 2.0.0.rc → 2.0.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 (75) hide show
  1. data/CHANGELOG.rdoc +94 -74
  2. data/README.rdoc +2 -2
  3. data/app/controllers/devise/confirmations_controller.rb +3 -6
  4. data/app/controllers/devise/omniauth_callbacks_controller.rb +1 -3
  5. data/app/controllers/devise/passwords_controller.rb +3 -6
  6. data/app/controllers/devise/registrations_controller.rb +34 -41
  7. data/app/controllers/devise/sessions_controller.rb +2 -3
  8. data/app/controllers/devise/unlocks_controller.rb +3 -5
  9. data/app/controllers/devise_controller.rb +169 -0
  10. data/app/views/devise/_links.erb +25 -0
  11. data/app/views/devise/confirmations/new.html.erb +1 -1
  12. data/app/views/devise/passwords/edit.html.erb +1 -1
  13. data/app/views/devise/passwords/new.html.erb +1 -1
  14. data/app/views/devise/registrations/new.html.erb +1 -1
  15. data/app/views/devise/sessions/new.html.erb +1 -1
  16. data/app/views/devise/shared/_links.erb +3 -25
  17. data/app/views/devise/unlocks/new.html.erb +1 -1
  18. data/config/locales/en.yml +4 -6
  19. data/lib/devise.rb +15 -11
  20. data/lib/devise/controllers/helpers.rb +8 -2
  21. data/lib/devise/controllers/scoped_views.rb +0 -16
  22. data/lib/devise/controllers/url_helpers.rb +16 -2
  23. data/lib/devise/failure_app.rb +43 -8
  24. data/lib/devise/models.rb +1 -1
  25. data/lib/devise/models/confirmable.rb +12 -9
  26. data/lib/devise/models/lockable.rb +1 -1
  27. data/lib/devise/models/serializable.rb +5 -2
  28. data/lib/devise/modules.rb +2 -2
  29. data/lib/devise/param_filter.rb +1 -1
  30. data/lib/devise/path_checker.rb +5 -1
  31. data/lib/devise/rails.rb +21 -0
  32. data/lib/devise/rails/routes.rb +16 -10
  33. data/lib/devise/rails/warden_compat.rb +0 -83
  34. data/lib/devise/strategies/authenticatable.rb +2 -2
  35. data/lib/devise/version.rb +1 -1
  36. data/lib/generators/active_record/devise_generator.rb +1 -1
  37. data/lib/generators/active_record/templates/migration.rb +0 -10
  38. data/lib/generators/devise/views_generator.rb +6 -14
  39. data/lib/generators/templates/devise.rb +11 -3
  40. data/lib/generators/templates/simple_form_for/confirmations/new.html.erb +1 -1
  41. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  42. data/lib/generators/templates/simple_form_for/passwords/new.html.erb +1 -1
  43. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  44. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +1 -1
  45. data/lib/generators/templates/simple_form_for/unlocks/new.html.erb +1 -1
  46. data/test/controllers/internal_helpers_test.rb +1 -2
  47. data/test/failure_app_test.rb +24 -20
  48. data/test/generators/active_record_generator_test.rb +3 -13
  49. data/test/generators/views_generator_test.rb +1 -1
  50. data/test/integration/authenticatable_test.rb +4 -7
  51. data/test/integration/http_authenticatable_test.rb +4 -4
  52. data/test/integration/lockable_test.rb +24 -12
  53. data/test/integration/registerable_test.rb +1 -1
  54. data/test/integration/timeoutable_test.rb +18 -4
  55. data/test/integration/token_authenticatable_test.rb +3 -3
  56. data/test/integration/trackable_test.rb +5 -5
  57. data/test/models/confirmable_test.rb +15 -0
  58. data/test/models/database_authenticatable_test.rb +6 -0
  59. data/test/models/lockable_test.rb +13 -0
  60. data/test/rails_app/app/mongoid/user.rb +1 -1
  61. data/test/rails_app/config/routes.rb +3 -5
  62. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +1 -1
  63. data/test/rails_app/lib/shared_admin.rb +1 -0
  64. data/test/rails_app/log/development.log +13 -0
  65. data/test/rails_app/log/test.log +290988 -0
  66. data/test/support/helpers.rb +0 -17
  67. metadata +105 -57
  68. data/.gitignore +0 -10
  69. data/.travis.yml +0 -13
  70. data/Gemfile +0 -35
  71. data/Gemfile.lock +0 -168
  72. data/Rakefile +0 -34
  73. data/devise.gemspec +0 -25
  74. data/lib/devise/controllers/internal_helpers.rb +0 -161
  75. data/lib/devise/controllers/shared_helpers.rb +0 -26
@@ -16,10 +16,8 @@ module Devise
16
16
 
17
17
  module Controllers
18
18
  autoload :Helpers, 'devise/controllers/helpers'
19
- autoload :InternalHelpers, 'devise/controllers/internal_helpers'
20
19
  autoload :Rememberable, 'devise/controllers/rememberable'
21
20
  autoload :ScopedViews, 'devise/controllers/scoped_views'
22
- autoload :SharedHelpers, 'devise/controllers/shared_helpers'
23
21
  autoload :UrlHelpers, 'devise/controllers/url_helpers'
24
22
  end
25
23
 
@@ -202,9 +200,8 @@ module Devise
202
200
  @@skip_session_storage = []
203
201
 
204
202
  # Which formats should be treated as navigational.
205
- # We need both :"*/*" and "*/*" to work on different Rails versions.
206
203
  mattr_accessor :navigational_formats
207
- @@navigational_formats = [:"*/*", "*/*", :html]
204
+ @@navigational_formats = ["*/*", :html]
208
205
 
209
206
  # When set to true, signing out a user signs out all other scopes.
210
207
  mattr_accessor :sign_out_all_scopes
@@ -214,6 +211,18 @@ module Devise
214
211
  mattr_accessor :sign_out_via
215
212
  @@sign_out_via = :get
216
213
 
214
+ # The parent controller all Devise controllers inherits from.
215
+ # Defaults to ApplicationController. This should be set early
216
+ # in the initialization process and should be set to a string.
217
+ mattr_accessor :parent_controller
218
+ @@parent_controller = "ApplicationController"
219
+
220
+ # The router Devise should use to generate routes. Defaults
221
+ # to :main_app. Should be overriden by engines in order
222
+ # to provide custom routes.
223
+ mattr_accessor :router_name
224
+ @@router_name = :main_app
225
+
217
226
  # DEPRECATED CONFIG
218
227
 
219
228
  # If true, uses salt as remember token and does not create it in the database.
@@ -334,7 +343,7 @@ module Devise
334
343
  #
335
344
  def self.add_module(module_name, options = {})
336
345
  ALL << module_name
337
- options.assert_valid_keys(:strategy, :model, :controller, :route)
346
+ options.assert_valid_keys(:strategy, :model, :controller, :route, :no_input)
338
347
 
339
348
  if strategy = options[:strategy]
340
349
  strategy = (strategy == true ? module_name : strategy)
@@ -346,7 +355,7 @@ module Devise
346
355
  CONTROLLERS[module_name] = controller
347
356
  end
348
357
 
349
- NO_INPUT << strategy if strategy && controller != :sessions
358
+ NO_INPUT << strategy if options[:no_input]
350
359
 
351
360
  if route = options[:route]
352
361
  case route
@@ -413,11 +422,6 @@ module Devise
413
422
  end
414
423
  end
415
424
 
416
- # Returns true if Rails version is bigger than 3.0.x
417
- def self.rack_session?
418
- Rails::VERSION::STRING[0,3] != "3.0"
419
- end
420
-
421
425
  # Regenerates url helpers considering Devise.mapping
422
426
  def self.regenerate_helpers!
423
427
  Devise::Controllers::UrlHelpers.remove_helpers!
@@ -168,7 +168,13 @@ module Devise
168
168
  def signed_in_root_path(resource_or_scope)
169
169
  scope = Devise::Mapping.find_scope!(resource_or_scope)
170
170
  home_path = "#{scope}_root_path"
171
- respond_to?(home_path, true) ? send(home_path) : root_path
171
+ if respond_to?(home_path, true)
172
+ send(home_path)
173
+ elsif respond_to?(:root_path)
174
+ root_path
175
+ else
176
+ "/"
177
+ end
172
178
  end
173
179
 
174
180
  # The default url to be used after signing in. This is used by all Devise
@@ -209,7 +215,7 @@ module Devise
209
215
  #
210
216
  # By default it is the root_path.
211
217
  def after_sign_out_path_for(resource_or_scope)
212
- root_path
218
+ respond_to?(:root_path) ? root_path : "/"
213
219
  end
214
220
 
215
221
  # Sign in a user and tries to redirect first to the stored location and
@@ -12,22 +12,6 @@ module Devise
12
12
  @scoped_views = value
13
13
  end
14
14
  end
15
-
16
- protected
17
-
18
- # Render a view for the specified scope. Turned off by default.
19
- # Accepts just :controller as option.
20
- def render_with_scope(action, path=self.controller_path)
21
- if self.class.scoped_views?
22
- begin
23
- render :template => "#{devise_mapping.scoped_path}/#{path.split("/").last}/#{action}"
24
- rescue ActionView::MissingTemplate
25
- render :template => "#{path}/#{action}"
26
- end
27
- else
28
- render :template => "#{path}/#{action}"
29
- end
30
- end
31
15
  end
32
16
  end
33
17
  end
@@ -16,7 +16,15 @@ module Devise
16
16
  # new_confirmation_path(:user) => new_user_confirmation_path
17
17
  # confirmation_path(:user) => user_confirmation_path
18
18
  #
19
- # Those helpers are added to your ApplicationController.
19
+ # Those helpers are included by default to ActionController::Base.
20
+ #
21
+ # In case you want to add such helpers to another class, you can do
22
+ # that as long as this new class includes both url_helpers and
23
+ # mounted_helpers. Example:
24
+ #
25
+ # include Rails.application.routes.url_helpers
26
+ # include Rails.application.routes.mounted_helpers
27
+ #
20
28
  module UrlHelpers
21
29
  def self.remove_helpers!
22
30
  self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method|
@@ -39,7 +47,7 @@ module Devise
39
47
  class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
40
48
  def #{method}(resource_or_scope, *args)
41
49
  scope = Devise::Mapping.find_scope!(resource_or_scope)
42
- send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
50
+ _devise_route_context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
43
51
  end
44
52
  URL_HELPERS
45
53
  end
@@ -48,6 +56,12 @@ module Devise
48
56
  end
49
57
 
50
58
  generate_helpers!(Devise::URL_HELPERS)
59
+
60
+ private
61
+
62
+ def _devise_route_context
63
+ @_devise_route_context ||= send(Devise.router_name)
64
+ end
51
65
  end
52
66
  end
53
67
  end
@@ -9,8 +9,9 @@ module Devise
9
9
  include ActionController::RackDelegation
10
10
  include ActionController::UrlFor
11
11
  include ActionController::Redirecting
12
+
12
13
  include Rails.application.routes.url_helpers
13
- include Devise::Controllers::SharedHelpers
14
+ include Rails.application.routes.mounted_helpers
14
15
 
15
16
  delegate :flash, :to => :request
16
17
 
@@ -20,7 +21,11 @@ module Devise
20
21
  end
21
22
 
22
23
  def self.default_url_options(*args)
23
- ApplicationController.default_url_options(*args)
24
+ if defined?(ApplicationController)
25
+ ApplicationController.default_url_options(*args)
26
+ else
27
+ {}
28
+ end
24
29
  end
25
30
 
26
31
  def respond
@@ -48,32 +53,50 @@ module Devise
48
53
 
49
54
  def redirect
50
55
  store_location!
51
- flash[:alert] = i18n_message
56
+ if flash[:timedout] && flash[:alert]
57
+ flash.keep(:timedout)
58
+ flash.keep(:alert)
59
+ else
60
+ flash[:alert] = i18n_message
61
+ end
52
62
  redirect_to redirect_url
53
63
  end
54
64
 
55
65
  protected
56
66
 
57
67
  def i18n_message(default = nil)
58
- message = warden.message || warden_options[:message] || default || :unauthenticated
68
+ message = warden_message || default || :unauthenticated
59
69
 
60
70
  if message.is_a?(Symbol)
61
71
  I18n.t(:"#{scope}.#{message}", :resource_name => scope,
62
- :scope => "devise.failure", :default => [message, message.to_s])
72
+ :scope => "devise.failure", :default => [message])
63
73
  else
64
74
  message.to_s
65
75
  end
66
76
  end
67
77
 
68
78
  def redirect_url
79
+ if warden_message == :timeout
80
+ flash[:timedout] = true
81
+ attempted_path || scope_path
82
+ else
83
+ scope_path
84
+ end
85
+ end
86
+
87
+ def scope_path
69
88
  opts = {}
70
89
  route = :"new_#{scope}_session_path"
71
90
  opts[:format] = request_format unless skip_format?
72
91
 
73
- if respond_to?(route)
74
- send(route, opts)
75
- else
92
+ context = send(Devise.router_name)
93
+
94
+ if context.respond_to?(route)
95
+ context.send(route, opts)
96
+ elsif respond_to?(:root_path)
76
97
  root_path(opts)
98
+ else
99
+ "/"
77
100
  end
78
101
  end
79
102
 
@@ -130,6 +153,10 @@ module Devise
130
153
  env['warden.options']
131
154
  end
132
155
 
156
+ def warden_message
157
+ @message ||= warden.message || warden_options[:message]
158
+ end
159
+
133
160
  def scope
134
161
  @scope ||= warden_options[:scope] || Devise.default_scope
135
162
  end
@@ -145,5 +172,13 @@ module Devise
145
172
  def store_location!
146
173
  session["#{scope}_return_to"] = attempted_path if request.get? && !http_auth?
147
174
  end
175
+
176
+ def is_navigational_format?
177
+ Devise.navigational_formats.include?(request_format)
178
+ end
179
+
180
+ def request_format
181
+ @request_format ||= request.format.try(:ref)
182
+ end
148
183
  end
149
184
  end
@@ -48,7 +48,6 @@ module Devise
48
48
  # for a complete description on those values.
49
49
  #
50
50
  def devise(*modules)
51
- include Devise::Models::Authenticatable
52
51
  options = modules.extract_options!.dup
53
52
 
54
53
  selected_modules = modules.map(&:to_sym).uniq.sort_by do |s|
@@ -56,6 +55,7 @@ module Devise
56
55
  end
57
56
 
58
57
  devise_modules_hook! do
58
+ include Devise::Models::Authenticatable
59
59
  selected_modules.each do |m|
60
60
  mod = Devise::Models.const_get(m.to_s.classify)
61
61
 
@@ -40,15 +40,17 @@ module Devise
40
40
  # is already confirmed, add an error to email field. If the user is invalid
41
41
  # add errors
42
42
  def confirm!
43
- unless_confirmed do
43
+ pending_any_confirmation do
44
44
  self.confirmation_token = nil
45
45
  self.confirmed_at = Time.now.utc
46
46
 
47
- if self.class.reconfirmable
47
+ if self.class.reconfirmable && unconfirmed_email.present?
48
48
  @bypass_postpone = true
49
- self.email = unconfirmed_email if unconfirmed_email.present?
49
+ self.email = unconfirmed_email
50
50
  self.unconfirmed_email = nil
51
- save
51
+
52
+ # We need to validate in such cases to enforce e-mail uniqueness
53
+ save(:validate => true)
52
54
  else
53
55
  save(:validate => false)
54
56
  end
@@ -66,14 +68,16 @@ module Devise
66
68
 
67
69
  # Send confirmation instructions by email
68
70
  def send_confirmation_instructions
71
+ self.confirmation_token = nil if reconfirmation_required?
69
72
  @reconfirmation_required = false
73
+
70
74
  generate_confirmation_token! if self.confirmation_token.blank?
71
75
  self.devise_mailer.confirmation_instructions(self).deliver
72
76
  end
73
77
 
74
78
  # Resend confirmation token. This method does not need to generate a new token.
75
79
  def resend_confirmation_token
76
- unless_confirmed { send_confirmation_instructions }
80
+ pending_any_confirmation { send_confirmation_instructions }
77
81
  end
78
82
 
79
83
  # Overwrites active_for_authentication? for confirmation
@@ -133,10 +137,9 @@ module Devise
133
137
  confirmation_sent_at && confirmation_sent_at.utc >= self.class.allow_unconfirmed_access_for.ago
134
138
  end
135
139
 
136
- # Checks whether the record is confirmed or not or a new email has been added, yielding to the block
137
- # if it's already confirmed, otherwise adds an error to email.
138
- def unless_confirmed
139
- unless confirmed? && !pending_reconfirmation?
140
+ # Checks whether the record requires any confirmation.
141
+ def pending_any_confirmation
142
+ if !confirmed? || pending_reconfirmation?
140
143
  yield
141
144
  else
142
145
  self.errors.add(:email, :already_confirmed)
@@ -79,7 +79,7 @@ module Devise
79
79
  # if the user can login or not (wrong password, etc)
80
80
  unlock_access! if lock_expired?
81
81
 
82
- if super
82
+ if super && !access_locked?
83
83
  self.failed_attempts = 0
84
84
  save(:validate => false)
85
85
  true
@@ -9,8 +9,11 @@ module Devise
9
9
  module Serializable
10
10
  extend ActiveSupport::Concern
11
11
 
12
- # TODO: to_xml does not call serializable_hash. Hopefully someone will fix this in AR.
13
- %w(to_xml serializable_hash).each do |method|
12
+ array = %w(serializable_hash)
13
+ # to_xml does not call serializable_hash on 3.1
14
+ array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
15
+
16
+ array.each do |method|
14
17
  class_eval <<-RUBY, __FILE__, __LINE__
15
18
  def #{method}(options=nil)
16
19
  options ||= {}
@@ -5,8 +5,8 @@ Devise.with_options :model => true do |d|
5
5
  d.with_options :strategy => true do |s|
6
6
  routes = [nil, :new, :destroy]
7
7
  s.add_module :database_authenticatable, :controller => :sessions, :route => { :session => routes }
8
- s.add_module :token_authenticatable
9
- s.add_module :rememberable
8
+ s.add_module :token_authenticatable, :controller => :sessions, :route => { :session => routes }, :no_input => true
9
+ s.add_module :rememberable, :no_input => true
10
10
  end
11
11
 
12
12
  # Other authentications
@@ -35,7 +35,7 @@ module Devise
35
35
 
36
36
  # Determine which values should be transformed to string or passed as-is to the query builder underneath
37
37
  def param_requires_string_conversion?(value)
38
- true unless value.is_a?(TrueClass) || value.is_a?(FalseClass) || value.is_a?(Fixnum)
38
+ [Fixnum, TrueClass, FalseClass, Regexp].none? {|clz| value.is_a? clz }
39
39
  end
40
40
  end
41
41
  end
@@ -3,7 +3,11 @@ module Devise
3
3
  include Rails.application.routes.url_helpers
4
4
 
5
5
  def self.default_url_options(*args)
6
- ApplicationController.default_url_options(*args)
6
+ if defined?(ApplicationController)
7
+ ApplicationController.default_url_options(*args)
8
+ else
9
+ {}
10
+ end
7
11
  end
8
12
 
9
13
  def initialize(env, scope)
@@ -42,6 +42,15 @@ module Devise
42
42
  end
43
43
  end
44
44
 
45
+ initializer "devise.fix_routes_proxy_missing_respond_to_bug" do
46
+ # We can get rid of this once we support Rails > 3.2
47
+ ActionDispatch::Routing::RoutesProxy.class_eval do
48
+ def respond_to?(method, include_private = false)
49
+ super || routes.url_helpers.respond_to?(method)
50
+ end
51
+ end
52
+ end
53
+
45
54
  initializer "devise.deprecations" do
46
55
  unless defined?(Rails::Generators)
47
56
  if Devise.case_insensitive_keys == false
@@ -71,6 +80,18 @@ module Devise
71
80
  "your Devise models (if they don't have one already).\n"
72
81
  end
73
82
  end
83
+
84
+ config.after_initialize do
85
+ if I18n.t(:"devise.registrations.reasons", :default => {}).present?
86
+ warn "\n[DEVISE] devise.registrations.reasons in yml files is deprecated, " \
87
+ "please use devise.registrations.signed_up_but_REASON instead.\n"
88
+ end
89
+
90
+ if I18n.t(:"devise.registrations.inactive_signed_up", :default => "").present?
91
+ warn "\n[DEVISE] devise.registrations.inactive_signed_up in yml files is deprecated, " \
92
+ "please use devise.registrations.signed_up_but_inactive instead.\n"
93
+ end
94
+ end
74
95
  end
75
96
  end
76
97
  end
@@ -84,15 +84,16 @@ module ActionDispatch::Routing
84
84
  #
85
85
  # You need to make sure that your sign_out controls trigger a request with a matching HTTP method.
86
86
  #
87
- # * :module => the namespace to find controlers. By default, devise will access devise/sessions,
88
- # devise/registrations and so on. If you want to namespace all at once, use module:
87
+ # * :module => the namespace to find controllers (default: "devise", thus
88
+ # accessing devise/sessions, devise/registrations, and so on). If you want
89
+ # to namespace all at once, use module:
89
90
  #
90
91
  # devise_for :users, :module => "users"
91
92
  #
92
93
  # Notice that whenever you use namespace in the router DSL, it automatically sets the module.
93
94
  # So the following setup:
94
95
  #
95
- # namespace :publisher
96
+ # namespace :publisher do
96
97
  # devise_for :account
97
98
  # end
98
99
  #
@@ -135,15 +136,15 @@ module ActionDispatch::Routing
135
136
  # devise_for :users
136
137
  # end
137
138
  #
138
- # However, since Devise uses the request path to retrieve the current user, it has one caveats.
139
- # If you are using a dynamic segment, as below:
139
+ # However, since Devise uses the request path to retrieve the current user,
140
+ # this has one caveat: If you are using a dynamic segment, like so ...
140
141
  #
141
142
  # scope ":locale" do
142
143
  # devise_for :users
143
144
  # end
144
145
  #
145
- # You are required to configure default_url_options in your ApplicationController class level, so
146
- # Devise can pick it:
146
+ # you are required to configure default_url_options in your
147
+ # ApplicationController class, so Devise can pick it:
147
148
  #
148
149
  # class ApplicationController < ActionController::Base
149
150
  # def self.default_url_options
@@ -207,7 +208,12 @@ module ActionDispatch::Routing
207
208
  routes = mapping.used_routes
208
209
 
209
210
  devise_scope mapping.name do
210
- yield if block_given?
211
+ if block_given?
212
+ ActiveSupport::Deprecation.warn "Passing a block to devise_for is deprecated. " \
213
+ "Please call devise_scope :#{mapping.name} do ... end with the block instead", caller
214
+ yield
215
+ end
216
+
211
217
  with_devise_exclusive_scope mapping.fullpath, mapping.name, options do
212
218
  routes.each { |mod| send("devise_#{mod}", mapping, mapping.controllers) }
213
219
  end
@@ -369,13 +375,13 @@ module ActionDispatch::Routing
369
375
  end
370
376
 
371
377
  def with_devise_exclusive_scope(new_path, new_as, options) #:nodoc:
372
- old_as, old_path, old_module, old_constraints, old_defaults, old_options =
378
+ old_as, old_path, old_module, old_constraints, old_defaults, old_options =
373
379
  *@scope.values_at(:as, :path, :module, :constraints, :defaults, :options)
374
380
  @scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
375
381
  new_as, new_path, nil, *options.values_at(:constraints, :defaults, :options)
376
382
  yield
377
383
  ensure
378
- @scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
384
+ @scope[:as], @scope[:path], @scope[:module], @scope[:constraints], @scope[:defaults], @scope[:options] =
379
385
  old_as, old_path, old_module, old_constraints, old_defaults, old_options
380
386
  end
381
387