1 # Copyright (C) The Arvados Authors. All rights reserved.
3 # SPDX-License-Identifier: AGPL-3.0
7 class Arvados::V1::LinksControllerTest < ActionController::TestCase
9 ['link', 'link_json'].each do |formatted_link|
10 test "no symbol keys in serialized hash #{formatted_link}" do
12 properties: {username: 'testusername'},
15 tail_uuid: users(:admin).uuid,
16 head_uuid: virtual_machines(:testvm).uuid
19 if formatted_link == 'link_json'
20 post :create, params: {link: link.to_json}
22 post :create, params: {link: link}
24 assert_response :success
25 assert_not_nil assigns(:object)
26 assert_equal 'testusername', assigns(:object).properties['username']
27 assert_equal false, assigns(:object).properties.has_key?(:username)
31 %w(created_at modified_at).each do |attr|
32 {nil: nil, bogus: 2.days.ago}.each do |bogustype, bogusvalue|
33 test "cannot set #{bogustype} #{attr} in create" do
34 authorize_with :active
35 post :create, params: {
40 }.merge(attr => bogusvalue)
42 assert_response :success
43 resp = JSON.parse @response.body
44 assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
46 test "cannot set #{bogustype} #{attr} in update" do
47 really_created_at = links(:test_timestamps).created_at
48 authorize_with :active
49 put :update, params: {
50 id: links(:test_timestamps).uuid,
52 :properties => {test: 'test'},
56 assert_response :success
57 resp = JSON.parse @response.body
60 assert_in_delta really_created_at, Time.parse(resp[attr]), 0.001
62 assert_in_delta Time.now, Time.parse(resp[attr]), 3.0
68 test "head must exist" do
72 tail_uuid: users(:active).uuid,
73 head_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
76 post :create, params: {link: link}
80 test "tail must exist" do
84 head_uuid: users(:active).uuid,
85 tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
88 post :create, params: {link: link}
92 test "head and tail exist, head_kind and tail_kind are returned" do
96 head_uuid: users(:active).uuid,
97 tail_uuid: users(:spectator).uuid,
100 post :create, params: {link: link}
101 assert_response :success
102 l = JSON.parse(@response.body)
103 assert 'arvados#user', l['head_kind']
104 assert 'arvados#user', l['tail_kind']
107 test "can supply head_kind and tail_kind without error" do
111 head_uuid: users(:active).uuid,
112 tail_uuid: users(:spectator).uuid,
113 head_kind: "arvados#user",
114 tail_kind: "arvados#user",
116 authorize_with :admin
117 post :create, params: {link: link}
118 assert_response :success
119 l = JSON.parse(@response.body)
120 assert 'arvados#user', l['head_kind']
121 assert 'arvados#user', l['tail_kind']
124 test "tail must be visible by user" do
128 head_uuid: users(:active).uuid,
129 tail_uuid: authorized_keys(:admin).uuid,
131 authorize_with :active
132 post :create, params: {link: link}
136 test "filter links with 'is_a' operator" do
137 authorize_with :admin
138 get :index, params: {
139 filters: [ ['tail_uuid', 'is_a', 'arvados#user'] ]
141 assert_response :success
142 found = assigns(:objects)
143 assert_not_equal 0, found.count
144 assert_equal found.count, (found.select { |f| f.tail_uuid.match User.uuid_regex }).count
147 test "filter links with 'is_a' operator includes remote objects" do
148 authorize_with :admin
149 get :index, params: {
151 ['tail_uuid', 'is_a', 'arvados#user'],
152 ['link_class', '=', 'permission'],
153 ['name', '=', 'can_read'],
154 ['head_uuid', '=', collections(:foo_file).uuid],
157 assert_response :success
158 found = assigns(:objects)
159 assert_not_equal 0, found.count
160 assert_includes(found.map(&:tail_uuid),
161 users(:federated_active).uuid)
164 test "filter links with 'is_a' operator with more than one" do
165 authorize_with :admin
166 get :index, params: {
167 filters: [ ['tail_uuid', 'is_a', ['arvados#user', 'arvados#group'] ] ],
169 assert_response :success
170 found = assigns(:objects)
171 assert_not_equal 0, found.count
172 assert_equal found.count, (found.select { |f|
173 f.tail_uuid.match User.uuid_regex or
174 f.tail_uuid.match Group.uuid_regex
178 test "filter links with 'is_a' operator with bogus type" do
179 authorize_with :admin
180 get :index, params: {
181 filters: [ ['tail_uuid', 'is_a', ['arvados#bogus'] ] ],
183 assert_response :success
184 found = assigns(:objects)
185 assert_equal 0, found.count
188 test "filter links with 'is_a' operator with collection" do
189 authorize_with :admin
190 get :index, params: {
191 filters: [ ['head_uuid', 'is_a', ['arvados#collection'] ] ],
193 assert_response :success
194 found = assigns(:objects)
195 assert_not_equal 0, found.count
196 assert_equal found.count, (found.select { |f| f.head_uuid.match Collection.uuid_regex}).count
199 test "test can still use where tail_kind" do
200 authorize_with :admin
201 get :index, params: {
202 where: { tail_kind: 'arvados#user' }
204 assert_response :success
205 found = assigns(:objects)
206 assert_not_equal 0, found.count
207 assert_equal found.count, (found.select { |f| f.tail_uuid.match User.uuid_regex }).count
210 test "test can still use where head_kind" do
211 authorize_with :admin
212 get :index, params: {
213 where: { head_kind: 'arvados#user' }
215 assert_response :success
216 found = assigns(:objects)
217 assert_not_equal 0, found.count
218 assert_equal found.count, (found.select { |f| f.head_uuid.match User.uuid_regex }).count
221 test "test can still use filter tail_kind" do
222 authorize_with :admin
223 get :index, params: {
224 filters: [ ['tail_kind', '=', 'arvados#user'] ]
226 assert_response :success
227 found = assigns(:objects)
228 assert_not_equal 0, found.count
229 assert_equal found.count, (found.select { |f| f.tail_uuid.match User.uuid_regex }).count
232 test "test can still use filter head_kind" do
233 authorize_with :admin
234 get :index, params: {
235 filters: [ ['head_kind', '=', 'arvados#user'] ]
237 assert_response :success
238 found = assigns(:objects)
239 assert_not_equal 0, found.count
240 assert_equal found.count, (found.select { |f| f.head_uuid.match User.uuid_regex }).count
243 test "head_kind matches head_uuid" do
247 head_uuid: groups(:public).uuid,
248 head_kind: "arvados#user",
249 tail_uuid: users(:spectator).uuid,
250 tail_kind: "arvados#user",
252 authorize_with :admin
253 post :create, params: {link: link}
257 test "tail_kind matches tail_uuid" do
261 head_uuid: users(:active).uuid,
262 head_kind: "arvados#user",
263 tail_uuid: groups(:public).uuid,
264 tail_kind: "arvados#user",
266 authorize_with :admin
267 post :create, params: {link: link}
271 test "test with virtual_machine" do
273 tail_kind: "arvados#user",
274 tail_uuid: users(:active).uuid,
275 head_kind: "arvados#virtual_machine",
276 head_uuid: virtual_machines(:testvm).uuid,
277 link_class: "permission",
279 properties: {username: "repo_and_user_name"}
281 authorize_with :admin
282 post :create, params: {link: link}
286 test "test with virtualMachine" do
288 tail_kind: "arvados#user",
289 tail_uuid: users(:active).uuid,
290 head_kind: "arvados#virtualMachine",
291 head_uuid: virtual_machines(:testvm).uuid,
292 link_class: "permission",
294 properties: {username: "repo_and_user_name"}
296 authorize_with :admin
297 post :create, params: {link: link}
298 assert_response :success
301 test "project owner can show a project permission" do
302 uuid = links(:project_viewer_can_read_project).uuid
303 authorize_with :active
304 get :show, params: {id: uuid}
305 assert_response :success
306 assert_equal(uuid, assigns(:object).andand.uuid)
309 test "admin can show a project permission" do
310 uuid = links(:project_viewer_can_read_project).uuid
311 authorize_with :admin
312 get :show, params: {id: uuid}
313 assert_response :success
314 assert_equal(uuid, assigns(:object).andand.uuid)
317 test "project viewer can't show others' project permissions" do
318 authorize_with :project_viewer
319 get :show, params: {id: links(:admin_can_write_aproject).uuid}
323 test "requesting a nonexistent link returns 404" do
324 authorize_with :active
325 get :show, params: {id: 'zzzzz-zzzzz-zzzzzzzzzzzzzzz'}
330 skip "retrieve all permissions using generic links index api" do
331 # Links.readable_by() does not return the full set of permission
332 # links that are visible to a user (i.e., all permission links
333 # whose head_uuid references an object for which the user has
334 # ownership or can_manage permission). Therefore, neither does
337 # It is possible to retrieve the full set of permissions for a
338 # single object via /arvados/v1/permissions.
339 authorize_with :active
340 get :index, params: {
341 filters: [['link_class', '=', 'permission'],
342 ['head_uuid', '=', groups(:aproject).uuid]]
344 assert_response :success
345 assert_not_nil assigns(:objects)
346 assert_includes(assigns(:objects).map(&:uuid),
347 links(:project_viewer_can_read_project).uuid)
350 test "admin can index project permissions" do
351 authorize_with :admin
352 get :index, params: {
353 filters: [['link_class', '=', 'permission'],
354 ['head_uuid', '=', groups(:aproject).uuid]]
356 assert_response :success
357 assert_not_nil assigns(:objects)
358 assert_includes(assigns(:objects).map(&:uuid),
359 links(:project_viewer_can_read_project).uuid)
362 test "project viewer can't index others' project permissions" do
363 authorize_with :project_viewer
364 get :index, params: {
365 filters: [['link_class', '=', 'permission'],
366 ['head_uuid', '=', groups(:aproject).uuid],
367 ['tail_uuid', '!=', users(:project_viewer).uuid]]
369 assert_response :success
370 assert_not_nil assigns(:objects)
371 assert_empty assigns(:objects)
374 # Granting permissions.
375 test "grant can_read on project to other users in group" do
376 authorize_with :user_foo_in_sharing_group
378 refute users(:user_bar_in_sharing_group).can?(read: collections(:collection_owned_by_foo).uuid)
380 post :create, params: {
382 tail_uuid: users(:user_bar_in_sharing_group).uuid,
383 link_class: 'permission',
385 head_uuid: collections(:collection_owned_by_foo).uuid,
388 assert_response :success
389 assert users(:user_bar_in_sharing_group).can?(read: collections(:collection_owned_by_foo).uuid)