Merge branch 'main' into 20831-user-table-locks
[arvados.git] / services / api / test / unit / permission_test.rb
index 3f9408837a1e55cd1f1c64b8ea8bb844f3c20bce..14c810d81ae363e4b3f45f166f48a8a11a7898fd 100644 (file)
@@ -46,7 +46,7 @@ class PermissionTest < ActiveSupport::TestCase
   end
 
   test "readable_by" do
   end
 
   test "readable_by" do
-    set_user_from_auth :active_trustedclient
+    set_user_from_auth :admin
 
     ob = Collection.create!
     Link.create!(tail_uuid: users(:active).uuid,
 
     ob = Collection.create!
     Link.create!(tail_uuid: users(:active).uuid,
@@ -57,7 +57,7 @@ class PermissionTest < ActiveSupport::TestCase
   end
 
   test "writable_by" do
   end
 
   test "writable_by" do
-    set_user_from_auth :active_trustedclient
+    set_user_from_auth :admin
 
     ob = Collection.create!
     Link.create!(tail_uuid: users(:active).uuid,
 
     ob = Collection.create!
     Link.create!(tail_uuid: users(:active).uuid,
@@ -84,7 +84,7 @@ class PermissionTest < ActiveSupport::TestCase
     assert users(:active).can?(write: ob)
     assert users(:active).can?(read: ob)
 
     assert users(:active).can?(write: ob)
     assert users(:active).can?(read: ob)
 
-    l1.update_attributes!(name: 'can_read')
+    l1.update!(name: 'can_read')
 
     assert !users(:active).can?(write: ob)
     assert users(:active).can?(read: ob)
 
     assert !users(:active).can?(write: ob)
     assert users(:active).can?(read: ob)
@@ -153,6 +153,7 @@ class PermissionTest < ActiveSupport::TestCase
     set_user_from_auth :admin
 
     owner_grp = Group.create!(owner_uuid: users(:active).uuid, group_class: "role")
     set_user_from_auth :admin
 
     owner_grp = Group.create!(owner_uuid: users(:active).uuid, group_class: "role")
+
     sp_grp = Group.create!(group_class: "project")
 
     Link.create!(link_class: 'permission',
     sp_grp = Group.create!(group_class: "project")
 
     Link.create!(link_class: 'permission',
@@ -217,6 +218,8 @@ class PermissionTest < ActiveSupport::TestCase
   end
 
   test "manager user gets permission to minions' articles via can_manage link" do
   end
 
   test "manager user gets permission to minions' articles via can_manage link" do
+    Rails.configuration.Users.RoleGroupsVisibleToAll = false
+    Rails.configuration.Users.ActivatedUsersAreVisibleToOthers = false
     manager = create :active_user, first_name: "Manage", last_name: "Er"
     minion = create :active_user, first_name: "Min", last_name: "Ion"
     minions_specimen = act_as_user minion do
     manager = create :active_user, first_name: "Manage", last_name: "Er"
     minion = create :active_user, first_name: "Min", last_name: "Ion"
     minions_specimen = act_as_user minion do
@@ -227,7 +230,7 @@ class PermissionTest < ActiveSupport::TestCase
     # anyone any additional permissions.)
     g = nil
     act_as_user manager do
     # anyone any additional permissions.)
     g = nil
     act_as_user manager do
-      g = create :group, name: "NoBigSecret Lab"
+      g = create :group, name: "NoBigSecret Lab", group_class: "role"
       assert_empty(User.readable_by(manager).where(uuid: minion.uuid),
                    "saw a user I shouldn't see")
       assert_raises(ArvadosModel::PermissionDeniedError,
       assert_empty(User.readable_by(manager).where(uuid: minion.uuid),
                    "saw a user I shouldn't see")
       assert_raises(ArvadosModel::PermissionDeniedError,
@@ -290,7 +293,7 @@ class PermissionTest < ActiveSupport::TestCase
                    "manager saw the minion's private stuff")
       assert_raises(ArvadosModel::PermissionDeniedError,
                    "manager could update minion's private stuff") do
                    "manager saw the minion's private stuff")
       assert_raises(ArvadosModel::PermissionDeniedError,
                    "manager could update minion's private stuff") do
-        minions_specimen.update_attributes(properties: {'x' => 'y'})
+        minions_specimen.update(properties: {'x' => 'y'})
       end
     end
 
       end
     end
 
@@ -307,12 +310,13 @@ class PermissionTest < ActiveSupport::TestCase
                          .where(uuid: minions_specimen.uuid),
                        "manager could not find minion's specimen by uuid")
       assert_equal(true,
                          .where(uuid: minions_specimen.uuid),
                        "manager could not find minion's specimen by uuid")
       assert_equal(true,
-                   minions_specimen.update_attributes(properties: {'x' => 'y'}),
+                   minions_specimen.update(properties: {'x' => 'y'}),
                    "manager could not update minion's specimen object")
     end
   end
 
   test "users with bidirectional read permission in group can see each other, but cannot see each other's private articles" do
                    "manager could not update minion's specimen object")
     end
   end
 
   test "users with bidirectional read permission in group can see each other, but cannot see each other's private articles" do
+    Rails.configuration.Users.ActivatedUsersAreVisibleToOthers = false
     a = create :active_user, first_name: "A"
     b = create :active_user, first_name: "B"
     other = create :active_user, first_name: "OTHER"
     a = create :active_user, first_name: "A"
     b = create :active_user, first_name: "B"
     other = create :active_user, first_name: "OTHER"
@@ -323,7 +327,7 @@ class PermissionTest < ActiveSupport::TestCase
                      "#{a.first_name} should not be able to see 'b' in the user list")
 
     act_as_system_user do
                      "#{a.first_name} should not be able to see 'b' in the user list")
 
     act_as_system_user do
-      g = create :group
+      g = create :group, group_class: "role"
       [a,b].each do |u|
         create(:permission_link,
                name: 'can_read', tail_uuid: u.uuid, head_uuid: g.uuid)
       [a,b].each do |u|
         create(:permission_link,
                name: 'can_read', tail_uuid: u.uuid, head_uuid: g.uuid)
@@ -351,17 +355,17 @@ class PermissionTest < ActiveSupport::TestCase
                    "OTHER can see #{u.first_name} in the user list")
       act_as_user u do
         assert_raises ArvadosModel::PermissionDeniedError, "wrote without perm" do
                    "OTHER can see #{u.first_name} in the user list")
       act_as_user u do
         assert_raises ArvadosModel::PermissionDeniedError, "wrote without perm" do
