devise 3.3.0 → 3.5.10

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 (138) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +29 -20
  3. data/CHANGELOG.md +219 -102
  4. data/CODE_OF_CONDUCT.md +22 -0
  5. data/CONTRIBUTING.md +2 -0
  6. data/Gemfile +3 -2
  7. data/Gemfile.lock +101 -80
  8. data/MIT-LICENSE +1 -1
  9. data/README.md +87 -43
  10. data/Rakefile +2 -1
  11. data/app/controllers/devise/confirmations_controller.rb +5 -1
  12. data/app/controllers/devise/omniauth_callbacks_controller.rb +4 -0
  13. data/app/controllers/devise/passwords_controller.rb +14 -4
  14. data/app/controllers/devise/registrations_controller.rb +10 -11
  15. data/app/controllers/devise/sessions_controller.rb +7 -2
  16. data/app/controllers/devise/unlocks_controller.rb +3 -0
  17. data/app/controllers/devise_controller.rb +44 -21
  18. data/app/mailers/devise/mailer.rb +4 -0
  19. data/app/views/devise/confirmations/new.html.erb +7 -3
  20. data/app/views/devise/mailer/password_change.html.erb +3 -0
  21. data/app/views/devise/passwords/edit.html.erb +14 -5
  22. data/app/views/devise/passwords/new.html.erb +7 -3
  23. data/app/views/devise/registrations/edit.html.erb +19 -9
  24. data/app/views/devise/registrations/new.html.erb +18 -7
  25. data/app/views/devise/sessions/new.html.erb +15 -6
  26. data/app/views/devise/shared/{_links.erb → _links.html.erb} +1 -1
  27. data/app/views/devise/unlocks/new.html.erb +7 -3
  28. data/config/locales/en.yml +4 -2
  29. data/devise.gemspec +2 -2
  30. data/gemfiles/Gemfile.rails-3.2-stable.lock +54 -48
  31. data/gemfiles/Gemfile.rails-4.0-stable +1 -0
  32. data/gemfiles/Gemfile.rails-4.0-stable.lock +63 -59
  33. data/gemfiles/{Gemfile.rails-head → Gemfile.rails-4.1-stable} +3 -5
  34. data/gemfiles/Gemfile.rails-4.1-stable.lock +171 -0
  35. data/gemfiles/Gemfile.rails-4.2-stable +30 -0
  36. data/gemfiles/Gemfile.rails-4.2-stable.lock +193 -0
  37. data/lib/devise/controllers/helpers.rb +12 -6
  38. data/lib/devise/controllers/rememberable.rb +9 -2
  39. data/lib/devise/controllers/sign_in_out.rb +2 -8
  40. data/lib/devise/controllers/store_location.rb +3 -1
  41. data/lib/devise/controllers/url_helpers.rb +7 -9
  42. data/lib/devise/encryptor.rb +22 -0
  43. data/lib/devise/failure_app.rb +56 -14
  44. data/lib/devise/hooks/timeoutable.rb +5 -7
  45. data/lib/devise/mapping.rb +2 -1
  46. data/lib/devise/models/authenticatable.rb +28 -28
  47. data/lib/devise/models/confirmable.rb +51 -17
  48. data/lib/devise/models/database_authenticatable.rb +17 -11
  49. data/lib/devise/models/lockable.rb +7 -3
  50. data/lib/devise/models/recoverable.rb +23 -15
  51. data/lib/devise/models/rememberable.rb +56 -22
  52. data/lib/devise/models/timeoutable.rb +0 -6
  53. data/lib/devise/models/trackable.rb +1 -2
  54. data/lib/devise/models/validatable.rb +3 -3
  55. data/lib/devise/models.rb +1 -1
  56. data/lib/devise/rails/routes.rb +33 -27
  57. data/lib/devise/rails.rb +1 -1
  58. data/lib/devise/strategies/authenticatable.rb +8 -6
  59. data/lib/devise/strategies/database_authenticatable.rb +2 -1
  60. data/lib/devise/strategies/rememberable.rb +13 -3
  61. data/lib/devise/test_helpers.rb +2 -2
  62. data/lib/devise/version.rb +1 -1
  63. data/lib/devise.rb +39 -37
  64. data/lib/generators/active_record/devise_generator.rb +2 -1
  65. data/lib/generators/active_record/templates/migration.rb +1 -1
  66. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  67. data/lib/generators/devise/controllers_generator.rb +44 -0
  68. data/lib/generators/devise/views_generator.rb +14 -3
  69. data/lib/generators/templates/controllers/README +14 -0
  70. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  71. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  72. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  73. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  74. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  75. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  76. data/lib/generators/templates/devise.rb +19 -13
  77. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  78. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  79. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  80. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  81. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  82. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  83. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +2 -2
  84. data/test/controllers/custom_registrations_controller_test.rb +6 -1
  85. data/test/controllers/helper_methods_test.rb +21 -0
  86. data/test/controllers/helpers_test.rb +5 -0
  87. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  88. data/test/controllers/internal_helpers_test.rb +10 -4
  89. data/test/controllers/load_hooks_controller_test.rb +19 -0
  90. data/test/controllers/passwords_controller_test.rb +1 -1
  91. data/test/controllers/sessions_controller_test.rb +3 -3
  92. data/test/controllers/url_helpers_test.rb +6 -0
  93. data/test/devise_test.rb +3 -3
  94. data/test/failure_app_test.rb +47 -0
  95. data/test/generators/controllers_generator_test.rb +48 -0
  96. data/test/generators/views_generator_test.rb +8 -1
  97. data/test/helpers/devise_helper_test.rb +9 -12
  98. data/test/integration/authenticatable_test.rb +1 -1
  99. data/test/integration/database_authenticatable_test.rb +11 -0
  100. data/test/integration/http_authenticatable_test.rb +1 -1
  101. data/test/integration/omniauthable_test.rb +12 -10
  102. data/test/integration/recoverable_test.rb +13 -0
  103. data/test/integration/rememberable_test.rb +50 -3
  104. data/test/integration/timeoutable_test.rb +13 -18
  105. data/test/mailers/confirmation_instructions_test.rb +1 -1
  106. data/test/mapping_test.rb +7 -0
  107. data/test/models/authenticatable_test.rb +10 -0
  108. data/test/models/confirmable_test.rb +99 -42
  109. data/test/models/database_authenticatable_test.rb +20 -0
  110. data/test/models/lockable_test.rb +45 -17
  111. data/test/models/recoverable_test.rb +62 -7
  112. data/test/models/rememberable_test.rb +68 -97
  113. data/test/models/validatable_test.rb +5 -5
  114. data/test/models_test.rb +15 -6
  115. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  116. data/test/rails_app/app/controllers/admins_controller.rb +0 -5
  117. data/test/rails_app/app/controllers/custom/registrations_controller.rb +10 -0
  118. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  119. data/test/rails_app/app/mailers/users/mailer.rb +0 -9
  120. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  121. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  122. data/test/rails_app/config/application.rb +1 -1
  123. data/test/rails_app/config/environments/production.rb +6 -2
  124. data/test/rails_app/config/environments/test.rb +7 -2
  125. data/test/rails_app/config/initializers/devise.rb +12 -15
  126. data/test/rails_app/config/routes.rb +6 -3
  127. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -2
  128. data/test/rails_app/lib/shared_user.rb +1 -1
  129. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  130. data/test/rails_test.rb +9 -0
  131. data/test/support/helpers.rb +13 -6
  132. data/test/support/integration.rb +2 -2
  133. data/test/test_helper.rb +5 -0
  134. data/test/test_helpers_test.rb +22 -7
  135. data/test/test_models.rb +2 -2
  136. data/test/time_helpers.rb +137 -0
  137. metadata +58 -8
  138. data/gemfiles/Gemfile.rails-head.lock +0 -190
