devise 3.2.4 → 4.0.0

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +33 -17
  4. data/CHANGELOG.md +57 -1033
  5. data/CODE_OF_CONDUCT.md +22 -0
  6. data/CONTRIBUTING.md +2 -0
  7. data/Gemfile +5 -5
  8. data/Gemfile.lock +138 -115
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +124 -65
  11. data/Rakefile +2 -1
  12. data/app/controllers/devise/confirmations_controller.rb +7 -3
  13. data/app/controllers/devise/omniauth_callbacks_controller.rb +8 -4
  14. data/app/controllers/devise/passwords_controller.rb +16 -6
  15. data/app/controllers/devise/registrations_controller.rb +22 -10
  16. data/app/controllers/devise/sessions_controller.rb +42 -14
  17. data/app/controllers/devise/unlocks_controller.rb +5 -2
  18. data/app/controllers/devise_controller.rb +63 -29
  19. data/app/mailers/devise/mailer.rb +4 -0
  20. data/app/views/devise/confirmations/new.html.erb +7 -3
  21. data/app/views/devise/mailer/password_change.html.erb +3 -0
  22. data/app/views/devise/passwords/edit.html.erb +14 -5
  23. data/app/views/devise/passwords/new.html.erb +7 -3
  24. data/app/views/devise/registrations/edit.html.erb +19 -9
  25. data/app/views/devise/registrations/new.html.erb +18 -7
  26. data/app/views/devise/sessions/new.html.erb +16 -7
  27. data/app/views/devise/shared/{_links.erb → _links.html.erb} +2 -2
  28. data/app/views/devise/unlocks/new.html.erb +7 -3
  29. data/bin/test +13 -0
  30. data/config/locales/en.yml +19 -16
  31. data/devise.gemspec +3 -4
  32. data/gemfiles/{Gemfile.rails-3.2-stable → Gemfile.rails-4.1-stable} +6 -6
  33. data/gemfiles/Gemfile.rails-4.1-stable.lock +167 -0
  34. data/gemfiles/{Gemfile.rails-head → Gemfile.rails-4.2-stable} +6 -6
  35. data/gemfiles/Gemfile.rails-4.2-stable.lock +189 -0
  36. data/gemfiles/Gemfile.rails-5.0-beta +37 -0
  37. data/gemfiles/Gemfile.rails-5.0-beta.lock +199 -0
  38. data/lib/devise/controllers/helpers.rb +94 -27
  39. data/lib/devise/controllers/rememberable.rb +9 -2
  40. data/lib/devise/controllers/sign_in_out.rb +2 -9
  41. data/lib/devise/controllers/store_location.rb +11 -3
  42. data/lib/devise/controllers/url_helpers.rb +7 -7
  43. data/lib/devise/encryptor.rb +22 -0
  44. data/lib/devise/failure_app.rb +72 -23
  45. data/lib/devise/hooks/activatable.rb +3 -4
  46. data/lib/devise/hooks/csrf_cleaner.rb +3 -1
  47. data/lib/devise/hooks/timeoutable.rb +13 -8
  48. data/lib/devise/mailers/helpers.rb +1 -1
  49. data/lib/devise/mapping.rb +6 -2
  50. data/lib/devise/models/authenticatable.rb +32 -28
  51. data/lib/devise/models/confirmable.rb +55 -22
  52. data/lib/devise/models/database_authenticatable.rb +32 -19
  53. data/lib/devise/models/lockable.rb +5 -5
  54. data/lib/devise/models/recoverable.rb +44 -20
  55. data/lib/devise/models/rememberable.rb +54 -27
  56. data/lib/devise/models/timeoutable.rb +0 -6
  57. data/lib/devise/models/trackable.rb +5 -3
  58. data/lib/devise/models/validatable.rb +3 -3
  59. data/lib/devise/models.rb +1 -1
  60. data/lib/devise/omniauth/url_helpers.rb +62 -4
  61. data/lib/devise/parameter_sanitizer.rb +176 -61
  62. data/lib/devise/rails/routes.rb +76 -59
  63. data/lib/devise/rails/warden_compat.rb +1 -10
  64. data/lib/devise/rails.rb +2 -11
  65. data/lib/devise/strategies/authenticatable.rb +15 -6
  66. data/lib/devise/strategies/database_authenticatable.rb +5 -4
  67. data/lib/devise/strategies/rememberable.rb +13 -3
  68. data/lib/devise/test_helpers.rb +12 -7
  69. data/lib/devise/token_generator.rb +1 -41
  70. data/lib/devise/version.rb +1 -1
  71. data/lib/devise.rb +150 -58
  72. data/lib/generators/active_record/devise_generator.rb +28 -4
  73. data/lib/generators/active_record/templates/migration.rb +3 -3
  74. data/lib/generators/active_record/templates/migration_existing.rb +3 -3
  75. data/lib/generators/devise/controllers_generator.rb +44 -0
  76. data/lib/generators/devise/install_generator.rb +15 -0
  77. data/lib/generators/devise/orm_helpers.rb +1 -18
  78. data/lib/generators/devise/views_generator.rb +14 -3
  79. data/lib/generators/templates/README +1 -1
  80. data/lib/generators/templates/controllers/README +14 -0
  81. data/lib/generators/templates/controllers/confirmations_controller.rb +28 -0
  82. data/lib/generators/templates/controllers/omniauth_callbacks_controller.rb +28 -0
  83. data/lib/generators/templates/controllers/passwords_controller.rb +32 -0
  84. data/lib/generators/templates/controllers/registrations_controller.rb +60 -0
  85. data/lib/generators/templates/controllers/sessions_controller.rb +25 -0
  86. data/lib/generators/templates/controllers/unlocks_controller.rb +28 -0
  87. data/lib/generators/templates/devise.rb +36 -28
  88. data/lib/generators/templates/markerb/confirmation_instructions.markerb +1 -1
  89. data/lib/generators/templates/markerb/password_change.markerb +3 -0
  90. data/lib/generators/templates/markerb/reset_password_instructions.markerb +1 -1
  91. data/lib/generators/templates/markerb/unlock_instructions.markerb +1 -1
  92. data/lib/generators/templates/simple_form_for/passwords/edit.html.erb +1 -1
  93. data/lib/generators/templates/simple_form_for/registrations/new.html.erb +1 -1
  94. data/lib/generators/templates/simple_form_for/sessions/new.html.erb +2 -2
  95. data/test/controllers/custom_registrations_controller_test.rb +40 -0
  96. data/test/controllers/custom_strategy_test.rb +7 -5
  97. data/test/controllers/helper_methods_test.rb +22 -0
  98. data/test/controllers/helpers_test.rb +41 -1
  99. data/test/controllers/inherited_controller_i18n_messages_test.rb +51 -0
  100. data/test/controllers/internal_helpers_test.rb +19 -15
  101. data/test/controllers/load_hooks_controller_test.rb +19 -0
  102. data/test/controllers/passwords_controller_test.rb +5 -4
  103. data/test/controllers/sessions_controller_test.rb +24 -21
  104. data/test/controllers/url_helpers_test.rb +7 -1
  105. data/test/devise_test.rb +48 -8
  106. data/test/failure_app_test.rb +107 -19
  107. data/test/generators/active_record_generator_test.rb +6 -26
  108. data/test/generators/controllers_generator_test.rb +48 -0
  109. data/test/generators/install_generator_test.rb +14 -3
  110. data/test/generators/views_generator_test.rb +8 -1
  111. data/test/helpers/devise_helper_test.rb +10 -12
  112. data/test/integration/authenticatable_test.rb +37 -21
  113. data/test/integration/confirmable_test.rb +54 -14
  114. data/test/integration/database_authenticatable_test.rb +12 -1
  115. data/test/integration/http_authenticatable_test.rb +4 -5
  116. data/test/integration/lockable_test.rb +10 -9
  117. data/test/integration/omniauthable_test.rb +13 -11
  118. data/test/integration/recoverable_test.rb +28 -15
  119. data/test/integration/registerable_test.rb +41 -33
  120. data/test/integration/rememberable_test.rb +51 -7
  121. data/test/integration/timeoutable_test.rb +23 -22
  122. data/test/integration/trackable_test.rb +3 -3
  123. data/test/mailers/confirmation_instructions_test.rb +10 -10
  124. data/test/mailers/reset_password_instructions_test.rb +8 -8
  125. data/test/mailers/unlock_instructions_test.rb +8 -8
  126. data/test/mapping_test.rb +7 -0
  127. data/test/models/authenticatable_test.rb +11 -1
  128. data/test/models/confirmable_test.rb +91 -42
  129. data/test/models/database_authenticatable_test.rb +26 -6
  130. data/test/models/lockable_test.rb +29 -17
  131. data/test/models/recoverable_test.rb +74 -7
  132. data/test/models/rememberable_test.rb +68 -94
  133. data/test/models/trackable_test.rb +28 -0
  134. data/test/models/validatable_test.rb +9 -17
  135. data/test/models_test.rb +15 -6
  136. data/test/omniauth/url_helpers_test.rb +4 -7
  137. data/test/orm/active_record.rb +6 -1
  138. data/test/parameter_sanitizer_test.rb +103 -53
  139. data/test/rails_app/app/active_record/user.rb +1 -0
  140. data/test/rails_app/app/active_record/user_on_engine.rb +7 -0
  141. data/test/rails_app/app/active_record/user_on_main_app.rb +7 -0
  142. data/test/rails_app/app/active_record/user_without_email.rb +8 -0
  143. data/test/rails_app/app/controllers/admins_controller.rb +1 -6
  144. data/test/rails_app/app/controllers/application_controller.rb +5 -2
  145. data/test/rails_app/app/controllers/application_with_fake_engine.rb +30 -0
  146. data/test/rails_app/app/controllers/custom/registrations_controller.rb +31 -0
  147. data/test/rails_app/app/controllers/home_controller.rb +5 -1
  148. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +3 -3
  149. data/test/rails_app/app/controllers/users_controller.rb +6 -6
  150. data/test/rails_app/app/mailers/users/from_proc_mailer.rb +3 -0
  151. data/test/rails_app/app/mailers/users/mailer.rb +0 -9
  152. data/test/rails_app/app/mailers/users/reply_to_mailer.rb +4 -0
  153. data/test/rails_app/app/mongoid/user_on_engine.rb +39 -0
  154. data/test/rails_app/app/mongoid/user_on_main_app.rb +39 -0
  155. data/test/rails_app/app/mongoid/user_without_email.rb +33 -0
  156. data/test/rails_app/config/application.rb +3 -3
  157. data/test/rails_app/config/boot.rb +4 -4
  158. data/test/rails_app/config/environments/production.rb +6 -2
  159. data/test/rails_app/config/environments/test.rb +13 -3
  160. data/test/rails_app/config/initializers/devise.rb +15 -16
  161. data/test/rails_app/config/initializers/secret_token.rb +1 -6
  162. data/test/rails_app/config/routes.rb +23 -3
  163. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +2 -2
  164. data/test/rails_app/lib/shared_user.rb +1 -1
  165. data/test/rails_app/lib/shared_user_without_email.rb +26 -0
  166. data/test/rails_app/lib/shared_user_without_omniauth.rb +13 -0
  167. data/test/rails_test.rb +9 -0
  168. data/test/routes_test.rb +33 -16
  169. data/test/support/assertions.rb +2 -3
  170. data/test/support/helpers.rb +13 -6
  171. data/test/support/http_method_compatibility.rb +51 -0
  172. data/test/support/integration.rb +4 -4
  173. data/test/support/webrat/integrations/rails.rb +9 -0
  174. data/test/test_helper.rb +7 -0
  175. data/test/test_helpers_test.rb +43 -38
  176. data/test/test_models.rb +3 -3
  177. metadata +77 -23
  178. data/gemfiles/Gemfile.rails-4.0-stable +0 -29
