Merge branch '4552-collection-unique-name' closes #4552
[arvados.git] / services / api / app / controllers / arvados / v1 / groups_controller.rb
1 class Arvados::V1::GroupsController < ApplicationController
2
3   def self._contents_requires_parameters
4     _index_requires_parameters.
5       merge({
6               uuid: {
7                 type: 'string', required: false, default: nil
8               },
9               # include_linked returns name links, which are obsolete, so
10               # remove it when clients have been migrated.
11               include_linked: {
12                 type: 'boolean', required: false, default: false
13               },
14             })
15   end
16
17   def render_404_if_no_object
18     if params[:action] == 'contents'
19       if !params[:uuid]
20         # OK!
21         @object = nil
22         true
23       elsif @object
24         # Project group
25         true
26       elsif (@object = User.where(uuid: params[:uuid]).first)
27         # "Home" pseudo-project
28         true
29       else
30         super
31       end
32     else
33       super
34     end
35   end
36
37   def contents
38     # Set @objects:
39     # include_linked returns name links, which are obsolete, so
40     # remove it when clients have been migrated.
41     load_searchable_objects(owner_uuid: @object.andand.uuid,
42                             include_linked: params[:include_linked])
43     sql = 'link_class=? and head_uuid in (?)'
44     sql_params = ['name', @objects.collect(&:uuid)]
45     if @object
46       sql += ' and tail_uuid=?'
47       sql_params << @object.uuid
48     end
49     @links = Link.where sql, *sql_params
50     @object_list = {
51       :kind  => "arvados#objectList",
52       :etag => "",
53       :self_link => "",
54       :links => @links.as_api_response(nil),
55       :offset => @offset,
56       :limit => @limit,
57       :items_available => @items_available,
58       :items => @objects.as_api_response(nil)
59     }
60     render json: @object_list
61   end
62
63   protected
64
65   def load_searchable_objects opts
66     all_objects = []
67     @items_available = 0
68
69     # Trick apply_where_limit_order_params into applying suitable
70     # per-table values. *_all are the real ones we'll apply to the
71     # aggregate set.
72     limit_all = @limit
73     offset_all = @offset
74     # save the orders from the current request as determined by load_param,
75     # but otherwise discard them because we're going to be getting objects
76     # from many models
77     request_orders = @orders.clone
78     @orders = []
79
80     [Group,
81      Job, PipelineInstance, PipelineTemplate,
82      Collection,
83      Human, Specimen, Trait].each do |klass|
84       @objects = klass.readable_by(*@read_users)
85       if klass == Group
86         @objects = @objects.where(group_class: 'project')
87       end
88       if opts[:owner_uuid]
89         conds = []
90         cond_params = []
91         conds << "#{klass.table_name}.owner_uuid = ?"
92         cond_params << opts[:owner_uuid]
93         if conds.any?
94           cond_sql = '(' + conds.join(') OR (') + ')'
95           @objects = @objects.where(cond_sql, *cond_params)
96         end
97       end
98
99       # If the currently requested orders specifically match the table_name for the current klass, apply the order
100       request_order = request_orders && request_orders.find{ |r| r =~ /^#{klass.table_name}\./i }
101       if request_order
102         @objects = @objects.order(request_order)
103       else
104         # default to created_at desc, ignoring any currently requested ordering because it doesn't apply to this klass
105         @objects = @objects.order("#{klass.table_name}.created_at desc")
106       end
107
108       @limit = limit_all - all_objects.count
109       apply_where_limit_order_params klass
110       klass_items_available = @objects.
111         except(:limit).except(:offset).
112         count(:id, distinct: true)
113       @items_available += klass_items_available
114       @offset = [@offset - klass_items_available, 0].max
115
116       all_objects += @objects.to_a
117     end
118
119     @objects = all_objects
120     @limit = limit_all
121     @offset = offset_all
122   end
123
124 end