Merge branch '21639-keep-cache-dict' refs #21639
[arvados.git] / services / api / test / integration / users_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 require 'helpers/users_test_helper'
7
8 class UsersTest < ActionDispatch::IntegrationTest
9   include UsersTestHelper
10
11   test "setup user multiple times" do
12     repo_name = 'usertestrepo'
13
14     post "/arvados/v1/users/setup",
15       params: {
16         repo_name: repo_name,
17         user: {
18           uuid: 'zzzzz-tpzed-abcdefghijklmno',
19           first_name: "in_create_test_first_name",
20           last_name: "test_last_name",
21           email: "foo@example.com"
22         }
23       },
24       headers: auth(:admin)
25
26     assert_response :success
27
28     response_items = json_response['items']
29
30     created = find_obj_in_resp response_items, 'arvados#user', nil
31
32     assert_equal 'in_create_test_first_name', created['first_name']
33     assert_not_nil created['uuid'], 'expected non-null uuid for the new user'
34     assert_equal 'zzzzz-tpzed-abcdefghijklmno', created['uuid']
35     assert_not_nil created['email'], 'expected non-nil email'
36     assert_nil created['identity_url'], 'expected no identity_url'
37
38     # repo link and link add user to 'All users' group
39
40     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
41         'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
42
43     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
44         'All users', created['uuid'], 'arvados#group', true, 'Group'
45
46     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
47         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
48
49     verify_system_group_permission_link_for created['uuid']
50
51     # invoke setup again with the same data
52     post "/arvados/v1/users/setup",
53       params: {
54         repo_name: repo_name,
55         vm_uuid: virtual_machines(:testvm).uuid,
56         user: {
57           uuid: 'zzzzz-tpzed-abcdefghijklmno',
58           first_name: "in_create_test_first_name",
59           last_name: "test_last_name",
60           email: "foo@example.com"
61         }
62       },
63       headers: auth(:admin)
64     assert_response 422         # cannot create another user with same UUID
65
66     # invoke setup on the same user
67     post "/arvados/v1/users/setup",
68       params: {
69         repo_name: repo_name,
70         vm_uuid: virtual_machines(:testvm).uuid,
71         uuid: 'zzzzz-tpzed-abcdefghijklmno',
72       },
73       headers: auth(:admin)
74
75     response_items = json_response['items']
76
77     created = find_obj_in_resp response_items, 'arvados#user', nil
78     assert_equal 'in_create_test_first_name', created['first_name']
79     assert_not_nil created['uuid'], 'expected non-null uuid for the new user'
80     assert_equal 'zzzzz-tpzed-abcdefghijklmno', created['uuid']
81     assert_not_nil created['email'], 'expected non-nil email'
82     assert_nil created['identity_url'], 'expected no identity_url'
83
84     # arvados#user, repo link and link add user to 'All users' group
85     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
86         'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
87
88     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
89         'All users', created['uuid'], 'arvados#group', true, 'Group'
90
91     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
92         virtual_machines(:testvm).uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
93
94     verify_system_group_permission_link_for created['uuid']
95   end
96
97   test "setup user in multiple steps and verify response" do
98     post "/arvados/v1/users/setup",
99       params: {
100         user: {
101           email: "foo@example.com"
102         }
103       },
104       headers: auth(:admin)
105
106     assert_response :success
107     response_items = json_response['items']
108     created = find_obj_in_resp response_items, 'arvados#user', nil
109
110     assert_not_nil created['uuid'], 'expected uuid for new user'
111     assert_not_nil created['email'], 'expected non-nil email'
112     assert_equal created['email'], 'foo@example.com', 'expected input email'
113
114     # two new links: system_group, and 'All users' group.
115
116     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
117         'All users', created['uuid'], 'arvados#group', true, 'Group'
118
119     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
120         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
121
122    # invoke setup with a repository
123     post "/arvados/v1/users/setup",
124       params: {
125         repo_name: 'newusertestrepo',
126         uuid: created['uuid']
127       },
128       headers: auth(:admin)
129
130     assert_response :success
131
132     response_items = json_response['items']
133     created = find_obj_in_resp response_items, 'arvados#user', nil
134
135     assert_equal 'foo@example.com', created['email'], 'expected input email'
136
137      # verify links
138     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
139         'All users', created['uuid'], 'arvados#group', true, 'Group'
140
141     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
142         'foo/newusertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
143
144     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
145         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
146
147     # invoke setup with a vm_uuid
148     post "/arvados/v1/users/setup",
149       params: {
150         vm_uuid: virtual_machines(:testvm).uuid,
151         user: {
152           email: 'junk_email'
153         },
154         uuid: created['uuid']
155       },
156       headers: auth(:admin)
157
158     assert_response :success
159
160     response_items = json_response['items']
161     created = find_obj_in_resp response_items, 'arvados#user', nil
162
163     assert_equal created['email'], 'foo@example.com', 'expected original email'
164
165     # verify links
166     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
167         'All users', created['uuid'], 'arvados#group', true, 'Group'
168
169     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
170         virtual_machines(:testvm).uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
171   end
172
173   test "setup and unsetup user" do
174     post "/arvados/v1/users/setup",
175       params: {
176         repo_name: 'newusertestrepo',
177         vm_uuid: virtual_machines(:testvm).uuid,
178         user: {email: 'foo@example.com'},
179       },
180       headers: auth(:admin)
181
182     assert_response :success
183     response_items = json_response['items']
184     created = find_obj_in_resp response_items, 'arvados#user', nil
185     assert_not_nil created['uuid'], 'expected uuid for the new user'
186     assert_equal created['email'], 'foo@example.com', 'expected given email'
187
188     # four extra links: system_group, login, group, repo and vm
189
190     verify_link response_items, 'arvados#group', true, 'permission', 'can_write',
191         'All users', created['uuid'], 'arvados#group', true, 'Group'
192
193     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
194         'foo/newusertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
195
196     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
197         virtual_machines(:testvm).uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
198
199     verify_link_existence created['uuid'], created['email'], true, true, true, true, false
200
201     # create a token
202     token = act_as_system_user do
203       ApiClientAuthorization.create!(user: User.find_by_uuid(created['uuid']), api_client: ApiClient.all.first).api_token
204     end
205
206     # share project and collections with the new user
207     act_as_system_user do
208       Link.create!(tail_uuid: created['uuid'],
209                    head_uuid: groups(:aproject).uuid,
210                    link_class: 'permission',
211                    name: 'can_manage')
212       Link.create!(tail_uuid: created['uuid'],
213                    head_uuid: collections(:collection_owned_by_active).uuid,
214                    link_class: 'permission',
215                    name: 'can_read')
216       Link.create!(tail_uuid: created['uuid'],
217                    head_uuid: collections(:collection_owned_by_active_with_file_stats).uuid,
218                    link_class: 'permission',
219                    name: 'can_write')
220     end
221
222     assert_equal 1, ApiClientAuthorization.where(user_id: User.find_by_uuid(created['uuid']).id).size, 'expected token not found'
223
224     post "/arvados/v1/users/#{created['uuid']}/unsetup", params: {}, headers: auth(:admin)
225
226     assert_response :success
227
228     created2 = json_response
229     assert_not_nil created2['uuid'], 'expected uuid for the newly created user'
230     assert_equal created['uuid'], created2['uuid'], 'expected uuid not found'
231     assert_equal 0, ApiClientAuthorization.where(user_id: User.find_by_uuid(created['uuid']).id).size, 'token should have been deleted by user unsetup'
232     # check permissions are deleted
233     assert_empty Link.where(tail_uuid: created['uuid'])
234
235     verify_link_existence created['uuid'], created['email'], false, false, false, false, false
236   end
237
238   def find_obj_in_resp (response_items, kind, head_kind=nil)
239     response_items.each do |x|
240       if x && x['kind']
241         return x if (x['kind'] == kind && x['head_kind'] == head_kind)
242       end
243     end
244     nil
245   end
246
247   test 'merge active into project_viewer account' do
248     post('/arvados/v1/groups',
249       params: {
250         group: {
251           group_class: 'project',
252           name: "active user's stuff",
253         },
254       },
255       headers: auth(:project_viewer))
256     assert_response(:success)
257     project_uuid = json_response['uuid']
258
259     post('/arvados/v1/users/merge',
260       params: {
261         new_user_token: api_client_authorizations(:project_viewer_trustedclient).api_token,
262         new_owner_uuid: project_uuid,
263         redirect_to_new_user: true,
264       },
265       headers: auth(:active_trustedclient))
266     assert_response(:success)
267
268     get('/arvados/v1/users/current', params: {}, headers: auth(:active))
269     assert_response(:success)
270     assert_equal(users(:project_viewer).uuid, json_response['uuid'])
271
272     get('/arvados/v1/authorized_keys/' + authorized_keys(:active).uuid,
273       params: {},
274       headers: auth(:active))
275     assert_response(:success)
276     assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
277     assert_equal(users(:project_viewer).uuid, json_response['authorized_user_uuid'])
278
279     get('/arvados/v1/repositories/' + repositories(:foo).uuid,
280       params: {},
281       headers: auth(:active))
282     assert_response(:success)
283     assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
284     assert_equal("#{users(:project_viewer).username}/foo", json_response['name'])
285
286     get('/arvados/v1/groups/' + groups(:aproject).uuid,
287       params: {},
288       headers: auth(:active))
289     assert_response(:success)
290     assert_equal(project_uuid, json_response['owner_uuid'])
291   end
292
293   test 'pre-activate user' do
294     post '/arvados/v1/users',
295       params: {
296         "user" => {
297           "email" => 'foo@example.com',
298           "is_active" => true,
299           "username" => "barney"
300         }
301       },
302       headers: {'HTTP_AUTHORIZATION' => "OAuth2 #{api_token(:admin)}"}
303     assert_response :success
304     rp = json_response
305     assert_not_nil rp["uuid"]
306     assert_equal true, rp["is_active"]
307     assert_equal false, rp["is_admin"]
308
309     get "/arvados/v1/users/#{rp['uuid']}",
310       params: {format: 'json'},
311       headers: auth(:admin)
312     assert_response :success
313     assert_equal rp["uuid"], json_response['uuid']
314     assert_equal false, json_response['is_admin']
315     assert_equal true, json_response['is_active']
316     assert_equal 'foo@example.com', json_response['email']
317     assert_equal 'barney', json_response['username']
318   end
319
320   test 'merge with repository name conflict' do
321     post('/arvados/v1/groups',
322       params: {
323         group: {
324           group_class: 'project',
325           name: "active user's stuff",
326         },
327       },
328       headers: auth(:project_viewer))
329     assert_response(:success)
330     project_uuid = json_response['uuid']
331
332     post('/arvados/v1/repositories/',
333          params: { :repository => { :name => "#{users(:project_viewer).username}/foo", :owner_uuid => users(:project_viewer).uuid } },
334          headers: auth(:project_viewer))
335     assert_response(:success)
336
337     post('/arvados/v1/users/merge',
338       params: {
339         new_user_token: api_client_authorizations(:project_viewer_trustedclient).api_token,
340         new_owner_uuid: project_uuid,
341         redirect_to_new_user: true,
342       },
343       headers: auth(:active_trustedclient))
344     assert_response(:success)
345
346     get('/arvados/v1/repositories/' + repositories(:foo).uuid,
347       params: {},
348       headers: auth(:active))
349     assert_response(:success)
350     assert_equal(users(:project_viewer).uuid, json_response['owner_uuid'])
351     assert_equal("#{users(:project_viewer).username}/migratedfoo", json_response['name'])
352
353   end
354
355   test "cannot set is_active to false directly" do
356     post('/arvados/v1/users',
357       params: {
358         user: {
359           email: "bob@example.com",
360           username: "bobby"
361         },
362       },
363       headers: auth(:admin))
364     assert_response(:success)
365     user = json_response
366     assert_equal false, user['is_active']
367
368     token = act_as_system_user do
369       ApiClientAuthorization.create!(user: User.find_by_uuid(user['uuid']), api_client: ApiClient.all.first).api_token
370     end
371     post("/arvados/v1/user_agreements/sign",
372         params: {uuid: 'zzzzz-4zz18-t68oksiu9m80s4y'},
373         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
374     assert_response :success
375
376     post("/arvados/v1/users/#{user['uuid']}/activate",
377       params: {},
378       headers: auth(:admin))
379     assert_response(:success)
380     user = json_response
381     assert_equal true, user['is_active']
382
383     put("/arvados/v1/users/#{user['uuid']}",
384          params: {
385            user: {is_active: false}
386          },
387          headers: auth(:admin))
388     assert_response 422
389   end
390
391   test "cannot self activate when AutoSetupNewUsers is false" do
392     Rails.configuration.Users.NewUsersAreActive = false
393     Rails.configuration.Users.AutoSetupNewUsers = false
394
395     user = nil
396     token = nil
397     act_as_system_user do
398       user = User.create!(email: "bob@example.com", username: "bobby")
399       ap = ApiClientAuthorization.create!(user: user, api_client: ApiClient.all.first)
400       token = ap.api_token
401     end
402
403     get("/arvados/v1/users/#{user['uuid']}",
404         params: {},
405         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
406     assert_response(:success)
407     user = json_response
408     assert_equal false, user['is_active']
409
410     post("/arvados/v1/users/#{user['uuid']}/activate",
411         params: {},
412         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
413     assert_response 422
414     assert_match(/Cannot activate without being invited/, json_response['errors'][0])
415   end
416
417
418   test "cannot self activate after unsetup" do
419     Rails.configuration.Users.NewUsersAreActive = false
420     Rails.configuration.Users.AutoSetupNewUsers = false
421
422     user = nil
423     token = nil
424     act_as_system_user do
425       user = User.create!(email: "bob@example.com", username: "bobby")
426       ap = ApiClientAuthorization.create!(user: user, api_client_id: 0)
427       token = ap.api_token
428     end
429
430     post("/arvados/v1/users/setup",
431         params: {uuid: user['uuid']},
432         headers: auth(:admin))
433     assert_response :success
434
435     post("/arvados/v1/users/#{user['uuid']}/activate",
436         params: {},
437         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
438     assert_response 403
439     assert_match(/Cannot activate without user agreements/, json_response['errors'][0])
440
441     post("/arvados/v1/user_agreements/sign",
442         params: {uuid: 'zzzzz-4zz18-t68oksiu9m80s4y'},
443         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
444     assert_response :success
445
446     post("/arvados/v1/users/#{user['uuid']}/activate",
447         params: {},
448         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
449     assert_response :success
450
451     get("/arvados/v1/users/#{user['uuid']}",
452         params: {},
453         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
454     assert_response(:success)
455     userJSON = json_response
456     assert_equal true, userJSON['is_active']
457
458     post("/arvados/v1/users/#{user['uuid']}/unsetup",
459         params: {},
460         headers: auth(:admin))
461     assert_response :success
462
463     # Need to get a new token, the old one was invalidated by the unsetup call
464     act_as_system_user do
465       ap = ApiClientAuthorization.create!(user: user, api_client_id: 0)
466       token = ap.api_token
467     end
468
469     get("/arvados/v1/users/#{user['uuid']}",
470         params: {},
471         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
472     assert_response(:success)
473     userJSON = json_response
474     assert_equal false, userJSON['is_active']
475
476     post("/arvados/v1/users/#{user['uuid']}/activate",
477         params: {},
478         headers: {"HTTP_AUTHORIZATION" => "Bearer #{token}"})
479     assert_response 422
480     assert_match(/Cannot activate without being invited/, json_response['errors'][0])
481   end
482
483   test "bypass_federation only accepted for admins" do
484     get "/arvados/v1/users",
485       params: {
486         bypass_federation: true
487       },
488       headers: auth(:admin)
489
490     assert_response :success
491
492     get "/arvados/v1/users",
493       params: {
494         bypass_federation: true
495       },
496       headers: auth(:active)
497
498     assert_response 403
499   end
500
501   test "disabling system root user not permitted" do
502     put("/arvados/v1/users/#{users(:system_user).uuid}",
503       params: {
504         user: {is_admin: false}
505       },
506       headers: auth(:admin))
507     assert_response 422
508
509     post("/arvados/v1/users/#{users(:system_user).uuid}/unsetup",
510       params: {},
511       headers: auth(:admin))
512     assert_response 422
513   end
514
515   test "creating users only accepted for admins" do
516     assert_equal false, users(:active).is_admin
517     post '/arvados/v1/users',
518       params: {
519         "user" => {
520           "email" => 'foo@example.com',
521           "username" => "barney"
522         }
523       },
524       headers: auth(:active)
525     assert_response 403
526   end
527
528   test "create users assigns the system root user as their owner" do
529     post '/arvados/v1/users',
530       params: {
531         "user" => {
532           "email" => 'foo@example.com',
533           "username" => "barney"
534         }
535       },
536       headers: auth(:admin)
537     assert_response :success
538     assert_not_nil json_response["uuid"]
539     assert_equal users(:system_user).uuid, json_response["owner_uuid"]
540   end
541
542   test "create users ignores provided owner_uuid field" do
543     assert_equal false, users(:admin).uuid == users(:system_user).uuid
544     post '/arvados/v1/users',
545       params: {
546         "user" => {
547           "email" => 'foo@example.com',
548           "owner_uuid" => users(:admin).uuid,
549           "username" => "barney"
550         }
551       },
552       headers: auth(:admin)
553     assert_response :success
554     assert_not_nil json_response["uuid"]
555     assert_equal users(:system_user).uuid, json_response["owner_uuid"]
556   end
557 end