20318: Implement BlockRead via ReadAt so it supports streaming.
[arvados.git] / services / api / test / unit / link_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 LinkTest < ActiveSupport::TestCase
8   fixtures :all
9
10   setup do
11     set_user_from_auth :admin_trustedclient
12   end
13
14   test "cannot delete an object referenced by unwritable links" do
15     ob = act_as_user users(:active) do
16       Specimen.create
17     end
18     link = act_as_user users(:admin) do
19       Link.create(tail_uuid: users(:active).uuid,
20                   head_uuid: ob.uuid,
21                   link_class: 'test',
22                   name: 'test')
23     end
24     assert_equal users(:admin).uuid, link.owner_uuid
25     assert_raises(ArvadosModel::PermissionDeniedError,
26                   "should not delete #{ob.uuid} with link #{link.uuid}") do
27       act_as_user users(:active) do
28         ob.destroy
29       end
30     end
31     act_as_user users(:admin) do
32       ob.destroy
33     end
34     assert_empty Link.where(uuid: link.uuid)
35   end
36
37   def new_active_link_valid?(link_attrs)
38     set_user_from_auth :active
39     begin
40       Link.
41         create({link_class: "permission",
42                  name: "can_read",
43                  head_uuid: groups(:aproject).uuid,
44                }.merge(link_attrs)).
45         valid?
46     rescue ArvadosModel::PermissionDeniedError
47       false
48     end
49   end
50
51   test "non-admin project owner can make it public" do
52     assert(new_active_link_valid?(tail_uuid: groups(:anonymous_group).uuid),
53            "non-admin project owner can't make their project public")
54   end
55
56   test "link granting permission to nonexistent user is invalid" do
57     refute new_active_link_valid?(tail_uuid:
58                                   users(:active).uuid.sub(/-\w+$/, "-#{'z' * 15}"))
59   end
60
61   test "link granting permission to remote user is valid" do
62     refute new_active_link_valid?(tail_uuid:
63                                   users(:active).uuid.sub(/^\w+-/, "foooo-"))
64     Rails.configuration.RemoteClusters = Rails.configuration.RemoteClusters.merge({foooo: ActiveSupport::InheritableOptions.new({Host: "bar.com"})})
65     assert new_active_link_valid?(tail_uuid:
66                                   users(:active).uuid.sub(/^\w+-/, "foooo-"))
67   end
68
69   test "link granting non-project permission to unreadable user is invalid" do
70     refute new_active_link_valid?(tail_uuid: users(:admin).uuid,
71                                   head_uuid: collections(:bar_file).uuid)
72   end
73
74   test "user can't add a Collection to a Project without permission" do
75     refute new_active_link_valid?(link_class: "name",
76                                   name: "Permission denied test name",
77                                   tail_uuid: collections(:bar_file).uuid)
78   end
79
80   test "user can't add a User to a Project" do
81     # Users *can* give other users permissions to projects.
82     # This test helps ensure that that exception is specific to permissions.
83     refute new_active_link_valid?(link_class: "name",
84                                   name: "Permission denied test name",
85                                   tail_uuid: users(:admin).uuid)
86   end
87
88   test "link granting project permissions to unreadable user is invalid" do
89     refute new_active_link_valid?(tail_uuid: users(:admin).uuid)
90   end
91
92   test "permission link can't exist on past collection versions" do
93     refute new_active_link_valid?(tail_uuid: groups(:public).uuid,
94                                   head_uuid: collections(:w_a_z_file_version_1).uuid)
95   end
96
97   def create_overlapping_permissions(names=[], attrs={})
98     names.map do |name|
99       link = Link.create!({
100                             link_class: "tmp",
101                             tail_uuid: users(:active).uuid,
102                             head_uuid: collections(:baz_file).uuid,
103                             name: name,
104                           }.merge(attrs).merge({name: name}))
105       ActiveRecord::Base.connection.execute "update links set link_class='permission' where uuid='#{link.uuid}'"
106       link.uuid
107     end
108   end
109
110   test "updating permission causes any conflicting links to be deleted" do
111     link1, link2 = create_overlapping_permissions(['can_read', 'can_manage'])
112     Link.find_by_uuid(link2).update!(name: 'can_write')
113     assert_empty Link.where(uuid: link1)
114   end
115
116   test "deleting permission causes any conflicting links to be deleted" do
117     rlink, wlink = create_overlapping_permissions(['can_read', 'can_write'])
118     Link.find_by_uuid(wlink).destroy
119     assert_empty Link.where(uuid: rlink)
120   end
121
122   test "updating login permission causes any conflicting links to be deleted" do
123     link1, link2 = create_overlapping_permissions(['can_login', 'can_login'], {properties: {username: 'foo1'}})
124     Link.find_by_uuid(link1).update!(properties: {'username' => 'foo2'})
125     Link.find_by_uuid(link2).update!(properties: {'username' => 'foo2'})
126     assert_empty Link.where(uuid: link1)
127   end
128
129   test "deleting login permission causes any conflicting links to be deleted" do
130     link1, link2 = create_overlapping_permissions(['can_login', 'can_login'], {properties: {username: 'foo1'}})
131     Link.find_by_uuid(link1).destroy
132     assert_empty Link.where(uuid: link2)
133   end
134 end