@@ -8,12 +8,40 @@ class FailureTest < ActiveSupport::TestCase
8
8
  end
9
9
  end
10
10
 
11
+ class FailureWithSubdomain < RootFailureApp
12
+ routes = ActionDispatch::Routing::RouteSet.new
13
+
14
+ routes.draw do
15
+ scope subdomain: 'sub' do
16
+ root to: 'foo#bar'
17
+ end
18
+ end
19
+
20
+ include routes.url_helpers
21
+ end
22
+
11
23
  class FailureWithI18nOptions < Devise::FailureApp
12
24
  def i18n_options(options)
13
25
  options.merge(name: 'Steve')
14
26
  end
15
27
  end
16
28
 
29
+ class FakeEngineApp < Devise::FailureApp
30
+ class FakeEngine
31
+ def new_user_on_engine_session_url _
32
+ '/user_on_engines/sign_in'
33
+ end
34
+ end
35
+
36
+ def main_app
37
+ raise 'main_app router called instead of fake_engine'
38
+ end
39
+
40
+ def fake_engine
41
+ @fake_engine ||= FakeEngine.new
42
+ end
43
+ end
44
+
17
45
  def self.context(name, &block)
18
46
  instance_eval(&block)
19
47
  end
@@ -25,11 +53,16 @@ class FailureTest < ActiveSupport::TestCase
25
53
  'REQUEST_METHOD' => 'GET',
