21700: Install Bundler system-wide in Rails postinst
[arvados.git] / services / api / test / integration / cross_origin_test.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: AGPL-3.0
4
5 require 'test_helper'
6
7 class CrossOriginTest < ActionDispatch::IntegrationTest
8   def options path, **kwargs
9     # Rails doesn't support OPTIONS the same way as GET, POST, etc.
10     reset! unless integration_session
11     integration_session.__send__(:process, :options, path, **kwargs).tap do
12       copy_session_variables!
13     end
14   end
15
16   %w(/login /logout /auth/example/callback /auth/joshid).each do |path|
17     test "OPTIONS requests are refused at #{path}" do
18       options path, params: {}, headers: {}
19       assert_no_cors_headers
20     end
21
22     test "CORS headers do not exist at GET #{path}" do
23       get path, params: {}, headers: {}
24       assert_no_cors_headers
25     end
26   end
27
28   %w(/discovery/v1/apis/arvados/v1/rest).each do |path|
29     test "CORS headers are set at GET #{path}" do
30       get path, params: {}, headers: {}
31       assert_response :success
32       assert_cors_headers
33     end
34   end
35
36   ['/arvados/v1/collections',
37    '/arvados/v1/users',
38    '/arvados/v1/api_client_authorizations'].each do |path|
39     test "CORS headers are set and body is empty at OPTIONS #{path}" do
40       options path, params: {}, headers: {}
41       assert_response :success
42       assert_cors_headers
43       assert_equal '', response.body
44     end
45
46     test "CORS headers are set at authenticated GET #{path}" do
47       get path, params: {}, headers: auth(:active_trustedclient)
48       assert_response :success
49       assert_cors_headers
50     end
51
52     # CORS headers are OK only if cookies are *not* used to determine
53     # whether a transaction is allowed. The following is a (far from
54     # perfect) test that the usual Rails cookie->session mechanism
55     # does not grant access to any resources.
56     ['GET', 'POST'].each do |method|
57       test "Session does not work at #{method} #{path}" do
58         send method.downcase, path, params: {format: 'json'}, headers: {user_id: 1}
59         assert_response 401
60         assert_cors_headers
61       end
62     end
63   end
64
65   protected
66   def assert_cors_headers
67     assert_equal '*', response.headers['Access-Control-Allow-Origin']
68     allowed = response.headers['Access-Control-Allow-Methods'].split(', ')
69     %w(GET HEAD POST PUT DELETE).each do |m|
70       assert_includes allowed, m, "A-C-A-Methods should include #{m}"
71     end
72     assert_equal 'Authorization, Content-Type', response.headers['Access-Control-Allow-Headers']
73   end
74
75   def assert_no_cors_headers
76     response.headers.keys.each do |h|
77       assert_no_match(/^Access-Control-/i, h)
78     end
79   end
80 end