Merge branch 'jszlenk/create_new_subproject' refs #21937
[arvados.git] / services / api / test / integration / permissions_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 PermissionsTest < ActionDispatch::IntegrationTest
8   include DbCurrentTime
9   fixtures :users, :groups, :api_client_authorizations, :collections
10
11   test "adding and removing direct can_read links" do
12     # try to read collection as spectator
13     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
14       params: {:format => :json},
15       headers: auth(:spectator)
16     assert_response 404
17
18     # try to add permission as spectator
19     post "/arvados/v1/links",
20       params: {
21         :format => :json,
22         :link => {
23           tail_uuid: users(:spectator).uuid,
24           link_class: 'permission',
25           name: 'can_read',
26           head_uuid: collections(:foo_file).uuid,
27           properties: {}
28         }
29       },
30       headers: auth(:spectator)
31     assert_response 422
32
33     # add permission as admin
34     post "/arvados/v1/links",
35       params: {
36         :format => :json,
37         :link => {
38           tail_uuid: users(:spectator).uuid,
39           link_class: 'permission',
40           name: 'can_read',
41           head_uuid: collections(:foo_file).uuid,
42           properties: {}
43         }
44       },
45       headers: auth(:admin)
46     u = json_response['uuid']
47     assert_response :success
48
49     # read collection as spectator
50     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
51       params: {:format => :json},
52       headers: auth(:spectator)
53     assert_response :success
54
55     # try to delete permission as spectator
56     delete "/arvados/v1/links/#{u}",
57       params: {:format => :json},
58       headers: auth(:spectator)
59     assert_response 403
60
61     # delete permission as admin
62     delete "/arvados/v1/links/#{u}",
63       params: {:format => :json},
64       headers: auth(:admin)
65     assert_response :success
66
67     # try to read collection as spectator
68     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
69       params: {:format => :json},
70       headers: auth(:spectator)
71     assert_response 404
72   end
73
74
75   test "adding can_read links from user to group, group to collection" do
76     # try to read collection as spectator
77     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
78       params: {:format => :json},
79       headers: auth(:spectator)
80     assert_response 404
81
82     # add permission for spectator to read group
83     post "/arvados/v1/links",
84       params: {
85         :format => :json,
86         :link => {
87           tail_uuid: users(:spectator).uuid,
88           link_class: 'permission',
89           name: 'can_read',
90           head_uuid: groups(:private_role).uuid,
91           properties: {}
92         }
93       },
94       headers: auth(:admin)
95     assert_response :success
96
97     # try to read collection as spectator
98     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
99       params: {:format => :json},
100       headers: auth(:spectator)
101     assert_response 404
102
103     # add permission for group to read collection
104     post "/arvados/v1/links",
105       params: {
106         :format => :json,
107         :link => {
108           tail_uuid: groups(:private_role).uuid,
109           link_class: 'permission',
110           name: 'can_read',
111           head_uuid: collections(:foo_file).uuid,
112           properties: {}
113         }
114       },
115       headers: auth(:admin)
116     u = json_response['uuid']
117     assert_response :success
118
119     # try to read collection as spectator
120     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
121       params: {:format => :json},
122       headers: auth(:spectator)
123     assert_response :success
124
125     # delete permission for group to read collection
126     delete "/arvados/v1/links/#{u}",
127       params: {:format => :json},
128       headers: auth(:admin)
129     assert_response :success
130
131     # try to read collection as spectator
132     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
133       params: {:format => :json},
134       headers: auth(:spectator)
135     assert_response 404
136
137   end
138
139
140   test "adding can_read links from group to collection, user to group" do
141     # try to read collection as spectator
142     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
143       params: {:format => :json},
144       headers: auth(:spectator)
145     assert_response 404
146
147     # add permission for group to read collection
148     post "/arvados/v1/links",
149       params: {
150         :format => :json,
151         :link => {
152           tail_uuid: groups(:private_role).uuid,
153           link_class: 'permission',
154           name: 'can_read',
155           head_uuid: collections(:foo_file).uuid,
156           properties: {}
157         }
158       },
159       headers: auth(:admin)
160     assert_response :success
161
162     # try to read collection as spectator
163     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
164       params: {:format => :json},
165       headers: auth(:spectator)
166     assert_response 404
167
168     # add permission for spectator to read group
169     post "/arvados/v1/links",
170       params: {
171         :format => :json,
172         :link => {
173           tail_uuid: users(:spectator).uuid,
174           link_class: 'permission',
175           name: 'can_read',
176           head_uuid: groups(:private_role).uuid,
177           properties: {}
178         }
179       },
180       headers: auth(:admin)
181     u = json_response['uuid']
182     assert_response :success
183
184     # try to read collection as spectator
185     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
186       params: {:format => :json},
187       headers: auth(:spectator)
188     assert_response :success
189
190     # delete permission for spectator to read group
191     delete "/arvados/v1/links/#{u}",
192       params: {:format => :json},
193       headers: auth(:admin)
194     assert_response :success
195
196     # try to read collection as spectator
197     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
198       params: {:format => :json},
199       headers: auth(:spectator)
200     assert_response 404
201
202   end
203
204   test "adding can_read links from user to group, group to group, group to collection" do
205     # try to read collection as spectator
206     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
207       params: {:format => :json},
208       headers: auth(:spectator)
209     assert_response 404
210
211     # add permission for user to read group
212     post "/arvados/v1/links",
213       params: {
214         :format => :json,
215         :link => {
216           tail_uuid: users(:spectator).uuid,
217           link_class: 'permission',
218           name: 'can_read',
219           head_uuid: groups(:private_role).uuid,
220           properties: {}
221         }
222       },
223       headers: auth(:admin)
224     assert_response :success
225
226     # add permission for group to read group
227     post "/arvados/v1/links",
228       params: {
229         :format => :json,
230         :link => {
231           tail_uuid: groups(:private_role).uuid,
232           link_class: 'permission',
233           name: 'can_read',
234           head_uuid: groups(:empty_lonely_group).uuid,
235           properties: {}
236         }
237       },
238       headers: auth(:admin)
239     assert_response :success
240
241     # add permission for group to read collection
242     post "/arvados/v1/links",
243       params: {
244         :format => :json,
245         :link => {
246           tail_uuid: groups(:empty_lonely_group).uuid,
247           link_class: 'permission',
248           name: 'can_read',
249           head_uuid: collections(:foo_file).uuid,
250           properties: {}
251         }
252       },
253       headers: auth(:admin)
254     u = json_response['uuid']
255     assert_response :success
256
257     # try to read collection as spectator
258     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
259       params: {:format => :json},
260       headers: auth(:spectator)
261     assert_response :success
262
263     # delete permission for group to read collection
264     delete "/arvados/v1/links/#{u}",
265       params: {:format => :json},
266       headers: auth(:admin)
267     assert_response :success
268
269     # try to read collection as spectator
270     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
271       params: {:format => :json},
272       headers: auth(:spectator)
273     assert_response 404
274   end
275
276   test "adding can_read links from group to collection, user to group, then trash group" do
277     # try to read collection as spectator
278     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
279       params: {:format => :json},
280       headers: auth(:spectator)
281     assert_response 404
282
283     # add permission for group to read collection
284     post "/arvados/v1/links",
285       params: {
286         :format => :json,
287         :link => {
288           tail_uuid: groups(:private_role).uuid,
289           link_class: 'permission',
290           name: 'can_read',
291           head_uuid: collections(:foo_file).uuid,
292           properties: {}
293         }
294       },
295       headers: auth(:admin)
296     assert_response :success
297
298     # try to read collection as spectator
299     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
300       params: {:format => :json},
301       headers: auth(:spectator)
302     assert_response 404
303
304     # add permission for spectator to read group
305     post "/arvados/v1/links",
306       params: {
307         :format => :json,
308         :link => {
309           tail_uuid: users(:spectator).uuid,
310           link_class: 'permission',
311           name: 'can_read',
312           head_uuid: groups(:private_role).uuid,
313           properties: {}
314         }
315       },
316       headers: auth(:admin)
317     u = json_response['uuid']
318     assert_response :success
319
320     # try to read collection as spectator
321     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
322       params: {:format => :json},
323       headers: auth(:spectator)
324     assert_response :success
325
326     # put the group in the trash, this should keep the group members
327     # but delete the permissions.
328     post "/arvados/v1/groups/#{groups(:private_role).uuid}/trash",
329       params: {:format => :json},
330       headers: auth(:admin)
331     assert_response :success
332
333     # try to read collection as spectator, should fail now
334     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
335       params: {:format => :json},
336       headers: auth(:spectator)
337     assert_response 404
338
339     # should not be able to grant permission to a trashed group
340     post "/arvados/v1/links",
341       params: {
342         :format => :json,
343         :link => {
344           tail_uuid: groups(:private_role).uuid,
345           link_class: 'permission',
346           name: 'can_read',
347           head_uuid: collections(:foo_file).uuid,
348           properties: {}
349         }
350       },
351       headers: auth(:admin)
352     assert_response 422
353
354     # can't take group out of the trash
355     post "/arvados/v1/groups/#{groups(:private_role).uuid}/untrash",
356       params: {:format => :json},
357       headers: auth(:admin)
358     assert_response 422
359
360     # when a role group is untrashed the permissions don't
361     # automatically come back
362     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
363       params: {:format => :json},
364       headers: auth(:spectator)
365     assert_response 404
366
367     # can't add permission for group to read collection either
368     post "/arvados/v1/links",
369       params: {
370         :format => :json,
371         :link => {
372           tail_uuid: groups(:private_role).uuid,
373           link_class: 'permission',
374           name: 'can_read',
375           head_uuid: collections(:foo_file).uuid,
376           properties: {}
377         }
378       },
379       headers: auth(:admin)
380     assert_response 422
381
382     # still can't read foo file
383     get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
384       params: {:format => :json},
385       headers: auth(:spectator)
386     assert_response 404
387   end
388
389   test "read-only group-admin cannot modify administered user" do
390     put "/arvados/v1/users/#{users(:active).uuid}",
391       params: {
392         :user => {
393           first_name: 'KilroyWasHere'
394         },
395         :format => :json
396       },
397       headers: auth(:rominiadmin)
398     assert_response 403
399   end
400
401   test "read-only group-admin cannot read or update non-administered user" do
402     get "/arvados/v1/users/#{users(:spectator).uuid}",
403       params: {:format => :json},
404       headers: auth(:rominiadmin)
405     assert_response 404
406
407     put "/arvados/v1/users/#{users(:spectator).uuid}",
408       params: {
409         :user => {
410           first_name: 'KilroyWasHere'
411         },
412         :format => :json
413       },
414       headers: auth(:rominiadmin)
415     assert_response 404
416   end
417
418   test "RO group-admin finds user's collections, RW group-admin can update" do
419     other_user_collection = act_as_user(users(:user_foo_in_sharing_group)) do
420       Collection.create()
421     end
422     [[:rominiadmin, false],
423      [:miniadmin, true]].each do |which_user, update_should_succeed|
424       get "/arvados/v1/collections",
425         params: {:format => :json},
426         headers: auth(which_user)
427       assert_response :success
428       resp_uuids = json_response['items'].collect { |i| i['uuid'] }
429       [[true, collections(:collection_owned_by_active).uuid],
430        [true, collections(:foo_collection_in_aproject).uuid],
431        [false, other_user_collection.uuid],
432       ].each do |should_find, uuid|
433         assert_equal(should_find, !resp_uuids.index(uuid).nil?,
434                      "%s should%s see %s in collection list" %
435                      [which_user.to_s,
436                       should_find ? '' : ' not',
437                       uuid])
438         put "/arvados/v1/collections/#{uuid}",
439           params: {
440             :collection => {
441               properties: {
442                 miniadmin_was_here: true
443               }
444             },
445             :format => :json
446           },
447           headers: auth(which_user)
448         if !should_find
449           assert_response 404
450         elsif !update_should_succeed
451           assert_response 403
452         else
453           assert_response :success
454         end
455       end
456     end
457   end
458
459   test "get_permissions returns list" do
460     # First confirm that user :active cannot get permissions on group :public
461     get "/arvados/v1/permissions/#{groups(:public).uuid}",
462       params: nil,
463       headers: auth(:active)
464     assert_response 404
465
466     get "/arvados/v1/links",
467         params: {
468           :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
469         },
470       headers: auth(:active)
471     assert_response :success
472     assert_equal [], json_response['items']
473
474     ### add some permissions, including can_manage
475     ### permission for user :active
476     post "/arvados/v1/links",
477       params: {
478         :format => :json,
479         :link => {
480           tail_uuid: users(:spectator).uuid,
481           link_class: 'permission',
482           name: 'can_read',
483           head_uuid: groups(:public).uuid,
484           properties: {}
485         }
486       },
487       headers: auth(:admin)
488     assert_response :success
489     can_read_uuid = json_response['uuid']
490
491     post "/arvados/v1/links",
492       params: {
493         :format => :json,
494         :link => {
495           tail_uuid: users(:inactive).uuid,
496           link_class: 'permission',
497           name: 'can_write',
498           head_uuid: groups(:public).uuid,
499           properties: {}
500         }
501       },
502       headers: auth(:admin)
503     assert_response :success
504     can_write_uuid = json_response['uuid']
505
506     # Still should not be able read these permission links
507     get "/arvados/v1/permissions/#{groups(:public).uuid}",
508       params: nil,
509       headers: auth(:active)
510     assert_response 404
511
512     get "/arvados/v1/links",
513         params: {
514           :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
515         },
516       headers: auth(:active)
517     assert_response :success
518     assert_equal [], json_response['items']
519
520     # Shouldn't be able to read links directly either
521     get "/arvados/v1/links/#{can_read_uuid}",
522         params: {},
523       headers: auth(:active)
524     assert_response 404
525
526     ### Now add a can_manage link
527     post "/arvados/v1/links",
528       params: {
529         :format => :json,
530         :link => {
531           tail_uuid: users(:active).uuid,
532           link_class: 'permission',
533           name: 'can_manage',
534           head_uuid: groups(:public).uuid,
535           properties: {}
536         }
537       },
538       headers: auth(:admin)
539     assert_response :success
540     can_manage_uuid = json_response['uuid']
541
542     # user :active should be able to retrieve permissions
543     # on group :public using get_permissions
544     get("/arvados/v1/permissions/#{groups(:public).uuid}",
545       params: { :format => :json },
546       headers: auth(:active))
547     assert_response :success
548
549     perm_uuids = json_response['items'].map { |item| item['uuid'] }
550     assert_includes perm_uuids, can_read_uuid, "can_read_uuid not found"
551     assert_includes perm_uuids, can_write_uuid, "can_write_uuid not found"
552     assert_includes perm_uuids, can_manage_uuid, "can_manage_uuid not found"
553
554     # user :active should be able to retrieve permissions
555     # on group :public using link list
556     get "/arvados/v1/links",
557         params: {
558           :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
559         },
560       headers: auth(:active)
561     assert_response :success
562
563     perm_uuids = json_response['items'].map { |item| item['uuid'] }
564     assert_includes perm_uuids, can_read_uuid, "can_read_uuid not found"
565     assert_includes perm_uuids, can_write_uuid, "can_write_uuid not found"
566     assert_includes perm_uuids, can_manage_uuid, "can_manage_uuid not found"
567
568     # Should be able to read links directly too
569     get "/arvados/v1/links/#{can_read_uuid}",
570       headers: auth(:active)
571     assert_response :success
572
573     ### Create some objects of different types (other than projects)
574     ### inside a subproject inside the shared project, and share those
575     ### individual objects with a 3rd user ("spectator").
576     post '/arvados/v1/groups',
577          params: {
578            group: {
579              owner_uuid: groups(:public).uuid,
580              name: 'permission test subproject',
581              group_class: 'project',
582            },
583          },
584          headers: auth(:admin)
585     assert_response :success
586     subproject_uuid = json_response['uuid']
587
588     test_types = ['collection', 'workflow', 'container_request']
589     test_type_create_attrs = {
590       'container_request' => {
591         command: ["echo", "foo"],
592         container_image: links(:docker_image_collection_tag).name,
593         cwd: "/tmp",
594         environment: {},
595         mounts: {"/out" => {kind: "tmp", capacity: 1000000}},
596         output_path: "/out",
597         runtime_constraints: {"vcpus" => 1, "ram" => 2},
598       },
599     }
600
601     test_object = {}
602     test_object_perm_link = {}
603     test_types.each do |test_type|
604       post "/arvados/v1/#{test_type}s",
605            params: {
606              test_type.to_sym => {
607                owner_uuid: subproject_uuid,
608                name: "permission test #{test_type} in subproject",
609              }.merge(test_type_create_attrs[test_type] || {}).to_json,
610            },
611            headers: auth(:admin)
612       assert_response :success
613       test_object[test_type] = json_response
614
615       post '/arvados/v1/links',
616            params: {
617              link: {
618                tail_uuid: users(:spectator).uuid,
619                link_class: 'permission',
620                name: 'can_read',
621                head_uuid: test_object[test_type]['uuid'],
622              }
623            },
624            headers: auth(:admin)
625       assert_response :success
626       test_object_perm_link[test_type] = json_response
627     end
628
629     # The "active-can_manage-project" permission should cause the
630     # "spectator-can_read-object" links to be visible to the "active"
631     # user.
632     test_types.each do |test_type|
633       get "/arvados/v1/permissions/#{test_object[test_type]['uuid']}",
634           headers: auth(:active)
635       assert_response :success
636       perm_uuids = json_response['items'].map { |item| item['uuid'] }
637       assert_includes perm_uuids, test_object_perm_link[test_type]['uuid'], "can_read_uuid not found"
638
639       get "/arvados/v1/links/#{test_object_perm_link[test_type]['uuid']}",
640           headers: auth(:active)
641       assert_response :success
642
643       [
644         ['head_uuid', '=', test_object[test_type]['uuid']],
645         ['head_uuid', 'in', [test_object[test_type]['uuid']]],
646         ['head_uuid', 'in', [users(:admin).uuid, test_object[test_type]['uuid']]],
647       ].each do |filter|
648         get "/arvados/v1/links",
649             params: {
650               filters: ([['link_class', '=', 'permission'], filter]).to_json,
651             },
652             headers: auth(:active)
653         assert_response :success
654         assert_not_empty json_response['items'], "could not find can_read link using index with filter #{filter}"
655         assert_equal test_object_perm_link[test_type]['uuid'], json_response['items'][0]['uuid']
656       end
657
658       # The "spectator-can_read-object" link should be visible to the
659       # subject user ("spectator") in a filter query, even without
660       # can_manage permission on the target object.
661       [
662         ['tail_uuid', '=', users(:spectator).uuid],
663       ].each do |filter|
664         get "/arvados/v1/links",
665             params: {
666               filters: ([['link_class', '=', 'permission'], filter]).to_json,
667             },
668             headers: auth(:spectator)
669         assert_response :success
670         perm_uuids = json_response['items'].map { |item| item['uuid'] }
671         assert_includes perm_uuids, test_object_perm_link[test_type]['uuid'], "could not find can_read link using index with filter #{filter}"
672       end
673     end
674
675     ### Now delete the can_manage link
676     delete "/arvados/v1/links/#{can_manage_uuid}",
677       headers: auth(:active)
678     assert_response :success
679
680     # Should not be able read these permission links again
681     test_types.each do |test_type|
682       get "/arvados/v1/permissions/#{groups(:public).uuid}",
683           headers: auth(:active)
684       assert_response 404
685
686       get "/arvados/v1/permissions/#{test_object[test_type]['uuid']}",
687           headers: auth(:active)
688       assert_response 404
689
690       get "/arvados/v1/links",
691           params: {
692             filters: [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
693           },
694           headers: auth(:active)
695       assert_response :success
696       assert_equal [], json_response['items']
697
698       [
699         ['head_uuid', '=', test_object[test_type]['uuid']],
700         ['head_uuid', 'in', [users(:admin).uuid, test_object[test_type]['uuid']]],
701         ['head_uuid', 'in', []],
702       ].each do |filter|
703         get "/arvados/v1/links",
704             params: {
705               :filters => [["link_class", "=", "permission"], filter].to_json
706             },
707             headers: auth(:active)
708         assert_response :success
709         assert_equal [], json_response['items']
710       end
711
712       # Should not be able to read links directly either
713       get "/arvados/v1/links/#{can_read_uuid}",
714           headers: auth(:active)
715       assert_response 404
716
717       test_types.each do |test_type|
718         get "/arvados/v1/links/#{test_object_perm_link[test_type]['uuid']}",
719             headers: auth(:active)
720         assert_response 404
721       end
722     end
723
724     ### Create a collection, and share it with a direct permission
725     ### link (as opposed to sharing its parent project)
726     post "/arvados/v1/collections",
727       params: {
728         collection: {
729           name: 'permission test',
730         }
731       },
732       headers: auth(:admin)
733     assert_response :success
734     collection_uuid = json_response['uuid']
735     post "/arvados/v1/links",
736       params: {
737         link: {
738           tail_uuid: users(:spectator).uuid,
739           link_class: 'permission',
740           name: 'can_read',
741           head_uuid: collection_uuid,
742           properties: {}
743         }
744       },
745       headers: auth(:admin)
746     assert_response :success
747     can_read_collection_uuid = json_response['uuid']
748
749     # Should not be able read the permission link via permissions API,
750     # because permission is only can_read, not can_manage
751     get "/arvados/v1/permissions/#{collection_uuid}",
752       headers: auth(:active)
753     assert_response 404
754
755     # Should not be able to read the permission link directly, for
756     # same reason
757     get "/arvados/v1/links/#{can_read_collection_uuid}",
758       headers: auth(:active)
759     assert_response 404
760
761     ### Now add a can_manage link
762     post "/arvados/v1/links",
763       params: {
764         link: {
765           tail_uuid: users(:active).uuid,
766           link_class: 'permission',
767           name: 'can_manage',
768           head_uuid: collection_uuid,
769           properties: {}
770         }
771       },
772       headers: auth(:admin)
773     assert_response :success
774     can_manage_collection_uuid = json_response['uuid']
775
776     # Should be able read both permission links via permissions API
777     get "/arvados/v1/permissions/#{collection_uuid}",
778       headers: auth(:active)
779     assert_response :success
780     perm_uuids = json_response['items'].map { |item| item['uuid'] }
781     assert_includes perm_uuids, can_read_collection_uuid, "can_read_uuid not found"
782     assert_includes perm_uuids, can_manage_collection_uuid, "can_manage_uuid not found"
783
784     # Should be able to read both permission links directly
785     [can_read_collection_uuid, can_manage_collection_uuid].each do |uuid|
786       get "/arvados/v1/links/#{uuid}",
787         headers: auth(:active)
788       assert_response :success
789     end
790   end
791
792   test "get_permissions returns 404 for nonexistent uuid" do
793     nonexistent = Group.generate_uuid
794     # make sure it really doesn't exist
795     get "/arvados/v1/groups/#{nonexistent}", params: nil, headers: auth(:admin)
796     assert_response 404
797
798     get "/arvados/v1/permissions/#{nonexistent}", params: nil, headers: auth(:active)
799     assert_response 404
800   end
801
802   test "get_permissions returns 403 if user can read but not manage" do
803     post "/arvados/v1/links",
804       params: {
805         :link => {
806           tail_uuid: users(:active).uuid,
807           link_class: 'permission',
808           name: 'can_read',
809           head_uuid: groups(:public).uuid,
810           properties: {}
811         }
812       },
813       headers: auth(:admin)
814     assert_response :success
815
816     get "/arvados/v1/permissions/#{groups(:public).uuid}",
817       params: nil,
818       headers: auth(:active)
819     assert_response 403
820   end
821
822   test "active user can read the empty collection" do
823     # The active user should be able to read the empty collection.
824
825     get("/arvados/v1/collections/#{empty_collection_pdh}",
826       params: {:format => :json},
827       headers: auth(:active))
828     assert_response :success
829     assert_empty json_response['manifest_text'], "empty collection manifest_text is not empty"
830   end
831
832   [['can_write', 'can_read', 'can_write'],
833    ['can_manage', 'can_write', 'can_manage'],
834    ['can_manage', 'can_read', 'can_manage'],
835    ['can_read', 'can_write', 'can_write'],
836    ['can_read', 'can_manage', 'can_manage'],
837    ['can_write', 'can_manage', 'can_manage'],
838   ].each do |perm1, perm2, expect|
839     test "creating #{perm2} permission returns existing #{perm1} link as #{expect}" do
840       link1 = act_as_system_user do
841         Link.create!({
842                        link_class: "permission",
843                        tail_uuid: users(:active).uuid,
844                        head_uuid: collections(:baz_file).uuid,
845                        name: perm1,
846                      })
847       end
848       post "/arvados/v1/links",
849            params: {
850              link: {
851                link_class: "permission",
852                tail_uuid: users(:active).uuid,
853                head_uuid: collections(:baz_file).uuid,
854                name: perm2,
855              },
856            },
857            headers: auth(:admin)
858       assert_response :success
859       assert_equal link1.uuid, json_response["uuid"]
860       assert_equal expect, json_response["name"]
861       link1.reload
862       assert_equal expect, link1.name
863     end
864   end
865
866   test "creating duplicate login permission returns existing link" do
867     link1 = act_as_system_user do
868       Link.create!({
869                      link_class: "permission",
870                      tail_uuid: users(:active).uuid,
871                      head_uuid: virtual_machines(:testvm2).uuid,
872                      name: "can_login",
873                      properties: {"username": "foo1"}
874                    })
875     end
876     link2 = act_as_system_user do
877       Link.create!({
878                      link_class: "permission",
879                      tail_uuid: users(:active).uuid,
880                      head_uuid: virtual_machines(:testvm2).uuid,
881                      name: "can_login",
882                      properties: {"username": "foo2"}
883                    })
884     end
885     link3 = act_as_system_user do
886       Link.create!({
887                      link_class: "permission",
888                      tail_uuid: users(:active).uuid,
889                      head_uuid: virtual_machines(:testvm2).uuid,
890                      name: "can_read",
891                    })
892     end
893     post "/arvados/v1/links",
894          params: {
895            link: {
896              link_class: "permission",
897              tail_uuid: users(:active).uuid,
898              head_uuid: virtual_machines(:testvm2).uuid,
899              name: "can_login",
900              properties: {"username": "foo2"},
901            },
902          },
903          headers: auth(:admin)
904     assert_response :success
905     assert_equal link2.uuid, json_response["uuid"]
906     assert_equal link2.created_at.to_date, json_response["created_at"].to_date
907     assert_equal "can_login", json_response["name"]
908     assert_equal "foo2", json_response["properties"]["username"]
909     link1.reload
910     assert_equal "foo1", link1.properties["username"]
911     link2.reload
912     assert_equal "foo2", link2.properties["username"]
913   end
914 end