@@ -0,0 +1,193 @@
1
+ GIT
2
+ remote: git://github.com/rails/rails.git
3
+ revision: 2a1b655bb7db42ed0dbadab5bb129a8515e86a40
4
+ branch: 4-2-stable
5
+ specs:
6
+ actionmailer (4.2.6)
7
+ actionpack (= 4.2.6)
8
+ actionview (= 4.2.6)
9
+ activejob (= 4.2.6)
10
+ mail (~> 2.5, >= 2.5.4)
11
+ rails-dom-testing (~> 1.0, >= 1.0.5)
12
+ actionpack (4.2.6)
13
+ actionview (= 4.2.6)
14
+ activesupport (= 4.2.6)
15
+ rack (~> 1.6)
16
+ rack-test (~> 0.6.2)
17
+ rails-dom-testing (~> 1.0, >= 1.0.5)
18
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
19
+ actionview (4.2.6)
20
+ activesupport (= 4.2.6)
21
+ builder (~> 3.1)
22
+ erubis (~> 2.7.0)
23
+ rails-dom-testing (~> 1.0, >= 1.0.5)
24
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
25
+ activejob (4.2.6)
26
+ activesupport (= 4.2.6)
27
+ globalid (>= 0.3.0)
28
+ activemodel (4.2.6)
29
+ activesupport (= 4.2.6)
30
+ builder (~> 3.1)
31
+ activerecord (4.2.6)
32
+ activemodel (= 4.2.6)
33
+ activesupport (= 4.2.6)
34
+ arel (~> 6.0)
35
+ activesupport (4.2.6)
36
+ i18n (~> 0.7)
37
+ json (~> 1.7, >= 1.7.7)
38
+ minitest (~> 5.1)
39
+ thread_safe (~> 0.3, >= 0.3.4)
40
+ tzinfo (~> 1.1)
41
+ rails (4.2.6)
42
+ actionmailer (= 4.2.6)
43
+ actionpack (= 4.2.6)
44
+ actionview (= 4.2.6)
45
+ activejob (= 4.2.6)
46
+ activemodel (= 4.2.6)
47
+ activerecord (= 4.2.6)
48
+ activesupport (= 4.2.6)
49
+ bundler (>= 1.3.0, < 2.0)
50
+ railties (= 4.2.6)
51
+ sprockets-rails
52
+ railties (4.2.6)
53
+ actionpack (= 4.2.6)
54
+ activesupport (= 4.2.6)
55
+ rake (>= 0.8.7)
56
+ thor (>= 0.18.1, < 2.0)
57
+
58
+ PATH
59
+ remote: ..
60
+ specs:
61
+ devise (3.5.8)
62
+ bcrypt (~> 3.0)
63
+ orm_adapter (~> 0.1)
64
+ railties (>= 3.2.6, < 5)
65
+ responders
66
+ thread_safe (~> 0.1)
67
+ warden (~> 1.2.3)
68
+
69
+ GEM
70
+ remote: https://rubygems.org/
71
+ specs:
72
+ arel (6.0.3)
73
+ bcrypt (3.1.11)
74
+ bson (3.2.6)
75
+ builder (3.2.2)
76
+ concurrent-ruby (1.0.1)
77
+ connection_pool (2.2.0)
78
+ erubis (2.7.0)
79
+ faraday (0.9.2)
80
+ multipart-post (>= 1.2, < 3)
81
+ globalid (0.3.6)
82
+ activesupport (>= 4.1.0)
83
+ hashie (3.4.3)
84
+ i18n (0.7.0)
85
+ json (1.8.3)
86
+ jwt (1.5.1)
87
+ loofah (2.0.3)
88
+ nokogiri (>= 1.5.9)
89
+ mail (2.6.4)
90
+ mime-types (>= 1.16, < 4)
91
+ metaclass (0.0.4)
92
+ mime-types (2.99.1)
93
+ mini_portile2 (2.0.0)
94
+ minitest (5.8.4)
95
+ mocha (1.1.0)
96
+ metaclass (~> 0.0.1)
97
+ mongoid (4.0.2)
98
+ activemodel (~> 4.0)
99
+ moped (~> 2.0.0)
100
+ origin (~> 2.1)
101
+ tzinfo (>= 0.3.37)
102
+ moped (2.0.7)
103
+ bson (~> 3.0)
104
+ connection_pool (~> 2.0)
105
+ optionable (~> 0.2.0)
106
+ multi_json (1.11.3)
107
+ multi_xml (0.5.5)
108
+ multipart-post (2.0.0)
109
+ nokogiri (1.6.7.2)
110
+ mini_portile2 (~> 2.0.0.rc2)
111
+ oauth2 (1.1.0)
112
+ faraday (>= 0.8, < 0.10)
113
+ jwt (~> 1.0, < 1.5.2)
114
+ multi_json (~> 1.3)
115
+ multi_xml (~> 0.5)
116
+ rack (>= 1.2, < 3)
117
+ omniauth (1.2.2)
118
+ hashie (>= 1.2, < 4)
119
+ rack (~> 1.0)
120
+ omniauth-facebook (3.0.0)
121
+ omniauth-oauth2 (~> 1.2)
122
+ omniauth-oauth2 (1.2.0)
123
+ faraday (>= 0.8, < 0.10)
124
+ multi_json (~> 1.3)
125
+ oauth2 (~> 1.0)
126
+ omniauth (~> 1.2)
127
+ omniauth-openid (1.0.1)
128
+ omniauth (~> 1.0)
129
+ rack-openid (~> 1.3.1)
130
+ optionable (0.2.0)
131
+ origin (2.2.0)
132
+ orm_adapter (0.5.0)
133
+ rack (1.6.4)
134
+ rack-openid (1.3.1)
135
+ rack (>= 1.1.0)
136
+ ruby-openid (>= 2.1.8)
137
+ rack-test (0.6.3)
138
+ rack (>= 1.0)
139
+ rails-deprecated_sanitizer (1.0.3)
140
+ activesupport (>= 4.2.0.alpha)
141
+ rails-dom-testing (1.0.7)
142
+ activesupport (>= 4.2.0.beta, < 5.0)
143
+ nokogiri (~> 1.6.0)
144
+ rails-deprecated_sanitizer (>= 1.0.1)
145
+ rails-html-sanitizer (1.0.3)
146
+ loofah (~> 2.0)
147
+ rake (11.1.2)
148
+ rdoc (4.2.2)
149
+ json (~> 1.4)
150
+ responders (2.1.2)
151
+ railties (>= 4.2.0, < 5.1)
152
+ ruby-openid (2.7.0)
153
+ sprockets (3.6.0)
154
+ concurrent-ruby (~> 1.0)
155
+ rack (> 1, < 3)
156
+ sprockets-rails (3.0.4)
157
+ actionpack (>= 4.0)
158
+ activesupport (>= 4.0)
159
+ sprockets (>= 3.0.0)
160
+ sqlite3 (1.3.11)
161
+ thor (0.19.1)
162
+ thread_safe (0.3.5)
163
+ tzinfo (1.2.2)
164
+ thread_safe (~> 0.1)
165
+ warden (1.2.6)
166
+ rack (>= 1.0)
167
+ webrat (0.7.3)
168
+ nokogiri (>= 1.2.0)
169
+ rack (>= 1.0)
170
+ rack-test (>= 0.5.3)
171
+
172
+ PLATFORMS
173
+ ruby
174
+
175
+ DEPENDENCIES
176
+ activerecord-jdbc-adapter
177
+ activerecord-jdbcsqlite3-adapter
178
+ devise!
179
+ jruby-openssl
180
+ mime-types (~> 2.99)
181
+ mocha (~> 1.1)
182
+ mongoid (~> 4.0.0)
183
+ omniauth (~> 1.2.2)
184
+ omniauth-facebook
185
+ omniauth-oauth2 (~> 1.2.0)
186
+ omniauth-openid (~> 1.0.1)
187
+ rails!
188
+ rdoc
189
+ sqlite3
190
+ webrat (= 0.7.3)
191
+
192
+ BUNDLED WITH
193
+ 1.11.2
@@ -7,7 +7,9 @@ module Devise
7
7
  include Devise::Controllers::StoreLocation