-          other.update_attributes!(prefs: {'pwned' => true})
+          other.update!(prefs: {'pwned' => true})
         end
         end
-        assert_equal(true, u.update_attributes!(prefs: {'thisisme' => true}),
+        assert_equal(true, u.update!(prefs: {'thisisme' => true}),
                      "#{u.first_name} can't update its own prefs")
       end
       act_as_user other do
         assert_raises(ArvadosModel::PermissionDeniedError,
                         "OTHER wrote #{u.first_name} without perm") do
                      "#{u.first_name} can't update its own prefs")
       end
       act_as_user other do
         assert_raises(ArvadosModel::PermissionDeniedError,
                         "OTHER wrote #{u.first_name} without perm") do
-          u.update_attributes!(prefs: {'pwned' => true})
+          u.update!(prefs: {'pwned' => true})
         end
         end
-        assert_equal(true, other.update_attributes!(prefs: {'thisisme' => true}),
+        assert_equal(true, other.update!(prefs: {'thisisme' => true}),
                      "OTHER can't update its own prefs")
       end
     end
                      "OTHER can't update its own prefs")
       end
     end
@@ -378,7 +382,7 @@ class PermissionTest < ActiveSupport::TestCase
     set_user_from_auth :rominiadmin
     ob = Collection.create!
     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable user" do
     set_user_from_auth :rominiadmin
     ob = Collection.create!
     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable user" do
