Merge branch '8784-dir-listings'
[arvados.git] / services / api / app / controllers / arvados / v1 / groups_controller.rb
index 7d4bca53357d2387f0a3ad144467226f82eb98f1..75ef095b71ce249d18fb23075782bd32deaf6663 100644 (file)
@@ -1,3 +1,7 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
 class Arvados::V1::GroupsController < ApplicationController
 
   def self._contents_requires_parameters
@@ -6,6 +10,9 @@ class Arvados::V1::GroupsController < ApplicationController
               uuid: {
                 type: 'string', required: false, default: nil
               },
+              recursive: {
+                type: 'boolean', required: false, description: 'Include contents from child groups recursively.'
+              },
             })
     params.delete(:select)
     params
@@ -91,12 +98,24 @@ 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
 
       # if current klass is same as params['last_object_class'], mark that fact
-      seen_last_class = true if(params['count'].andand.==('none') and (params['last_object_class'].nil? or params['last_object_class'].empty? or params['last_object_class'] == klass.to_s))
+      seen_last_class = true if((params['count'].andand.==('none')) and
+                                (params['last_object_class'].nil? or
+                                 params['last_object_class'].empty? or
+                                 params['last_object_class'] == klass.to_s))
 
       # if klasses are specified, skip all other klass types
       next if wanted_klasses.any? and !wanted_klasses.include?(klass.to_s)
@@ -115,12 +134,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|
@@ -133,15 +151,28 @@ class Arvados::V1::GroupsController < ApplicationController
         end
       end.compact
 
-      @objects = klass.readable_by(*@read_users).
-        order(request_order).where(where_conds)
-      @limit = limit_all - all_objects.count
+      if klass == Collection and params[:include_trash]
+        @objects = klass.unscoped.readable_by(*@read_users).
+          order(request_order).where(where_conds)
+      else
+        @objects = klass.readable_by(*@read_users).
+          order(request_order).where(where_conds)
+      end
+      klass_limit = limit_all - all_objects.count
+      @limit = klass_limit
       apply_where_limit_order_params klass
-      klass_object_list = object_list
+      klass_object_list = object_list(model_class: klass)
       klass_items_available = klass_object_list[:items_available] || 0
       @items_available += klass_items_available
       @offset = [@offset - klass_items_available, 0].max
       all_objects += klass_object_list[:items]
+
+      if klass_object_list[:limit] < klass_limit
+        # object_list() had to reduce @limit to comply with
+        # max_index_database_read. From now on, we'll do all queries
+        # with limit=0 and just accumulate items_available.
+        limit_all = all_objects.count
+      end
     end
 
     @objects = all_objects