26
54
  'warden.options' => { scope: :user },
27
55
  'rack.session' => {},
28
- 'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime::HTML),
56
+ 'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime[:html]),
29
57
  'rack.input' => "",
30
58
  'warden' => OpenStruct.new(message: nil)
31
59
  }.merge!(env_params)
32
60
 
61
+ # Passing nil for action_dispatch.request.formats prevents the default from being used in Rails 5, need to remove it
62
+ if env.has_key?('action_dispatch.request.formats') && env['action_dispatch.request.formats'].nil?
63
+ env.delete 'action_dispatch.request.formats' unless env['action_dispatch.request.formats']
64
+ end
65
+
33
66
  @response = (env.delete(:app) || Devise::FailureApp).call(env).to_a
34
67
  @request = ActionDispatch::Request.new(env)
35
68
  end
@@ -42,6 +75,13 @@ class FailureTest < ActiveSupport::TestCase
42
75
  assert_equal 'http://test.host/users/sign_in', @response.second['Location']
43
76
  end
44
77
 
78
+ test 'returns to the default redirect location considering subdomain' do
79
+ call_failure('warden.options' => { scope: :subdomain_user })
80
+ assert_equal 302, @response.first
81
+ assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
82
+ assert_equal 'http://sub.test.host/subdomain_users/sign_in', @response.second['Location']
83
+ end
84
+
45
85
  test 'returns to the default redirect location for wildcard requests' do
