devise 3.1.0 → 3.2.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.

Files changed (63) hide show
  1. data/CHANGELOG.md +119 -94
  2. data/Gemfile.lock +2 -2
  3. data/README.md +2 -2
  4. data/app/controllers/devise/confirmations_controller.rb +3 -8
  5. data/app/controllers/devise/passwords_controller.rb +1 -1
  6. data/app/controllers/devise/registrations_controller.rb +6 -6
  7. data/app/controllers/devise/sessions_controller.rb +3 -3
  8. data/app/controllers/devise/unlocks_controller.rb +1 -1
  9. data/app/controllers/devise_controller.rb +6 -2
  10. data/app/mailers/devise/mailer.rb +15 -13
  11. data/config/locales/en.yml +2 -3
  12. data/gemfiles/Gemfile.rails-3.2.x.lock +4 -4
  13. data/lib/devise/controllers/helpers.rb +16 -84
  14. data/lib/devise/controllers/rememberable.rb +2 -12
  15. data/lib/devise/controllers/sign_in_out.rb +103 -0
  16. data/lib/devise/failure_app.rb +11 -2
  17. data/lib/devise/hooks/forgetable.rb +1 -1
  18. data/lib/devise/hooks/proxy.rb +21 -0
  19. data/lib/devise/hooks/rememberable.rb +1 -1
  20. data/lib/devise/hooks/timeoutable.rb +4 -1
  21. data/lib/devise/models/authenticatable.rb +8 -9
  22. data/lib/devise/models/confirmable.rb +0 -4
  23. data/lib/devise/models/database_authenticatable.rb +17 -7
  24. data/lib/devise/models/lockable.rb +6 -4
  25. data/lib/devise/models/recoverable.rb +0 -8
  26. data/lib/devise/models.rb +0 -5
  27. data/lib/devise/modules.rb +0 -1
  28. data/lib/devise/parameter_sanitizer.rb +9 -3
  29. data/lib/devise/rails/routes.rb +30 -15
  30. data/lib/devise/test_helpers.rb +1 -0
  31. data/lib/devise/version.rb +1 -1
  32. data/lib/devise.rb +23 -12
  33. data/lib/generators/mongoid/devise_generator.rb +0 -3
  34. data/lib/generators/templates/devise.rb +6 -10
  35. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  36. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  37. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  38. data/test/controllers/internal_helpers_test.rb +2 -2
  39. data/test/controllers/sessions_controller_test.rb +1 -1
  40. data/test/devise_test.rb +12 -1
  41. data/test/failure_app_test.rb +11 -0
  42. data/test/integration/confirmable_test.rb +11 -13
  43. data/test/integration/http_authenticatable_test.rb +0 -10
  44. data/test/integration/recoverable_test.rb +2 -2
  45. data/test/integration/rememberable_test.rb +3 -3
  46. data/test/integration/timeoutable_test.rb +28 -0
  47. data/test/mapping_test.rb +2 -2
  48. data/test/models/confirmable_test.rb +0 -9
  49. data/test/models/database_authenticatable_test.rb +19 -1
  50. data/test/models/lockable_test.rb +16 -10
  51. data/test/models/recoverable_test.rb +0 -10
  52. data/test/parameter_sanitizer_test.rb +9 -0
  53. data/test/rails_app/app/mongoid/user.rb +0 -3
  54. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -3
  55. data/test/rails_app/db/schema.rb +0 -1
  56. data/test/rails_app/lib/shared_user.rb +1 -1
  57. data/test/support/locale/en.yml +4 -0
  58. data/test/test_helpers_test.rb +22 -0
  59. metadata +4 -8
  60. data/lib/devise/models/token_authenticatable.rb +0 -92
  61. data/lib/devise/strategies/token_authenticatable.rb +0 -91
  62. data/test/integration/token_authenticatable_test.rb +0 -205
  63. data/test/models/token_authenticatable_test.rb +0 -55
@@ -2,6 +2,11 @@ require 'devise/strategies/database_authenticatable'
2
2
  require 'bcrypt'
3
3
 