8
8
 
9
9
  included do
10
- helper_method :warden, :signed_in?, :devise_controller?
10
+ if respond_to?(:helper_method)
11
+ helper_method :warden, :signed_in?, :devise_controller?
12
+ end
11
13
  end
12
14
 
13
15
  module ClassMethods
@@ -69,7 +71,9 @@ module Devise
69
71
  end.compact
70
72
  end
71
73
 
72
- helper_method "current_#{group_name}", "current_#{group_name.to_s.pluralize}", "#{group_name}_signed_in?"
74
+ if respond_to?(:helper_method)
75
+ helper_method "current_#{group_name}", "current_#{group_name.to_s.pluralize}", "#{group_name}_signed_in?"
76
+ end
73
77
  METHODS
74
78
  end
75
79
 
@@ -126,7 +130,9 @@ module Devise
126
130
  METHODS
127
131
 
128
132
  ActiveSupport.on_load(:action_controller) do
129
- helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
133
+ if respond_to?(:helper_method)
134
+ helper_method "current_#{mapping}", "#{mapping}_signed_in?", "#{mapping}_session"
135
+ end
130
136
  end
131
137
  end
132
138
 
@@ -190,10 +196,10 @@ module Devise
190
196
  # root path. For a user scope, you can define the default url in
191
197
  # the following way:
