Froze rails gems
[depot.git] / vendor / rails / actionpack / test / controller / request_forgery_protection_test.rb
1 require 'abstract_unit'
2 require 'digest/sha1'
3
4 ActionController::Routing::Routes.draw do |map|
5 map.connect ':controller/:action/:id'
6 end
7
8 # simulates cookie session store
9 class FakeSessionDbMan
10 def self.generate_digest(data)
11 Digest::SHA1.hexdigest("secure")
12 end
13 end
14
15 # common controller actions
16 module RequestForgeryProtectionActions
17 def index
18 render :inline => "<%= form_tag('/') {} %>"
19 end
20
21 def show_button
22 render :inline => "<%= button_to('New', '/') {} %>"
23 end
24
25 def remote_form
26 render :inline => "<% form_remote_tag(:url => '/') {} %>"
27 end
28
29 def unsafe
30 render :text => 'pwn'
31 end
32
33 def rescue_action(e) raise e end
34 end
35
36 # sample controllers
37 class RequestForgeryProtectionController < ActionController::Base
38 include RequestForgeryProtectionActions
39 protect_from_forgery :only => :index, :secret => 'abc'
40 end
41
42 class RequestForgeryProtectionWithoutSecretController < ActionController::Base
43 include RequestForgeryProtectionActions
44 protect_from_forgery
45 end
46
47 # no token is given, assume the cookie store is used
48 class CsrfCookieMonsterController < ActionController::Base
49 include RequestForgeryProtectionActions
50 protect_from_forgery :only => :index
51 end
52
53 # sessions are turned off
54 class SessionOffController < ActionController::Base
55 protect_from_forgery :secret => 'foobar'
56 session :off
57 def rescue_action(e) raise e end
58 include RequestForgeryProtectionActions
59 end
60
61 class FreeCookieController < CsrfCookieMonsterController
62 self.allow_forgery_protection = false
63
64 def index
65 render :inline => "<%= form_tag('/') {} %>"
66 end
67
68 def show_button
69 render :inline => "<%= button_to('New', '/') {} %>"
70 end
71 end
72
73 # common test methods
74
75 module RequestForgeryProtectionTests
76 def teardown
77 ActionController::Base.request_forgery_protection_token = nil
78 end
79
80
81 def test_should_render_form_with_token_tag
82 get :index
83 assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
84 end
85
86 def test_should_render_button_to_with_token_tag
87 get :show_button
88 assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
89 end
90
91 def test_should_render_remote_form_with_only_one_token_parameter
92 get :remote_form
93 assert_equal 1, @response.body.scan(@token).size
94 end
95
96 def test_should_allow_get
97 get :index
98 assert_response :success
99 end
100
101 def test_should_allow_post_without_token_on_unsafe_action
102 post :unsafe
103 assert_response :success
104 end
105
106 def test_should_not_allow_html_post_without_token
107 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
108 assert_raises(ActionController::InvalidAuthenticityToken) { post :index, :format => :html }
109 end
110
111 def test_should_not_allow_html_put_without_token
112 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
113 assert_raises(ActionController::InvalidAuthenticityToken) { put :index, :format => :html }
114 end
115
116 def test_should_not_allow_html_delete_without_token
117 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
118 assert_raises(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html }
119 end
120
121 def test_should_allow_api_formatted_post_without_token
122 assert_nothing_raised do
123 post :index, :format => 'xml'
124 end
125 end
126
127 def test_should_not_allow_api_formatted_put_without_token
128 assert_nothing_raised do
129 put :index, :format => 'xml'
130 end
131 end
132
133 def test_should_allow_api_formatted_delete_without_token
134 assert_nothing_raised do
135 delete :index, :format => 'xml'
136 end
137 end
138
139 def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
140 assert_raises(ActionController::InvalidAuthenticityToken) do
141 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
142 post :index, :format => 'xml'
143 end
144 end
145
146 def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
147 assert_raises(ActionController::InvalidAuthenticityToken) do
148 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
149 put :index, :format => 'xml'
150 end
151 end
152
153 def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
154 assert_raises(ActionController::InvalidAuthenticityToken) do
155 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
156 delete :index, :format => 'xml'
157 end
158 end
159
160 def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
161 assert_raises(ActionController::InvalidAuthenticityToken) do
162 @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
163 post :index, :format => 'xml'
164 end
165 end
166
167 def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
168 assert_raises(ActionController::InvalidAuthenticityToken) do
169 @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
170 put :index, :format => 'xml'
171 end
172 end
173
174 def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
175 assert_raises(ActionController::InvalidAuthenticityToken) do
176 @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
177 delete :index, :format => 'xml'
178 end
179 end
180
181 def test_should_allow_xhr_post_without_token
182 assert_nothing_raised { xhr :post, :index }
183 end
184 def test_should_not_allow_xhr_post_with_html_without_token
185 @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
186 assert_raise(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
187 end
188
189 def test_should_allow_xhr_put_without_token
190 assert_nothing_raised { xhr :put, :index }
191 end
192
193 def test_should_allow_xhr_delete_without_token
194 assert_nothing_raised { xhr :delete, :index }
195 end
196
197 def test_should_allow_post_with_token
198 post :index, :authenticity_token => @token
199 assert_response :success
200 end
201
202 def test_should_allow_put_with_token
203 put :index, :authenticity_token => @token
204 assert_response :success
205 end
206
207 def test_should_allow_delete_with_token
208 delete :index, :authenticity_token => @token
209 assert_response :success
210 end
211
212 def test_should_allow_post_with_xml
213 @request.env['CONTENT_TYPE'] = Mime::XML.to_s
214 post :index, :format => 'xml'
215 assert_response :success
216 end
217
218 def test_should_allow_put_with_xml
219 @request.env['CONTENT_TYPE'] = Mime::XML.to_s
220 put :index, :format => 'xml'
221 assert_response :success
222 end
223
224 def test_should_allow_delete_with_xml
225 @request.env['CONTENT_TYPE'] = Mime::XML.to_s
226 delete :index, :format => 'xml'
227 assert_response :success
228 end
229 end
230
231 # OK let's get our test on
232
233 class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
234 include RequestForgeryProtectionTests
235 def setup
236 @controller = RequestForgeryProtectionController.new
237 @request = ActionController::TestRequest.new
238 @request.format = :html
239 @response = ActionController::TestResponse.new
240 class << @request.session
241 def session_id() '123' end
242 end
243 @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
244 ActionController::Base.request_forgery_protection_token = :authenticity_token
245 end
246 end
247
248 class RequestForgeryProtectionWithoutSecretControllerTest < Test::Unit::TestCase
249 def setup
250 @controller = RequestForgeryProtectionWithoutSecretController.new
251 @request = ActionController::TestRequest.new
252 @response = ActionController::TestResponse.new
253 class << @request.session
254 def session_id() '123' end
255 end
256 @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
257 ActionController::Base.request_forgery_protection_token = :authenticity_token
258 end
259
260 # def test_should_raise_error_without_secret
261 # assert_raises ActionController::InvalidAuthenticityToken do
262 # get :index
263 # end
264 # end
265 end
266
267 class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
268 include RequestForgeryProtectionTests
269 def setup
270 @controller = CsrfCookieMonsterController.new
271 @request = ActionController::TestRequest.new
272 @response = ActionController::TestResponse.new
273 class << @request.session
274 attr_accessor :dbman
275 end
276 # simulate a cookie session store
277 @request.session.dbman = FakeSessionDbMan
278 @token = Digest::SHA1.hexdigest("secure")
279 ActionController::Base.request_forgery_protection_token = :authenticity_token
280 end
281 end
282
283 class FreeCookieControllerTest < Test::Unit::TestCase
284 def setup
285 @controller = FreeCookieController.new
286 @request = ActionController::TestRequest.new
287 @response = ActionController::TestResponse.new
288 @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
289 end
290
291 def test_should_not_render_form_with_token_tag
292 get :index
293 assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
294 end
295
296 def test_should_not_render_button_to_with_token_tag
297 get :show_button
298 assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token, false
299 end
300
301 def test_should_allow_all_methods_without_token
302 [:post, :put, :delete].each do |method|
303 assert_nothing_raised { send(method, :index)}
304 end
305 end
306 end
307
308 class SessionOffControllerTest < Test::Unit::TestCase
309 def setup
310 @controller = SessionOffController.new
311 @request = ActionController::TestRequest.new
312 @response = ActionController::TestResponse.new
313 @token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
314 end
315
316 # TODO: Rewrite this test.
317 # This test was passing but for the wrong reason.
318 # Sessions aren't really being turned off, so an exception was raised
319 # because sessions weren't on - not because the token didn't match.
320 #
321 # def test_should_raise_correct_exception
322 # @request.session = {} # session(:off) doesn't appear to work with controller tests
323 # assert_raises(ActionController::InvalidAuthenticityToken) do
324 # post :index, :authenticity_token => @token, :format => :html
325 # end
326 # end
327 end