[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