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