17111: Deselect unsigned_manifest_text by default in groups#contents.
[arvados.git] / services / api / test / functional / arvados / v1 / groups_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
7 class Arvados::V1::GroupsControllerTest < ActionController::TestCase
8
9   test "attempt to delete group without read or write access" do
10     authorize_with :active
11     post :destroy, params: {id: groups(:empty_lonely_group).uuid}
12     assert_response 404
13   end
14
15   test "attempt to delete group without write access" do
16     authorize_with :active
17     post :destroy, params: {id: groups(:all_users).uuid}
18     assert_response 403
19   end
20
21   test "get list of projects" do
22     authorize_with :active
23     get :index, params: {filters: [['group_class', '=', 'project']], format: :json}
24     assert_response :success
25     group_uuids = []
26     json_response['items'].each do |group|
27       assert_equal 'project', group['group_class']
28       group_uuids << group['uuid']
29     end
30     assert_includes group_uuids, groups(:aproject).uuid
31     assert_includes group_uuids, groups(:asubproject).uuid
32     assert_includes group_uuids, groups(:private).uuid
33     assert_not_includes group_uuids, groups(:system_group).uuid
34     assert_not_includes group_uuids, groups(:private_and_can_read_foofile).uuid
35   end
36
37   test "get list of groups that are not projects" do
38     authorize_with :active
39     get :index, params: {filters: [['group_class', '!=', 'project']], format: :json}
40     assert_response :success
41     group_uuids = []
42     json_response['items'].each do |group|
43       assert_not_equal 'project', group['group_class']
44       group_uuids << group['uuid']
45     end
46     assert_not_includes group_uuids, groups(:aproject).uuid
47     assert_not_includes group_uuids, groups(:asubproject).uuid
48   end
49
50   test "get list of groups with bogus group_class" do
51     authorize_with :active
52     get :index, params: {
53       filters: [['group_class', '=', 'nogrouphasthislittleclass']],
54       format: :json,
55     }
56     assert_response :success
57     assert_equal [], json_response['items']
58     assert_equal 0, json_response['items_available']
59   end
60
61   def check_project_contents_response disabled_kinds=[]
62     assert_response :success
63     assert_operator 2, :<=, json_response['items_available']
64     assert_operator 2, :<=, json_response['items'].count
65     kinds = json_response['items'].collect { |i| i['kind'] }.uniq
66     expect_kinds = %w'arvados#group arvados#specimen arvados#pipelineTemplate arvados#job' - disabled_kinds
67     assert_equal expect_kinds, (expect_kinds & kinds)
68
69     json_response['items'].each do |i|
70       if i['kind'] == 'arvados#group'
71         assert(i['group_class'] == 'project',
72                "group#contents returned a non-project group")
73       end
74     end
75
76     disabled_kinds.each do |d|
77       assert_equal true, !kinds.include?(d)
78     end
79   end
80
81   test 'get group-owned objects' do
82     authorize_with :active
83     get :contents, params: {
84       id: groups(:aproject).uuid,
85       format: :json,
86     }
87     check_project_contents_response
88   end
89
90   test "user with project read permission can see project objects" do
91     authorize_with :project_viewer
92     get :contents, params: {
93       id: groups(:aproject).uuid,
94       format: :json,
95     }
96     check_project_contents_response
97   end
98
99   test "list objects across projects" do
100     authorize_with :project_viewer
101     get :contents, params: {
102       format: :json,
103       filters: [['uuid', 'is_a', 'arvados#specimen']]
104     }
105     assert_response :success
106     found_uuids = json_response['items'].collect { |i| i['uuid'] }
107     [[:in_aproject, true],
108      [:in_asubproject, true],
109      [:owned_by_private_group, false]].each do |specimen_fixture, should_find|
110       if should_find
111         assert_includes found_uuids, specimens(specimen_fixture).uuid, "did not find specimen fixture '#{specimen_fixture}'"
112       else
113         refute_includes found_uuids, specimens(specimen_fixture).uuid, "found specimen fixture '#{specimen_fixture}'"
114       end
115     end
116   end
117
118   test "list trashed collections and projects" do
119     authorize_with :active
120     get(:contents, params: {
121           format: :json,
122           include_trash: true,
123           filters: [
124             ['uuid', 'is_a', ['arvados#collection', 'arvados#group']],
125             ['is_trashed', '=', true],
126           ],
127           limit: 10000,
128         })
129     assert_response :success
130     found_uuids = json_response['items'].collect { |i| i['uuid'] }
131     assert_includes found_uuids, groups(:trashed_project).uuid
132     refute_includes found_uuids, groups(:aproject).uuid
133     assert_includes found_uuids, collections(:expired_collection).uuid
134     refute_includes found_uuids, collections(:w_a_z_file).uuid
135   end
136
137   test "list objects in home project" do
138     authorize_with :active
139     get :contents, params: {
140       format: :json,
141       limit: 200,
142       id: users(:active).uuid
143     }
144     assert_response :success
145     found_uuids = json_response['items'].collect { |i| i['uuid'] }
146     assert_includes found_uuids, specimens(:owned_by_active_user).uuid, "specimen did not appear in home project"
147     refute_includes found_uuids, specimens(:in_asubproject).uuid, "specimen appeared unexpectedly in home project"
148   end
149
150   test "user with project read permission can see project collections" do
151     authorize_with :project_viewer
152     get :contents, params: {
153       id: groups(:asubproject).uuid,
154       format: :json,
155     }
156     ids = json_response['items'].map { |item| item["uuid"] }
157     assert_includes ids, collections(:baz_file_in_asubproject).uuid
158   end
159
160   [
161     ['collections.name', 'asc', :<=, "name"],
162     ['collections.name', 'desc', :>=, "name"],
163     ['name', 'asc', :<=, "name"],
164     ['name', 'desc', :>=, "name"],
165     ['collections.created_at', 'asc', :<=, "created_at"],
166     ['collections.created_at', 'desc', :>=, "created_at"],
167     ['created_at', 'asc', :<=, "created_at"],
168     ['created_at', 'desc', :>=, "created_at"],
169   ].each do |column, order, operator, field|
170     test "user with project read permission can sort projects on #{column} #{order}" do
171       authorize_with :project_viewer
172       get :contents, params: {
173         id: groups(:asubproject).uuid,
174         format: :json,
175         filters: [['uuid', 'is_a', "arvados#collection"]],
176         order: "#{column} #{order}"
177       }
178       sorted_values = json_response['items'].collect { |item| item[field] }
179       if field == "name"
180         # Here we avoid assuming too much about the database
181         # collation. Both "alice"<"Bob" and "alice">"Bob" can be
182         # correct. Hopefully it _is_ safe to assume that if "a" comes
183         # before "b" in the ascii alphabet, "aX">"bY" is never true for
184         # any strings X and Y.
185         reliably_sortable_names = sorted_values.select do |name|
186           name[0] >= 'a' && name[0] <= 'z'
187         end.uniq do |name|
188           name[0]
189         end
190         # Preserve order of sorted_values. But do not use &=. If
191         # sorted_values has out-of-order duplicates, we want to preserve
192         # them here, so we can detect them and fail the test below.
193         sorted_values.select! do |name|
194           reliably_sortable_names.include? name
195         end
196       end
197       assert_sorted(operator, sorted_values)
198     end
199   end
200
201   def assert_sorted(operator, sorted_items)
202     actually_checked_anything = false
203     previous = nil
204     sorted_items.each do |entry|
205       if !previous.nil?
206         assert_operator(previous, operator, entry,
207                         "Entries sorted incorrectly.")
208         actually_checked_anything = true
209       end
210       previous = entry
211     end
212     assert actually_checked_anything, "Didn't even find two items to compare."
213   end
214
215   # Even though the project_viewer tests go through other controllers,
216   # I'm putting them here so they're easy to find alongside the other
217   # project tests.
218   def check_new_project_link_fails(link_attrs)
219     @controller = Arvados::V1::LinksController.new
220     post :create, params: {
221       link: {
222         link_class: "permission",
223         name: "can_read",
224         head_uuid: groups(:aproject).uuid,
225       }.merge(link_attrs)
226     }
227     assert_includes(403..422, response.status)
228   end
229
230   test "user with project read permission can't add users to it" do
231     authorize_with :project_viewer
232     check_new_project_link_fails(tail_uuid: users(:spectator).uuid)
233   end
234
235   test "user with project read permission can't add items to it" do
236     authorize_with :project_viewer
237     check_new_project_link_fails(tail_uuid: collections(:baz_file).uuid)
238   end
239
240   test "user with project read permission can't rename items in it" do
241     authorize_with :project_viewer
242     @controller = Arvados::V1::LinksController.new
243     post :update, params: {
244       id: jobs(:running).uuid,
245       name: "Denied test name",
246     }
247     assert_includes(403..404, response.status)
248   end
249
250   test "user with project read permission can't remove items from it" do
251     @controller = Arvados::V1::PipelineTemplatesController.new
252     authorize_with :project_viewer
253     post :update, params: {
254       id: pipeline_templates(:two_part).uuid,
255       pipeline_template: {
256         owner_uuid: users(:project_viewer).uuid,
257       }
258     }
259     assert_response 403
260   end
261
262   test "user with project read permission can't delete it" do
263     authorize_with :project_viewer
264     post :destroy, params: {id: groups(:aproject).uuid}
265     assert_response 403
266   end
267
268   test 'get group-owned objects with limit' do
269     authorize_with :active
270     get :contents, params: {
271       id: groups(:aproject).uuid,
272       limit: 1,
273       format: :json,
274     }
275     assert_response :success
276     assert_operator 1, :<, json_response['items_available']
277     assert_equal 1, json_response['items'].count
278   end
279
280   test 'get group-owned objects with limit and offset' do
281     authorize_with :active
282     get :contents, params: {
283       id: groups(:aproject).uuid,
284       limit: 1,
285       offset: 12345,
286       format: :json,
287     }
288     assert_response :success
289     assert_operator 1, :<, json_response['items_available']
290     assert_equal 0, json_response['items'].count
291   end
292
293   test 'get group-owned objects with additional filter matching nothing' do
294     authorize_with :active
295     get :contents, params: {
296       id: groups(:aproject).uuid,
297       filters: [['uuid', 'in', ['foo_not_a_uuid','bar_not_a_uuid']]],
298       format: :json,
299     }
300     assert_response :success
301     assert_equal [], json_response['items']
302     assert_equal 0, json_response['items_available']
303   end
304
305   %w(offset limit).each do |arg|
306     ['foo', '', '1234five', '0x10', '-8'].each do |val|
307       test "Raise error on bogus #{arg} parameter #{val.inspect}" do
308         authorize_with :active
309         get :contents, params: {
310           :id => groups(:aproject).uuid,
311           :format => :json,
312           arg => val,
313         }
314         assert_response 422
315       end
316     end
317   end
318
319   test "Collection contents don't include manifest_text or unsigned_manifest_text" do
320     authorize_with :active
321     get :contents, params: {
322       id: groups(:aproject).uuid,
323       filters: [["uuid", "is_a", "arvados#collection"]],
324       format: :json,
325     }
326     assert_response :success
327     refute(json_response["items"].any? { |c| not c["portable_data_hash"] },
328            "response included an item without a portable data hash")
329     refute(json_response["items"].any? { |c| c.include?("manifest_text") },
330            "response included an item with manifest_text")
331     refute(json_response["items"].any? { |c| c.include?("unsigned_manifest_text") },
332            "response included an item with unsigned_manifest_text")
333   end
334
335   test 'get writable_by list for owned group' do
336     authorize_with :active
337     get :show, params: {
338       id: groups(:aproject).uuid,
339       format: :json
340     }
341     assert_response :success
342     assert_not_nil(json_response['writable_by'],
343                    "Should receive uuid list in 'writable_by' field")
344     assert_includes(json_response['writable_by'], users(:active).uuid,
345                     "owner should be included in writable_by list")
346   end
347
348   test 'no writable_by list for group with read-only access' do
349     authorize_with :rominiadmin
350     get :show, params: {
351       id: groups(:testusergroup_admins).uuid,
352       format: :json
353     }
354     assert_response :success
355     assert_equal([json_response['owner_uuid']],
356                  json_response['writable_by'],
357                  "Should only see owner_uuid in 'writable_by' field")
358   end
359
360   test 'get writable_by list by admin user' do
361     authorize_with :admin
362     get :show, params: {
363       id: groups(:testusergroup_admins).uuid,
364       format: :json
365     }
366     assert_response :success
367     assert_not_nil(json_response['writable_by'],
368                    "Should receive uuid list in 'writable_by' field")
369     assert_includes(json_response['writable_by'],
370                     users(:admin).uuid,
371                     "Current user should be included in 'writable_by' field")
372   end
373
374   test 'creating subproject with duplicate name fails' do
375     authorize_with :active
376     post :create, params: {
377       group: {
378         name: 'A Project',
379         owner_uuid: users(:active).uuid,
380         group_class: 'project',
381       },
382     }
383     assert_response 422
384     response_errors = json_response['errors']
385     assert_not_nil response_errors, 'Expected error in response'
386     assert(response_errors.first.include?('duplicate key'),
387            "Expected 'duplicate key' error in #{response_errors.first}")
388   end
389
390   test 'creating duplicate named subproject succeeds with ensure_unique_name' do
391     authorize_with :active
392     post :create, params: {
393       group: {
394         name: 'A Project',
395         owner_uuid: users(:active).uuid,
396         group_class: 'project',
397       },
398       ensure_unique_name: true
399     }
400     assert_response :success
401     new_project = json_response
402     assert_not_equal(new_project['uuid'],
403                      groups(:aproject).uuid,
404                      "create returned same uuid as existing project")
405     assert_match(/^A Project \(\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}Z\)$/,
406                  new_project['name'])
407   end
408
409   [
410     [['owner_uuid', '!=', 'zzzzz-tpzed-xurymjxw79nv3jz'], 200,
411         'zzzzz-d1hrv-subprojpipeline', 'zzzzz-d1hrv-1xfj6xkicf2muk2'],
412     [["pipeline_instances.state", "not in", ["Complete", "Failed"]], 200,
413         'zzzzz-d1hrv-1xfj6xkicf2muk2', 'zzzzz-d1hrv-i3e77t9z5y8j9cc'],
414     [['container_requests.requesting_container_uuid', '=', nil], 200,
415         'zzzzz-xvhdp-cr4queuedcontnr', 'zzzzz-xvhdp-cr4requestercn2'],
416     [['container_requests.no_such_column', '=', nil], 422],
417     [['container_requests.', '=', nil], 422],
418     [['.requesting_container_uuid', '=', nil], 422],
419     [['no_such_table.uuid', '!=', 'zzzzz-tpzed-xurymjxw79nv3jz'], 422],
420   ].each do |filter, expect_code, expect_uuid, not_expect_uuid|
421     test "get contents with '#{filter}' filter" do
422       authorize_with :active
423       get :contents, params: {filters: [filter], format: :json}
424       assert_response expect_code
425       if expect_code == 200
426         assert_not_empty json_response['items']
427         item_uuids = json_response['items'].collect {|item| item['uuid']}
428         assert_includes(item_uuids, expect_uuid)
429         assert_not_includes(item_uuids, not_expect_uuid)
430       end
431     end
432   end
433
434   test 'get contents with jobs and pipeline instances disabled' do
435     Rails.configuration.API.DisabledAPIs = ConfigLoader.to_OrderedOptions(
436       {'jobs.index'=>{}, 'pipeline_instances.index'=>{}})
437
438     authorize_with :active
439     get :contents, params: {
440       id: groups(:aproject).uuid,
441       format: :json,
442     }
443     check_project_contents_response %w'arvados#pipelineInstance arvados#job'
444   end
445
446   test 'get contents with low max_index_database_read' do
447     # Some result will certainly have at least 12 bytes in a
448     # restricted column
449     Rails.configuration.API.MaxIndexDatabaseRead = 12
450     authorize_with :active
451     get :contents, params: {
452           id: groups(:aproject).uuid,
453           format: :json,
454         }
455     assert_response :success
456     assert_not_empty(json_response['items'])
457     assert_operator(json_response['items'].count,
458                     :<, json_response['items_available'])
459   end
460
461   test 'get contents, recursive=true' do
462     authorize_with :active
463     params = {
464       id: groups(:aproject).uuid,
465       recursive: true,
466       format: :json,
467     }
468     get :contents, params: params
469     owners = json_response['items'].map do |item|
470       item['owner_uuid']
471     end
472     assert_includes(owners, groups(:aproject).uuid)
473     assert_includes(owners, groups(:asubproject).uuid)
474   end
475
476   [false, nil].each do |recursive|
477     test "get contents, recursive=#{recursive.inspect}" do
478       authorize_with :active
479       params = {
480         id: groups(:aproject).uuid,
481         format: :json,
482       }
483       params[:recursive] = false if recursive == false
484       get :contents, params: params
485       owners = json_response['items'].map do |item|
486         item['owner_uuid']
487       end
488       assert_includes(owners, groups(:aproject).uuid)
489       refute_includes(owners, groups(:asubproject).uuid)
490     end
491   end
492
493   test 'get home project contents, recursive=true' do
494     authorize_with :active
495     get :contents, params: {
496           id: users(:active).uuid,
497           recursive: true,
498           format: :json,
499         }
500     owners = json_response['items'].map do |item|
501       item['owner_uuid']
502     end
503     assert_includes(owners, users(:active).uuid)
504     assert_includes(owners, groups(:aproject).uuid)
505     assert_includes(owners, groups(:asubproject).uuid)
506   end
507
508   ### trashed project tests ###
509
510   #
511   # The structure is
512   #
513   # trashed_project         (zzzzz-j7d0g-trashedproject1)
514   #   trashed_subproject    (zzzzz-j7d0g-trashedproject2)
515   #   trashed_subproject3   (zzzzz-j7d0g-trashedproject3)
516   #   zzzzz-xvhdp-cr5trashedcontr
517
518   [:active,
519    :admin].each do |auth|
520     # project: to query,    to untrash,    is visible, parent contents listing success
521     [
522      [:trashed_project,     [],                 false, true],
523      [:trashed_project,     [:trashed_project], true,  true],
524      [:trashed_subproject,  [],                 false, false],
525      [:trashed_subproject,  [:trashed_project], true,  true],
526      [:trashed_subproject3, [:trashed_project], false, true],
527      [:trashed_subproject3, [:trashed_subproject3], false, false],
528      [:trashed_subproject3, [:trashed_project, :trashed_subproject3], true, true],
529     ].each do |project, untrash, visible, success|
530
531       test "contents listing #{project} #{untrash} as #{auth}" do
532         authorize_with auth
533         untrash.each do |pr|
534           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
535         end
536         get :contents, params: {
537               id: groups(project).owner_uuid,
538               format: :json
539             }
540         if success
541           assert_response :success
542           item_uuids = json_response['items'].map do |item|
543             item['uuid']
544           end
545           if visible
546             assert_includes(item_uuids, groups(project).uuid)
547           else
548             assert_not_includes(item_uuids, groups(project).uuid)
549           end
550         else
551           assert_response 404
552         end
553       end
554
555       test "contents of #{project} #{untrash} as #{auth}" do
556         authorize_with auth
557         untrash.each do |pr|
558           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
559         end
560         get :contents, params: {
561               id: groups(project).uuid,
562               format: :json
563             }
564         if visible
565           assert_response :success
566         else
567           assert_response 404
568         end
569       end
570
571       test "index #{project} #{untrash} as #{auth}" do
572         authorize_with auth
573         untrash.each do |pr|
574           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
575         end
576         get :index, params: {
577               format: :json,
578             }
579         assert_response :success
580         item_uuids = json_response['items'].map do |item|
581           item['uuid']
582         end
583         if visible
584           assert_includes(item_uuids, groups(project).uuid)
585         else
586           assert_not_includes(item_uuids, groups(project).uuid)
587         end
588       end
589
590       test "show #{project} #{untrash} as #{auth}" do
591         authorize_with auth
592         untrash.each do |pr|
593           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
594         end
595         get :show, params: {
596               id: groups(project).uuid,
597               format: :json
598             }
599         if visible
600           assert_response :success
601         else
602           assert_response 404
603         end
604       end
605
606       test "show include_trash=false #{project} #{untrash} as #{auth}" do
607         authorize_with auth
608         untrash.each do |pr|
609           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
610         end
611         get :show, params: {
612               id: groups(project).uuid,
613               format: :json,
614               include_trash: false
615             }
616         if visible
617           assert_response :success
618         else
619           assert_response 404
620         end
621       end
622
623       test "show include_trash #{project} #{untrash} as #{auth}" do
624         authorize_with auth
625         untrash.each do |pr|
626           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
627         end
628         get :show, params: {
629               id: groups(project).uuid,
630               format: :json,
631               include_trash: true
632             }
633         assert_response :success
634       end
635
636       test "index include_trash #{project} #{untrash} as #{auth}" do
637         authorize_with auth
638         untrash.each do |pr|
639           Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
640         end
641         get :index, params: {
642               format: :json,
643               include_trash: true
644             }
645         assert_response :success
646         item_uuids = json_response['items'].map do |item|
647           item['uuid']
648         end
649         assert_includes(item_uuids, groups(project).uuid)
650       end
651     end
652
653     test "delete project #{auth}" do
654       authorize_with auth
655       [:trashed_project].each do |pr|
656         Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
657       end
658       assert !Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
659       post :destroy, params: {
660             id: groups(:trashed_project).uuid,
661             format: :json,
662           }
663       assert_response :success
664       assert Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
665     end
666
667     test "untrash project #{auth}" do
668       authorize_with auth
669       assert Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
670       post :untrash, params: {
671             id: groups(:trashed_project).uuid,
672             format: :json,
673           }
674       assert_response :success
675       assert !Group.find_by_uuid(groups(:trashed_project).uuid).is_trashed
676     end
677
678     test "untrash project with name conflict #{auth}" do
679       authorize_with auth
680       [:trashed_project].each do |pr|
681         Group.find_by_uuid(groups(pr).uuid).update! is_trashed: false
682       end
683       gc = Group.create!({owner_uuid: "zzzzz-j7d0g-trashedproject1",
684                          name: "trashed subproject 3",
685                          group_class: "project"})
686       post :untrash, params: {
687             id: groups(:trashed_subproject3).uuid,
688             format: :json,
689             ensure_unique_name: true
690            }
691       assert_response :success
692       assert_match /^trashed subproject 3 \(\d{4}-\d\d-\d\d.*?Z\)$/, json_response['name']
693     end
694
695     test "move trashed subproject to new owner #{auth}" do
696       authorize_with auth
697       assert_nil Group.readable_by(users(auth)).where(uuid: groups(:trashed_subproject).uuid).first
698       put :update, params: {
699             id: groups(:trashed_subproject).uuid,
700             group: {
701               owner_uuid: users(:active).uuid
702             },
703             include_trash: true,
704             format: :json,
705           }
706       assert_response :success
707       assert_not_nil Group.readable_by(users(auth)).where(uuid: groups(:trashed_subproject).uuid).first
708     end
709   end
710
711   test 'get shared owned by another user' do
712     authorize_with :user_bar_in_sharing_group
713
714     act_as_system_user do
715       Link.create!(
716         tail_uuid: users(:user_bar_in_sharing_group).uuid,
717         link_class: 'permission',
718         name: 'can_read',
719         head_uuid: groups(:project_owned_by_foo).uuid)
720     end
721
722     get :shared, params: {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
723
724     assert_equal 1, json_response['items'].length
725     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
726
727     assert_equal 1, json_response['included'].length
728     assert_equal json_response['included'][0]["uuid"], users(:user_foo_in_sharing_group).uuid
729   end
730
731   test 'get shared, owned by unreadable project' do
732     authorize_with :user_bar_in_sharing_group
733
734     act_as_system_user do
735       Group.find_by_uuid(groups(:project_owned_by_foo).uuid).update!(owner_uuid: groups(:aproject).uuid)
736       Link.create!(
737         tail_uuid: users(:user_bar_in_sharing_group).uuid,
738         link_class: 'permission',
739         name: 'can_read',
740         head_uuid: groups(:project_owned_by_foo).uuid)
741     end
742
743     get :shared, params: {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
744
745     assert_equal 1, json_response['items'].length
746     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
747
748     assert_equal 0, json_response['included'].length
749   end
750
751   test 'get shared, add permission link' do
752     authorize_with :user_bar_in_sharing_group
753
754     act_as_system_user do
755       Link.create!(tail_uuid: groups(:group_for_sharing_tests).uuid,
756                    head_uuid: groups(:project_owned_by_foo).uuid,
757                    link_class: 'permission',
758                    name: 'can_manage')
759     end
760
761     get :shared, params: {:filters => [["group_class", "=", "project"]], :include => "owner_uuid"}
762
763     assert_equal 1, json_response['items'].length
764     assert_equal groups(:project_owned_by_foo).uuid, json_response['items'][0]["uuid"]
765
766     assert_equal 1, json_response['included'].length
767     assert_equal users(:user_foo_in_sharing_group).uuid, json_response['included'][0]["uuid"]
768   end
769
770   ### contents with exclude_home_project
771
772   test 'contents, exclude home owned by another user' do
773     authorize_with :user_bar_in_sharing_group
774
775     act_as_system_user do
776       Link.create!(
777         tail_uuid: users(:user_bar_in_sharing_group).uuid,
778         link_class: 'permission',
779         name: 'can_read',
780         head_uuid: groups(:project_owned_by_foo).uuid)
781       Link.create!(
782         tail_uuid: users(:user_bar_in_sharing_group).uuid,
783         link_class: 'permission',
784         name: 'can_read',
785         head_uuid: collections(:collection_owned_by_foo).uuid)
786     end
787
788     get :contents, params: {:include => "owner_uuid", :exclude_home_project => true}
789
790     assert_equal 2, json_response['items'].length
791     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
792     assert_equal json_response['items'][1]["uuid"], collections(:collection_owned_by_foo).uuid
793
794     assert_equal 1, json_response['included'].length
795     assert_equal json_response['included'][0]["uuid"], users(:user_foo_in_sharing_group).uuid
796   end
797
798   test 'contents, exclude home, owned by unreadable project' do
799     authorize_with :user_bar_in_sharing_group
800
801     act_as_system_user do
802       Group.find_by_uuid(groups(:project_owned_by_foo).uuid).update!(owner_uuid: groups(:aproject).uuid)
803       Link.create!(
804         tail_uuid: users(:user_bar_in_sharing_group).uuid,
805         link_class: 'permission',
806         name: 'can_read',
807         head_uuid: groups(:project_owned_by_foo).uuid)
808     end
809
810     get :contents, params: {:include => "owner_uuid", :exclude_home_project => true}
811
812     assert_equal 1, json_response['items'].length
813     assert_equal json_response['items'][0]["uuid"], groups(:project_owned_by_foo).uuid
814
815     assert_equal 0, json_response['included'].length
816   end
817
818   test 'contents, exclude home, add permission link' do
819     authorize_with :user_bar_in_sharing_group
820
821     act_as_system_user do
822       Link.create!(tail_uuid: groups(:group_for_sharing_tests).uuid,
823                    head_uuid: groups(:project_owned_by_foo).uuid,
824                    link_class: 'permission',
825                    name: 'can_manage')
826     end
827
828     get :contents, params: {:include => "owner_uuid", :exclude_home_project => true}
829
830     assert_equal 1, json_response['items'].length
831     assert_equal groups(:project_owned_by_foo).uuid, json_response['items'][0]["uuid"]
832
833     assert_equal 1, json_response['included'].length
834     assert_equal users(:user_foo_in_sharing_group).uuid, json_response['included'][0]["uuid"]
835   end
836
837   test 'contents, exclude home, with parent specified' do
838     authorize_with :active
839
840     get :contents, params: {id: groups(:aproject).uuid, :include => "owner_uuid", :exclude_home_project => true}
841
842     assert_response 422
843   end
844 end