1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
7 class PermissionsTest < ActionDispatch::IntegrationTest
9 fixtures :users, :groups, :api_client_authorizations, :collections
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)
18 # try to add permission as spectator
19 post "/arvados/v1/links",
23 tail_uuid: users(:spectator).uuid,
24 link_class: 'permission',
26 head_uuid: collections(:foo_file).uuid,
30 headers: auth(:spectator)
33 # add permission as admin
34 post "/arvados/v1/links",
38 tail_uuid: users(:spectator).uuid,
39 link_class: 'permission',
41 head_uuid: collections(:foo_file).uuid,
46 u = json_response['uuid']
47 assert_response :success
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
55 # try to delete permission as spectator
56 delete "/arvados/v1/links/#{u}",
57 params: {:format => :json},
58 headers: auth(:spectator)
61 # delete permission as admin
62 delete "/arvados/v1/links/#{u}",
63 params: {:format => :json},
65 assert_response :success
67 # try to read collection as spectator
68 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
69 params: {:format => :json},
70 headers: auth(:spectator)
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)
82 # add permission for spectator to read group
83 post "/arvados/v1/links",
87 tail_uuid: users(:spectator).uuid,
88 link_class: 'permission',
90 head_uuid: groups(:private_role).uuid,
95 assert_response :success
97 # try to read collection as spectator
98 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
99 params: {:format => :json},
100 headers: auth(:spectator)
103 # add permission for group to read collection
104 post "/arvados/v1/links",
108 tail_uuid: groups(:private_role).uuid,
109 link_class: 'permission',
111 head_uuid: collections(:foo_file).uuid,
115 headers: auth(:admin)
116 u = json_response['uuid']
117 assert_response :success
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
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
131 # try to read collection as spectator
132 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
133 params: {:format => :json},
134 headers: auth(:spectator)
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)
147 # add permission for group to read collection
148 post "/arvados/v1/links",
152 tail_uuid: groups(:private_role).uuid,
153 link_class: 'permission',
155 head_uuid: collections(:foo_file).uuid,
159 headers: auth(:admin)
160 assert_response :success
162 # try to read collection as spectator
163 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
164 params: {:format => :json},
165 headers: auth(:spectator)
168 # add permission for spectator to read group
169 post "/arvados/v1/links",
173 tail_uuid: users(:spectator).uuid,
174 link_class: 'permission',
176 head_uuid: groups(:private_role).uuid,
180 headers: auth(:admin)
181 u = json_response['uuid']
182 assert_response :success
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
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
196 # try to read collection as spectator
197 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
198 params: {:format => :json},
199 headers: auth(:spectator)
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)
211 # add permission for user to read group
212 post "/arvados/v1/links",
216 tail_uuid: users(:spectator).uuid,
217 link_class: 'permission',
219 head_uuid: groups(:private_role).uuid,
223 headers: auth(:admin)
224 assert_response :success
226 # add permission for group to read group
227 post "/arvados/v1/links",
231 tail_uuid: groups(:private_role).uuid,
232 link_class: 'permission',
234 head_uuid: groups(:empty_lonely_group).uuid,
238 headers: auth(:admin)
239 assert_response :success
241 # add permission for group to read collection
242 post "/arvados/v1/links",
246 tail_uuid: groups(:empty_lonely_group).uuid,
247 link_class: 'permission',
249 head_uuid: collections(:foo_file).uuid,
253 headers: auth(:admin)
254 u = json_response['uuid']
255 assert_response :success
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
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
269 # try to read collection as spectator
270 get "/arvados/v1/collections/#{collections(:foo_file).uuid}",
271 params: {:format => :json},
272 headers: auth(:spectator)
276 test "read-only group-admin cannot modify administered user" do
277 put "/arvados/v1/users/#{users(:active).uuid}",
280 first_name: 'KilroyWasHere'
284 headers: auth(:rominiadmin)
288 test "read-only group-admin cannot read or update non-administered user" do
289 get "/arvados/v1/users/#{users(:spectator).uuid}",
290 params: {:format => :json},
291 headers: auth(:rominiadmin)
294 put "/arvados/v1/users/#{users(:spectator).uuid}",
297 first_name: 'KilroyWasHere'
301 headers: auth(:rominiadmin)
305 test "RO group-admin finds user's specimens, RW group-admin can update" do
306 [[:rominiadmin, false],
307 [:miniadmin, true]].each do |which_user, update_should_succeed|
308 get "/arvados/v1/specimens",
309 params: {:format => :json},
310 headers: auth(which_user)
311 assert_response :success
312 resp_uuids = json_response['items'].collect { |i| i['uuid'] }
313 [[true, specimens(:owned_by_active_user).uuid],
314 [true, specimens(:owned_by_private_group).uuid],
315 [false, specimens(:owned_by_spectator).uuid],
316 ].each do |should_find, uuid|
317 assert_equal(should_find, !resp_uuids.index(uuid).nil?,
318 "%s should%s see %s in specimen list" %
320 should_find ? '' : 'not ',
322 put "/arvados/v1/specimens/#{uuid}",
326 miniadmin_was_here: true
331 headers: auth(which_user)
334 elsif !update_should_succeed
337 assert_response :success
343 test "get_permissions returns list" do
344 # First confirm that user :active cannot get permissions on group :public
345 get "/arvados/v1/permissions/#{groups(:public).uuid}",
347 headers: auth(:active)
350 get "/arvados/v1/links",
352 :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
354 headers: auth(:active)
355 assert_response :success
356 assert_equal [], json_response['items']
358 ### add some permissions, including can_manage
359 ### permission for user :active
360 post "/arvados/v1/links",
364 tail_uuid: users(:spectator).uuid,
365 link_class: 'permission',
367 head_uuid: groups(:public).uuid,
371 headers: auth(:admin)
372 assert_response :success
373 can_read_uuid = json_response['uuid']
375 post "/arvados/v1/links",
379 tail_uuid: users(:inactive).uuid,
380 link_class: 'permission',
382 head_uuid: groups(:public).uuid,
386 headers: auth(:admin)
387 assert_response :success
388 can_write_uuid = json_response['uuid']
390 # Still should not be able read these permission links
391 get "/arvados/v1/permissions/#{groups(:public).uuid}",
393 headers: auth(:active)
396 get "/arvados/v1/links",
398 :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
400 headers: auth(:active)
401 assert_response :success
402 assert_equal [], json_response['items']
404 # Shouldn't be able to read links directly either
405 get "/arvados/v1/links/#{can_read_uuid}",
407 headers: auth(:active)
410 ### Now add a can_manage link
411 post "/arvados/v1/links",
415 tail_uuid: users(:active).uuid,
416 link_class: 'permission',
418 head_uuid: groups(:public).uuid,
422 headers: auth(:admin)
423 assert_response :success
424 can_manage_uuid = json_response['uuid']
426 # user :active should be able to retrieve permissions
427 # on group :public using get_permissions
428 get("/arvados/v1/permissions/#{groups(:public).uuid}",
429 params: { :format => :json },
430 headers: auth(:active))
431 assert_response :success
433 perm_uuids = json_response['items'].map { |item| item['uuid'] }
434 assert_includes perm_uuids, can_read_uuid, "can_read_uuid not found"
435 assert_includes perm_uuids, can_write_uuid, "can_write_uuid not found"
436 assert_includes perm_uuids, can_manage_uuid, "can_manage_uuid not found"
438 # user :active should be able to retrieve permissions
439 # on group :public using link list
440 get "/arvados/v1/links",
442 :filters => [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
444 headers: auth(:active)
445 assert_response :success
447 perm_uuids = json_response['items'].map { |item| item['uuid'] }
448 assert_includes perm_uuids, can_read_uuid, "can_read_uuid not found"
449 assert_includes perm_uuids, can_write_uuid, "can_write_uuid not found"
450 assert_includes perm_uuids, can_manage_uuid, "can_manage_uuid not found"
452 # Should be able to read links directly too
453 get "/arvados/v1/links/#{can_read_uuid}",
454 headers: auth(:active)
455 assert_response :success
457 ### Create some objects of different types (other than projects)
458 ### inside a subproject inside the shared project, and share those
459 ### individual objects with a 3rd user ("spectator").
460 post '/arvados/v1/groups',
463 owner_uuid: groups(:public).uuid,
464 name: 'permission test subproject',
465 group_class: 'project',
468 headers: auth(:admin)
469 assert_response :success
470 subproject_uuid = json_response['uuid']
472 test_types = ['collection', 'workflow', 'container_request']
473 test_type_create_attrs = {
474 'container_request' => {
475 command: ["echo", "foo"],
476 container_image: links(:docker_image_collection_tag).name,
479 mounts: {"/out" => {kind: "tmp", capacity: 1000000}},
481 runtime_constraints: {"vcpus" => 1, "ram" => 2},
486 test_object_perm_link = {}
487 test_types.each do |test_type|
488 post "/arvados/v1/#{test_type}s",
490 test_type.to_sym => {
491 owner_uuid: subproject_uuid,
492 name: "permission test #{test_type} in subproject",
493 }.merge(test_type_create_attrs[test_type] || {}).to_json,
495 headers: auth(:admin)
496 assert_response :success
497 test_object[test_type] = json_response
499 post '/arvados/v1/links',
502 tail_uuid: users(:spectator).uuid,
503 link_class: 'permission',
505 head_uuid: test_object[test_type]['uuid'],
508 headers: auth(:admin)
509 assert_response :success
510 test_object_perm_link[test_type] = json_response
513 # The "active-can_manage-project" permission should cause the
514 # "spectator-can_read-object" links to be visible to the "active"
516 test_types.each do |test_type|
517 get "/arvados/v1/permissions/#{test_object[test_type]['uuid']}",
518 headers: auth(:active)
519 assert_response :success
520 perm_uuids = json_response['items'].map { |item| item['uuid'] }
521 assert_includes perm_uuids, test_object_perm_link[test_type]['uuid'], "can_read_uuid not found"
523 get "/arvados/v1/links/#{test_object_perm_link[test_type]['uuid']}",
524 headers: auth(:active)
525 assert_response :success
528 ['head_uuid', '=', test_object[test_type]['uuid']],
529 ['head_uuid', 'in', [test_object[test_type]['uuid']]],
530 ['head_uuid', 'in', [users(:admin).uuid, test_object[test_type]['uuid']]],
532 get "/arvados/v1/links",
534 filters: ([['link_class', '=', 'permission'], filter]).to_json,
536 headers: auth(:active)
537 assert_response :success
538 assert_not_empty json_response['items'], "could not find can_read link using index with filter #{filter}"
539 assert_equal test_object_perm_link[test_type]['uuid'], json_response['items'][0]['uuid']
542 # The "spectator-can_read-object" link should be visible to the
543 # subject user ("spectator") in a filter query, even without
544 # can_manage permission on the target object.
546 ['tail_uuid', '=', users(:spectator).uuid],
548 get "/arvados/v1/links",
550 filters: ([['link_class', '=', 'permission'], filter]).to_json,
552 headers: auth(:spectator)
553 assert_response :success
554 perm_uuids = json_response['items'].map { |item| item['uuid'] }
555 assert_includes perm_uuids, test_object_perm_link[test_type]['uuid'], "could not find can_read link using index with filter #{filter}"
559 ### Now delete the can_manage link
560 delete "/arvados/v1/links/#{can_manage_uuid}",
561 headers: auth(:active)
562 assert_response :success
564 # Should not be able read these permission links again
565 test_types.each do |test_type|
566 get "/arvados/v1/permissions/#{groups(:public).uuid}",
567 headers: auth(:active)
570 get "/arvados/v1/permissions/#{test_object[test_type]['uuid']}",
571 headers: auth(:active)
574 get "/arvados/v1/links",
576 filters: [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
578 headers: auth(:active)
579 assert_response :success
580 assert_equal [], json_response['items']
583 ['head_uuid', '=', test_object[test_type]['uuid']],
584 ['head_uuid', 'in', [users(:admin).uuid, test_object[test_type]['uuid']]],
585 ['head_uuid', 'in', []],
587 get "/arvados/v1/links",
589 :filters => [["link_class", "=", "permission"], filter].to_json
591 headers: auth(:active)
592 assert_response :success
593 assert_equal [], json_response['items']
596 # Should not be able to read links directly either
597 get "/arvados/v1/links/#{can_read_uuid}",
598 headers: auth(:active)
601 test_types.each do |test_type|
602 get "/arvados/v1/links/#{test_object_perm_link[test_type]['uuid']}",
603 headers: auth(:active)
608 ### Create a collection, and share it with a direct permission
609 ### link (as opposed to sharing its parent project)
610 post "/arvados/v1/collections",
613 name: 'permission test',
616 headers: auth(:admin)
617 assert_response :success
618 collection_uuid = json_response['uuid']
619 post "/arvados/v1/links",
622 tail_uuid: users(:spectator).uuid,
623 link_class: 'permission',
625 head_uuid: collection_uuid,
629 headers: auth(:admin)
630 assert_response :success
631 can_read_collection_uuid = json_response['uuid']
633 # Should not be able read the permission link via permissions API,
634 # because permission is only can_read, not can_manage
635 get "/arvados/v1/permissions/#{collection_uuid}",
636 headers: auth(:active)
639 # Should not be able to read the permission link directly, for
641 get "/arvados/v1/links/#{can_read_collection_uuid}",
642 headers: auth(:active)
645 ### Now add a can_manage link
646 post "/arvados/v1/links",
649 tail_uuid: users(:active).uuid,
650 link_class: 'permission',
652 head_uuid: collection_uuid,
656 headers: auth(:admin)
657 assert_response :success
658 can_manage_collection_uuid = json_response['uuid']
660 # Should be able read both permission links via permissions API
661 get "/arvados/v1/permissions/#{collection_uuid}",
662 headers: auth(:active)
663 assert_response :success
664 perm_uuids = json_response['items'].map { |item| item['uuid'] }
665 assert_includes perm_uuids, can_read_collection_uuid, "can_read_uuid not found"
666 assert_includes perm_uuids, can_manage_collection_uuid, "can_manage_uuid not found"
668 # Should be able to read both permission links directly
669 [can_read_collection_uuid, can_manage_collection_uuid].each do |uuid|
670 get "/arvados/v1/links/#{uuid}",
671 headers: auth(:active)
672 assert_response :success
676 test "get_permissions returns 404 for nonexistent uuid" do
677 nonexistent = Group.generate_uuid
678 # make sure it really doesn't exist
679 get "/arvados/v1/groups/#{nonexistent}", params: nil, headers: auth(:admin)
682 get "/arvados/v1/permissions/#{nonexistent}", params: nil, headers: auth(:active)
686 test "get_permissions returns 403 if user can read but not manage" do
687 post "/arvados/v1/links",
690 tail_uuid: users(:active).uuid,
691 link_class: 'permission',
693 head_uuid: groups(:public).uuid,
697 headers: auth(:admin)
698 assert_response :success
700 get "/arvados/v1/permissions/#{groups(:public).uuid}",
702 headers: auth(:active)
706 test "active user can read the empty collection" do
707 # The active user should be able to read the empty collection.
709 get("/arvados/v1/collections/#{empty_collection_pdh}",
710 params: {:format => :json},
711 headers: auth(:active))
712 assert_response :success
713 assert_empty json_response['manifest_text'], "empty collection manifest_text is not empty"