4
4
  module Devise
5
+ # Digests the password using bcrypt.
6
+ def self.bcrypt(klass, password)
7
+ ::BCrypt::Password.create("#{password}#{klass.pepper}", :cost => klass.stretches).to_s
8
+ end
9
+
5
10
  module Models
6
11
  # Authenticatable Module, responsible for encrypting password and validating
7
12
  # authenticity of a user while signing in.
@@ -34,7 +39,7 @@ module Devise
34
39
  # Generates password encryption based on the given value.
35
40
  def password=(new_password)
36
41
  @password = new_password
37
- self.encrypted_password = password_digest(@password) if @password.present?
42
+ self.encrypted_password = Devise.bcrypt(self.class, @password) if @password.present?
38
43
  end
39
44
 
40
45
  # Verifies whether an password (ie from sign in) is the user password.
@@ -96,7 +101,7 @@ module Devise
96
101
  end
97
102
 
98
103
  # Destroy record when :current_password matches, otherwise returns
99
- # error on :current_password. It also automatically rejects
104
+ # error on :current_password. It also automatically rejects
100
105
  # :current_password if it is blank.
101
106
  def destroy_with_password(current_password)
102
107
  result = if valid_password?(current_password)
@@ -110,6 +115,16 @@ module Devise
110
115
  result
111
116
  end
112
117
 
118
+ # A callback initiated after successfully authenticating. This can be
119
+ # used to insert your own logic that is only run after the user successfully
120
+ # authenticates.
121
+ #
122
+ # Example:
123
+ #
124
+ # def after_database_authentication
125
+ # self.update_attribute(:invite_code, nil)
126
+ # end
127
+ #
113
128
  def after_database_authentication
114
129
  end
115
130
 
@@ -120,11 +135,6 @@ module Devise
120
135
 
121
136
  protected
122
137
 
123
- # Digests the password using bcrypt.
124
- def password_digest(password)
125
- ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
126
- end
127
-
128
138
  module ClassMethods
129
139
  Devise::Models.config(self, :pepper, :stretches)
130
140
 
@@ -112,6 +112,8 @@ module Devise
112
112
  # leaks the existence of an account.
113
113
  if Devise.paranoid
114
114
  super
115
+ elsif lock_strategy_enabled?(:failed_attempts) && last_attempt?
116
+ :last_attempt
115
117
  elsif lock_strategy_enabled?(:failed_attempts) && attempts_exceeded?
116
118
  :locked
117
119
  else
@@ -125,6 +127,10 @@ module Devise
125
127
  self.failed_attempts > self.class.maximum_attempts
126
128
  end
127
129
 
130
+ def last_attempt?
131
+ self.failed_attempts == self.class.maximum_attempts
132
+ end
133
+
128
134
  # Tells if the lock is expired if :time unlock strategy is active
129
135
  def lock_expired?
130
136
  if unlock_strategy_enabled?(:time)
@@ -165,10 +171,6 @@ module Devise
165
171
  unlock_token = Devise.token_generator.digest(self, :unlock_token, unlock_token)
166
172
 
167
173
  lockable = find_or_initialize_with_error_by(:unlock_token, unlock_token)
168
- if !lockable.persisted? && Devise.allow_insecure_token_lookup
169
- lockable = find_or_initialize_with_error_by(:unlock_token, original_token)
170
- end
171
-
172
174
  lockable.unlock_access! if lockable.persisted?
173
175
  lockable.unlock_token = original_token
174
176
  lockable
@@ -101,11 +101,6 @@ module Devise
101
101
  recoverable
102
102
  end
103
103
 
104
- # Generate a token checking if one does not already exist in the database.
105
- def reset_password_token
106
- generate_token(:reset_password_token)
107
- end
108
-
109
104
  # Attempt to find a user by its reset_password_token to reset its
110
105
  # password. If a user is found and token is still valid, reset its password and automatically
111
106
  # try saving the record. If not user is found, returns a new user
@@ -116,9 +111,6 @@ module Devise
116
111
  reset_password_token = Devise.token_generator.digest(self, :reset_password_token, original_token)