192
198
  #
193
- # map.user_root '/users', controller: 'users' # creates user_root_path
199
+ # get '/users' => 'users#index', as: :user_root # creates user_root_path
194
200
  #
195
- # map.namespace :user do |user|
196
- # user.root controller: 'users' # creates user_root_path
201
+ # namespace :user do
202
+ # root 'users#index' # creates user_root_path
197
203
  # end
198
204
  #
199
205
  # If the resource root path is not defined, root_path is used. However,
@@ -2,18 +2,25 @@ module Devise
2
2
  module Controllers
3
3
  # A module that may be optionally included in a controller in order
4
4
  # to provide remember me behavior. Useful when signing in is done
5
- # through a callback, like in Omniauth.
5
+ # through a callback, like in OmniAuth.
6
6
  module Rememberable
7
7
  # Return default cookie values retrieved from session options.
8
8
  def self.cookie_values
9
9
  Rails.configuration.session_options.slice(:path, :domain, :secure)
10
10
  end
11
11
 
12
+ def remember_me_is_active?(resource)
13
+ return false unless resource.respond_to?(:remember_me)
14
+ scope = Devise::Mapping.find_scope!(resource)
15
+ _, token, generated_at = cookies.signed[remember_key(resource, scope)]
16
+ resource.remember_me?(token, generated_at)
17
+ end
18
+
12
19
  # Remembers the given resource by setting up a cookie
