[ARVADOS] created: efcfd2cdc9a9ed6ab3af54e9a4e149d4bdf1f8d3

Git user git at public.curoverse.com
Fri Jun 2 14:54:39 EDT 2017


        at  efcfd2cdc9a9ed6ab3af54e9a4e149d4bdf1f8d3 (commit)


commit efcfd2cdc9a9ed6ab3af54e9a4e149d4bdf1f8d3
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Jun 2 14:53:20 2017 -0400

    11652: Add "recursive" flag to groups#contents controller.
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at curoverse.com>

diff --git a/services/api/app/controllers/arvados/v1/groups_controller.rb b/services/api/app/controllers/arvados/v1/groups_controller.rb
index fc64899..4c33be6 100644
--- a/services/api/app/controllers/arvados/v1/groups_controller.rb
+++ b/services/api/app/controllers/arvados/v1/groups_controller.rb
@@ -91,6 +91,15 @@ class Arvados::V1::GroupsController < ApplicationController
       end
     end
 
+    filter_by_owner = {}
+    if @object
+      if params['recursive']
+        filter_by_owner[:owner_uuid] = [@object.uuid] + @object.descendant_project_uuids
+      else
+        filter_by_owner[:owner_uuid] = @object.uuid
+      end
+    end
+
     seen_last_class = false
     klasses.each do |klass|
       @offset = 0 if seen_last_class  # reset offset for the new next type being processed
@@ -118,12 +127,11 @@ class Arvados::V1::GroupsController < ApplicationController
         klass.default_orders.join(", ")
 
       @select = nil
-      where_conds = {}
-      where_conds[:owner_uuid] = @object.uuid if @object
+      where_conds = filter_by_owner
       if klass == Collection
         @select = klass.selectable_attributes - ["manifest_text"]
       elsif klass == Group
-        where_conds[:group_class] = "project"
+        where_conds = where_conds.merge(group_class: "project")
       end
 
       @filters = request_filters.map do |col, op, val|
diff --git a/services/api/app/models/user.rb b/services/api/app/models/user.rb
index 742db4c..d944474 100644
--- a/services/api/app/models/user.rb
+++ b/services/api/app/models/user.rb
@@ -144,33 +144,20 @@ class User < ArvadosModel
   # and perm_hash[:write] are true if this user can read and write
   # objects owned by group_uuid.
   def calculate_group_permissions
-    conn = ActiveRecord::Base.connection
-    self.class.transaction do
-      # Check whether the temporary view has already been created
-      # during this connection. If not, create it.
-      conn.exec_query 'SAVEPOINT check_permission_view'
-      begin
-        conn.exec_query('SELECT 1 FROM permission_view LIMIT 0')
-      rescue
-        conn.exec_query 'ROLLBACK TO SAVEPOINT check_permission_view'
-        sql = File.read(Rails.root.join('lib', 'create_permission_view.sql'))
-        conn.exec_query(sql)
-      ensure
-        conn.exec_query 'RELEASE SAVEPOINT check_permission_view'
-      end
-    end
+    install_view('permission')
 
     group_perms = {}
-    conn.exec_query('SELECT target_owner_uuid, max(perm_level)
-                    FROM permission_view
-                    WHERE user_uuid = $1
-                    AND target_owner_uuid IS NOT NULL
-                    GROUP BY target_owner_uuid',
-                    # "name" arg is a query label that appears in logs:
-                    "group_permissions for #{uuid}",
-                    # "binds" arg is an array of [col_id, value] for '$1' vars:
-                    [[nil, uuid]],
-                    ).rows.each do |group_uuid, max_p_val|
+    ActiveRecord::Base.connection.
+      exec_query('SELECT target_owner_uuid, max(perm_level)
+                  FROM permission_view
+                  WHERE user_uuid = $1
+                  AND target_owner_uuid IS NOT NULL
+                  GROUP BY target_owner_uuid',
+                  # "name" arg is a query label that appears in logs:
+                  "group_permissions for #{uuid}",
+                  # "binds" arg is an array of [col_id, value] for '$1' vars:
+                  [[nil, uuid]],
+                  ).rows.each do |group_uuid, max_p_val|
       group_perms[group_uuid] = PERMS_FOR_VAL[max_p_val.to_i]
     end
     Rails.cache.write "groups_for_user_#{self.uuid}", group_perms
