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.
- data/CHANGELOG.md +119 -94
- data/Gemfile.lock +2 -2
- data/README.md +2 -2
- data/app/controllers/devise/confirmations_controller.rb +3 -8
- data/app/controllers/devise/passwords_controller.rb +1 -1
- data/app/controllers/devise/registrations_controller.rb +6 -6
- data/app/controllers/devise/sessions_controller.rb +3 -3
- data/app/controllers/devise/unlocks_controller.rb +1 -1
- data/app/controllers/devise_controller.rb +6 -2
- data/app/mailers/devise/mailer.rb +15 -13
- data/config/locales/en.yml +2 -3
- data/gemfiles/Gemfile.rails-3.2.x.lock +4 -4
- data/lib/devise/controllers/helpers.rb +16 -84
- data/lib/devise/controllers/rememberable.rb +2 -12
- data/lib/devise/controllers/sign_in_out.rb +103 -0
- data/lib/devise/failure_app.rb +11 -2
- data/lib/devise/hooks/forgetable.rb +1 -1
- data/lib/devise/hooks/proxy.rb +21 -0
- data/lib/devise/hooks/rememberable.rb +1 -1
- data/lib/devise/hooks/timeoutable.rb +4 -1
- data/lib/devise/models/authenticatable.rb +8 -9
- data/lib/devise/models/confirmable.rb +0 -4
- data/lib/devise/models/database_authenticatable.rb +17 -7
- data/lib/devise/models/lockable.rb +6 -4
- data/lib/devise/models/recoverable.rb +0 -8
- data/lib/devise/models.rb +0 -5
- data/lib/devise/modules.rb +0 -1
- data/lib/devise/parameter_sanitizer.rb +9 -3
- data/lib/devise/rails/routes.rb +30 -15
- data/lib/devise/test_helpers.rb +1 -0
- data/lib/devise/version.rb +1 -1
- data/lib/devise.rb +23 -12
- data/lib/generators/mongoid/devise_generator.rb +0 -3
- data/lib/generators/templates/devise.rb +6 -10
- data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
- data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
- data/test/controllers/internal_helpers_test.rb +2 -2
- data/test/controllers/sessions_controller_test.rb +1 -1
- data/test/devise_test.rb +12 -1
- data/test/failure_app_test.rb +11 -0
- data/test/integration/confirmable_test.rb +11 -13
- data/test/integration/http_authenticatable_test.rb +0 -10
- data/test/integration/recoverable_test.rb +2 -2
- data/test/integration/rememberable_test.rb +3 -3
- data/test/integration/timeoutable_test.rb +28 -0
- data/test/mapping_test.rb +2 -2
- data/test/models/confirmable_test.rb +0 -9
- data/test/models/database_authenticatable_test.rb +19 -1
- data/test/models/lockable_test.rb +16 -10
- data/test/models/recoverable_test.rb +0 -10
- data/test/parameter_sanitizer_test.rb +9 -0
- data/test/rails_app/app/mongoid/user.rb +0 -3
- data/test/rails_app/db/migrate/20100401102949_create_tables.rb +0 -3
- data/test/rails_app/db/schema.rb +0 -1
- data/test/rails_app/lib/shared_user.rb +1 -1
- data/test/support/locale/en.yml +4 -0
- data/test/test_helpers_test.rb +22 -0
- metadata +4 -8
- data/lib/devise/models/token_authenticatable.rb +0 -92
- data/lib/devise/strategies/token_authenticatable.rb +0 -91
- data/test/integration/token_authenticatable_test.rb +0 -205
- 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 =
|
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
|
|
data/lib/devise/modules.rb
CHANGED
@@ -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
|
-
|
50
|
+
permit self.for(:sign_in)
|
51
51
|
end
|
52
52
|
|
53
53
|
def sign_up
|
54
|
-
|
54
|
+
permit self.for(:sign_up)
|
55
55
|
end
|
56
56
|
|
57
57
|
def account_update
|
58
|
-
|
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)
|
data/lib/devise/rails/routes.rb
CHANGED
@@ -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.
|
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
|
|
data/lib/devise/test_helpers.rb
CHANGED
@@ -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
|
data/lib/devise/version.rb
CHANGED
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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 = [:
|
60
|
-
# enable it only for
|
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
|
-
#
|
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 => @
|
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 => @
|
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 => @
|
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, :
|
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, :
|
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
|
-
|
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")
|
data/test/failure_app_test.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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, :
|
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
|
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
|