46
86
  call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
47
87
  assert_equal 302, @response.first
@@ -57,6 +97,22 @@ class FailureTest < ActiveSupport::TestCase
57
97
  end
58
98
  end
59
99
 
100
+ test 'returns to the root path considering subdomain if no session path is available' do
101
+ swap Devise, router_name: :fake_app do
102
+ call_failure app: FailureWithSubdomain
103
+ assert_equal 302, @response.first
104
+ assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
105
+ assert_equal 'http://sub.test.host/', @response.second['Location']
106
+ end
107
+ end
108
+
109
+ test 'returns to the default redirect location considering the router for supplied scope' do
110
+ call_failure app: FakeEngineApp, 'warden.options' => { scope: :user_on_engine }
111
+ assert_equal 302, @response.first
112
+ assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
113
+ assert_equal 'http://test.host/user_on_engines/sign_in', @response.second['Location']
114
+ end
115
+
60
116
  if Rails.application.config.respond_to?(:relative_url_root)
61
117
  test 'returns to the default redirect location considering the relative url root' do
62
118
  swap Rails.application.config, relative_url_root: "/sample" do
@@ -65,6 +121,14 @@ class FailureTest < ActiveSupport::TestCase
65
121
  assert_equal 'http://test.host/sample/users/sign_in', @response.second['Location']
66
122
  end
67
123
  end
124
+
125
+ test 'returns to the default redirect location considering the relative url root and subdomain' do
126
+ swap Rails.application.config, relative_url_root: "/sample" do
127
+ call_failure('warden.options' => { scope: :subdomain_user })
128
+ assert_equal 302, @response.first
129
+ assert_equal 'http://sub.test.host/sample/subdomain_users/sign_in', @response.second['Location']
130
+ end
131
+ end
68
132
  end
69
133
 
70
134
  test 'uses the proxy failure message as symbol' do
@@ -73,6 +137,13 @@ class FailureTest < ActiveSupport::TestCase
73
137
  assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
74
138
  end
75
139
 
140
+ test 'supports authentication_keys as a Hash for the flash message' do
141
+ swap Devise, authentication_keys: { email: true, login: true } do
142
+ call_failure('warden' => OpenStruct.new(message: :invalid))
143
+ assert_equal 'Invalid email, login or password.', @request.flash[:alert]
144
+ end
145
+ end
146
+
76
147
  test 'uses custom i18n options' do