13
20
  def remember_me(resource)
14
21
  return if env["devise.skip_storage"]
15
22
  scope = Devise::Mapping.find_scope!(resource)
16
- resource.remember_me!(resource.extend_remember_period)
23
+ resource.remember_me!
17
24
  cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)
18
25
  end
19
26
 
@@ -6,7 +6,7 @@ module Devise
6
6
  # Return true if the given scope is signed in session. If no scope given, return
7
7
  # true if any scope is signed in. Does not run authentication hooks.
8
8
  def signed_in?(scope=nil)
9
- [ scope || Devise.mappings.keys ].flatten.any? do |_scope|
9
+ [scope || Devise.mappings.keys].flatten.any? do |_scope|
10
10
  warden.authenticate?(scope: _scope)
11
11
  end
12
12
  end
@@ -90,13 +90,7 @@ module Devise
90
90
  session.keys.grep(/^devise\./).each { |k| session.delete(k) }
91
91
  end
92
92
 
93
- def expire_data_after_sign_out!
94
- # session.keys will return an empty array if the session is not yet loaded.
95
- # This is a bug in both Rack and Rails.
96
- # A call to #empty? forces the session to be loaded.
97
- session.empty?
98
- session.keys.grep(/^devise\./).each { |k| session.delete(k) }
99
- end
93
+ alias :expire_data_after_sign_out! :expire_data_after_sign_in!
100
94
  end
101
95
  end
102
96
  end
@@ -35,7 +35,9 @@ module Devise
35
35
  session_key = stored_location_key_for(resource_or_scope)
36
36
  uri = parse_uri(location)
37
37
  if uri
38
- session[session_key] = [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
38
+ path = [uri.path.sub(/\A\/+/, '/'), uri.query].compact.join('?')
39
+ path = [path, uri.fragment].compact.join('#')
40
+ session[session_key] = path
39
41
  end
40
42
  end
41
43
 
@@ -42,16 +42,14 @@ module Devise
42
42
  [:path, :url].each do |path_or_url|
43
43
  actions.each do |action|
44
44
  action = action ? "#{action}_" : ""
45
- method = "#{action}#{module_name}_#{path_or_url}"
45
+ method = :"#{action}#{module_name}_#{path_or_url}"
46
46
 
47
- class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1
48
- def #{method}(resource_or_scope, *args)
49
- scope = Devise::Mapping.find_scope!(resource_or_scope)
50
- router_name = Devise.mappings[scope].router_name
51
- context = router_name ? send(router_name) : _devise_route_context
52
- context.send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args)
53
- end
54
- URL_HELPERS
47
+ define_method method do |resource_or_scope, *args|
48
+ scope = Devise::Mapping.find_scope!(resource_or_scope)
49
+ router_name = Devise.mappings[scope].router_name
50
+ context = router_name ? send(router_name) : _devise_route_context
51
+ context.send("#{action}#{scope}_#{module_name}_#{path_or_url}", *args)
52
+ end
55
53
  end