-      ob.update_attributes!(owner_uuid: users(:active).uuid)
+      ob.update!(owner_uuid: users(:active).uuid)
     end
   end
 
     end
   end
 
@@ -393,7 +397,7 @@ class PermissionTest < ActiveSupport::TestCase
     set_user_from_auth :rominiadmin
     ob = Collection.create!
     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable group" do
     set_user_from_auth :rominiadmin
     ob = Collection.create!
     assert_raises ArvadosModel::PermissionDeniedError, "changed owner to unwritable group" do
-      ob.update_attributes!(owner_uuid: groups(:aproject).uuid)
+      ob.update!(owner_uuid: groups(:aproject).uuid)
     end
   end
 
     end
   end
 
@@ -423,7 +427,13 @@ class PermissionTest < ActiveSupport::TestCase
   test "add user to group, then remove them" do
     set_user_from_auth :admin
     grp = Group.create!(owner_uuid: system_user_uuid, group_class: "role")
   test "add user to group, then remove them" do
     set_user_from_auth :admin
     grp = Group.create!(owner_uuid: system_user_uuid, group_class: "role")
-    col = Collection.create!(owner_uuid: grp.uuid)
+    col = Collection.create!(owner_uuid: system_user_uuid)
+
+    l0 = Link.create!(tail_uuid: grp.uuid,
+                 head_uuid: col.uuid,
+                 link_class: 'permission',
+                 name: 'can_read')
+
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
 
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
 
@@ -459,7 +469,7 @@ class PermissionTest < ActiveSupport::TestCase
 
   test "add user to group, then change permission level" do
     set_user_from_auth :admin
 
   test "add user to group, then change permission level" do
     set_user_from_auth :admin
-    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "role")
+    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "project")
     col = Collection.create!(owner_uuid: grp.uuid)
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
     col = Collection.create!(owner_uuid: grp.uuid)
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
@@ -468,10 +478,6 @@ class PermissionTest < ActiveSupport::TestCase
                  head_uuid: grp.uuid,
                  link_class: 'permission',
                  name: 'can_manage')
                  head_uuid: grp.uuid,
                  link_class: 'permission',
                  name: 'can_manage')
-    l2 = Link.create!(tail_uuid: grp.uuid,
-                 head_uuid: users(:active).uuid,
-                 link_class: 'permission',
-                 name: 'can_read')
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
@@ -498,7 +504,7 @@ class PermissionTest < ActiveSupport::TestCase
 
   test "add user to group, then add overlapping permission link to group" do
     set_user_from_auth :admin
 
   test "add user to group, then add overlapping permission link to group" do
     set_user_from_auth :admin
-    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "role")
+    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "project")
     col = Collection.create!(owner_uuid: grp.uuid)
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
     col = Collection.create!(owner_uuid: grp.uuid)
     assert_empty Collection.readable_by(users(:active)).where(uuid: col.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
@@ -507,10 +513,6 @@ class PermissionTest < ActiveSupport::TestCase
                  head_uuid: grp.uuid,
                  link_class: 'permission',
                  name: 'can_manage')
                  head_uuid: grp.uuid,
                  link_class: 'permission',
                  name: 'can_manage')
-    l2 = Link.create!(tail_uuid: grp.uuid,
-                 head_uuid: users(:active).uuid,
-                 link_class: 'permission',
-                 name: 'can_read')
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
@@ -527,19 +529,31 @@ class PermissionTest < ActiveSupport::TestCase
     assert users(:active).can?(write: col.uuid)
     assert users(:active).can?(manage: col.uuid)
 
     assert users(:active).can?(write: col.uuid)
     assert users(:active).can?(manage: col.uuid)
 