117
112
 
118
113
  recoverable = find_or_initialize_with_error_by(:reset_password_token, reset_password_token)
119
- if !recoverable.persisted? && Devise.allow_insecure_token_lookup
120
- recoverable = find_or_initialize_with_error_by(:reset_password_token, original_token)
121
- end
122
114
 
123
115
  if recoverable.persisted?
124
116
  if recoverable.reset_password_period_valid?
data/lib/devise/models.rb CHANGED
@@ -84,11 +84,6 @@ module Devise
84
84
  devise_modules_hook! do
85
85
  include Devise::Models::Authenticatable
86
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
87
  selected_modules.each do |m|
93
88
  mod = Devise::Models.const_get(m.to_s.classify)
94
89
 
@@ -5,7 +5,6 @@ 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, :controller => :sessions, :route => { :session => routes }, :no_input => true
9
8
  s.add_module :rememberable, :no_input => true
10
9
  end
11
10
 
@@ -47,19 +47,25 @@ module Devise
47
47
  end
48
48
 
49
49
  def sign_in
50
- default_params.permit self.for(:sign_in)
50
+ permit self.for(:sign_in)
51
51
  end
52
52
 
53
53
  def sign_up
54
- default_params.permit self.for(:sign_up)
54
+ permit self.for(:sign_up)
55
55
  end
56
56
 
57
57
  def account_update
58
- default_params.permit self.for(:account_update)
58
+ permit self.for(:account_update)
59
59
  end
60
60
 
61
61
  private
62
62
 
63
+ # TODO: We do need to flatten so it works with strong_parameters
64
+ # gem. We should drop it once we move to Rails 4 only support.
65
+ def permit(keys)
66
+ default_params.permit(*Array(keys))
67
+ end
68
+
63
69
  # Change for(kind) to return the values in the @permitted
64
70
  # hash, allowing the developer to customize at runtime.
65
71
  def default_for(kind)
@@ -58,6 +58,28 @@ module ActionDispatch::Routing
58
58
  # user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
59
59
  # POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
60
60
  #
61
+ # ==== Routes integration
62
+ #
63
+ # +devise_for+ is meant to play nicely with other routes methods. For example,
64
+ # by calling +devise_for+ inside a namespace, it automatically nests your devise
65
+ # controllers:
66
+ #
67
+ # namespace :publisher do
68
+ # devise_for :account
69
+ # end
70
+ #
71
+ # The snippet above will use publisher/sessions controller instead of devise/sessions
72
+ # controller. You can revert this change or configure it directly by passing the :module
73
+ # option described below to +devise_for+.
74
+ #
75
+ # Also note that when you use a namespace it will affect all the helpers and methods
76
+ # for controllers and views. For example, using the above setup you'll end with
77
+ # following methods: current_publisher_account, authenticate_publisher_account!,
78
+ # publisher_account_signed_in, etc.
79
+ #
80
+ # The only aspect not affect by the router configuration is the model name. The
81
+ # model name can be explicitly set via the :class_name option.
82
+ #
61
83
  # ==== Options
62
84
  #
63
85
  # You can configure your routes with some options:
@@ -104,20 +126,6 @@ module ActionDispatch::Routing
104
126
  #
105
127
  # devise_for :users, :module => "users"
106
128
  #
107
- # Notice that whenever you use namespace in the router DSL, it automatically sets the module.
108
- # So the following setup:
109
- #
110
- # namespace :publisher do
111
- # devise_for :account
112
- # end
113
- #
114
- # Will use publisher/sessions controller instead of devise/sessions controller. You can revert
115
- # this by providing the :module option to devise_for.
116
- #
117
- # Also pay attention that when you use a namespace it will affect all the helpers and methods for controllers
118
- # and views. For example, using the above setup you'll end with following methods:
119
- # current_publisher_account, authenticate_publisher_account!, publisher_account_signed_in, etc.
120
- #
121
129
  # * :skip => tell which controller you want to skip routes from being created:
122
130
  #
123
131
  # devise_for :users, :skip => :sessions
