Merge branch '8784-dir-listings'
[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   include CurrentApiClient  # for empty_collection
10   fixtures :users, :groups, :api_client_authorizations, :collections
11
12   teardown do
13     User.invalidate_permissions_cache db_current_time.to_i
14   end
15
16   test "adding and removing direct can_read links" do
17     # try to read collection as spectator
18     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
19     assert_response 404
20
21     # try to add permission as spectator
22     post "/arvados/v1/links", {
23       :format => :json,
24       :link => {
25         tail_uuid: users(:spectator).uuid,
26         link_class: 'permission',
27         name: 'can_read',
28         head_uuid: collections(:foo_file).uuid,
29         properties: {}
30       }
31     }, auth(:spectator)
32     assert_response 422
33
34     # add permission as admin
35     post "/arvados/v1/links", {
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     }, auth(:admin)
45     u = json_response['uuid']
46     assert_response :success
47
48     # read collection as spectator
49     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
50     assert_response :success
51
52     # try to delete permission as spectator
53     delete "/arvados/v1/links/#{u}", {:format => :json}, auth(:spectator)
54     assert_response 403
55
56     # delete permission as admin
57     delete "/arvados/v1/links/#{u}", {:format => :json}, auth(:admin)
58     assert_response :success
59
60     # try to read collection as spectator
61     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
62     assert_response 404
63   end
64
65
66   test "adding can_read links from user to group, group to collection" do
67     # try to read collection as spectator
68     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
69     assert_response 404
70
71     # add permission for spectator to read group
72     post "/arvados/v1/links", {
73       :format => :json,
74       :link => {
75         tail_uuid: users(:spectator).uuid,
76         link_class: 'permission',
77         name: 'can_read',
78         head_uuid: groups(:private).uuid,
79         properties: {}
80       }
81     }, auth(:admin)
82     assert_response :success
83
84     # try to read collection as spectator
85     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
86     assert_response 404
87
88     # add permission for group to read collection
89     post "/arvados/v1/links", {
90       :format => :json,
91       :link => {
92         tail_uuid: groups(:private).uuid,
93         link_class: 'permission',
94         name: 'can_read',
95         head_uuid: collections(:foo_file).uuid,
96         properties: {}
97       }
98     }, auth(:admin)
99     u = json_response['uuid']
100     assert_response :success
101
102     # try to read collection as spectator
103     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
104     assert_response :success
105
106     # delete permission for group to read collection
107     delete "/arvados/v1/links/#{u}", {:format => :json}, auth(:admin)
108     assert_response :success
109
110     # try to read collection as spectator
111     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
112     assert_response 404
113
114   end
115
116
117   test "adding can_read links from group to collection, user to group" do
118     # try to read collection as spectator
119     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
120     assert_response 404
121
122     # add permission for group to read collection
123     post "/arvados/v1/links", {
124       :format => :json,
125       :link => {
126         tail_uuid: groups(:private).uuid,
127         link_class: 'permission',
128         name: 'can_read',
129         head_uuid: collections(:foo_file).uuid,
130         properties: {}
131       }
132     }, auth(:admin)
133     assert_response :success
134
135     # try to read collection as spectator
136     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
137     assert_response 404
138
139     # add permission for spectator to read group
140     post "/arvados/v1/links", {
141       :format => :json,
142       :link => {
143         tail_uuid: users(:spectator).uuid,
144         link_class: 'permission',
145         name: 'can_read',
146         head_uuid: groups(:private).uuid,
147         properties: {}
148       }
149     }, auth(:admin)
150     u = json_response['uuid']
151     assert_response :success
152
153     # try to read collection as spectator
154     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
155     assert_response :success
156
157     # delete permission for spectator to read group
158     delete "/arvados/v1/links/#{u}", {:format => :json}, auth(:admin)
159     assert_response :success
160
161     # try to read collection as spectator
162     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
163     assert_response 404
164
165   end
166
167   test "adding can_read links from user to group, group to group, group to collection" do
168     # try to read collection as spectator
169     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
170     assert_response 404
171
172     # add permission for user to read group
173     post "/arvados/v1/links", {
174       :format => :json,
175       :link => {
176         tail_uuid: users(:spectator).uuid,
177         link_class: 'permission',
178         name: 'can_read',
179         head_uuid: groups(:private).uuid,
180         properties: {}
181       }
182     }, auth(:admin)
183     assert_response :success
184
185     # add permission for group to read group
186     post "/arvados/v1/links", {
187       :format => :json,
188       :link => {
189         tail_uuid: groups(:private).uuid,
190         link_class: 'permission',
191         name: 'can_read',
192         head_uuid: groups(:empty_lonely_group).uuid,
193         properties: {}
194       }
195     }, auth(:admin)
196     assert_response :success
197
198     # add permission for group to read collection
199     post "/arvados/v1/links", {
200       :format => :json,
201       :link => {
202         tail_uuid: groups(:empty_lonely_group).uuid,
203         link_class: 'permission',
204         name: 'can_read',
205         head_uuid: collections(:foo_file).uuid,
206         properties: {}
207       }
208     }, auth(:admin)
209     u = json_response['uuid']
210     assert_response :success
211
212     # try to read collection as spectator
213     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
214     assert_response :success
215
216     # delete permission for group to read collection
217     delete "/arvados/v1/links/#{u}", {:format => :json}, auth(:admin)
218     assert_response :success
219
220     # try to read collection as spectator
221     get "/arvados/v1/collections/#{collections(:foo_file).uuid}", {:format => :json}, auth(:spectator)
222     assert_response 404
223   end
224
225   test "read-only group-admin cannot modify administered user" do
226     put "/arvados/v1/users/#{users(:active).uuid}", {
227       :user => {
228         first_name: 'KilroyWasHere'
229       },
230       :format => :json
231     }, auth(:rominiadmin)
232     assert_response 403
233   end
234
235   test "read-only group-admin cannot read or update non-administered user" do
236     get "/arvados/v1/users/#{users(:spectator).uuid}", {
237       :format => :json
238     }, auth(:rominiadmin)
239     assert_response 404
240
241     put "/arvados/v1/users/#{users(:spectator).uuid}", {
242       :user => {
243         first_name: 'KilroyWasHere'
244       },
245       :format => :json
246     }, auth(:rominiadmin)
247     assert_response 404
248   end
249
250   test "RO group-admin finds user's specimens, RW group-admin can update" do
251     [[:rominiadmin, false],
252      [:miniadmin, true]].each do |which_user, update_should_succeed|
253       get "/arvados/v1/specimens", {:format => :json}, auth(which_user)
254       assert_response :success
255       resp_uuids = json_response['items'].collect { |i| i['uuid'] }
256       [[true, specimens(:owned_by_active_user).uuid],
257        [true, specimens(:owned_by_private_group).uuid],
258        [false, specimens(:owned_by_spectator).uuid],
259       ].each do |should_find, uuid|
260         assert_equal(should_find, !resp_uuids.index(uuid).nil?,
261                      "%s should%s see %s in specimen list" %
262                      [which_user.to_s,
263                       should_find ? '' : 'not ',
264                       uuid])
265         put "/arvados/v1/specimens/#{uuid}", {
266           :specimen => {
267             properties: {
268               miniadmin_was_here: true
269             }
270           },
271           :format => :json
272         }, auth(which_user)
273         if !should_find
274           assert_response 404
275         elsif !update_should_succeed
276           assert_response 403
277         else
278           assert_response :success
279         end
280       end
281     end
282   end
283
284   test "get_permissions returns list" do
285     # First confirm that user :active cannot get permissions on group :public
286     get "/arvados/v1/permissions/#{groups(:public).uuid}", nil, auth(:active)
287     assert_response 404
288
289     # add some permissions, including can_manage
290     # permission for user :active
291     post "/arvados/v1/links", {
292       :format => :json,
293       :link => {
294         tail_uuid: users(:spectator).uuid,
295         link_class: 'permission',
296         name: 'can_read',
297         head_uuid: groups(:public).uuid,
298         properties: {}
299       }
300     }, auth(:admin)
301     assert_response :success
302     can_read_uuid = json_response['uuid']
303
304     post "/arvados/v1/links", {
305       :format => :json,
306       :link => {
307         tail_uuid: users(:inactive).uuid,
308         link_class: 'permission',
309         name: 'can_write',
310         head_uuid: groups(:public).uuid,
311         properties: {}
312       }
313     }, auth(:admin)
314     assert_response :success
315     can_write_uuid = json_response['uuid']
316
317     post "/arvados/v1/links", {
318       :format => :json,
319       :link => {
320         tail_uuid: users(:active).uuid,
321         link_class: 'permission',
322         name: 'can_manage',
323         head_uuid: groups(:public).uuid,
324         properties: {}
325       }
326     }, auth(:admin)
327     assert_response :success
328     can_manage_uuid = json_response['uuid']
329
330     # Now user :active should be able to retrieve permissions
331     # on group :public.
332     get("/arvados/v1/permissions/#{groups(:public).uuid}",
333         { :format => :json },
334         auth(:active))
335     assert_response :success
336
337     perm_uuids = json_response['items'].map { |item| item['uuid'] }
338     assert_includes perm_uuids, can_read_uuid, "can_read_uuid not found"
339     assert_includes perm_uuids, can_write_uuid, "can_write_uuid not found"
340     assert_includes perm_uuids, can_manage_uuid, "can_manage_uuid not found"
341   end
342
343   test "get_permissions returns 404 for nonexistent uuid" do
344     nonexistent = Group.generate_uuid
345     # make sure it really doesn't exist
346     get "/arvados/v1/groups/#{nonexistent}", nil, auth(:admin)
347     assert_response 404
348
349     get "/arvados/v1/permissions/#{nonexistent}", nil, auth(:active)
350     assert_response 404
351   end
352
353   test "get_permissions returns 403 if user can read but not manage" do
354     post "/arvados/v1/links", {
355       :link => {
356         tail_uuid: users(:active).uuid,
357         link_class: 'permission',
358         name: 'can_read',
359         head_uuid: groups(:public).uuid,
360         properties: {}
361       }
362     }, auth(:admin)
363     assert_response :success
364
365     get "/arvados/v1/permissions/#{groups(:public).uuid}", nil, auth(:active)
366     assert_response 403
367   end
368
369   test "active user can read the empty collection" do
370     # The active user should be able to read the empty collection.
371
372     get("/arvados/v1/collections/#{empty_collection_uuid}",
373         { :format => :json },
374         auth(:active))
375     assert_response :success
376     assert_empty json_response['manifest_text'], "empty collection manifest_text is not empty"
377   end
378 end