Merge branch 'master' into 3112-report-bug
[arvados.git] / services / api / test / unit / permission_test.rb
1 require 'test_helper'
2
3 class PermissionTest < ActiveSupport::TestCase
4   include CurrentApiClient
5
6   test "Grant permissions on an object I own" do
7     set_user_from_auth :active_trustedclient
8
9     ob = Specimen.create
10     assert ob.save
11
12     # Ensure I have permission to manage this group even when its owner changes
13     perm_link = Link.create(tail_uuid: users(:active).uuid,
14                             head_uuid: ob.uuid,
15                             link_class: 'permission',
16                             name: 'can_manage')
17     assert perm_link.save, "should give myself permission on my own object"
18   end
19
20   test "Delete permission links when deleting an object" do
21     set_user_from_auth :active_trustedclient
22
23     ob = Specimen.create!
24     Link.create!(tail_uuid: users(:active).uuid,
25                  head_uuid: ob.uuid,
26                  link_class: 'permission',
27                  name: 'can_manage')
28     ob_uuid = ob.uuid
29     assert ob.destroy, "Could not destroy object with 1 permission link"
30     assert_empty(Link.where(head_uuid: ob_uuid),
31                  "Permission link was not deleted when object was deleted")
32   end
33
34   test "permission links owned by root" do
35     set_user_from_auth :active_trustedclient
36     ob = Specimen.create!
37     perm_link = Link.create!(tail_uuid: users(:active).uuid,
38                              head_uuid: ob.uuid,
39                              link_class: 'permission',
40                              name: 'can_read')
41     assert_equal system_user_uuid, perm_link.owner_uuid
42   end
43
44   test "readable_by" do
45     set_user_from_auth :active_trustedclient
46
47     ob = Specimen.create!
48     Link.create!(tail_uuid: users(:active).uuid,
49                  head_uuid: ob.uuid,
50                  link_class: 'permission',
51                  name: 'can_read')
52     assert Specimen.readable_by(users(:active)).where(uuid: ob.uuid).any?, "user does not have read permission"
53   end
54
55   test "writable_by" do
56     set_user_from_auth :active_trustedclient
57
58     ob = Specimen.create!
59     Link.create!(tail_uuid: users(:active).uuid,
60                  head_uuid: ob.uuid,
61                  link_class: 'permission',
62                  name: 'can_write')
63     assert ob.writable_by.include?(users(:active).uuid), "user does not have write permission"
64   end
65
66   test "user owns group, group can_manage object's group, user can add permissions" do
67     set_user_from_auth :admin
68
69     owner_grp = Group.create!(owner_uuid: users(:active).uuid)
70
71     sp_grp = Group.create!
72     sp = Specimen.create!(owner_uuid: sp_grp.uuid)
73
74     manage_perm = Link.create!(link_class: 'permission',
75                                name: 'can_manage',
76                                tail_uuid: owner_grp.uuid,
77                                head_uuid: sp_grp.uuid)
78
79     # active user owns owner_grp, which has can_manage permission on sp_grp
80     # user should be able to add permissions on sp.
81     set_user_from_auth :active_trustedclient
82     test_perm = Link.create(tail_uuid: users(:active).uuid,
83                             head_uuid: sp.uuid,
84                             link_class: 'permission',
85                             name: 'can_write')
86     test_uuid = test_perm.uuid
87     assert test_perm.save, "could not save new permission on target object"
88     assert test_perm.destroy, "could not delete new permission on target object"
89   end
90
91   # TODO(twp): fix bug #3091, which should fix this test.
92   test "can_manage permission on a non-group object" do
93     skip
94     set_user_from_auth :admin
95
96     ob = Specimen.create!
97     # grant can_manage permission to active
98     perm_link = Link.create!(tail_uuid: users(:active).uuid,
99                              head_uuid: ob.uuid,
100                              link_class: 'permission',
101                              name: 'can_manage')
102     # ob is owned by :admin, the link is owned by root
103     assert_equal users(:admin).uuid, ob.owner_uuid
104     assert_equal system_user_uuid, perm_link.owner_uuid
105
106     # user "active" can modify the permission link
107     set_user_from_auth :active_trustedclient
108     perm_link.properties["foo"] = 'bar'
109     assert perm_link.save, "could not save modified link"
110
111     assert_equal 'bar', perm_link.properties['foo'], "link properties do not include foo = bar"
112   end
113
114   test "user without can_manage permission may not modify permission link" do
115     set_user_from_auth :admin
116
117     ob = Specimen.create!
118     # grant can_manage permission to active
119     perm_link = Link.create!(tail_uuid: users(:active).uuid,
120                              head_uuid: ob.uuid,
121                              link_class: 'permission',
122                              name: 'can_read')
123     # ob is owned by :admin, the link is owned by root
124     assert_equal ob.owner_uuid, users(:admin).uuid
125     assert_equal perm_link.owner_uuid, system_user_uuid
126
127     # user "active" may not modify the permission link
128     set_user_from_auth :active_trustedclient
129     perm_link.name = 'can_manage'
130     assert_raises ArvadosModel::PermissionDeniedError do
131       perm_link.save
132     end
133   end
134
135   test "manager user gets permission to minions' articles via can_manage link" do
136     manager = create :active_user, first_name: "Manage", last_name: "Er"
137     minion = create :active_user, first_name: "Min", last_name: "Ion"
138     minions_specimen = act_as_user minion do
139       Specimen.create!
140     end
141     # Manager creates a group. (Make sure it doesn't magically give
142     # anyone any additional permissions.)
143     g = nil
144     act_as_user manager do
145       g = create :group, name: "NoBigSecret Lab"
146       assert_empty(User.readable_by(manager).where(uuid: minion.uuid),
147                    "saw a user I shouldn't see")
148       assert_raises(ArvadosModel::PermissionDeniedError,
149                     ActiveRecord::RecordInvalid,
150                     "gave can_read permission to a user I shouldn't see") do
151         create(:permission_link,
152                name: 'can_read', tail_uuid: minion.uuid, head_uuid: g.uuid)
153       end
154       %w(can_manage can_write can_read).each do |perm_type|
155         assert_raises(ArvadosModel::PermissionDeniedError,
156                       ActiveRecord::RecordInvalid,
157                       "escalated privileges") do
158           create(:permission_link,
159                  name: perm_type, tail_uuid: g.uuid, head_uuid: minion.uuid)
160         end
161       end
162       assert_empty(User.readable_by(manager).where(uuid: minion.uuid),
163                    "manager saw minion too soon")
164       assert_empty(User.readable_by(minion).where(uuid: manager.uuid),
165                    "minion saw manager too soon")
166       assert_empty(Group.readable_by(minion).where(uuid: g.uuid),
167                    "minion saw manager's new NoBigSecret Lab group too soon")
168
169       # Manager declares everybody on the system should be able to see
170       # the NoBigSecret Lab group.
171       create(:permission_link,
172              name: 'can_read',
173              tail_uuid: 'zzzzz-j7d0g-fffffffffffffff',
174              head_uuid: g.uuid)
175       # ...but nobody has joined the group yet. Manager still can't see
176       # minion.
177       assert_empty(User.readable_by(manager).where(uuid: minion.uuid),
178                    "manager saw minion too soon")
179     end
180
181     act_as_user minion do
182       # Minion can see the group.
183       assert_not_empty(Group.readable_by(minion).where(uuid: g.uuid),
184                        "minion could not see the NoBigSecret Lab group")
185       # Minion joins the group.
186       create(:permission_link,
187              name: 'can_read',
188              tail_uuid: g.uuid,
189              head_uuid: minion.uuid)
190     end
191
192     act_as_user manager do
193       # Now, manager can see minion.
194       assert_not_empty(User.readable_by(manager).where(uuid: minion.uuid),
195                        "manager could not see minion")
196       # But cannot obtain further privileges this way.
197       assert_raises(ArvadosModel::PermissionDeniedError,
198                     "escalated privileges") do
199         create(:permission_link,
200                name: 'can_manage', tail_uuid: manager.uuid, head_uuid: minion.uuid)
201       end
202       assert_empty(Specimen
203                      .readable_by(manager)
204                      .where(uuid: minions_specimen.uuid),
205                    "manager saw the minion's private stuff")
206       assert_raises(ArvadosModel::PermissionDeniedError,
207                    "manager could update minion's private stuff") do
208         minions_specimen.update_attributes(properties: {'x' => 'y'})
209       end
210     end
211
212     act_as_system_user do
213       # Root can give Manager more privileges over Minion.
214       create(:permission_link,
215              name: 'can_manage', tail_uuid: g.uuid, head_uuid: minion.uuid)
216     end
217
218     act_as_user manager do
219       # Now, manager can read and write Minion's stuff.
220       assert_not_empty(Specimen
221                          .readable_by(manager)
222                          .where(uuid: minions_specimen.uuid),
223                        "manager could not find minion's specimen by uuid")
224       assert_equal(true,
225                    minions_specimen.update_attributes(properties: {'x' => 'y'}),
226                    "manager could not update minion's specimen object")
227     end
228   end
229
230   test "users with bidirectional read permission in group can see each other, but cannot see each other's private articles" do
231     a = create :active_user, first_name: "A"
232     b = create :active_user, first_name: "B"
233     other = create :active_user, first_name: "OTHER"
234     act_as_system_user do
235       g = create :group
236       [a,b].each do |u|
237         create(:permission_link,
238                name: 'can_read', tail_uuid: u.uuid, head_uuid: g.uuid)
239         create(:permission_link,
240                name: 'can_read', head_uuid: u.uuid, tail_uuid: g.uuid)
241       end
242     end
243     a_specimen = act_as_user a do
244       Specimen.create!
245     end
246     assert_not_empty(Specimen.readable_by(a).where(uuid: a_specimen.uuid),
247                      "A cannot read own Specimen, following test probably useless.")
248     assert_empty(Specimen.readable_by(b).where(uuid: a_specimen.uuid),
249                  "B can read A's Specimen")
250     [a,b].each do |u|
251       assert_empty(User.readable_by(u).where(uuid: other.uuid),
252                    "#{u.first_name} can see OTHER in the user list")
253       assert_empty(User.readable_by(other).where(uuid: u.uuid),
254                    "OTHER can see #{u.first_name} in the user list")
255       act_as_user u do
256         assert_raises ArvadosModel::PermissionDeniedError, "wrote without perm" do
257           other.update_attributes!(prefs: {'pwned' => true})
258         end
259         assert_equal(true, u.update_attributes!(prefs: {'thisisme' => true}),
260                      "#{u.first_name} can't update its own prefs")
261       end
262       act_as_user other do
263         assert_raises(ArvadosModel::PermissionDeniedError,
264                         "OTHER wrote #{u.first_name} without perm") do
265           u.update_attributes!(prefs: {'pwned' => true})
266         end
267         assert_equal(true, other.update_attributes!(prefs: {'thisisme' => true}),
268                      "OTHER can't update its own prefs")
269       end
270     end
271   end
272
273   test "cannot create with owner = unwritable user" do
274     set_user_from_auth :rominiadmin
275     assert_raises ArvadosModel::PermissionDeniedError, "created with owner = unwritable user" do
276       Specimen.create!(owner_uuid: users(:active).uuid)
277     end
278   end
279
280   test "cannot change owner to unwritable user" do
281     set_user_from_auth :rominiadmin
282     ob = Specimen.create!
283     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable user" do
284       ob.update_attributes!(owner_uuid: users(:active).uuid)
285     end
286   end
287
288   test "cannot create with owner = unwritable group" do
289     set_user_from_auth :rominiadmin
290     assert_raises ArvadosModel::PermissionDeniedError, "created with owner = unwritable group" do
291       Specimen.create!(owner_uuid: groups(:aproject).uuid)
292     end
293   end
294
295   test "cannot change owner to unwritable group" do
296     set_user_from_auth :rominiadmin
297     ob = Specimen.create!
298     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable group" do
299       ob.update_attributes!(owner_uuid: groups(:aproject).uuid)
300     end
301   end
302
303 end