@@ -378,8 +386,14 @@ module ActionDispatch::Routing
378
386
  end
379
387
 
380
388
  def devise_omniauth_callback(mapping, controllers) #:nodoc:
389
+ if mapping.fullpath =~ /:[a-zA-Z_]/
390
+ raise "[DEVISE] Nesting omniauth callbacks under scopes with dynamic segments " \
391
+ "is not supported. Please, use Devise.omniauth_path_prefix instead."
392
+ end
393
+
381
394
  path, @scope[:path] = @scope[:path], nil
382
- path_prefix = Devise.omniauth_path_prefix || "/#{mapping.path}/auth".squeeze("/")
395
+ path_prefix = Devise.omniauth_path_prefix || "/#{mapping.fullpath}/auth".squeeze("/")
396
+
383
397
  set_omniauth_path_prefix!(path_prefix)
384
398
 
385
399
  providers = Regexp.union(mapping.to.omniauth_providers.map(&:to_s))
@@ -442,6 +456,7 @@ Devise.secret_key was not set. Please add the following to your Devise initializ
442
456
 
443
457
  config.secret_key = '#{SecureRandom.hex(64)}'
444
458
 
459
+ Please ensure you restarted your application after installing Devise or setting the key.
445
460
  ERROR
446
461
  end
447
462
 
@@ -108,6 +108,7 @@ module Devise
108
108
  Warden::Manager._run_callbacks(:before_failure, env, options)
109
109
 
110
110
  status, headers, response = Devise.warden_config[:failure_app].call(env).to_a
111
+ @controller.response.headers.merge!(headers)
111
112
  @controller.send :render, :status => status, :text => response.body,
112
113
  :content_type => headers["Content-Type"], :location => headers["Location"]
113
114
  nil # causes process return @response
@@ -1,3 +1,3 @@
1
1
  module Devise
2
- VERSION = "3.1.0".freeze
2
+ VERSION = "3.2.0".freeze
3
3
  end
data/lib/devise.rb CHANGED
@@ -20,9 +20,14 @@ module Devise
20
20
  autoload :Helpers, 'devise/controllers/helpers'
21
21
  autoload :Rememberable, 'devise/controllers/rememberable'
22
22
  autoload :ScopedViews, 'devise/controllers/scoped_views'
23
+ autoload :SignInOut, 'devise/controllers/sign_in_out'
23
24
  autoload :UrlHelpers, 'devise/controllers/url_helpers'
24
25
  end
25
26
 
27
+ module Hooks
28
+ autoload :Proxy, 'devise/hooks/proxy'
29
+ end
30
+
26
31
  module Mailers
27
32
  autoload :Helpers, 'devise/mailers/helpers'
28
33
  end
@@ -50,15 +55,21 @@ module Devise
50
55
  mattr_accessor :secret_key
51
56
  @@secret_key = nil
52
57
 
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
58
+ [ :allow_insecure_token_lookup,
59
+ :allow_insecure_sign_in_after_confirmation,
60
+ :token_authentication_key ].each do |method|
61
+ class_eval <<-RUBY
62
+ def self.#{method}
63
+ ActiveSupport::Deprecation.warn "Devise.#{method} is deprecated " \
64
+ "and has no effect"
65
+ end
57
66
 
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
67
+ def self.#{method}=(val)
68
+ ActiveSupport::Deprecation.warn "Devise.#{method}= is deprecated " \
69
+ "and has no effect"
70
+ end
71
+ RUBY
72
+ end
62
73
 
63
74
  # Custom domain or key for cookies. Not set by default
64
75
  mattr_accessor :rememberable_options
@@ -195,10 +206,6 @@ module Devise
195
206
  mattr_accessor :mailer_sender
196
207
  @@mailer_sender = nil
197
208
 
198
- # Authentication token params key name of choice. E.g. /users/sign_in?some_key=...
199
- mattr_accessor :token_authentication_key
200
- @@token_authentication_key = :auth_token
201
-
202
209
  # Skip session storage for the following strategies
203
210
  mattr_accessor :skip_session_storage
