Merge branch 'master' into 13822-nm-delayed-daemon
[arvados.git] / services / api / test / integration / user_sessions_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 UserSessionsApiTest < ActionDispatch::IntegrationTest
8   def client_url
9     'https://wb.example.com'
10   end
11
12   def mock_auth_with(email: nil, username: nil, identity_url: nil)
13     mock = {
14       'provider' => 'josh_id',
15       'uid' => 'https://edward.example.com',
16       'info' => {
17         'identity_url' => 'https://edward.example.com',
18         'name' => 'Edward Example',
19         'first_name' => 'Edward',
20         'last_name' => 'Example',
21       },
22     }
23     mock['info']['email'] = email unless email.nil?
24     mock['info']['username'] = username unless username.nil?
25     mock['info']['identity_url'] = identity_url unless identity_url.nil?
26     post('/auth/josh_id/callback',
27          {return_to: client_url},
28          {'omniauth.auth' => mock})
29     assert_response :redirect, 'Did not redirect to client with token'
30   end
31
32   test 'assign username from sso' do
33     mock_auth_with(email: 'foo@example.com', username: 'bar')
34     u = assigns(:user)
35     assert_equal 'bar', u.username
36   end
37
38   test 'no assign username from sso' do
39     mock_auth_with(email: 'foo@example.com')
40     u = assigns(:user)
41     assert_equal 'foo', u.username
42   end
43
44   test 'existing user login' do
45     mock_auth_with(identity_url: "https://active-user.openid.local")
46     u = assigns(:user)
47     assert_equal 'zzzzz-tpzed-xurymjxw79nv3jz', u.uuid
48   end
49
50   test 'user redirect_to_user_uuid' do
51     mock_auth_with(identity_url: "https://redirects-to-active-user.openid.local")
52     u = assigns(:user)
53     assert_equal 'zzzzz-tpzed-xurymjxw79nv3jz', u.uuid
54   end
55
56   test 'user double redirect_to_user_uuid' do
57     mock_auth_with(identity_url: "https://double-redirects-to-active-user.openid.local")
58     u = assigns(:user)
59     assert_equal 'zzzzz-tpzed-xurymjxw79nv3jz', u.uuid
60   end
61
62   test 'create new user during omniauth callback' do
63     mock_auth_with(email: 'edward@example.com')
64     assert_equal(0, @response.redirect_url.index(client_url),
65                  'Redirected to wrong address after succesful login: was ' +
66                  @response.redirect_url + ', expected ' + client_url + '[...]')
67     assert_not_nil(@response.redirect_url.index('api_token='),
68                    'Expected api_token in query string of redirect url ' +
69                    @response.redirect_url)
70   end
71
72   # Test various combinations of auto_setup configuration and email
73   # address provided during a new user's first session setup.
74   [{result: :nope, email: nil, cfg: {auto: true, repo: true, vm: true}},
75    {result: :yup, email: nil, cfg: {auto: true}},
76    {result: :nope, email: '@example.com', cfg: {auto: true, repo: true, vm: true}},
77    {result: :yup, email: '@example.com', cfg: {auto: true}},
78    {result: :nope, email: 'root@', cfg: {auto: true, repo: true, vm: true}},
79    {result: :nope, email: 'root@', cfg: {auto: true, repo: true}},
80    {result: :nope, email: 'root@', cfg: {auto: true, vm: true}},
81    {result: :yup, email: 'root@', cfg: {auto: true}},
82    {result: :nope, email: 'gitolite@', cfg: {auto: true, repo: true}},
83    {result: :nope, email: '*_*@', cfg: {auto: true, vm: true}},
84    {result: :yup, email: 'toor@', cfg: {auto: true, vm: true, repo: true}},
85    {result: :yup, email: 'foo@', cfg: {auto: true, vm: true},
86      uniqprefix: 'foo'},
87    {result: :yup, email: 'foo@', cfg: {auto: true, repo: true},
88      uniqprefix: 'foo'},
89    {result: :yup, email: 'auto_setup_vm_login@', cfg: {auto: true, repo: true},
90      uniqprefix: 'auto_setup_vm_login'},
91    ].each do |testcase|
92     test "user auto-activate #{testcase.inspect}" do
93       # Configure auto_setup behavior according to testcase[:cfg]
94       Rails.configuration.auto_setup_new_users = testcase[:cfg][:auto]
95       Rails.configuration.auto_setup_new_users_with_vm_uuid =
96         (testcase[:cfg][:vm] ? virtual_machines(:testvm).uuid : false)
97       Rails.configuration.auto_setup_new_users_with_repository =
98         testcase[:cfg][:repo]
99
100       mock_auth_with(email: testcase[:email])
101       u = assigns(:user)
102       vm_links = Link.where('link_class=? and tail_uuid=? and head_uuid like ?',
103                             'permission', u.uuid,
104                             '%-' + VirtualMachine.uuid_prefix + '-%')
105       repo_links = Link.where('link_class=? and tail_uuid=? and head_uuid like ?',
106                               'permission', u.uuid,
107                               '%-' + Repository.uuid_prefix + '-%')
108       repos = Repository.where('uuid in (?)', repo_links.collect(&:head_uuid))
109       case u[:result]
110       when :nope
111         assert_equal false, u.is_invited, "should not have been set up"
112         assert_empty vm_links, "should not have VM login permission"
113         assert_empty repo_links, "should not have repo permission"
114       when :yup
115         assert_equal true, u.is_invited
116         if testcase[:cfg][:vm]
117           assert_equal 1, vm_links.count, "wrong number of VM perm links"
118         else
119           assert_empty vm_links, "should not have VM login permission"
120         end
121         if testcase[:cfg][:repo]
122           assert_equal 1, repo_links.count, "wrong number of repo perm links"
123           assert_equal 1, repos.count, "wrong number of repos"
124           assert_equal 'can_manage', repo_links.first.name, "wrong perm type"
125         else
126           assert_empty repo_links, "should not have repo permission"
127         end
128       end
129       if (prefix = testcase[:uniqprefix])
130         # This email address conflicts with a test fixture. Make sure
131         # every VM login and repository name got digits added to make
132         # it unique.
133         (repos.collect(&:name) +
134          vm_links.collect { |link| link.properties['username'] }
135          ).each do |name|
136           r = name.match(/^(.{#{prefix.length}})(\d+)$/)
137           assert_not_nil r, "#{name.inspect} does not match {prefix}\\d+"
138           assert_equal(prefix, r[1],
139                        "#{name.inspect} was not {#{prefix.inspect} plus digits}")
140         end
141       end
142     end
143   end
144 end