devise 1.1.3 → 1.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.
Files changed (157) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.rdoc +94 -0
  4. data/Gemfile +24 -13
  5. data/Gemfile.lock +119 -75
  6. data/MIT-LICENSE +1 -1
  7. data/README.rdoc +144 -101
  8. data/Rakefile +3 -24
  9. data/app/controllers/devise/confirmations_controller.rb +1 -1
  10. data/app/controllers/devise/omniauth_callbacks_controller.rb +26 -0
  11. data/app/controllers/devise/passwords_controller.rb +1 -1
  12. data/app/controllers/devise/registrations_controller.rb +60 -7
  13. data/app/controllers/devise/sessions_controller.rb +6 -4
  14. data/app/controllers/devise/unlocks_controller.rb +1 -1
  15. data/app/helpers/devise_helper.rb +10 -2
  16. data/app/mailers/devise/mailer.rb +27 -10
  17. data/app/views/devise/confirmations/new.html.erb +1 -1
  18. data/app/views/devise/passwords/edit.html.erb +2 -2
  19. data/app/views/devise/passwords/new.html.erb +1 -1
  20. data/app/views/devise/registrations/edit.html.erb +1 -1
  21. data/app/views/devise/registrations/new.html.erb +1 -1
  22. data/app/views/devise/sessions/new.html.erb +1 -1
  23. data/app/views/devise/shared/_links.erb +6 -0
  24. data/app/views/devise/unlocks/new.html.erb +1 -1
  25. data/config/locales/en.yml +11 -2
  26. data/devise.gemspec +25 -0
  27. data/lib/devise/controllers/helpers.rb +119 -116
  28. data/lib/devise/controllers/internal_helpers.rb +29 -8
  29. data/lib/devise/controllers/rememberable.rb +52 -0
  30. data/lib/devise/controllers/scoped_views.rb +4 -6
  31. data/lib/devise/controllers/url_helpers.rb +3 -5
  32. data/lib/devise/encryptors/authlogic_sha512.rb +1 -1
  33. data/lib/devise/encryptors/base.rb +1 -1
  34. data/lib/devise/encryptors/restful_authentication_sha1.rb +4 -4
  35. data/lib/devise/failure_app.rb +46 -10
  36. data/lib/devise/hooks/activatable.rb +2 -2
  37. data/lib/devise/hooks/forgetable.rb +1 -3
  38. data/lib/devise/hooks/rememberable.rb +5 -42
  39. data/lib/devise/hooks/timeoutable.rb +1 -1
  40. data/lib/devise/mapping.rb +18 -7
  41. data/lib/devise/models/authenticatable.rb +73 -31
  42. data/lib/devise/models/confirmable.rb +16 -20
  43. data/lib/devise/models/database_authenticatable.rb +27 -37
  44. data/lib/devise/models/encryptable.rb +72 -0
  45. data/lib/devise/models/lockable.rb +27 -21
  46. data/lib/devise/models/omniauthable.rb +23 -0
  47. data/lib/devise/models/recoverable.rb +13 -3
  48. data/lib/devise/models/registerable.rb +13 -0
  49. data/lib/devise/models/rememberable.rb +39 -34
  50. data/lib/devise/models/timeoutable.rb +20 -3
  51. data/lib/devise/models/token_authenticatable.rb +22 -10
  52. data/lib/devise/models/validatable.rb +16 -4
  53. data/lib/devise/models.rb +4 -16
  54. data/lib/devise/modules.rb +15 -8
  55. data/lib/devise/omniauth/config.rb +18 -0
  56. data/lib/devise/omniauth/url_helpers.rb +33 -0
  57. data/lib/devise/omniauth.rb +32 -0
  58. data/lib/devise/orm/active_record.rb +2 -0
  59. data/lib/devise/orm/mongoid.rb +4 -2
  60. data/lib/devise/rails/routes.rb +67 -20
  61. data/lib/devise/rails/warden_compat.rb +101 -15
  62. data/lib/devise/rails.rb +33 -44
  63. data/lib/devise/schema.rb +16 -16
  64. data/lib/devise/strategies/authenticatable.rb +48 -7
  65. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  66. data/lib/devise/strategies/rememberable.rb +6 -5
  67. data/lib/devise/strategies/token_authenticatable.rb +6 -2
  68. data/lib/devise/test_helpers.rb +13 -3
  69. data/lib/devise/version.rb +1 -1
  70. data/lib/devise.rb +162 -50
  71. data/lib/generators/active_record/devise_generator.rb +2 -2
  72. data/lib/generators/active_record/templates/migration.rb +2 -0
  73. data/lib/generators/devise/devise_generator.rb +3 -1
  74. data/lib/generators/devise/orm_helpers.rb +1 -1
  75. data/lib/generators/devise/views_generator.rb +8 -45
  76. data/lib/generators/mongoid/devise_generator.rb +2 -2
  77. data/lib/generators/templates/devise.rb +82 -39
  78. data/test/controllers/helpers_test.rb +78 -72
  79. data/test/controllers/internal_helpers_test.rb +29 -8
  80. data/test/controllers/url_helpers_test.rb +2 -1
  81. data/test/devise_test.rb +10 -0
  82. data/test/failure_app_test.rb +86 -22
  83. data/test/generators/active_record_generator_test.rb +24 -0
  84. data/test/generators/devise_generator_test.rb +33 -0
  85. data/test/generators/install_generator_test.rb +13 -0
  86. data/test/generators/mongoid_generator_test.rb +22 -0
  87. data/test/generators/views_generator_test.rb +35 -0
  88. data/test/indifferent_hash.rb +33 -0
  89. data/test/integration/authenticatable_test.rb +165 -62
  90. data/test/integration/database_authenticatable_test.rb +22 -0
  91. data/test/integration/http_authenticatable_test.rb +12 -2
  92. data/test/integration/omniauthable_test.rb +138 -0
  93. data/test/integration/recoverable_test.rb +39 -20
  94. data/test/integration/registerable_test.rb +60 -4
  95. data/test/integration/rememberable_test.rb +72 -29
  96. data/test/integration/timeoutable_test.rb +10 -1
  97. data/test/integration/token_authenticatable_test.rb +55 -6
  98. data/test/mailers/confirmation_instructions_test.rb +4 -0
  99. data/test/mailers/reset_password_instructions_test.rb +4 -0
  100. data/test/mailers/unlock_instructions_test.rb +4 -0
  101. data/test/mapping_test.rb +37 -3
  102. data/test/models/confirmable_test.rb +32 -15
  103. data/test/models/database_authenticatable_test.rb +14 -71
  104. data/test/models/encryptable_test.rb +65 -0
  105. data/test/models/lockable_test.rb +48 -11
  106. data/test/models/recoverable_test.rb +28 -2
  107. data/test/models/rememberable_test.rb +186 -125
  108. data/test/models/token_authenticatable_test.rb +19 -1
  109. data/test/models_test.rb +12 -5
  110. data/test/omniauth/url_helpers_test.rb +54 -0
  111. data/test/orm/mongoid.rb +3 -2
  112. data/test/rails_app/Rakefile +10 -0
  113. data/test/rails_app/app/active_record/admin.rb +4 -1
  114. data/test/rails_app/app/active_record/user.rb +5 -4
  115. data/test/rails_app/app/controllers/{sessions_controller.rb → admins/sessions_controller.rb} +1 -1
  116. data/test/rails_app/app/controllers/application_controller.rb +0 -1
  117. data/test/rails_app/app/controllers/home_controller.rb +9 -0
  118. data/test/rails_app/app/controllers/users/omniauth_callbacks_controller.rb +14 -0
  119. data/test/rails_app/app/mongoid/admin.rb +4 -1
  120. data/test/rails_app/app/mongoid/shim.rb +16 -3
  121. data/test/rails_app/app/mongoid/user.rb +5 -5
  122. data/test/rails_app/app/views/admins/index.html.erb +1 -0
  123. data/test/rails_app/app/views/admins/sessions/new.html.erb +2 -0
  124. data/test/rails_app/app/views/home/index.html.erb +1 -0
  125. data/test/rails_app/app/views/home/private.html.erb +1 -0
  126. data/test/rails_app/app/views/layouts/application.html.erb +24 -0
  127. data/test/rails_app/app/views/users/index.html.erb +1 -0
  128. data/test/rails_app/app/views/users/mailer/confirmation_instructions.erb +1 -0
  129. data/test/rails_app/app/views/users/sessions/new.html.erb +1 -0
  130. data/test/rails_app/config/application.rb +5 -0
  131. data/test/rails_app/config/boot.rb +2 -2
  132. data/test/rails_app/config/database.yml +18 -0
  133. data/test/rails_app/config/initializers/devise.rb +71 -31
  134. data/test/rails_app/config/routes.rb +14 -6
  135. data/test/rails_app/config.ru +4 -0
  136. data/test/rails_app/db/migrate/20100401102949_create_tables.rb +21 -17
  137. data/test/rails_app/db/schema.rb +17 -51
  138. data/test/rails_app/lib/shared_admin.rb +9 -0
  139. data/test/rails_app/lib/shared_user.rb +23 -0
  140. data/test/rails_app/public/404.html +26 -0
  141. data/test/rails_app/public/422.html +26 -0
  142. data/test/rails_app/public/500.html +26 -0
  143. data/test/rails_app/public/favicon.ico +0 -0
  144. data/test/rails_app/script/rails +10 -0
  145. data/test/routes_test.rb +42 -9
  146. data/test/schema_test.rb +33 -0
  147. data/test/support/integration.rb +4 -4
  148. data/test/support/locale/en.yml +4 -0
  149. data/test/support/webrat/integrations/rails.rb +11 -19
  150. data/test/test_helper.rb +8 -2
  151. data/test/test_helpers_test.rb +64 -2
  152. metadata +106 -30
  153. data/TODO +0 -3
  154. data/lib/devise/encryptors/bcrypt.rb +0 -19
  155. data/lib/generators/devise_install_generator.rb +0 -4
  156. data/lib/generators/devise_views_generator.rb +0 -4
  157. data/test/support/test_silencer.rb +0 -5