204
211
  @@skip_session_storage = []
@@ -266,6 +273,10 @@ module Devise
266
273
  mattr_accessor :paranoid
267
274
  @@paranoid = false
268
275
 
276
+ # When true, warn user if he just used next-to-last attempt of authentication
277
+ mattr_accessor :last_attempt_warning
278
+ @@last_attempt_warning = false
279
+
269
280
  # Stores the token generator
270
281
  mattr_accessor :token_generator
271
282
  @@token_generator = nil
@@ -47,9 +47,6 @@ module Mongoid
47
47
  # field :failed_attempts, :type => Integer, :default => 0 # Only if lock strategy is :failed_attempts
48
48
  # field :unlock_token, :type => String # Only if unlock strategy is :email or :both
49
49
  # field :locked_at, :type => Time
50
-
51
- ## Token authenticatable
52
- # field :authentication_token, :type => String
53
50
  RUBY
54
51
  end
55
52
  end
@@ -56,12 +56,9 @@ Devise.setup do |config|
56
56
 
57
57
  # Tell if authentication through HTTP Auth is enabled. False by default.
58
58
  # It can be set to an array that will enable http authentication only for the
59
- # given strategies, for example, `config.http_authenticatable = [:token]` will
60
- # enable it only for token authentication. The supported strategies are:
59
+ # given strategies, for example, `config.http_authenticatable = [:database]` will
60
+ # enable it only for database authentication. The supported strategies are:
61
61
  # :database = Support basic authentication with authentication key + password
62
- # :token = Support basic authentication with token authentication key
63
- # :token_options = Support token authentication with options as defined in
64
- # http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
65
62
  # config.http_authenticatable = false
66
63
 
67
64
  # If http headers should be returned for AJAX requests. True by default.
@@ -76,7 +73,7 @@ Devise.setup do |config|
76
73
  # config.paranoid = true
77
74
 
78
75
  # By default Devise will store the user in session. You can skip storage for
79
- # :http_auth and :token_auth by adding those symbols to the array below.
76
+ # particular strategies by setting this option.
80
77
  # Notice that if you are skipping storage for all authentication paths, you
81
78
  # may want to disable generating routes to Devise's sessions controller by
82
79
  # passing :skip => :sessions to `devise_for` in your config/routes.rb
@@ -176,6 +173,9 @@ Devise.setup do |config|
176
173
  # Time interval to unlock the account if :time is enabled as unlock_strategy.
177
174
  # config.unlock_in = 1.hour
178
175
 
176
+ # Warn on the last attempt before the account is locked.
177
+ # config.last_attempt_warning = false
178
+
179
179
  # ==> Configuration for :recoverable
180
180
  #
181
181
  # Defines which key will be used when recovering the password for an account
@@ -196,10 +196,6 @@ Devise.setup do |config|
196
196
  # Require the `devise-encryptable` gem when using anything other than bcrypt
197
197
  # config.encryptor = :sha512
198
198
 
199
- # ==> Configuration for :token_authenticatable
200
- # Defines name of the authentication token params key
201
- # config.token_authentication_key = :auth_token
202
-
203
199
  # ==> Scopes configuration
204
200
  # Turn scoped views on. Before rendering "sessions/new", it will first check for
205
201
  # "users/sessions/new". It's turned off by default because it's slower if you
@@ -2,4 +2,4 @@ Welcome <%= @email %>!
2
2
 
3
3
  You can confirm your account through the link below:
4
4
 
5
- <%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>
5
+ <%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %>
@@ -2,7 +2,7 @@ Hello <%= @resource.email %>!
2
2
 
3
3
  Someone has requested a link to change your password, and you can do this through the link below.
4
4
 
5
- <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>
5
+ <%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %>
6
6
 
7
7
  If you didn't request this, please ignore this email.
8
8
  Your password won't change until you access the link above and create a new one.
@@ -4,4 +4,4 @@ Your account has been locked due to an excessive number of unsuccessful sign in
4
4
 
5
5
  Click the link below to unlock your account:
6
6
 
