12626: Add tests for missing new_owner_uuid.
[arvados.git] / services / api / test / functional / arvados / v1 / users_controller_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 Arvados::V1::UsersControllerTest < ActionController::TestCase
9   include CurrentApiClient
10   include UsersTestHelper
11
12   setup do
13     @initial_link_count = Link.count
14     @vm_uuid = virtual_machines(:testvm).uuid
15     ActionMailer::Base.deliveries = []
16   end
17
18   test "activate a user after signing UA" do
19     authorize_with :inactive_but_signed_user_agreement
20     post :activate, id: users(:inactive_but_signed_user_agreement).uuid
21     assert_response :success
22     assert_not_nil assigns(:object)
23     me = JSON.parse(@response.body)
24     assert_equal true, me['is_active']
25   end
26
27   test "refuse to activate a user before signing UA" do
28     act_as_system_user do
29     required_uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
30                                 system_user_uuid,
31                                 'signature',
32                                 'require',
33                                 system_user_uuid,
34                                 Collection.uuid_like_pattern).
35       collect(&:head_uuid)
36
37       assert required_uuids.length > 0
38
39       signed_uuids = Link.where(owner_uuid: system_user_uuid,
40                                 link_class: 'signature',
41                                 name: 'click',
42                                 tail_uuid: users(:inactive).uuid,
43                                 head_uuid: required_uuids).
44                           collect(&:head_uuid)
45
46       assert_equal 0, signed_uuids.length
47     end
48
49     authorize_with :inactive
50     assert_equal false, users(:inactive).is_active
51
52     post :activate, id: users(:inactive).uuid
53     assert_response 403
54
55     resp = json_response
56     assert resp['errors'].first.include? 'Cannot activate without user agreements'
57     assert_nil resp['is_active']
58   end
59
60   test "activate an already-active user" do
61     authorize_with :active
62     post :activate, id: users(:active).uuid
63     assert_response :success
64     me = JSON.parse(@response.body)
65     assert_equal true, me['is_active']
66   end
67
68   test "respond 401 if given token exists but user record is missing" do
69     authorize_with :valid_token_deleted_user
70     get :current, {format: :json}
71     assert_response 401
72   end
73
74   test "create new user with user as input" do
75     authorize_with :admin
76     post :create, user: {
77       first_name: "test_first_name",
78       last_name: "test_last_name",
79       email: "foo@example.com"
80     }
81     assert_response :success
82     created = JSON.parse(@response.body)
83     assert_equal 'test_first_name', created['first_name']
84     assert_not_nil created['uuid'], 'expected uuid for the newly created user'
85     assert_not_nil created['email'], 'expected non-nil email'
86     assert_nil created['identity_url'], 'expected no identity_url'
87   end
88
89   test "create user with user, vm and repo as input" do
90     authorize_with :admin
91     repo_name = 'usertestrepo'
92
93     post :setup, {
94       repo_name: repo_name,
95       openid_prefix: 'https://www.google.com/accounts/o8/id',
96       user: {
97         uuid: 'zzzzz-tpzed-abcdefghijklmno',
98         first_name: "in_create_test_first_name",
99         last_name: "test_last_name",
100         email: "foo@example.com"
101       }
102     }
103     assert_response :success
104     response_items = JSON.parse(@response.body)['items']
105
106     created = find_obj_in_resp response_items, 'User', nil
107
108     assert_equal 'in_create_test_first_name', created['first_name']
109     assert_not_nil created['uuid'], 'expected non-null uuid for the new user'
110     assert_equal 'zzzzz-tpzed-abcdefghijklmno', created['uuid']
111     assert_not_nil created['email'], 'expected non-nil email'
112     assert_nil created['identity_url'], 'expected no identity_url'
113
114     # arvados#user, repo link and link add user to 'All users' group
115     verify_links_added 4
116
117     verify_link response_items, 'arvados#user', true, 'permission', 'can_login',
118         created['uuid'], created['email'], 'arvados#user', false, 'User'
119
120     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
121         "foo/#{repo_name}", created['uuid'], 'arvados#repository', true, 'Repository'
122
123     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
124         'All users', created['uuid'], 'arvados#group', true, 'Group'
125
126     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
127         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
128
129     verify_system_group_permission_link_for created['uuid']
130   end
131
132   test "setup user with bogus uuid and expect error" do
133     authorize_with :admin
134
135     post :setup, {
136       uuid: 'bogus_uuid',
137       repo_name: 'usertestrepo',
138       vm_uuid: @vm_uuid
139     }
140     response_body = JSON.parse(@response.body)
141     response_errors = response_body['errors']
142     assert_not_nil response_errors, 'Expected error in response'
143     assert (response_errors.first.include? 'Path not found'), 'Expected 404'
144   end
145
146   test "setup user with bogus uuid in user and expect error" do
147     authorize_with :admin
148
149     post :setup, {
150       user: {uuid: 'bogus_uuid'},
151       repo_name: 'usertestrepo',
152       vm_uuid: @vm_uuid,
153       openid_prefix: 'https://www.google.com/accounts/o8/id'
154     }
155     response_body = JSON.parse(@response.body)
156     response_errors = response_body['errors']
157     assert_not_nil response_errors, 'Expected error in response'
158     assert (response_errors.first.include? 'ArgumentError: Require user email'),
159       'Expected RuntimeError'
160   end
161
162   test "setup user with no uuid and user, expect error" do
163     authorize_with :admin
164
165     post :setup, {
166       repo_name: 'usertestrepo',
167       vm_uuid: @vm_uuid,
168       openid_prefix: 'https://www.google.com/accounts/o8/id'
169     }
170     response_body = JSON.parse(@response.body)
171     response_errors = response_body['errors']
172     assert_not_nil response_errors, 'Expected error in response'
173     assert (response_errors.first.include? 'Required uuid or user'),
174         'Expected ArgumentError'
175   end
176
177   test "setup user with no uuid and email, expect error" do
178     authorize_with :admin
179
180     post :setup, {
181       user: {},
182       repo_name: 'usertestrepo',
183       vm_uuid: @vm_uuid,
184       openid_prefix: 'https://www.google.com/accounts/o8/id'
185     }
186     response_body = JSON.parse(@response.body)
187     response_errors = response_body['errors']
188     assert_not_nil response_errors, 'Expected error in response'
189     assert (response_errors.first.include? '<ArgumentError: Require user email'),
190         'Expected ArgumentError'
191   end
192
193   test "invoke setup with existing uuid, vm and repo and verify links" do
194     authorize_with :admin
195     inactive_user = users(:inactive)
196
197     post :setup, {
198       uuid: users(:inactive).uuid,
199       repo_name: 'usertestrepo',
200       vm_uuid: @vm_uuid
201     }
202
203     assert_response :success
204
205     response_items = JSON.parse(@response.body)['items']
206     resp_obj = find_obj_in_resp response_items, 'User', nil
207
208     assert_not_nil resp_obj['uuid'], 'expected uuid for the new user'
209     assert_equal inactive_user['uuid'], resp_obj['uuid']
210     assert_equal inactive_user['email'], resp_obj['email'],
211         'expecting inactive user email'
212
213     # expect repo and vm links
214     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
215         'inactiveuser/usertestrepo', resp_obj['uuid'], 'arvados#repository', true, 'Repository'
216
217     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
218         @vm_uuid, resp_obj['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
219   end
220
221   test "invoke setup with existing uuid but different email, expect original email" do
222     authorize_with :admin
223     inactive_user = users(:inactive)
224
225     post :setup, {
226       uuid: inactive_user['uuid'],
227       user: {email: 'junk_email'}
228     }
229
230     assert_response :success
231
232     response_items = JSON.parse(@response.body)['items']
233     resp_obj = find_obj_in_resp response_items, 'User', nil
234
235     assert_not_nil resp_obj['uuid'], 'expected uuid for the new user'
236     assert_equal inactive_user['uuid'], resp_obj['uuid']
237     assert_equal inactive_user['email'], resp_obj['email'],
238         'expecting inactive user email'
239   end
240
241   test "setup user with valid email and repo as input" do
242     authorize_with :admin
243
244     post :setup, {
245       repo_name: 'usertestrepo',
246       user: {email: 'foo@example.com'},
247       openid_prefix: 'https://www.google.com/accounts/o8/id'
248     }
249
250     assert_response :success
251     response_items = JSON.parse(@response.body)['items']
252     response_object = find_obj_in_resp response_items, 'User', nil
253     assert_not_nil response_object['uuid'], 'expected uuid for the new user'
254     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
255
256     # four extra links; system_group, login, group and repo perms
257     verify_links_added 4
258   end
259
260   test "setup user with fake vm and expect error" do
261     authorize_with :admin
262
263     post :setup, {
264       repo_name: 'usertestrepo',
265       vm_uuid: 'no_such_vm',
266       user: {email: 'foo@example.com'},
267       openid_prefix: 'https://www.google.com/accounts/o8/id'
268     }
269
270     response_body = JSON.parse(@response.body)
271     response_errors = response_body['errors']
272     assert_not_nil response_errors, 'Expected error in response'
273     assert (response_errors.first.include? "No vm found for no_such_vm"),
274           'Expected RuntimeError: No vm found for no_such_vm'
275   end
276
277   test "setup user with valid email, repo and real vm as input" do
278     authorize_with :admin
279
280     post :setup, {
281       repo_name: 'usertestrepo',
282       openid_prefix: 'https://www.google.com/accounts/o8/id',
283       vm_uuid: @vm_uuid,
284       user: {email: 'foo@example.com'}
285     }
286
287     assert_response :success
288     response_items = JSON.parse(@response.body)['items']
289     response_object = find_obj_in_resp response_items, 'User', nil
290     assert_not_nil response_object['uuid'], 'expected uuid for the new user'
291     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
292
293     # five extra links; system_group, login, group, vm, repo
294     verify_links_added 5
295   end
296
297   test "setup user with valid email, no vm and no repo as input" do
298     authorize_with :admin
299
300     post :setup, {
301       user: {email: 'foo@example.com'},
302       openid_prefix: 'https://www.google.com/accounts/o8/id'
303     }
304
305     assert_response :success
306     response_items = JSON.parse(@response.body)['items']
307     response_object = find_obj_in_resp response_items, 'User', nil
308     assert_not_nil response_object['uuid'], 'expected uuid for new user'
309     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
310
311     # three extra links; system_group, login, and group
312     verify_links_added 3
313
314     verify_link response_items, 'arvados#user', true, 'permission', 'can_login',
315         response_object['uuid'], response_object['email'], 'arvados#user', false, 'User'
316
317     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
318         'All users', response_object['uuid'], 'arvados#group', true, 'Group'
319
320     verify_link response_items, 'arvados#repository', false, 'permission', 'can_manage',
321         'foo/usertestrepo', response_object['uuid'], 'arvados#repository', true, 'Repository'
322
323     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
324         nil, response_object['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
325   end
326
327   test "setup user with email, first name, repo name and vm uuid" do
328     authorize_with :admin
329
330     post :setup, {
331       openid_prefix: 'https://www.google.com/accounts/o8/id',
332       repo_name: 'usertestrepo',
333       vm_uuid: @vm_uuid,
334       user: {
335         first_name: 'test_first_name',
336         email: 'foo@example.com'
337       }
338     }
339
340     assert_response :success
341     response_items = JSON.parse(@response.body)['items']
342     response_object = find_obj_in_resp response_items, 'User', nil
343     assert_not_nil response_object['uuid'], 'expected uuid for new user'
344     assert_equal response_object['email'], 'foo@example.com', 'expected given email'
345     assert_equal 'test_first_name', response_object['first_name'],
346         'expecting first name'
347
348     # five extra links; system_group, login, group, repo and vm
349     verify_links_added 5
350   end
351
352   test "setup user with an existing user email and check different object is created" do
353     authorize_with :admin
354     inactive_user = users(:inactive)
355
356     post :setup, {
357       openid_prefix: 'https://www.google.com/accounts/o8/id',
358       repo_name: 'usertestrepo',
359       user: {
360         email: inactive_user['email']
361       }
362     }
363
364     assert_response :success
365     response_items = JSON.parse(@response.body)['items']
366     response_object = find_obj_in_resp response_items, 'User', nil
367     assert_not_nil response_object['uuid'], 'expected uuid for new user'
368     assert_not_equal response_object['uuid'], inactive_user['uuid'],
369         'expected different uuid after create operation'
370     assert_equal inactive_user['email'], response_object['email'], 'expected given email'
371     # system_group, openid, group, and repo. No vm link.
372     verify_links_added 4
373   end
374
375   test "setup user with openid prefix" do
376     authorize_with :admin
377
378     post :setup, {
379       repo_name: 'usertestrepo',
380       openid_prefix: 'http://www.example.com/account',
381       user: {
382         first_name: "in_create_test_first_name",
383         last_name: "test_last_name",
384         email: "foo@example.com"
385       }
386     }
387
388     assert_response :success
389
390     response_items = JSON.parse(@response.body)['items']
391     created = find_obj_in_resp response_items, 'User', nil
392
393     assert_equal 'in_create_test_first_name', created['first_name']
394     assert_not_nil created['uuid'], 'expected uuid for new user'
395     assert_not_nil created['email'], 'expected non-nil email'
396     assert_nil created['identity_url'], 'expected no identity_url'
397
398     # verify links
399     # four new links: system_group, arvados#user, repo, and 'All users' group.
400     verify_links_added 4
401
402     verify_link response_items, 'arvados#user', true, 'permission', 'can_login',
403         created['uuid'], created['email'], 'arvados#user', false, 'User'
404
405     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
406         'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
407
408     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
409         'All users', created['uuid'], 'arvados#group', true, 'Group'
410
411     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
412         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
413   end
414
415   test "invoke setup with no openid prefix, expect error" do
416     authorize_with :admin
417
418     post :setup, {
419       repo_name: 'usertestrepo',
420       user: {
421         first_name: "in_create_test_first_name",
422         last_name: "test_last_name",
423         email: "foo@example.com"
424       }
425     }
426
427     response_body = JSON.parse(@response.body)
428     response_errors = response_body['errors']
429     assert_not_nil response_errors, 'Expected error in response'
430     assert (response_errors.first.include? 'openid_prefix parameter is missing'),
431         'Expected ArgumentError'
432   end
433
434   test "setup user with user, vm and repo and verify links" do
435     authorize_with :admin
436
437     post :setup, {
438       user: {
439         first_name: "in_create_test_first_name",
440         last_name: "test_last_name",
441         email: "foo@example.com"
442       },
443       vm_uuid: @vm_uuid,
444       repo_name: 'usertestrepo',
445       openid_prefix: 'https://www.google.com/accounts/o8/id'
446     }
447
448     assert_response :success
449
450     response_items = JSON.parse(@response.body)['items']
451     created = find_obj_in_resp response_items, 'User', nil
452
453     assert_equal 'in_create_test_first_name', created['first_name']
454     assert_not_nil created['uuid'], 'expected uuid for new user'
455     assert_not_nil created['email'], 'expected non-nil email'
456     assert_nil created['identity_url'], 'expected no identity_url'
457
458     # five new links: system_group, arvados#user, repo, vm and 'All
459     # users' group link
460     verify_links_added 5
461
462     verify_link response_items, 'arvados#user', true, 'permission', 'can_login',
463         created['uuid'], created['email'], 'arvados#user', false, 'User'
464
465     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
466         'foo/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
467
468     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
469         'All users', created['uuid'], 'arvados#group', true, 'Group'
470
471     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
472         @vm_uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
473   end
474
475   test "create user as non admin user and expect error" do
476     authorize_with :active
477
478     post :create, {
479       user: {email: 'foo@example.com'}
480     }
481
482     response_body = JSON.parse(@response.body)
483     response_errors = response_body['errors']
484     assert_not_nil response_errors, 'Expected error in response'
485     assert (response_errors.first.include? 'PermissionDenied'),
486           'Expected PermissionDeniedError'
487   end
488
489   test "setup user as non admin user and expect error" do
490     authorize_with :active
491
492     post :setup, {
493       openid_prefix: 'https://www.google.com/accounts/o8/id',
494       user: {email: 'foo@example.com'}
495     }
496
497     response_body = JSON.parse(@response.body)
498     response_errors = response_body['errors']
499     assert_not_nil response_errors, 'Expected error in response'
500     assert (response_errors.first.include? 'Forbidden'),
501           'Expected Forbidden error'
502   end
503
504   test "setup active user with repo and no vm" do
505     authorize_with :admin
506     active_user = users(:active)
507
508     # invoke setup with a repository
509     post :setup, {
510       repo_name: 'usertestrepo',
511       uuid: active_user['uuid']
512     }
513
514     assert_response :success
515
516     response_items = JSON.parse(@response.body)['items']
517     created = find_obj_in_resp response_items, 'User', nil
518
519     assert_equal active_user[:email], created['email'], 'expected input email'
520
521      # verify links
522     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
523         'All users', created['uuid'], 'arvados#group', true, 'Group'
524
525     verify_link response_items, 'arvados#repository', true, 'permission', 'can_manage',
526         'active/usertestrepo', created['uuid'], 'arvados#repository', true, 'Repository'
527
528     verify_link response_items, 'arvados#virtualMachine', false, 'permission', 'can_login',
529         nil, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
530   end
531
532   test "setup active user with vm and no repo" do
533     authorize_with :admin
534     active_user = users(:active)
535     repos_query = Repository.where(owner_uuid: active_user.uuid)
536     repo_link_query = Link.where(tail_uuid: active_user.uuid,
537                                  link_class: "permission", name: "can_manage")
538     repos_count = repos_query.count
539     repo_link_count = repo_link_query.count
540
541     # invoke setup with a repository
542     post :setup, {
543       vm_uuid: @vm_uuid,
544       uuid: active_user['uuid'],
545       email: 'junk_email'
546     }
547
548     assert_response :success
549
550     response_items = JSON.parse(@response.body)['items']
551     created = find_obj_in_resp response_items, 'User', nil
552
553     assert_equal active_user['email'], created['email'], 'expected original email'
554
555     # verify links
556     verify_link response_items, 'arvados#group', true, 'permission', 'can_read',
557         'All users', created['uuid'], 'arvados#group', true, 'Group'
558
559     assert_equal(repos_count, repos_query.count)
560     assert_equal(repo_link_count, repo_link_query.count)
561
562     verify_link response_items, 'arvados#virtualMachine', true, 'permission', 'can_login',
563         @vm_uuid, created['uuid'], 'arvados#virtualMachine', false, 'VirtualMachine'
564   end
565
566   test "unsetup active user" do
567     active_user = users(:active)
568     assert_not_nil active_user['uuid'], 'expected uuid for the active user'
569     assert active_user['is_active'], 'expected is_active for active user'
570
571     verify_link_existence active_user['uuid'], active_user['email'],
572           false, true, true, true, true
573
574     authorize_with :admin
575
576     # now unsetup this user
577     post :unsetup, id: active_user['uuid']
578     assert_response :success
579
580     response_user = JSON.parse(@response.body)
581     assert_not_nil response_user['uuid'], 'expected uuid for the upsetup user'
582     assert_equal active_user['uuid'], response_user['uuid'], 'expected uuid not found'
583     assert !response_user['is_active'], 'expected user to be inactive'
584     assert !response_user['is_invited'], 'expected user to be uninvited'
585
586     verify_link_existence response_user['uuid'], response_user['email'],
587           false, false, false, false, false
588
589     active_user = User.find_by_uuid(users(:active).uuid)
590     readable_groups = active_user.groups_i_can(:read)
591     all_users_group = Group.all.collect(&:uuid).select { |g| g.match(/-f+$/) }
592     refute_includes(readable_groups, all_users_group,
593                     "active user can read All Users group after being deactivated")
594     assert_equal(false, active_user.is_invited,
595                  "active user is_invited after being deactivated & reloaded")
596   end
597
598   test "setup user with send notification param false and verify no email" do
599     authorize_with :admin
600
601     post :setup, {
602       openid_prefix: 'http://www.example.com/account',
603       send_notification_email: 'false',
604       user: {
605         email: "foo@example.com"
606       }
607     }
608
609     assert_response :success
610     response_items = JSON.parse(@response.body)['items']
611     created = find_obj_in_resp response_items, 'User', nil
612     assert_not_nil created['uuid'], 'expected uuid for the new user'
613     assert_equal created['email'], 'foo@example.com', 'expected given email'
614
615     setup_email = ActionMailer::Base.deliveries.last
616     assert_nil setup_email, 'expected no setup email'
617   end
618
619   test "setup user with send notification param true and verify email" do
620     authorize_with :admin
621
622     post :setup, {
623       openid_prefix: 'http://www.example.com/account',
624       send_notification_email: 'true',
625       user: {
626         email: "foo@example.com"
627       }
628     }
629
630     assert_response :success
631     response_items = JSON.parse(@response.body)['items']
632     created = find_obj_in_resp response_items, 'User', nil
633     assert_not_nil created['uuid'], 'expected uuid for the new user'
634     assert_equal created['email'], 'foo@example.com', 'expected given email'
635
636     setup_email = ActionMailer::Base.deliveries.last
637     assert_not_nil setup_email, 'Expected email after setup'
638
639     assert_equal Rails.configuration.user_notifier_email_from, setup_email.from[0]
640     assert_equal 'foo@example.com', setup_email.to[0]
641     assert_equal 'Welcome to Curoverse - shell account enabled', setup_email.subject
642     assert (setup_email.body.to_s.include? 'Your Arvados shell account has been set up'),
643         'Expected Your Arvados shell account has been set up in email body'
644     assert (setup_email.body.to_s.include? "#{Rails.configuration.workbench_address}users/#{created['uuid']}/virtual_machines"), 'Expected virtual machines url in email body'
645   end
646
647   test "setup inactive user by changing is_active to true" do
648     authorize_with :admin
649     active_user = users(:active)
650
651     # invoke setup with a repository
652     put :update, {
653           id: active_user['uuid'],
654           user: {
655             is_active: true,
656           }
657         }
658     assert_response :success
659     assert_equal active_user['uuid'], json_response['uuid']
660     updated = User.where(uuid: active_user['uuid']).first
661     assert_equal(true, updated.is_active)
662     assert_equal({read: true}, updated.group_permissions[all_users_group_uuid])
663   end
664
665   test "non-admin user can get basic information about readable users" do
666     authorize_with :spectator
667     get(:index)
668     check_non_admin_index
669     check_readable_users_index [:spectator], [:inactive, :active]
670   end
671
672   test "non-admin user gets only safe attributes from users#show" do
673     g = act_as_system_user do
674       create :group
675     end
676     users = create_list :active_user, 2, join_groups: [g]
677     token = create :token, user: users[0]
678     authorize_with_token token
679     get :show, id: users[1].uuid
680     check_non_admin_show
681   end
682
683   [2, 4].each do |limit|
684     test "non-admin user can limit index to #{limit}" do
685       g = act_as_system_user do
686         create :group
687       end
688       users = create_list :active_user, 4, join_groups: [g]
689       token = create :token, user: users[0]
690
691       authorize_with_token token
692       get(:index, limit: limit)
693       check_non_admin_index
694       assert_equal(limit, json_response["items"].size,
695                    "non-admin index limit was ineffective")
696     end
697   end
698
699   test "admin has full index powers" do
700     authorize_with :admin
701     check_inactive_user_findable
702   end
703
704   test "reader token can grant admin index powers" do
705     authorize_with :spectator
706     check_inactive_user_findable(reader_tokens: [api_token(:admin)])
707   end
708
709   test "admin can filter on user.is_active" do
710     authorize_with :admin
711     get(:index, filters: [["is_active", "=", "true"]])
712     assert_response :success
713     check_readable_users_index [:active, :spectator], [:inactive]
714   end
715
716   test "admin can search where user.is_active" do
717     authorize_with :admin
718     get(:index, where: {is_active: true})
719     assert_response :success
720     check_readable_users_index [:active, :spectator], [:inactive]
721   end
722
723   test "update active_no_prefs user profile and expect notification email" do
724     authorize_with :admin
725
726     put :update, {
727       id: users(:active_no_prefs).uuid,
728       user: {
729         prefs: {:profile => {'organization' => 'example.com'}}
730       }
731     }
732     assert_response :success
733
734     found_email = false
735     ActionMailer::Base.deliveries.andand.each do |email|
736       if email.subject == "Profile created by #{users(:active_no_prefs).email}"
737         found_email = true
738         break
739       end
740     end
741     assert_equal true, found_email, 'Expected email after creating profile'
742   end
743
744   test "update active_no_prefs_profile user profile and expect notification email" do
745     authorize_with :admin
746
747     user = {}
748     user[:prefs] = users(:active_no_prefs_profile_no_getting_started_shown).prefs
749     user[:prefs][:profile] = {:profile => {'organization' => 'example.com'}}
750     put :update, {
751       id: users(:active_no_prefs_profile_no_getting_started_shown).uuid,
752       user: user
753     }
754     assert_response :success
755
756     found_email = false
757     ActionMailer::Base.deliveries.andand.each do |email|
758       if email.subject == "Profile created by #{users(:active_no_prefs_profile_no_getting_started_shown).email}"
759         found_email = true
760         break
761       end
762     end
763     assert_equal true, found_email, 'Expected email after creating profile'
764   end
765
766   test "update active user profile and expect no notification email" do
767     authorize_with :admin
768
769     put :update, {
770       id: users(:active).uuid,
771       user: {
772         prefs: {:profile => {'organization' => 'anotherexample.com'}}
773       }
774     }
775     assert_response :success
776
777     found_email = false
778     ActionMailer::Base.deliveries.andand.each do |email|
779       if email.subject == "Profile created by #{users(:active).email}"
780         found_email = true
781         break
782       end
783     end
784     assert_equal false, found_email, 'Expected no email after updating profile'
785   end
786
787   test "user API response includes writable_by" do
788     authorize_with :active
789     get :current
790     assert_response :success
791     assert_includes(json_response["writable_by"], users(:active).uuid,
792                     "user's writable_by should include self")
793     assert_includes(json_response["writable_by"], users(:active).owner_uuid,
794                     "user's writable_by should include its owner_uuid")
795   end
796
797   [
798     [:admin, true],
799     [:active, false],
800   ].each do |auth_user, expect_success|
801     test "update_uuid as #{auth_user}" do
802       authorize_with auth_user
803       orig_uuid = users(:active).uuid
804       post :update_uuid, {
805              id: orig_uuid,
806              new_uuid: 'zbbbb-tpzed-abcde12345abcde',
807            }
808       if expect_success
809         assert_response :success
810         assert_empty User.where(uuid: orig_uuid)
811       else
812         assert_response 403
813         assert_not_empty User.where(uuid: orig_uuid)
814       end
815     end
816   end
817
818   test "refuse to merge with redirect_to_user_uuid=false (not yet supported)" do
819     authorize_with :project_viewer_trustedclient
820     post :merge, {
821            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
822            new_owner_uuid: users(:active).uuid,
823            redirect_to_new_user: false,
824          }
825     assert_response(422)
826   end
827
828   test "refuse to merge user into self" do
829     authorize_with(:active_trustedclient)
830     post(:merge, {
831            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
832            new_owner_uuid: users(:active).uuid,
833            redirect_to_new_user: true,
834          })
835     assert_response(422)
836   end
837
838   [[:active, :project_viewer_trustedclient],
839    [:active_trustedclient, :project_viewer]].each do |src, dst|
840     test "refuse to merge with untrusted token (#{src} -> #{dst})" do
841       authorize_with(src)
842       post(:merge, {
843              new_user_token: api_client_authorizations(dst).api_token,
844              new_owner_uuid: api_client_authorizations(dst).user.uuid,
845              redirect_to_new_user: true,
846            })
847       assert_response(403)
848     end
849   end
850
851   [[:expired_trustedclient, :project_viewer_trustedclient],
852    [:project_viewer_trustedclient, :expired_trustedclient]].each do |src, dst|
853     test "refuse to merge with expired token (#{src} -> #{dst})" do
854       authorize_with(src)
855       post(:merge, {
856              new_user_token: api_client_authorizations(dst).api_token,
857              new_owner_uuid: api_client_authorizations(dst).user.uuid,
858              redirect_to_new_user: true,
859            })
860       assert_response(401)
861     end
862   end
863
864   [['src', :active_trustedclient],
865    ['dst', :project_viewer_trustedclient]].each do |which_scoped, auth|
866     test "refuse to merge with scoped #{which_scoped} token" do
867       act_as_system_user do
868         api_client_authorizations(auth).update_attributes(scopes: ["GET /", "POST /", "PUT /"])
869       end
870       authorize_with(:active_trustedclient)
871       post(:merge, {
872              new_user_token: api_client_authorizations(:project_viewer_trustedclient).api_token,
873              new_owner_uuid: users(:project_viewer).uuid,
874              redirect_to_new_user: true,
875            })
876       assert_response(403)
877     end
878   end
879
880   test "refuse to merge if new_owner_uuid is not writable" do
881     authorize_with(:project_viewer_trustedclient)
882     post(:merge, {
883            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
884            new_owner_uuid: groups(:anonymously_accessible_project).uuid,
885            redirect_to_new_user: true,
886          })
887     assert_response(403)
888   end
889
890   test "refuse to merge if new_owner_uuid is empty" do
891     authorize_with(:project_viewer_trustedclient)
892     post(:merge, {
893            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
894            new_owner_uuid: "",
895            redirect_to_new_user: true,
896          })
897     assert_response(422)
898   end
899
900   test "refuse to merge if new_owner_uuid is not provided" do
901     authorize_with(:project_viewer_trustedclient)
902     post(:merge, {
903            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
904            redirect_to_new_user: true,
905          })
906     assert_response(422)
907   end
908
909   test "refuse to update redirect_to_user_uuid directly" do
910     authorize_with(:active_trustedclient)
911     patch(:update, {
912             id: users(:active).uuid,
913             user: {
914               redirect_to_user_uuid: users(:active).uuid,
915             },
916           })
917     assert_response(403)
918   end
919
920   test "merge 'project_viewer' account into 'active' account" do
921     authorize_with(:project_viewer_trustedclient)
922     post(:merge, {
923            new_user_token: api_client_authorizations(:active_trustedclient).api_token,
924            new_owner_uuid: users(:active).uuid,
925            redirect_to_new_user: true,
926          })
927     assert_response(:success)
928     assert_equal(users(:project_viewer).redirect_to_user_uuid, users(:active).uuid)
929
930     auth = ApiClientAuthorization.validate(token: api_client_authorizations(:project_viewer).api_token)
931     assert_not_nil(auth)
932     assert_not_nil(auth.user)
933     assert_equal(users(:active).uuid, auth.user.uuid)
934   end
935
936   NON_ADMIN_USER_DATA = ["uuid", "kind", "is_active", "email", "first_name",
937                          "last_name", "username"].sort
938
939   def check_non_admin_index
940     assert_response :success
941     response_items = json_response["items"]
942     assert_not_nil response_items
943     response_items.each do |user_data|
944       check_non_admin_item user_data
945       assert(user_data["is_active"], "non-admin index returned inactive user")
946     end
947   end
948
949   def check_non_admin_show
950     assert_response :success
951     check_non_admin_item json_response
952   end
953
954   def check_non_admin_item user_data
955     assert_equal(NON_ADMIN_USER_DATA, user_data.keys.sort,
956                  "data in response had missing or extra attributes")
957     assert_equal("arvados#user", user_data["kind"])
958   end
959
960
961   def check_readable_users_index expect_present, expect_missing
962     response_uuids = json_response["items"].map { |u| u["uuid"] }
963     expect_present.each do |user_key|
964       assert_includes(response_uuids, users(user_key).uuid,
965                       "#{user_key} missing from index")
966     end
967     expect_missing.each do |user_key|
968       refute_includes(response_uuids, users(user_key).uuid,
969                       "#{user_key} included in index")
970     end
971   end
972
973   def check_inactive_user_findable(params={})
974     inactive_user = users(:inactive)
975     get(:index, params.merge(filters: [["email", "=", inactive_user.email]]))
976     assert_response :success
977     user_list = json_response["items"]
978     assert_equal(1, user_list.andand.count)
979     # This test needs to check a column non-admins have no access to,
980     # to ensure that admins see all user information.
981     assert_equal(inactive_user.identity_url, user_list.first["identity_url"],
982                  "admin's filtered index did not return inactive user")
983   end
984
985   def verify_links_added more
986     assert_equal @initial_link_count+more, Link.count,
987         "Started with #{@initial_link_count} links, expected #{more} more"
988   end
989
990   def find_obj_in_resp (response_items, object_type, head_kind=nil)
991     return_obj = nil
992     response_items.each { |x|
993       if !x
994         next
995       end
996
997       if object_type == 'User'
998         if ArvadosModel::resource_class_for_uuid(x['uuid']) == User
999           return_obj = x
1000           break
1001         end
1002       else  # looking for a link
1003         if x['head_uuid'] and ArvadosModel::resource_class_for_uuid(x['head_uuid']).kind == head_kind
1004           return_obj = x
1005           break
1006         end
1007       end
1008     }
1009     return return_obj
1010   end
1011 end