diff --git a/services/api/lib/can_be_an_owner.rb b/services/api/lib/can_be_an_owner.rb
index 75a6350..e9f016d 100644
--- a/services/api/lib/can_be_an_owner.rb
+++ b/services/api/lib/can_be_an_owner.rb
@@ -22,6 +22,22 @@ module CanBeAnOwner
     base.validate :restrict_uuid_change_breaking_associations
   end
 
+  def descendant_project_uuids
+    install_view('ancestor')
+    ActiveRecord::Base.connection.
+      exec_query('SELECT ancestor_view.uuid
+                  FROM ancestor_view
+                  LEFT JOIN groups ON groups.uuid=ancestor_view.uuid
+                  WHERE ancestor_uuid = $1 AND groups.group_class = $2',
+                  # "name" arg is a query label that appears in logs:
+                  "descendant_project_uuids for #{self.uuid}",
+                  # "binds" arg is an array of [col_id, value] for '$1' vars:
+                  [[nil, self.uuid], [nil, 'project']],
+                  ).rows.map do |project_uuid,|
+      project_uuid
+    end
+  end
+
   protected
 
   def restrict_uuid_change_breaking_associations
@@ -44,4 +60,21 @@ module CanBeAnOwner
     end
   end
 
+  def install_view(type)
+    conn = ActiveRecord::Base.connection
+    self.class.transaction do
+      # Check whether the temporary view has already been created
+      # during this connection. If not, create it.
+      conn.exec_query "SAVEPOINT check_#{type}_view"
+      begin
+        conn.exec_query("SELECT 1 FROM #{type}_view LIMIT 0")
+      rescue
+        conn.exec_query "ROLLBACK TO SAVEPOINT check_#{type}_view"
+        sql = File.read(Rails.root.join("lib", "create_#{type}_view.sql"))
+        conn.exec_query(sql)
+      ensure
+        conn.exec_query "RELEASE SAVEPOINT check_#{type}_view"
+      end
+    end
+  end
 end
diff --git a/services/api/lib/create_ancestor_view.sql b/services/api/lib/create_ancestor_view.sql
new file mode 100644
index 0000000..105fd04
--- /dev/null
+++ b/services/api/lib/create_ancestor_view.sql
@@ -0,0 +1,14 @@
+CREATE TEMPORARY VIEW ancestor_view AS
+WITH RECURSIVE
+ancestor (uuid, ancestor_uuid) AS (
+     SELECT groups.uuid::varchar(32)       AS uuid,
+            groups.owner_uuid::varchar(32) AS ancestor_uuid
+            FROM groups
+     UNION
+     SELECT ancestor.uuid::varchar(32)     AS uuid,
+            groups.owner_uuid::varchar(32) AS ancestor_uuid
+            FROM ancestor
+            INNER JOIN groups
+            ON groups.uuid = ancestor.ancestor_uuid
+)
+SELECT * FROM ancestor;
diff --git a/services/api/test/functional/arvados/v1/groups_controller_test.rb b/services/api/test/functional/arvados/v1/groups_controller_test.rb
index 02d8c15..e82113e 100644
--- a/services/api/test/functional/arvados/v1/groups_controller_test.rb
+++ b/services/api/test/functional/arvados/v1/groups_controller_test.rb
@@ -477,4 +477,18 @@ class Arvados::V1::GroupsControllerTest < ActionController::TestCase
     assert_operator(json_response['items'].count,
                     :<, json_response['items_available'])
   end
+
+  test 'get contents recursive=true' do
+    authorize_with :active
+    get :contents, {
+          id: groups(:aproject).uuid,
+          recursive: true,
+          format: :json,
+        }
+    owners = json_response['items'].map do |item|
+      item['owner_uuid']
+    end
+    assert_includes(owners, groups(:aproject).uuid)
+    assert_includes(owners, groups(:asubproject).uuid)
+  end
 end

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list