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 a collection inside a subproject inside the shared
458 ### project, and share the collection with a 3rd user
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 post '/arvados/v1/collections',
475 owner_uuid: subproject_uuid,
476 name: 'permission test collection in subproject',
479 headers: auth(:admin)
480 assert_response :success
481 collection_uuid = json_response['uuid']
483 post '/arvados/v1/links',
486 tail_uuid: users(:spectator).uuid,
487 link_class: 'permission',
489 head_uuid: collection_uuid,
492 headers: auth(:admin)
493 assert_response :success
494 can_read_collection_uuid = json_response['uuid']
496 # The "active-can_manage-project" permission should cause the
497 # "spectator-can_read-collection" link to be visible to the
499 get "/arvados/v1/permissions/#{collection_uuid}",
500 headers: auth(:active)
501 assert_response :success
502 perm_uuids = json_response['items'].map { |item| item['uuid'] }
503 assert_includes perm_uuids, can_read_collection_uuid, "can_read_uuid not found"
505 get "/arvados/v1/links/#{can_read_collection_uuid}",
506 headers: auth(:active)
507 assert_response :success
510 ['head_uuid', '=', collection_uuid],
511 ['head_uuid', 'in', [collection_uuid]],
512 ['head_uuid', 'in', [users(:admin).uuid, collection_uuid]],
514 get "/arvados/v1/links",
516 filters: ([['link_class', '=', 'permission'], filter]).to_json,
518 headers: auth(:active)
519 assert_response :success
520 assert_not_empty json_response['items'], "could not find can_read link using index with filter #{filter}"
521 assert_equal can_read_collection_uuid, json_response['items'][0]['uuid']
524 # The "spectator-can_read-collection" link should be visible to
525 # the subject user ("spectator") in a filter query, even without
526 # can_manage permission on the target object.
528 ['tail_uuid', '=', users(:spectator).uuid],
530 get "/arvados/v1/links",
532 filters: ([['link_class', '=', 'permission'], filter]).to_json,
534 headers: auth(:spectator)
535 assert_response :success
536 perm_uuids = json_response['items'].map { |item| item['uuid'] }
537 assert_includes perm_uuids, can_read_collection_uuid, "could not find can_read link using index with filter #{filter}"
540 ### Now delete the can_manage link
541 delete "/arvados/v1/links/#{can_manage_uuid}",
542 headers: auth(:active)
543 assert_response :success
545 # Should not be able read these permission links again
546 get "/arvados/v1/permissions/#{groups(:public).uuid}",
547 headers: auth(:active)
550 get "/arvados/v1/permissions/#{collection_uuid}",
551 headers: auth(:active)
554 get "/arvados/v1/links",
556 filters: [["link_class", "=", "permission"], ["head_uuid", "=", groups(:public).uuid]].to_json
558 headers: auth(:active)
559 assert_response :success
560 assert_equal [], json_response['items']
563 ['head_uuid', '=', collection_uuid],
564 ['head_uuid', 'in', [users(:admin).uuid, collection_uuid]],
565 ['head_uuid', 'in', []],
567 get "/arvados/v1/links",
569 :filters => [["link_class", "=", "permission"], filter].to_json
571 headers: auth(:active)
572 assert_response :success
573 assert_equal [], json_response['items']
576 # Should not be able to read links directly either
577 get "/arvados/v1/links/#{can_read_uuid}",
579 headers: auth(:active)
582 get "/arvados/v1/links/#{can_read_collection_uuid}",
583 headers: auth(:active)
586 ### Create a collection, and share it with a direct permission
587 ### link (as opposed to sharing its parent project)
588 post "/arvados/v1/collections",
591 name: 'permission test',
594 headers: auth(:admin)
595 assert_response :success
596 collection_uuid = json_response['uuid']
597 post "/arvados/v1/links",
600 tail_uuid: users(:spectator).uuid,
601 link_class: 'permission',
603 head_uuid: collection_uuid,
607 headers: auth(:admin)
608 assert_response :success
609 can_read_collection_uuid = json_response['uuid']
611 # Should not be able read the permission link via permissions API,
612 # because permission is only can_read, not can_manage
613 get "/arvados/v1/permissions/#{collection_uuid}",
614 headers: auth(:active)
617 # Should not be able to read the permission link directly, for
619 get "/arvados/v1/links/#{can_read_collection_uuid}",
620 headers: auth(:active)
623 ### Now add a can_manage link
624 post "/arvados/v1/links",
627 tail_uuid: users(:active).uuid,
628 link_class: 'permission',
630 head_uuid: collection_uuid,
634 headers: auth(:admin)
635 assert_response :success
636 can_manage_collection_uuid = json_response['uuid']
638 # Should be able read both permission links via permissions API
639 get "/arvados/v1/permissions/#{collection_uuid}",
640 headers: auth(:active)
641 assert_response :success
642 perm_uuids = json_response['items'].map { |item| item['uuid'] }
643 assert_includes perm_uuids, can_read_collection_uuid, "can_read_uuid not found"
644 assert_includes perm_uuids, can_manage_collection_uuid, "can_manage_uuid not found"
646 # Should be able to read both permission links directly
647 [can_read_collection_uuid, can_manage_collection_uuid].each do |uuid|
648 get "/arvados/v1/links/#{uuid}",
649 headers: auth(:active)
650 assert_response :success
654 test "get_permissions returns 404 for nonexistent uuid" do
655 nonexistent = Group.generate_uuid
656 # make sure it really doesn't exist
657 get "/arvados/v1/groups/#{nonexistent}", params: nil, headers: auth(:admin)
660 get "/arvados/v1/permissions/#{nonexistent}", params: nil, headers: auth(:active)
664 test "get_permissions returns 403 if user can read but not manage" do
665 post "/arvados/v1/links",
668 tail_uuid: users(:active).uuid,
669 link_class: 'permission',
671 head_uuid: groups(:public).uuid,
675 headers: auth(:admin)
676 assert_response :success
678 get "/arvados/v1/permissions/#{groups(:public).uuid}",
680 headers: auth(:active)
684 test "active user can read the empty collection" do
685 # The active user should be able to read the empty collection.
687 get("/arvados/v1/collections/#{empty_collection_pdh}",
688 params: {:format => :json},
689 headers: auth(:active))
690 assert_response :success
691 assert_empty json_response['manifest_text'], "empty collection manifest_text is not empty"