56
54
  end
57
55
  end
@@ -0,0 +1,22 @@
1
+ require 'bcrypt'
2
+
3
+ module Devise
4
+ module Encryptor
5
+ def self.digest(klass, password)
6
+ if klass.pepper.present?
7
+ password = "#{password}#{klass.pepper}"
8
+ end
9
+ ::BCrypt::Password.create(password, cost: klass.stretches).to_s
10
+ end
11
+
12
+ def self.compare(klass, encrypted_password, password)
13
+ return false if encrypted_password.blank?
14
+ bcrypt = ::BCrypt::Password.new(encrypted_password)
15
+ if klass.pepper.present?
16
+ password = "#{password}#{klass.pepper}"
17
+ end
18
+ password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
19
+ Devise.secure_compare(password, encrypted_password)
20
+ end
21
+ end
22
+ end
@@ -22,9 +22,12 @@ module Devise
22
22
  @respond.call(env)
23
23
  end
24
24
 
25
+ # Try retrieving the URL options from the parent controller (usually
26
+ # ApplicationController). Instance methods are not supported at the moment,
27
+ # so only the class-level attribute is used.
25
28
  def self.default_url_options(*args)
26
- if defined?(ApplicationController)
27
- ApplicationController.default_url_options(*args)
29
+ if defined?(Devise.parent_controller.constantize)
30
+ Devise.parent_controller.constantize.try(:default_url_options) || {}
28
31
  else
29
32
  {}
30
33
  end
@@ -48,18 +51,31 @@ module Devise
48
51
  end
49
52
 
50
53
  def recall
51
- env["PATH_INFO"] = attempted_path
52
- flash.now[:alert] = i18n_message(:invalid)
54
+ config = Rails.application.config
55
+
56
+ if config.try(:relative_url_root)
57
+ base_path = Pathname.new(config.relative_url_root)
58
+ full_path = Pathname.new(attempted_path)
59
+
60
+ env["SCRIPT_NAME"] = config.relative_url_root
61
+ env["PATH_INFO"] = '/' + full_path.relative_path_from(base_path).to_s
62
+ else
63
+ env["PATH_INFO"] = attempted_path
64
+ end
65
+
66
+ flash.now[:alert] = i18n_message(:invalid) if is_flashing_format?
53
67
  self.response = recall_app(warden_options[:recall]).call(env)
54
68
  end
55
69
 
56
70
  def redirect
57
71
  store_location!
58
- if flash[:timedout] && flash[:alert]
59
- flash.keep(:timedout)
60
- flash.keep(:alert)
61
- else
62
- flash[:alert] = i18n_message
72
+ if is_flashing_format?
73
+ if flash[:timedout] && flash[:alert]
74
+ flash.keep(:timedout)
75
+ flash.keep(:alert)
76
+ else
77
+ flash[:alert] = i18n_message
78
+ end
63
79
  end
64
80
  redirect_to redirect_url
65
81
  end
@@ -78,6 +94,9 @@ module Devise
78
94
  options[:resource_name] = scope
79
95
  options[:scope] = "devise.failure"
80
96
  options[:default] = [message]
97
+ auth_keys = scope_class.authentication_keys
98
+ keys = auth_keys.respond_to?(:keys) ? auth_keys.keys : auth_keys
99
+ options[:authentication_keys] = keys.join(I18n.translate(:"support.array.words_connector"))
81
100
  options = i18n_options(options)
82
101
 
83
102
  I18n.t(:"#{scope}.#{message}", options)
@@ -88,7 +107,7 @@ module Devise
88
107
 
89
108
  def redirect_url
90
109
  if warden_message == :timeout
91
- flash[:timedout] = true
110
+ flash[:timedout] = true if is_flashing_format?
92
111
 
93
112
  path = if request.get?