@@ -13,11 +13,11 @@ class FailureTest < ActiveSupport::TestCase
13
13
  'REQUEST_METHOD' => 'GET',
14
14
  'warden.options' => { :scope => :user },
15
15
  'rack.session' => {},
16
- 'action_dispatch.request.formats' => Array(env_params.delete('formats') || :html),
16
+ 'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime::HTML),
17
17
  'rack.input' => "",
18
18
  'warden' => OpenStruct.new(:message => nil)
19
19
  }.merge!(env_params)
20
-
20
+
21
21
  @response = Devise::FailureApp.call(env).to_a
22
22
  @request = ActionDispatch::Request.new(env)
23
23
  end
@@ -28,6 +28,11 @@ class FailureTest < ActiveSupport::TestCase
28
28
  assert_equal 302, @response.first
29
29
  end
30
30
 
31
+ test 'return 302 status for wildcard requests' do
32
+ call_failure 'action_dispatch.request.formats' => nil, 'HTTP_ACCEPT' => '*/*'
33
+ assert_equal 302, @response.first
34
+ end
35
+
31
36
  test 'return to the default redirect location' do
32
37
  call_failure
33
38
  assert_equal 'You need to sign in or sign up before continuing.', @request.flash[:alert]
@@ -64,6 +69,13 @@ class FailureTest < ActiveSupport::TestCase
64
69
  assert_equal 302, @response.first