7
- <%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %>
7
+ <%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @token) %>
@@ -55,7 +55,7 @@ class HelpersTest < ActionController::TestCase
55
55
  end
56
56
 
57
57
  test 'require no authentication tests current mapping' do
58
- @mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
58
+ @mock_warden.expects(:authenticate?).with(:rememberable, :scope => :user).returns(true)
59
59
  @mock_warden.expects(:user).with(:user).returns(User.new)
60
60
  @controller.expects(:redirect_to).with(root_path)
61
61
  @controller.send :require_no_authentication
@@ -71,7 +71,7 @@ class HelpersTest < ActionController::TestCase
71
71
  end
72
72
 
73
73
  test 'require no authentication sets a flash message' do
74
- @mock_warden.expects(:authenticate?).with(:rememberable, :token_authenticatable, :scope => :user).returns(true)
74
+ @mock_warden.expects(:authenticate?).with(:rememberable, :scope => :user).returns(true)
75
75
  @mock_warden.expects(:user).with(:user).returns(User.new)
76
76
  @controller.expects(:redirect_to).with(root_path)
77
77
  @controller.send :require_no_authentication
@@ -10,7 +10,7 @@ class SessionsControllerTest < ActionController::TestCase
10
10
  end
11
11
  request.env["devise.mapping"] = Devise.mappings[:user]
12
12
  request.session["user_return_to"] = 'foo.bar'