94
113
  attempted_path
@@ -102,15 +121,28 @@ module Devise
102
121
  end
103
122
  end
104
123
 
124
+ def route(scope)
125
+ :"new_#{scope}_session_url"
126
+ end
127
+
105
128
  def scope_url
106
129
  opts = {}
107
- route = :"new_#{scope}_session_url"
130
+ route = route(scope)
108
131
  opts[:format] = request_format unless skip_format?
109
132
 
110
133
  config = Rails.application.config
111
- opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
112
134
 
113
- context = send(Devise.available_router_name)
135
+ # Rails 4.2 goes into an infinite loop if opts[:script_name] is unset
136
+ if (Rails::VERSION::MAJOR >= 4) && (Rails::VERSION::MINOR >= 2)
137
+ opts[:script_name] = (config.relative_url_root if config.respond_to?(:relative_url_root))
138
+ else
139
+ if config.respond_to?(:relative_url_root) && config.relative_url_root.present?
140
+ opts[:script_name] = config.relative_url_root
141
+ end
142
+ end
143
+
144
+ router_name = Devise.mappings[scope].router_name || Devise.available_router_name
145
+ context = send(router_name)
114
146
 
115
147
  if context.respond_to?(route)
116
148
  context.send(route, opts)
@@ -144,7 +176,7 @@ module Devise
144
176
  # It does not make sense to send authenticate headers in ajax requests
145
177
  # or if the user disabled them.
146
178
  def http_auth_header?
147
- Devise.mappings[scope].to.http_authenticatable && !request.xhr?
179
+ scope_class.http_authenticatable && !request.xhr?
148
180
  end
149
181
 
150
182
  def http_auth_body
@@ -182,6 +214,10 @@ module Devise
182
214
  @scope ||= warden_options[:scope] || Devise.default_scope
183
215
  end
184
216
 
217
+ def scope_class
218
+ @scope_class ||= Devise.mappings[scope].to
219
+ end
220
+
185
221
  def attempted_path
186
222
  warden_options[:attempted_path]
187
223
  end
@@ -198,6 +234,12 @@ module Devise
198
234
  Devise.navigational_formats.include?(request_format)
199
235
  end
200
236
 
237
+ # Check if flash messages should be emitted. Default is to do it on
238
+ # navigational formats
239
+ def is_flashing_format?
240
+ is_navigational_format?
241
+ end
242
+
201
243
  def request_format
202
244
  @request_format ||= request.format.try(:ref)
203
245
  end
@@ -7,7 +7,8 @@ Warden::Manager.after_set_user do |record, warden, options|
7
7
  scope = options[:scope]
8
8
  env = warden.request.env
9
9
 
10
- if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) && options[:store] != false
10
+ if record && record.respond_to?(:timedout?) && warden.authenticated?(scope) &&
11
+ options[:store] != false && !env['devise.skip_timeoutable']
11
12
  last_request_at = warden.session(scope)['last_request_at']
12
13
 
13
14
  if last_request_at.is_a? Integer
@@ -18,13 +19,10 @@ Warden::Manager.after_set_user do |record, warden, options|
18
19
 
19
20
  proxy = Devise::Hooks::Proxy.new(warden)
20
21
 
21
- if record.timedout?(last_request_at) && !env['devise.skip_timeout']
22
+ if record.timedout?(last_request_at) &&
23
+ !env['devise.skip_timeout'] &&
24
+ !proxy.remember_me_is_active?(record)
22
25
  Devise.sign_out_all_scopes ? proxy.sign_out : proxy.sign_out(scope)
23
-
24
- if record.respond_to?(:expire_auth_token_on_timeout) && record.expire_auth_token_on_timeout
25
- record.reset_authentication_token!
26
- end
27
-
28
26
  throw :warden, scope: scope, message: :timeout
29
27
  end
30
28
 
@@ -31,9 +31,10 @@ module Devise
31
31
  # Receives an object and find a scope for it. If a scope cannot be found,
32
32
  # raises an error. If a symbol is given, it's considered to be the scope.
33
33
  def self.find_scope!(obj)
34
+ obj = obj.devise_scope if obj.respond_to?(:devise_scope)
34
35
  case obj
35
36
  when String, Symbol
36
- return obj
37
+ return obj.to_sym
37
38
  when Class