65
70
  end
66
71
  end
72
+
73
+ test 'redirects the correct format if it is a non-html format request' do
74
+ swap Devise, :navigational_formats => [:js] do
75
+ call_failure('formats' => :js)
76
+ assert_equal 'http://test.host/users/sign_in.js', @response.second["Location"]
77
+ end
78
+ end
67
79
  end
68
80
 
69
81
  context 'For HTTP request' do
@@ -72,46 +84,76 @@ class FailureTest < ActiveSupport::TestCase
72
84
  assert_equal 401, @response.first
73
85
  end
74
86
 
75
- test 'return WWW-authenticate headers' do
87
+ test 'return 401 status for unknown formats' do
88
+ call_failure 'formats' => []
89
+ assert_equal 401, @response.first
90
+ end
91
+
92
+ test 'return WWW-authenticate headers if model allows' do
76
93
  call_failure('formats' => :xml)
77
94
  assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
78
95
  end
79
96
 
80
- test 'dont return WWW-authenticate on ajax call if http_authenticatable_on_xhr false' do
81
- swap Devise, :http_authenticatable_on_xhr => false do
82
- call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
83
- assert_equal 302, @response.first
84
- assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
85
- assert_nil @response.second['WWW-Authenticate']
97
+ test 'does not return WWW-authenticate headers if model does not allow' do
98
+ swap Devise, :http_authenticatable => false do
99
+ call_failure('formats' => :xml)
100
+ assert_nil @response.second["WWW-Authenticate"]
86
101
  end
87
102
  end
88
103
 
89
- test 'return WWW-authenticate on ajax call if http_authenticatable_on_xhr true' do
90
- swap Devise, :http_authenticatable_on_xhr => true do
91
- call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
104
+ test 'works for any non navigational format' do
105
+ swap Devise, :navigational_formats => [] do
106
+ call_failure('formats' => :html)
92
107
  assert_equal 401, @response.first
93
- assert_equal 'Basic realm="Application"', @response.second["WWW-Authenticate"]
94
108
  end
95
109
  end
96
-
97
- test 'uses the proxy failure message as response body' do
110
+
111
+ test 'uses the failure message as response body' do
98
112
  call_failure('formats' => :xml, 'warden' => OpenStruct.new(:message => :invalid))
99
113
  assert_match '<error>Invalid email or password.</error>', @response.third.body