13
- user = create_user
13
+ create_user
14
14
  post :create, :user => {
15
15
  :email => "wrong@email.com",
16
16
  :password => "wrongpassword"
data/test/devise_test.rb CHANGED
@@ -11,6 +11,17 @@ module Devise
11
11
  end
12
12
 
13
13
  class DeviseTest < ActiveSupport::TestCase
14
+ test 'bcrypt on the class' do
15
+ password = "super secret"
16
+ klass = Struct.new(:pepper, :stretches).new("blahblah", 2)
17
+ hash = Devise.bcrypt(klass, password)
18
+ assert_equal ::BCrypt::Password.create(hash), hash
19
+
20
+ klass = Struct.new(:pepper, :stretches).new("bla", 2)
21
+ hash = Devise.bcrypt(klass, password)
22
+ assert_not_equal ::BCrypt::Password.new(hash), hash
23
+ end
24
+
14
25
  test 'model options can be configured through Devise' do
15
26
  swap Devise, :allow_unconfirmed_access_for => 113, :pepper => "foo" do
16
27
  assert_equal 113, Devise.allow_unconfirmed_access_for
@@ -59,7 +70,7 @@ class DeviseTest < ActiveSupport::TestCase
59
70
  Devise::ALL.delete(:kivi)
60
71
  Devise::CONTROLLERS.delete(:kivi)
61
72
  end
62
-
73
+
63
74
  test 'should complain when comparing empty or different sized passes' do
64
75
  [nil, ""].each do |empty|
65
76
  assert_not Devise.secure_compare(empty, "something")
@@ -8,6 +8,12 @@ class FailureTest < ActiveSupport::TestCase
8
8
  end
9
9
  end
10
10
 
11
+ class FailureWithI18nOptions < Devise::FailureApp
12
+ def i18n_options(options)
13
+ options.merge(:name => 'Steve')
14
+ end
15
+ end
16
+
11
17
  def self.context(name, &block)
12
18
  instance_eval(&block)
13
19
  end
@@ -67,6 +73,11 @@ class FailureTest < ActiveSupport::TestCase
67
73
  assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
68
74
  end
69
75
 
76
+ test 'uses custom i18n options' do
77
+ call_failure('warden' => OpenStruct.new(:message => :does_not_exist), :app => FailureWithI18nOptions)
78
+ assert_equal 'User Steve does not exist', @request.flash[:alert]
79
+ end
80
+
70
81
  test 'uses the proxy failure message as string' do
71
82
  call_failure('warden' => OpenStruct.new(:message => 'Hello world'))
72
83
  assert_equal 'Hello world', @request.flash[:alert]
@@ -56,24 +56,12 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
56
56
  assert_not user.confirmed?
57
57
  visit_user_confirmation_with_token(user.raw_confirmation_token)
58
58
 
59
- assert_contain 'Your account was successfully confirmed. Please sign in.'
59
+ assert_contain 'Your account was successfully confirmed.'
60
60
  assert_current_url '/users/sign_in'
61
61
  assert user.reload.confirmed?
62
62
  end
63
63
  end
64
64
 
65
- test 'user should be signed in after confirmation if allow_insecure_sign_in_after_confirmation is enabled' do
66
- swap Devise, :confirm_within => 3.days, :allow_insecure_sign_in_after_confirmation => true do
67
- user = create_user(:confirm => false, :confirmation_sent_at => 2.days.ago)
68
- assert_not user.confirmed?
69
- visit_user_confirmation_with_token(user.raw_confirmation_token)
70
-
71
- assert_contain 'Your account was successfully confirmed. You are now signed in.'
72
- assert_current_url root_url
73
- assert user.reload.confirmed?
74
- end
75
- end
76
-
77
65
  test 'user should be redirected to a custom path after confirmation' do
78
66
  Devise::ConfirmationsController.any_instance.stubs(:after_confirmation_path_for).returns("/?custom=1")
79
67
 
@@ -135,6 +123,16 @@ class ConfirmationTest < ActionDispatch::IntegrationTest
135
123
  end
136
124
  end
137
125
 
126
+ test 'unconfirmed but signed in user should be redirected to their root path' do
127
+ swap Devise, :allow_unconfirmed_access_for => 1.day do
128
+ user = sign_in_as_user(:confirm => false)
129
+
130
+ visit_user_confirmation_with_token(user.raw_confirmation_token)
131
+ assert_contain 'Your account was successfully confirmed.'
132
+ assert_current_url '/'
133
+ end
134
+ end
135
+
138
136
  test 'error message is configurable by resource name' do
139
137
  store_translations :en, :devise => {
140
138
  :failure => { :user => { :unconfirmed => "Not confirmed user" } }
@@ -88,16 +88,6 @@ class HttpAuthenticationTest < ActionDispatch::IntegrationTest
88
88
  end
89
89
  end
90
90
 
91
- test 'sign in should authenticate with really long token' do
92
- token = "token_containing_so_many_characters_that_the_base64_encoding_will_wrap"
93
- user = create_user
94
- user.update_attribute :authentication_token, token
95
- get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{Base64.encode64("#{token}:x")}"
96
- assert_response :success
97
- assert_match "<email>user@test.com</email>", response.body
98
- assert warden.authenticated?(:user)
99
- end
100
-
101
91
  private
102
92
 
103
93
  def sign_in_as_new_user_with_http(username="user@test.com", password="12345678")
@@ -190,7 +190,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
190
190
  end
191
191
 
192
192
  test 'sign in user automatically after changing its password' do
193
- user = create_user
193
+ create_user
194
194
  request_forgot_password
195
195
  reset_password
196
196
 
@@ -260,7 +260,7 @@ class PasswordTest < ActionDispatch::IntegrationTest
260
260
  end
261
261
 
262
262
  test 'change password with valid parameters in XML format should return valid response' do
263
- user = create_user
263
+ create_user
264
264
  request_forgot_password
265
265
  put user_password_path(:format => 'xml'), :user => {
266
266
  :reset_password_token => 'abcdef', :password => '987654321', :password_confirmation => '987654321'
@@ -64,14 +64,14 @@ class RememberMeTest < ActionDispatch::IntegrationTest
64
64
  # since we changed the domain. This is the only difference with the
65
65
  # previous test.
66
66
  swap Devise, :rememberable_options => { :domain => "omg.somewhere.com" } do
67
- user = sign_in_as_user :remember_me => true
67
+ sign_in_as_user :remember_me => true
68
68
  assert_nil request.cookies["remember_user_token"]
69
69
  end
70
70
  end
71
71
 
72
72
  test 'generate remember token with a custom key' do
73
73
  swap Devise, :rememberable_options => { :key => "v1lat_token" } do
74
- user = sign_in_as_user :remember_me => true
74
+ sign_in_as_user :remember_me => true
75
75
  assert request.cookies["v1lat_token"]
76
76
  end
77
77
  end
@@ -79,7 +79,7 @@ class RememberMeTest < ActionDispatch::IntegrationTest
79
79
  test 'generate remember token after sign in setting session options' do
80
80
  begin
81
81
  Rails.configuration.session_options[:domain] = "omg.somewhere.com"
82
- user = sign_in_as_user :remember_me => true
82
+ sign_in_as_user :remember_me => true
83
83
  assert_nil request.cookies["remember_user_token"]
84
84
  ensure
85
85
  Rails.configuration.session_options.delete(:domain)
@@ -45,6 +45,20 @@ class SessionTimeoutTest < ActionDispatch::IntegrationTest
45
45
  assert_not warden.authenticated?(:user)
46
46
  end
47
47
 
48
+ test 'time out all sessions after default limit time when sign_out_all_scopes is true' do
49
+ swap Devise, sign_out_all_scopes: true do
50
+ sign_in_as_admin
51
+
52
+ user = sign_in_as_user
53
+ get expire_user_path(user)
54
+ assert_not_nil last_request_at
55
+
56
+ get root_path
57
+ assert_not warden.authenticated?(:user)
58
+ assert_not warden.authenticated?(:admin)
59
+ end
60
+ end
61
+
48
62
  test 'time out user session after deault limit time and redirect to latest get request' do
49
63
  user = sign_in_as_user
50
64
  visit edit_form_user_path(user)
@@ -67,6 +81,20 @@ class SessionTimeoutTest < ActionDispatch::IntegrationTest
67
81
  assert_contain 'Signed out successfully'
68
82
  end
69
83
 
84
+ test 'expired session is not extended by sign in page' do
85
+ user = sign_in_as_user
86
+ get expire_user_path(user)
87
+ assert warden.authenticated?(:user)
88
+
89
+ get "/users/sign_in"
90
+ assert_redirected_to "/users/sign_in"
91
+ follow_redirect!
92
+
93
+ assert_response :success
94
+ assert_contain 'Sign in'
95
+ assert_not warden.authenticated?(:user)
96
+ end
97
+
70
98
  test 'time out is not triggered on sign in' do
71
99
  user = sign_in_as_user
72
100
  get expire_user_path(user)
data/test/mapping_test.rb CHANGED
@@ -50,12 +50,12 @@ class MappingTest < ActiveSupport::TestCase
50
50
  end
51
51
 
52
52
  test 'has strategies depending on the model declaration' do
53
- assert_equal [:rememberable, :token_authenticatable, :database_authenticatable], Devise.mappings[:user].strategies
53
+ assert_equal [:rememberable, :database_authenticatable], Devise.mappings[:user].strategies
54
54
  assert_equal [:database_authenticatable], Devise.mappings[:admin].strategies
55
55
  end
56
56
 
57
57
  test 'has no input strategies depending on the model declaration' do
58
- assert_equal [:rememberable, :token_authenticatable], Devise.mappings[:user].no_input_strategies
58
+ assert_equal [:rememberable], Devise.mappings[:user].no_input_strategies
59
59
  assert_equal [], Devise.mappings[:admin].no_input_strategies
60
60
  end
61
61
 
@@ -51,15 +51,6 @@ class ConfirmableTest < ActiveSupport::TestCase
51
51
  assert_equal "was already confirmed, please try signing in", user.errors[:email].join
52
52
  end
53
53
 
54
- test 'DEPRECATED: should find and confirm a user automatically' do
55
- swap Devise, allow_insecure_token_lookup: true do
56
- user = create_user
57
- confirmed_user = User.confirm_by_token(user.confirmation_token)
58
- assert_equal confirmed_user, user
59
- assert user.reload.confirmed?
60
- end
61
- end
62
-
63
54
  test 'should find and confirm a user automatically based on the raw token' do
64
55
  user = create_user
65
56
  raw = user.raw_confirmation_token