77
148
  call_failure('warden' => OpenStruct.new(message: :does_not_exist), app: FailureWithI18nOptions)
78
149
  assert_equal 'User Steve does not exist', @request.flash[:alert]
@@ -89,7 +160,7 @@ class FailureTest < ActiveSupport::TestCase
89
160
  assert_equal 'text/html; charset=utf-8', @response.second['Content-Type']
90
161
  end
91
162
 
92
- test 'setup a default message' do
163
+ test 'set up a default message' do
93
164
  call_failure
94
165
  assert_match(/You are being/, @response.last.body)
95
166
  assert_match(/redirected/, @response.last.body)
@@ -98,14 +169,14 @@ class FailureTest < ActiveSupport::TestCase
98
169
 
99
170
  test 'works for any navigational format' do
100
171
  swap Devise, navigational_formats: [:xml] do
101
- call_failure('formats' => Mime::XML)
172
+ call_failure('formats' => Mime[:xml])
102
173
  assert_equal 302, @response.first
103
174
  end
104
175
  end
105
176
 
106
177
  test 'redirects the correct format if it is a non-html format request' do
107
178
  swap Devise, navigational_formats: [:js] do
108
- call_failure('formats' => Mime::JS)
179
+ call_failure('formats' => Mime[:js])
109
180
  assert_equal 'http://test.host/users/sign_in.js', @response.second["Location"]
110
181
  end
111
182
  end
@@ -113,18 +184,18 @@ class FailureTest < ActiveSupport::TestCase
113
184
 
114
185
  context 'For HTTP request' do
115
186
  test 'return 401 status' do
116
- call_failure('formats' => Mime::XML)
187
+ call_failure('formats' => Mime[:xml])
117
188
  assert_equal 401, @response.first
118
189
  end
119
190
 
120
191
  test 'return appropriate body for xml' do
121
- call_failure('formats' => Mime::XML)
192
+ call_failure('formats' => Mime[:xml])
122
193
  result = %(<?xml version="1.0" encoding="UTF-8"?>\n<errors>\n <error>You need to sign in or sign up before continuing.</error>\n</errors>\n)
123
194
  assert_equal result, @response.last.body
124
195
  end
125
196
 
126
197
  test 'return appropriate body for json' do
127
- call_failure('formats' => Mime::JSON)
198
+ call_failure('formats' => Mime[:json])
128
199
  result = %({"error":"You need to sign in or sign up before continuing."})
129
200
  assert_equal result, @response.last.body
130
201
  end
@@ -135,26 +206,26 @@ class FailureTest < ActiveSupport::TestCase
135
206
  end
136
207
 
137
208
  test 'return WWW-authenticate headers if model allows' do
138
- call_failure('formats' => Mime::XML)
209
+ call_failure('formats' => Mime[:xml])
139
210
  assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
140
211
  end
141
212
 
142
213
  test 'does not return WWW-authenticate headers if model does not allow' do
143
214
  swap Devise, http_authenticatable: false do
144
- call_failure('formats' => Mime::XML)
215
+ call_failure('formats' => Mime[:xml])
145
216
  assert_nil @response.second["WWW-Authenticate"]
146
217
  end
147
218
  end
148
219
 
149
220
  test 'works for any non navigational format' do
150
221
  swap Devise, navigational_formats: [] do
151
- call_failure('formats' => Mime::HTML)
222
+ call_failure('formats' => Mime[:html])
152
223
  assert_equal 401, @response.first
153
224
  end
154
225
  end
155
226
 
156
227
  test 'uses the failure message as response body' do
157
- call_failure('formats' => Mime::XML, 'warden' => OpenStruct.new(message: :invalid))
228
+ call_failure('formats' => Mime[:xml], 'warden' => OpenStruct.new(message: :invalid))
158
229
  assert_match '<error>Invalid email or password.</error>', @response.third.body
159
230
  end
160
231
 
@@ -162,7 +233,7 @@ class FailureTest < ActiveSupport::TestCase
162
233
  context 'when http_authenticatable_on_xhr is false' do
163
234
  test 'dont return 401 with navigational formats' do
