12032: Tests for group delete behavior.
authorPeter Amstutz <peter.amstutz@curoverse.com>
Thu, 24 Aug 2017 21:09:49 +0000 (17:09 -0400)
committerPeter Amstutz <peter.amstutz@curoverse.com>
Thu, 14 Sep 2017 23:39:06 +0000 (19:39 -0400)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz@veritasgenetics.com>

services/api/app/models/group.rb
services/api/db/migrate/20170824202826_trashable_groups.rb [new file with mode: 0644]
services/api/db/structure.sql
services/api/lib/create_permission_view.sql
services/api/test/unit/group_test.rb

index 0dd2a73576c00a32e6310307798e8acf9a4de0cf..861800d2093878c3cd16011e4eac1c0cee3ae18d 100644 (file)
@@ -3,12 +3,15 @@
 # SPDX-License-Identifier: AGPL-3.0
 
 require 'can_be_an_owner'
+require 'trashable'
 
 class Group < ArvadosModel
   include HasUuid
   include KindAndEtag
   include CommonApiTemplate
   include CanBeAnOwner
+  include Trashable
+
   after_create :invalidate_permissions_cache
   after_update :maybe_invalidate_permissions_cache
   before_create :assign_name
@@ -18,6 +21,9 @@ class Group < ArvadosModel
     t.add :group_class
     t.add :description
     t.add :writable_by
+    t.add :delete_at
+    t.add :trash_at
+    t.add :is_trashed
   end
 
   def maybe_invalidate_permissions_cache
diff --git a/services/api/db/migrate/20170824202826_trashable_groups.rb b/services/api/db/migrate/20170824202826_trashable_groups.rb
new file mode 100644 (file)
index 0000000..b7e3373
--- /dev/null
@@ -0,0 +1,7 @@
+class TrashableGroups < ActiveRecord::Migration
+  def change
+    add_column :groups, :trash_at, :datetime
+    add_column :groups, :delete_at, :datetime
+    add_column :groups, :is_trashed, :boolean, null: false, default: false
+  end
+end
index 7e6bb1dca4f0f71612e800339beba6e2f5d11344..90aa0a37c1f2cf3dc1ccfd1bc1e6b649f89b07a0 100644 (file)
@@ -391,7 +391,10 @@ CREATE TABLE groups (
     name character varying(255) NOT NULL,
     description character varying(524288),
     updated_at timestamp without time zone NOT NULL,
-    group_class character varying(255)
+    group_class character varying(255),
+    trash_at timestamp without time zone,
+    delete_at timestamp without time zone,
+    is_trashed boolean DEFAULT false NOT NULL
 );
 
 
@@ -2791,3 +2794,5 @@ INSERT INTO schema_migrations (version) VALUES ('20170419175801');
 
 INSERT INTO schema_migrations (version) VALUES ('20170628185847');
 
+INSERT INTO schema_migrations (version) VALUES ('20170824202826');
+
index 82839e89e37ff85a5cdbc17f04211887f47a1164..e6195d7911f43667d885ba3f626a683da945e0f0 100644 (file)
@@ -37,7 +37,7 @@ perm_edges (tail_uuid, head_uuid, val, follow, trashed) AS (
               LEFT JOIN groups ON pv.val<3 AND groups.uuid = links.head_uuid
               WHERE links.link_class = 'permission'
        UNION ALL
-       SELECT owner_uuid, uuid, 3, true, 0::smallint FROM groups
+       SELECT owner_uuid, uuid, 3, true, CASE is_trashed WHEN true THEN 1 ELSE 0 END FROM groups
        ),
 perm (val, follow, user_uuid, target_uuid, trashed, startnode) AS (
      SELECT 3::smallint             AS val,
index a1123b10ca635edbfe195754f8f3bec90d7bccc3..11f546bc6e1fc26ab2bb282907ece55b4c4c88ea 100644 (file)
@@ -60,4 +60,44 @@ class GroupTest < ActiveSupport::TestCase
     assert g_foo.errors.messages[:owner_uuid].join(" ").match(/ownership cycle/)
   end
 
+  test "delete group hides contents" do
+    set_user_from_auth :active_trustedclient
+
+    g_foo = Group.create!(name: "foo")
+    col = Collection.create!(owner_uuid: g_foo.uuid)
+
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).any?
+    g_foo.update! is_trashed: true
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).empty?
+    g_foo.update! is_trashed: false
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).any?
+  end
+
+
+  test "delete group propagates to subgroups" do
+    set_user_from_auth :active_trustedclient
+
+    g_foo = Group.create!(name: "foo")
+    g_bar = Group.create!(name: "bar", owner_uuid: g_foo.uuid)
+    col = Collection.create!(owner_uuid: g_bar.uuid)
+
+    assert Group.readable_by(users(:active)).where(uuid: g_foo.uuid).any?
+    assert Group.readable_by(users(:active)).where(uuid: g_bar.uuid).any?
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).any?
+
+    g_foo.update! is_trashed: true
+    assert Group.readable_by(users(:active)).where(uuid: g_foo.uuid).empty?
+    assert Group.readable_by(users(:active)).where(uuid: g_bar.uuid).empty?
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).empty?
+
+    assert Group.readable_by(users(:active), {:include_trashed => true}).where(uuid: g_foo.uuid).any?
+    assert Group.readable_by(users(:active), {:include_trashed => true}).where(uuid: g_bar.uuid).any?
+    assert Collection.readable_by(users(:active), {:include_trashed => true}).where(uuid: col.uuid).any?
+
+    g_foo.update! is_trashed: false
+    assert Group.readable_by(users(:active)).where(uuid: g_foo.uuid).any?
+    assert Group.readable_by(users(:active)).where(uuid: g_bar.uuid).any?
+    assert Collection.readable_by(users(:active)).where(uuid: col.uuid).any?
+  end
+
 end