38
39
  Devise.mappings.each_value { |m| return m.name if obj <= m.to }
39
40
  else
@@ -1,3 +1,4 @@
1
+ require 'active_model/version'
1
2
  require 'devise/hooks/activatable'
2
3
  require 'devise/hooks/csrf_cleaner'
3
4
 
@@ -37,7 +38,7 @@ module Devise
37
38
  # calling model.active_for_authentication?. This method is overwritten by other devise modules. For instance,
38
39
  # :confirmable overwrites .active_for_authentication? to only return true if your model was confirmed.
39
40
  #
40
- # You overwrite this method yourself, but if you do, don't forget to call super:
41
+ # You can overwrite this method yourself, but if you do, don't forget to call super:
41
42
  #
42
43
  # def active_for_authentication?
43
44
  # super && special_condition_is_valid?
@@ -95,29 +96,22 @@ module Devise
95
96
  def authenticatable_salt
96
97
  end
97
98
 
98
- array = %w(serializable_hash)
99
- # to_xml does not call serializable_hash on 3.1
100
- array << "to_xml" if Rails::VERSION::STRING[0,3] == "3.1"
101
-
102
- array.each do |method|
103
- class_eval <<-RUBY, __FILE__, __LINE__
104
- # Redefine to_xml and serializable_hash in models for more secure defaults.
105
- # By default, it removes from the serializable model all attributes that
106
- # are *not* accessible. You can remove this default by using :force_except
107
- # and passing a new list of attributes you want to exempt. All attributes
108
- # given to :except will simply add names to exempt to Devise internal list.
109
- def #{method}(options=nil)
110
- options ||= {}
111
- options[:except] = Array(options[:except])
112
-
113
- if options[:force_except]
114
- options[:except].concat Array(options[:force_except])
115
- else
116
- options[:except].concat BLACKLIST_FOR_SERIALIZATION
117
- end
118
- super(options)
119
- end
120
- RUBY
99
+ # Redefine serializable_hash in models for more secure defaults.
100
+ # By default, it removes from the serializable model all attributes that
101
+ # are *not* accessible. You can remove this default by using :force_except
102
+ # and passing a new list of attributes you want to exempt. All attributes
103
+ # given to :except will simply add names to exempt to Devise internal list.
104
+ def serializable_hash(options = nil)
105
+ options ||= {}
106
+ options[:except] = Array(options[:except])
107
+
108
+ if options[:force_except]
109
+ options[:except].concat Array(options[:force_except])
110
+ else
111
+ options[:except].concat BLACKLIST_FOR_SERIALIZATION
112
+ end
113
+
114
+ super(options)
121
115
  end
122
116
 
123
117
  protected
@@ -170,7 +164,13 @@ module Devise
170
164
  # end
171
165
  #
172
166
  def send_devise_notification(notification, *args)
173
- devise_mailer.send(notification, self, *args).deliver
167
+ message = devise_mailer.send(notification, self, *args)
168
+ # Remove once we move to Rails 4.2+ only.
169
+ if message.respond_to?(:deliver_now)
170
+ message.deliver_now
171
+ else
172
+ message.deliver
173
+ end
174
174
  end
175
175
 
176
176
  def downcase_keys
@@ -246,14 +246,14 @@ module Devise
246
246
  to_adapter.find_first(devise_parameter_filter.filter(tainted_conditions).merge(opts))
247
247
  end
248
248
 
249
- # Find an initialize a record setting an error if it can't be found.
249
+ # Find or initialize a record setting an error if it can't be found.
250
250
  def find_or_initialize_with_error_by(attribute, value, error=:invalid) #:nodoc:
251
251
  find_or_initialize_with_errors([attribute], { attribute => value }, error)
252
252
  end
253
253
 
254
- # Find an initialize a group of attributes based on a list of required attributes.
254
+ # Find or initialize a record with group of attributes based on a list of required attributes.
255
255
  def find_or_initialize_with_errors(required_attributes, attributes, error=:invalid) #:nodoc:
256
- attributes = attributes.slice(*required_attributes)
256
+ attributes = attributes.slice(*required_attributes).with_indifferent_access
257
257
  attributes.delete_if { |key, value| value.blank? }
258
258
 
259
259
  if attributes.size == required_attributes.size