164
235
  swap Devise, http_authenticatable_on_xhr: false do
165
- call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
236
+ call_failure('formats' => Mime[:html], 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
166
237
  assert_equal 302, @response.first
167
238
  assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
168
239
  end
@@ -170,7 +241,7 @@ class FailureTest < ActiveSupport::TestCase
170
241
 
171
242
  test 'dont return 401 with non navigational formats' do
172
243
  swap Devise, http_authenticatable_on_xhr: false do
173
- call_failure('formats' => Mime::JSON, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
244
+ call_failure('formats' => Mime[:json], 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
174
245
  assert_equal 302, @response.first
175
246
  assert_equal 'http://test.host/users/sign_in.json', @response.second["Location"]
176
247
  end
@@ -180,14 +251,14 @@ class FailureTest < ActiveSupport::TestCase
180
251
  context 'when http_authenticatable_on_xhr is true' do
181
252
  test 'return 401' do
182
253
  swap Devise, http_authenticatable_on_xhr: true do
183
- call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
254
+ call_failure('formats' => Mime[:html], 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
184
255
  assert_equal 401, @response.first
185
256
  end
186
257
  end
187
258
 
188
259
  test 'skip WWW-Authenticate header' do
189
260
  swap Devise, http_authenticatable_on_xhr: true do
190
- call_failure('formats' => Mime::HTML, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
261
+ call_failure('formats' => Mime[:html], 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
191
262
  assert_nil @response.second['WWW-Authenticate']
192
263
  end
193
264
  end
@@ -203,7 +274,7 @@ class FailureTest < ActiveSupport::TestCase
203
274
  "warden" => stub_everything
204
275
  }
205
276
  call_failure(env)
206
- assert @response.third.body.include?('<h2>Sign in</h2>')
277
+ assert @response.third.body.include?('<h2>Log in</h2>')
207
278
  assert @response.third.body.include?('Invalid email or password.')
208
279
  end
209
280
 
@@ -214,8 +285,8 @@ class FailureTest < ActiveSupport::TestCase
214
285
  "warden" => stub_everything
215
286
  }
216
287
  call_failure(env)
217
- assert @response.third.body.include?('<h2>Sign in</h2>')
218
- assert @response.third.body.include?('You have to confirm your account before continuing.')
288
+ assert @response.third.body.include?('<h2>Log in</h2>')
289
+ assert @response.third.body.include?('You have to confirm your email address before continuing.')
219
290
  end
220
291
 
221
292
  test 'calls the original controller if inactive account' do
@@ -225,8 +296,25 @@ class FailureTest < ActiveSupport::TestCase
225
296
  "warden" => stub_everything
226
297
  }
227
298
  call_failure(env)
228
- assert @response.third.body.include?('<h2>Sign in</h2>')
299
+ assert @response.third.body.include?('<h2>Log in</h2>')
229
300
  assert @response.third.body.include?('Your account is not activated yet.')
230
301
  end
302
+
303
+ if Rails.application.config.respond_to?(:relative_url_root)
304
+ test 'calls the original controller with the proper environment considering the relative url root' do
305
+ swap Rails.application.config, relative_url_root: "/sample" do
306
+ env = {
307
+ "warden.options" => { recall: "devise/sessions#new", attempted_path: "/sample/users/sign_in"},
308
+ "devise.mapping" => Devise.mappings[:user],
309
+ "warden" => stub_everything
310
+ }
311
+ call_failure(env)
312
+ assert @response.third.body.include?('<h2>Log in</h2>')
313
+ assert @response.third.body.include?('Invalid email or password.')
314
+ assert_equal @request.env["SCRIPT_NAME"], '/sample'
315
+ assert_equal @request.env["PATH_INFO"], '/users/sign_in'
316
+ end
317
+ end
318
+ end
231
319
  end
232
320
  end
@@ -37,6 +37,12 @@ if DEVISE_ORM == :active_record
37
37
  assert_no_file "app/models/monster.rb"
38
38
  assert_no_migration "db/migrate/devise_create_monsters.rb"
39
39
  end
40
+
41
+ test "use string column type for ip addresses" do
42
+ run_generator %w(monster)
43
+ assert_migration "db/migrate/devise_create_monsters.rb", /t.string :current_sign_in_ip/
44
+ assert_migration "db/migrate/devise_create_monsters.rb", /t.string :last_sign_in_ip/
45
+ end
40
46
  end
41
47
 
42
48
  module RailsEngine
@@ -63,7 +69,6 @@ if DEVISE_ORM == :active_record
63
69
  setup :prepare_destination
64
70
 
65
71
  test "all files are properly created in rails 4.0" do
66
- ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(false)
67
72
  simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
68
73
  run_generator ["monster"]
69
74
 
@@ -74,30 +79,5 @@ if DEVISE_ORM == :active_record
74
79
  end
75
80
  end
76
81
 
77
- test "all files are properly created in rails 3.2 when strong_parameters gem is not installed" do
78
- ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
79
- ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(false)
80
- simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
81
- run_generator ["monster"]
82
-
83
- assert_file "app/models/rails_engine/monster.rb", /devise/
84
- assert_file "app/models/rails_engine/monster.rb" do |content|
85
- assert_match /attr_accessible :email/, content
86
- end
87
- end
88
- end
89
-
90
- test "all files are properly created in rails 3.2 when strong_parameters gem is installed" do
91
- ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:rails_3?).returns(true)
92
- ActiveRecord::Generators::DeviseGenerator.any_instance.stubs(:strong_parameters_enabled?).returns(true)
93
- simulate_inside_engine(RailsEngine::Engine, RailsEngine) do
94
- run_generator ["monster"]
95
-
96
- assert_file "app/models/rails_engine/monster.rb", /devise/
97
- assert_file "app/models/rails_engine/monster.rb" do |content|
98
- assert_no_match /attr_accessible :email/, content
99
- end
100
- end
101
- end
102
82
  end
103
83
  end
@@ -0,0 +1,48 @@
1
+ require "test_helper"
2
+
3
+ class ControllersGeneratorTest < Rails::Generators::TestCase
4
+ tests Devise::Generators::ControllersGenerator
5
+ destination File.expand_path("../../tmp", __FILE__)
6
+ setup :prepare_destination
7
+
8
+ test "Assert no controllers are created with no params" do
9
+ capture(:stderr) { run_generator }
10
+ assert_no_file "app/controllers/sessions_controller.rb"
11
+ assert_no_file "app/controllers/registrations_controller.rb"
12
+ assert_no_file "app/controllers/confirmations_controller.rb"
13
+ assert_no_file "app/controllers/passwords_controller.rb"
14
+ assert_no_file "app/controllers/unlocks_controller.rb"
15
+ assert_no_file "app/controllers/omniauth_callbacks_controller.rb"
16
+ end
17
+
18
+ test "Assert all controllers are properly created with scope param" do
19
+ run_generator %w(users)
20
+ assert_class_names 'users'
21
+
22
+ run_generator %w(admins)
23
+ assert_class_names 'admins'
24
+ end
25
+
26
+ test "Assert specified controllers with scope" do
27
+ run_generator %w(users -c sessions)
28
+ assert_file "app/controllers/users/sessions_controller.rb"
29
+ assert_no_file "app/controllers/users/registrations_controller.rb"
30
+ assert_no_file "app/controllers/users/confirmations_controller.rb"
31
+ assert_no_file "app/controllers/users/passwords_controller.rb"
32
+ assert_no_file "app/controllers/users/unlocks_controller.rb"
33
+ assert_no_file "app/controllers/users/omniauth_callbacks_controller.rb"
34
+ end
35
+
36
+ private
37
+
38
+ def assert_class_names(scope, options = {})
39
+ base_dir = "app/controllers#{scope.blank? ? '' : ('/' + scope)}"
40
+ scope_prefix = scope.blank? ? '' : (scope.camelize + '::')
41
+ controllers = options[:controllers] ||
42
+ %w(confirmations passwords registrations sessions unlocks omniauth_callbacks)
43
+
44
+ controllers.each do |c|
45
+ assert_file "#{base_dir}/#{c}_controller.rb", /#{scope_prefix + c.camelize}/
46
+ end
47
+ end
48
+ end
@@ -5,9 +5,20 @@ class InstallGeneratorTest < Rails::Generators::TestCase
5
5
  destination File.expand_path("../../tmp", __FILE__)
6
6
  setup :prepare_destination
7
7
 
8
- test "Assert all files are properly created" do
9
- run_generator
10
- assert_file "config/initializers/devise.rb"
8
+ test "assert all files are properly created" do
9
+ run_generator(["--orm=active_record"])
10
+ assert_file "config/initializers/devise.rb", /devise\/orm\/active_record/
11
11
  assert_file "config/locales/devise.en.yml"
12
12
  end
13
+
14
+ test "fails if no ORM is specified" do
15
+ stderr = capture(:stderr) do
16
+ run_generator
17
+ end
18
+
19
+ assert_match %r{An ORM must be set to install Devise}, stderr
20
+
21
+ assert_no_file "config/initializers/devise.rb"
22
+ assert_no_file "config/locales/devise.en.yml"
23
+ end
13
24
  end
@@ -46,6 +46,13 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
46
46
  assert_no_file "app/views/devise/mailer/confirmation_instructions.html.erb"
47
47
  end
48
48
 
49
+ test "Assert mailer specific directory with simple form" do
50
+ run_generator %w(-v mailer -b simple_form_for)
51
+ assert_file "app/views/devise/mailer/confirmation_instructions.html.erb"
52
+ assert_file "app/views/devise/mailer/reset_password_instructions.html.erb"
53
+ assert_file "app/views/devise/mailer/unlock_instructions.html.erb"
54
+ end
55
+
49
56
  test "Assert specified directories with scope" do
50
57
  run_generator %w(users -v sessions)
51
58
  assert_file "app/views/users/sessions/new.html.erb"
@@ -78,7 +85,7 @@ class ViewsGeneratorTest < Rails::Generators::TestCase
78
85
  assert_file "app/views/#{scope}/registrations/new.html.erb"
79
86
  assert_file "app/views/#{scope}/registrations/edit.html.erb"
80
87
  assert_file "app/views/#{scope}/sessions/new.html.erb"
81
- assert_file "app/views/#{scope}/shared/_links.erb"
88
+ assert_file "app/views/#{scope}/shared/_links.html.erb"
82
89
  assert_file "app/views/#{scope}/unlocks/new.html.erb"
83
90
  end
84
91
 
@@ -1,24 +1,23 @@
1
1
  require 'test_helper'
2
2
 
3
- class DeviseHelperTest < ActionDispatch::IntegrationTest
3
+ class DeviseHelperTest < Devise::IntegrationTest
4
4
  setup do
5
- model_labels = { models: { user: "utilisateur" } }
6
-
7
- I18n.backend.store_translations :fr,
8
- {
5
+ model_labels = { models: { user: "the user" } }
6
+ translations = {
9
7
  errors: { messages: { not_saved: {
10
- one: "Erreur lors de l'enregistrement de '%{resource}': 1 erreur.",
11
- other: "Erreur lors de l'enregistrement de '%{resource}': %{count} erreurs."
8
+ one: "Can't save %{resource} because of 1 error",
9
+ other: "Can't save %{resource} because of %{count} errors",
12
10
  } } },
13
11
  activerecord: model_labels,
14
12
  mongoid: model_labels
15
13
  }
16
14
 
17
- I18n.locale = 'fr'
15
+ I18n.available_locales
16
+ I18n.backend.store_translations(:en, translations)
18
17
  end
19
18
 
20
19
  teardown do
21
- I18n.locale = 'en'
20
+ I18n.reload!
22
21
  end
23
22
 
24
23
  test 'test errors.messages.not_saved with single error from i18n' do
@@ -29,7 +28,7 @@ class DeviseHelperTest < ActionDispatch::IntegrationTest
29
28
  click_button 'Sign up'
30
29
 
31
30
  assert_have_selector '#error_explanation'
32
- assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 1 erreur"
31
+ assert_contain "Can't save the user because of 1 error"
33
32
  end
34
33
 
35
34
  test 'test errors.messages.not_saved with multiple errors from i18n' do
@@ -45,7 +44,6 @@ class DeviseHelperTest < ActionDispatch::IntegrationTest
45
44
  click_button 'Sign up'
46
45
 
47
46
  assert_have_selector '#error_explanation'
48
- assert_contain "Erreur lors de l'enregistrement de 'utilisateur': 2 erreurs"
47
+ assert_contain "Can't save the user because of 2 errors"
49
48
  end
50
49
  end
51
-