100
114
  end
101
115
 
102
- test 'works for any non navigational format' do
103
- swap Devise, :navigational_formats => [] do
104
- call_failure('formats' => :html)
105
- assert_equal 401, @response.first
116
+ context 'on ajax call' do
117
+ context 'when http_authenticatable_on_xhr is false' do
118
+ test 'dont return 401 with navigational formats' do
119
+ swap Devise, :http_authenticatable_on_xhr => false do
120
+ call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
121
+ assert_equal 302, @response.first
122
+ assert_equal 'http://test.host/users/sign_in', @response.second["Location"]
123
+ end
124
+ end
125
+
126
+ test 'dont return 401 with non navigational formats' do
127
+ swap Devise, :http_authenticatable_on_xhr => false do
128
+ call_failure('formats' => :json, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
129
+ assert_equal 302, @response.first
130
+ assert_equal 'http://test.host/users/sign_in.json', @response.second["Location"]
131
+ end
132
+ end
133
+ end
134
+
135
+ context 'when http_authenticatable_on_xhr is true' do
136
+ test 'return 401' do
137
+ swap Devise, :http_authenticatable_on_xhr => true do
138
+ call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
139
+ assert_equal 401, @response.first
140
+ end
141
+ end
142
+
143
+ test 'skip WWW-Authenticate header' do
144
+ swap Devise, :http_authenticatable_on_xhr => true do
145
+ call_failure('formats' => :html, 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest')
146
+ assert_nil @response.second['WWW-Authenticate']
147
+ end
148
+ end
106
149
  end
107
150
  end
108
151
  end
109
152
 
110
153
  context 'With recall' do
111
- test 'calls the original controller' do
154
+ test 'calls the original controller if invalid email or password' do
112
155
  env = {
113
- "action_dispatch.request.parameters" => { :controller => "devise/sessions" },
114
- "warden.options" => { :recall => "new", :attempted_path => "/users/sign_in" },
156
+ "warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in" },
115
157
  "devise.mapping" => Devise.mappings[:user],
116
158
  "warden" => stub_everything
117
159
  }
@@ -119,5 +161,27 @@ class FailureTest < ActiveSupport::TestCase
119
161
  assert @response.third.body.include?('<h2>Sign in</h2>')
120
162
  assert @response.third.body.include?('Invalid email or password.')
121
163
  end
164
+
165
+ test 'calls the original controller if not confirmed email' do
166
+ env = {
167
+ "warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :unconfirmed },
168
+ "devise.mapping" => Devise.mappings[:user],
169
+ "warden" => stub_everything
170
+ }
171
+ call_failure(env)
172
+ assert @response.third.body.include?('<h2>Sign in</h2>')
173
+ assert @response.third.body.include?('You have to confirm your account before continuing.')
174
+ end
175
+
176
+ test 'calls the original controller if inactive account' do
177
+ env = {
178
+ "warden.options" => { :recall => "devise/sessions#new", :attempted_path => "/users/sign_in", :message => :inactive },
179
+ "devise.mapping" => Devise.mappings[:user],
180
+ "warden" => stub_everything
181
+ }
182
+ call_failure(env)
183
+ assert @response.third.body.include?('<h2>Sign in</h2>')
184
+ assert @response.third.body.include?('Your account was not activated yet.')
185
+ end
122
186
  end
123
187
  end
@@ -0,0 +1,24 @@
1
+ require "test_helper"
2
+
3
+ if DEVISE_ORM == :active_record
4
+ require "generators/active_record/devise_generator"
5
+
6
+ class ActiveRecordGeneratorTest < Rails::Generators::TestCase
7
+ tests ActiveRecord::Generators::DeviseGenerator
8
+ destination File.expand_path("../../tmp", __FILE__)
9
+ setup :prepare_destination
10
+
11
+ test "all files are properly created" do
12
+ run_generator %w(monster)
13
+ assert_file "app/models/monster.rb", /devise/, /attr_accessible (:[a-z_]+(, )?)+/
14
+ assert_migration "db/migrate/devise_create_monsters.rb"
15
+ end
16
+
17
+ test "all files are properly deleted" do
18
+ run_generator %w(monster)
19
+ run_generator %w(monster), :behavior => :revoke
20
+ assert_no_file "app/models/monster.rb"
21
+ assert_no_migration "db/migrate/devise_create_monsters.rb"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ require "generators/devise/devise_generator"
4
+
5
+ class DeviseGeneratorTest < Rails::Generators::TestCase
6
+ tests Devise::Generators::DeviseGenerator
7
+ destination File.expand_path("../../tmp", __FILE__)
8
+
9
+ setup do
10
+ prepare_destination
11
+ copy_routes
12
+ end
13
+
14
+ test "route generation for simple model names" do
15
+ run_generator %w(monster name:string)
16
+ assert_file "config/routes.rb", /devise_for :monsters/
17
+ end
18
+
19
+ test "route generation for namespaced model names" do
20
+ run_generator %w(monster/goblin name:string)
21
+ match = /devise_for :goblins, :class_name => "Monster::Goblin"/
22
+ assert_file "config/routes.rb", match
23
+ end
24
+
25
+ def copy_routes
26
+ routes = File.expand_path("../../rails_app/config/routes.rb", __FILE__)
27
+ destination = File.join(destination_root, "config")
28
+
29
+ FileUtils.mkdir_p(destination)
30
+ FileUtils.cp routes, destination
31
+ end
32
+
33
+ end
@@ -0,0 +1,13 @@
1
+ require "test_helper"
2
+
3
+ class InstallGeneratorTest < Rails::Generators::TestCase
4
+ tests Devise::Generators::InstallGenerator
5
+ destination File.expand_path("../../tmp", __FILE__)
6
+ setup :prepare_destination
7
+
8
+ test "Assert all files are properly created" do
9
+ run_generator
10
+ assert_file "config/initializers/devise.rb"
11
+ assert_file "config/locales/devise.en.yml"
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ require "test_helper"
2
+
3
+ if DEVISE_ORM == :mongo_id
4
+ require "generators/mongo_id/devise_generator"
5
+
6
+ class MongoidGeneratorTest < Rails::Generators::TestCase
7
+ tests Mongoid::Generators::DeviseGenerator
8
+ destination File.expand_path("../../tmp", __FILE__)
9
+ setup :prepare_destination
10
+
11
+ test "all files are properly created" do
12
+ run_generator %w(monster)
13
+ assert_file "app/models/monster.rb", /devise/
14
+ end
15
+
16
+ test "all files are properly deleted" do
17
+ run_generator %w(monster)
18
+ run_generator %w(monster), :behavior => :revoke
19
+ assert_no_file "app/models/monster.rb"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ require "test_helper"
2
+
3
+ class ViewsGeneratorTest < Rails::Generators::TestCase
4
+ tests Devise::Generators::ViewsGenerator
5
+ destination File.expand_path("../../tmp", __FILE__)
6
+ setup :prepare_destination
7
+
8
+ test "Assert all views are properly created with no params" do
9
+ run_generator
10
+ assert_files
11
+ end
12
+
13
+ test "Assert all views are properly created with scope param param" do
14
+ run_generator %w(users)
15
+ assert_files "users"
16
+
17
+ run_generator %w(admins)
18
+ assert_files "admins"
19
+ end
20
+
21
+ def assert_files(scope = nil, template_engine = nil)
22
+ scope = "devise" if scope.nil?
23
+ assert_file "app/views/#{scope}/confirmations/new.html.erb"
24
+ assert_file "app/views/#{scope}/mailer/confirmation_instructions.html.erb"
25
+ assert_file "app/views/#{scope}/mailer/reset_password_instructions.html.erb"
26
+ assert_file "app/views/#{scope}/mailer/unlock_instructions.html.erb"
27
+ assert_file "app/views/#{scope}/passwords/edit.html.erb"
28
+ assert_file "app/views/#{scope}/passwords/new.html.erb"
29
+ assert_file "app/views/#{scope}/registrations/new.html.erb"
30
+ assert_file "app/views/#{scope}/registrations/edit.html.erb"
31
+ assert_file "app/views/#{scope}/sessions/new.html.erb"
32
+ assert_file "app/views/#{scope}/shared/_links.erb"
33
+ assert_file "app/views/#{scope}/unlocks/new.html.erb"
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ require 'test_helper'
2
+
3
+ class IndifferentHashTest < ActiveSupport::TestCase
4
+ setup do
5
+ @hash = Devise::IndifferentHash.new
6
+ end
7
+
8
+ test "it overwrites getter and setter" do
9
+ @hash[:foo] = "bar"
10
+ assert_equal "bar", @hash["foo"]
11
+ assert_equal "bar", @hash[:foo]
12
+
13
+ @hash["foo"] = "baz"
14
+ assert_equal "baz", @hash["foo"]
15
+ assert_equal "baz", @hash[:foo]
16
+ end
17
+
18
+ test "it overwrites update" do
19
+ @hash.update :foo => "bar"
20
+ assert_equal "bar", @hash["foo"]
21
+ assert_equal "bar", @hash[:foo]
22
+
23
+ @hash.update "foo" => "baz"
24
+ assert_equal "baz", @hash["foo"]
25
+ assert_equal "baz", @hash[:foo]
26
+ end
27
+
28
+ test "it returns a Hash on to_hash" do
29
+ @hash[:foo] = "bar"
30
+ assert_equal Hash["foo", "bar"], @hash.to_hash
31
+ assert_kind_of Hash, @hash.to_hash
32
+ end
33
+ end if defined?(Devise::IndifferentHash)
@@ -1,15 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class AuthenticationSanityTest < ActionController::IntegrationTest
4
-
5
- def setup
6
- Devise.sign_out_all_scopes = false
7
- end
8
-
9
- def teardown
10
- Devise.sign_out_all_scopes = false
11
- end
12
-
13
4
  test 'home should be accessible without sign in' do
14
5
  visit '/'
15
6
  assert_response :success
@@ -18,14 +9,12 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
18
9
 
19
10
  test 'sign in as user should not authenticate admin scope' do
20
11
  sign_in_as_user
21
-
22
12
  assert warden.authenticated?(:user)
23
13
  assert_not warden.authenticated?(:admin)
24
14
  end
25
15
 
26
16
  test 'sign in as admin should not authenticate user scope' do
27
17
  sign_in_as_admin
28
-
29
18
  assert warden.authenticated?(:admin)
30
19
  assert_not warden.authenticated?(:user)
31
20
  end
@@ -33,59 +22,61 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
33
22
  test 'sign in as both user and admin at same time' do
34
23
  sign_in_as_user
35
24
  sign_in_as_admin
36
-
37
25
  assert warden.authenticated?(:user)
38
26
  assert warden.authenticated?(:admin)
39
27
  end
40
28
 
41
29
  test 'sign out as user should not touch admin authentication if sign_out_all_scopes is false' do
42
- sign_in_as_user
43
- sign_in_as_admin
44
-
45
- get destroy_user_session_path
46
- assert_not warden.authenticated?(:user)
47
- assert warden.authenticated?(:admin)
30
+ swap Devise, :sign_out_all_scopes => false do
31
+ sign_in_as_user
32
+ sign_in_as_admin
33
+ get destroy_user_session_path
34
+ assert_not warden.authenticated?(:user)
35
+ assert warden.authenticated?(:admin)
36
+ end
48
37
  end
49
38
 
50
39
  test 'sign out as admin should not touch user authentication if sign_out_all_scopes is false' do
51
- sign_in_as_user
52
- sign_in_as_admin
40
+ swap Devise, :sign_out_all_scopes => false do
41
+ sign_in_as_user
42
+ sign_in_as_admin
53
43
 
54
- get destroy_admin_session_path
55
- assert_not warden.authenticated?(:admin)
56
- assert warden.authenticated?(:user)
44
+ get destroy_admin_session_path
45
+ assert_not warden.authenticated?(:admin)
46
+ assert warden.authenticated?(:user)
47
+ end
57
48
  end
58
49
 
59
50
  test 'sign out as user should also sign out admin if sign_out_all_scopes is true' do
60
- Devise.sign_out_all_scopes = true
61
- sign_in_as_user
62
- sign_in_as_admin
51
+ swap Devise, :sign_out_all_scopes => true do
52
+ sign_in_as_user
53
+ sign_in_as_admin
63
54
 
64
- get destroy_user_session_path
65
- assert_not warden.authenticated?(:user)
66
- assert_not warden.authenticated?(:admin)
55
+ get destroy_user_session_path
56
+ assert_not warden.authenticated?(:user)
57
+ assert_not warden.authenticated?(:admin)
58
+ end
67
59
  end
68
60
 
69
61
  test 'sign out as admin should also sign out user if sign_out_all_scopes is true' do
70
- Devise.sign_out_all_scopes = true
71
- sign_in_as_user
72
- sign_in_as_admin
62
+ swap Devise, :sign_out_all_scopes => true do
63
+ sign_in_as_user
64
+ sign_in_as_admin
73
65
 
74
- get destroy_admin_session_path
75
- assert_not warden.authenticated?(:admin)
76
- assert_not warden.authenticated?(:user)
66
+ get destroy_admin_session_path
67
+ assert_not warden.authenticated?(:admin)
68
+ assert_not warden.authenticated?(:user)
69
+ end
77
70
  end
78
71
 
79
72
  test 'not signed in as admin should not be able to access admins actions' do
80
73
  get admins_path
81
-
82
74
  assert_redirected_to new_admin_session_path
83
75
  assert_not warden.authenticated?(:admin)
84
76
  end
85
77
 
86
78
  test 'not signed in as admin should not be able to access private route restricted to admins' do
87
79
  get private_path
88
-
89
80
  assert_redirected_to new_admin_session_path
90
81
  assert_not warden.authenticated?(:admin)
91
82
  end
@@ -94,7 +85,6 @@ class AuthenticationSanityTest < ActionController::IntegrationTest
94
85
  sign_in_as_user
95
86
  assert warden.authenticated?(:user)
96
87
  assert_not warden.authenticated?(:admin)
97
-
98
88
  get private_path
99
89
  assert_redirected_to new_admin_session_path
100
90
  end
@@ -215,6 +205,13 @@ class AuthenticationRedirectTest < ActionController::IntegrationTest
215
205
  assert_nil session[:"user_return_to"]
216
206
  end
217
207
 
208
+ test 'sign in with xml format returns xml response' do
209
+ create_user
210
+ post user_session_path(:format => 'xml', :user => {:email => "user@test.com", :password => '123456'})
211
+ assert_response :success
212
+ assert_match /<\?xml version="1.0" encoding="UTF-8"\?>/, response.body
213
+ end
214
+
218
215
  test 'redirect to configured home path for a given scope after sign in' do
219
216
  sign_in_as_admin
220
217
  assert_equal "/admin_area/home", @request.path
@@ -236,6 +233,36 @@ class AuthenticationSessionTest < ActionController::IntegrationTest
236
233
  get '/users'
237
234
  assert_equal "Cart", @controller.user_session[:cart]
238
235
  end
236
+
237
+ test 'does not explode when invalid user class is stored in session' do
238
+ klass = User
239
+ paths = ActiveSupport::Dependencies.autoload_paths.dup
240
+
241
+ begin
242
+ sign_in_as_user
243
+ assert warden.authenticated?(:user)
244
+
245
+ Object.send :remove_const, :User
246
+ ActiveSupport::Dependencies.autoload_paths.clear
247
+
248
+ visit "/users"
249
+ assert_not warden.authenticated?(:user)
250
+ ensure
251
+ Object.const_set(:User, klass)
252
+ ActiveSupport::Dependencies.autoload_paths.replace(paths)
253
+ end
254
+ end
255
+
256
+ test 'session id is changed on sign in' do
257
+ get '/users'
258
+ session_id = request.session["session_id"]
259
+
260
+ get '/users'
261
+ assert_equal session_id, request.session["session_id"]
262
+
263
+ sign_in_as_user
264
+ assert_not_equal session_id, request.session["session_id"]
265
+ end
239
266
  end
240
267
 
241
268
  class AuthenticationWithScopesTest < ActionController::IntegrationTest
@@ -277,25 +304,13 @@ class AuthenticationWithScopesTest < ActionController::IntegrationTest
277
304
  end
278
305
  end
279
306
  end
280
-
281
- test 'uses the mapping from router' do
282
- sign_in_as_user :visit => "/as/sign_in"
283
- assert warden.authenticated?(:user)
284
- assert_not warden.authenticated?(:admin)
285
- end
286
-
287
- test 'uses the mapping from nested devise_for call' do
288
- sign_in_as_user :visit => "/devise_for/sign_in"
289
- assert warden.authenticated?(:user)
290
- assert_not warden.authenticated?(:admin)
291
- end
292
307
  end
293
308
 
294
309
  class AuthenticationOthersTest < ActionController::IntegrationTest
295
310
  test 'uses the custom controller with the custom controller view' do
296
311
  get '/admin_area/sign_in'
297
312
  assert_contain 'Sign in'
298
- assert_contain 'Welcome to "sessions" controller!'
313
+ assert_contain 'Welcome to "admins/sessions" controller!'
299
314
  assert_contain 'Welcome to "sessions/new" view!'
300
315
  end
301
316
 
@@ -304,6 +319,11 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
304
319
  assert_equal 404, response.status
305
320
  end
306
321
 
322
+ test 'does not intercept Rails 401 responses' do
323
+ get '/unauthenticated'
324
+ assert_equal 401, response.status
325
+ end
326
+
307
327
  test 'render 404 on roles without mapping' do
308
328
  assert_raise AbstractController::ActionNotFound do
309
329
  get '/sign_in'
@@ -317,28 +337,111 @@ class AuthenticationOthersTest < ActionController::IntegrationTest
317
337
  end
318
338
  end
319
339
 
320
- test 'registration in xml format' do
340
+ test 'registration in xml format works when recognizing path' do
321
341
  assert_nothing_raised do
322
342
  post user_registration_path(:format => 'xml', :user => {:email => "test@example.com", :password => "invalid"} )
323
343
  end
324
344
  end
325
345
 
326
- test 'does not explode when invalid user class is stored in session' do
327
- klass = User
328
- paths = ActiveSupport::Dependencies.autoload_paths.dup
346
+ test 'uses the mapping from router' do
347
+ sign_in_as_user :visit => "/as/sign_in"
348
+ assert warden.authenticated?(:user)
349
+ assert_not warden.authenticated?(:admin)
350
+ end
329
351
 
330
- begin
352
+ test 'uses the mapping from nested devise_for call' do
353
+ sign_in_as_user :visit => "/devise_for/sign_in"
354
+ assert warden.authenticated?(:user)
355
+ assert_not warden.authenticated?(:admin)
356
+ end
357
+ end
358
+
359
+ class AuthenticationRequestKeysTest < ActionController::IntegrationTest
360
+ test 'request keys are used on authentication' do
361
+ host! 'foo.bar.baz'
362
+
363
+ swap Devise, :request_keys => [:subdomain] do
364
+ User.expects(:find_for_authentication).with(:subdomain => 'foo', :email => 'user@test.com').returns(create_user)
331
365
  sign_in_as_user
332
366
  assert warden.authenticated?(:user)
367
+ end
368
+ end
333
369
 
334
- Object.send :remove_const, :User
335
- ActiveSupport::Dependencies.autoload_paths.clear
370
+ test 'invalid request keys raises NoMethodError' do
371
+ swap Devise, :request_keys => [:unknown_method] do
372
+ assert_raise NoMethodError do
373
+ sign_in_as_user
374
+ end
336
375
 
337
- visit "/users"
338
376
  assert_not warden.authenticated?(:user)
339
- ensure
340
- Object.const_set(:User, klass)
341
- ActiveSupport::Dependencies.autoload_paths.replace(paths)
342
377
  end
343
378
  end
379
+
380
+ test 'blank request keys cause authentication to abort' do
381
+ host! 'test.com'
382
+
383
+ swap Devise, :request_keys => [:subdomain] do
384
+ sign_in_as_user
385
+ assert_contain "Invalid email or password."
386
+ assert_not warden.authenticated?(:user)
387
+ end
388
+ end
389
+
390
+ test 'blank request keys cause authentication to abort unless if marked as not required' do
391
+ host! 'test.com'
392
+
393
+ swap Devise, :request_keys => { :subdomain => false } do
394
+ sign_in_as_user
395
+ assert warden.authenticated?(:user)
396
+ end
397
+ end
398
+ end
399
+
400
+ class AuthenticationSignOutViaTest < ActionController::IntegrationTest
401
+ def sign_in!(scope)
402
+ sign_in_as_admin(:visit => send("new_#{scope}_session_path"))
403
+ assert warden.authenticated?(scope)
404
+ end
405
+
406
+ test 'allow sign out via delete when sign_out_via provides only delete' do
407
+ sign_in!(:sign_out_via_delete)
408
+ delete destroy_sign_out_via_delete_session_path
409
+ assert_not warden.authenticated?(:sign_out_via_delete)
410
+ end
411
+
412
+ test 'do not allow sign out via get when sign_out_via provides only delete' do
413
+ sign_in!(:sign_out_via_delete)
414
+ get destroy_sign_out_via_delete_session_path
415
+ assert warden.authenticated?(:sign_out_via_delete)
416
+ end
417
+
418
+ test 'allow sign out via post when sign_out_via provides only post' do
419
+ sign_in!(:sign_out_via_post)
420
+ post destroy_sign_out_via_post_session_path
421
+ assert_not warden.authenticated?(:sign_out_via_post)
422
+ end
423
+
424
+ test 'do not allow sign out via get when sign_out_via provides only post' do
425
+ sign_in!(:sign_out_via_post)
426
+ get destroy_sign_out_via_delete_session_path
427
+ assert warden.authenticated?(:sign_out_via_post)
428
+ end
429
+
430
+ test 'allow sign out via delete when sign_out_via provides delete and post' do
431
+ sign_in!(:sign_out_via_delete_or_post)
432
+ delete destroy_sign_out_via_delete_or_post_session_path
433
+ assert_not warden.authenticated?(:sign_out_via_delete_or_post)
434
+ end
435
+
436
+ test 'allow sign out via post when sign_out_via provides delete and post' do
437
+ sign_in!(:sign_out_via_delete_or_post)
438
+ post destroy_sign_out_via_delete_or_post_session_path
439
+ assert_not warden.authenticated?(:sign_out_via_delete_or_post)
440
+ end
441
+
442
+ test 'do not allow sign out via get when sign_out_via provides delete and post' do
443
+ sign_in!(:sign_out_via_delete_or_post)
444
+ get destroy_sign_out_via_delete_or_post_session_path
445
+ assert warden.authenticated?(:sign_out_via_delete_or_post)
446
+ end
344
447
  end