-    l3.destroy!
+    # Creating l3 should have automatically deleted l1 and upgraded to
+    # the max permission of {l1, l3}, i.e., can_manage (see #18693) so
+    # there should be no can_read link now.
+    refute Link.where(tail_uuid: l3.tail_uuid,
+                      head_uuid: l3.head_uuid,
+                      link_class: 'permission',
+                      name: 'can_read').any?
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
     assert users(:active).can?(write: col.uuid)
 
     assert Collection.readable_by(users(:active)).where(uuid: col.uuid).first
     assert users(:active).can?(read: col.uuid)
     assert users(:active).can?(write: col.uuid)
-    assert !users(:active).can?(manage: col.uuid)
+    assert users(:active).can?(manage: col.uuid)
   end
 
 
   test "add user to group, then add overlapping permission link to subproject" do
     set_user_from_auth :admin
   end
 
 
   test "add user to group, then add overlapping permission link to subproject" do
     set_user_from_auth :admin
-    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "project")
-    prj = Group.create!(owner_uuid: grp.uuid, group_class: "project")
+    grp = Group.create!(owner_uuid: system_user_uuid, group_class: "role")
+    prj = Group.create!(owner_uuid: system_user_uuid, group_class: "project")
+
+    l0 = Link.create!(tail_uuid: grp.uuid,
+                 head_uuid: prj.uuid,
+                 link_class: 'permission',
+                 name: 'can_manage')
+
     assert_empty Group.readable_by(users(:active)).where(uuid: prj.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
 
     assert_empty Group.readable_by(users(:active)).where(uuid: prj.uuid)
     assert_empty User.readable_by(users(:active)).where(uuid: users(:project_viewer).uuid)
 
@@ -567,11 +581,50 @@ class PermissionTest < ActiveSupport::TestCase
     assert users(:active).can?(write: prj.uuid)
     assert users(:active).can?(manage: prj.uuid)
 
     assert users(:active).can?(write: prj.uuid)
     assert users(:active).can?(manage: prj.uuid)
 
-    l3.destroy!
+    # Creating l3 should have automatically deleted l0 and upgraded to
+    # the max permission of {l0, l3}, i.e., can_manage (see #18693) so
+    # there should be no can_read link now.
+    refute Link.where(tail_uuid: l3.tail_uuid,
+                      head_uuid: l3.head_uuid,
+                      link_class: 'permission',
+                      name: 'can_read').any?
 
     assert Group.readable_by(users(:active)).where(uuid: prj.uuid).first
     assert users(:active).can?(read: prj.uuid)
     assert users(:active).can?(write: prj.uuid)
 
     assert Group.readable_by(users(:active)).where(uuid: prj.uuid).first
     assert users(:active).can?(read: prj.uuid)
     assert users(:active).can?(write: prj.uuid)
-    assert !users(:active).can?(manage: prj.uuid)
+    assert users(:active).can?(manage: prj.uuid)
+  end
+
+  [system_user_uuid, anonymous_user_uuid].each do |u|
+    test "cannot delete system user #{u}" do
+      act_as_system_user do
+        assert_raises ArvadosModel::PermissionDeniedError do
+          User.find_by_uuid(u).destroy
+        end
+      end
+    end
+  end
+
+  [system_group_uuid, anonymous_group_uuid, public_project_uuid].each do |g|
+    test "cannot delete system group #{g}" do
+      act_as_system_user do
+        assert_raises ArvadosModel::PermissionDeniedError do
+          Group.find_by_uuid(g).destroy
+        end
+      end
+    end
+  end
+
+  # Show query plan for readable_by query. The plan for a test db
+  # might not resemble the plan for a production db, but it doesn't
+  # hurt to show the test db plan in test logs, and the .
+  [false, true].each do |include_trash|
+    test "query plan, include_trash=#{include_trash}" do
+      sql = Collection.readable_by(users(:active), include_trash: include_trash).to_sql
+      sql = "explain analyze #{sql}"
+      STDERR.puts sql
+      q = ActiveRecord::Base.connection.exec_query(sql)
+      q.rows.each do |row| STDERR.puts(row) end
+    end
   end
 end
   end
 end