Fix unexpected nil in @required_user_agreements. refs #1699
[arvados.git] / apps / workbench / app / controllers / collections_controller.rb
1 class CollectionsController < ApplicationController
2   skip_before_filter :find_object_by_uuid, :only => [:graph]
3
4   def graph
5     index
6   end
7
8   def index
9     @collections = Collection.limit(100).to_hash
10     @links = Link.eager.limit(100).where(head_kind: 'arvados#collection', link_class: 'resources', name: 'wants') |
11       Link.eager.limit(100).where(tail_kind: 'arvados#collection', link_class: 'data_origin')
12     @collections.merge!(Collection.
13                         limit(100).
14                         where(uuid: @links.select{|x|x.head_kind=='arvados#collection'}.collect(&:head_uuid) |
15                               @links.select{|x|x.tail_kind=='arvados#collection'}.collect(&:tail_uuid)).
16                         to_hash)
17     @collection_info = {}
18     @collections.each do |uuid, c|
19       ci = (@collection_info[uuid] ||= {uuid: uuid})
20       ci[:created_at] = c.created_at
21     end
22     @links.each do |l|
23       if l.head_kind == 'arvados#collection'
24         c = (@collection_info[l.head_uuid] ||= {uuid: l.head_uuid})
25         if l.link_class == 'resources' and l.name == 'wants'
26           if l.head.respond_to? :created_at
27             c[:created_at] = l.head.created_at
28           end
29           c[:wanted] = true
30           if l.owner_uuid == current_user.uuid
31             c[:wanted_by_me] = true
32           end
33         end
34       end
35       if l.tail_kind == 'arvados#collection'
36         c = (@collection_info[l.tail_uuid] ||= {uuid: l.tail_uuid})
37         if l.link_class == 'data_origin'
38           c[:origin] = l
39         end
40       end
41     end
42   end
43
44   def show_file
45     opts = params.merge(arvados_api_token: Thread.current[:arvados_api_token])
46     if r = params[:file].match(/(\.\w+)/)
47       ext = r[1]
48     end
49     self.response.headers['Content-Type'] =
50       Rack::Mime::MIME_TYPES[ext] || 'application/octet-stream'
51     self.response_body = FileStreamer.new opts
52   end
53
54   def show
55     return super if !@object
56     @provenance = []
57     @output2job = {}
58     @output2colorindex = {}
59     @sourcedata = {params[:uuid] => {uuid: params[:uuid]}}
60     @protected = {}
61
62     colorindex = -1
63     any_hope_left = true
64     while any_hope_left
65       any_hope_left = false
66       Job.where(output: @sourcedata.keys).sort_by { |a| a.finished_at || a.created_at }.reverse.each do |job|
67         if !@output2colorindex[job.output]
68           any_hope_left = true
69           @output2colorindex[job.output] = (colorindex += 1) % 10
70           @provenance << {job: job, output: job.output}
71           @sourcedata.delete job.output
72           @output2job[job.output] = job
73           job.dependencies.each do |new_source_data|
74             unless @output2colorindex[new_source_data]
75               @sourcedata[new_source_data] = {uuid: new_source_data}
76             end
77           end
78         end
79       end
80     end
81
82     Link.where(head_uuid: @sourcedata.keys | @output2job.keys).each do |link|
83       if link.link_class == 'resources' and link.name == 'wants'
84         @protected[link.head_uuid] = true
85       end
86     end
87     Link.where(tail_uuid: @sourcedata.keys).each do |link|
88       if link.link_class == 'data_origin'
89         @sourcedata[link.tail_uuid][:data_origins] ||= []
90         @sourcedata[link.tail_uuid][:data_origins] << [link.name, link.head_kind, link.head_uuid]
91       end
92     end
93     Collection.where(uuid: @sourcedata.keys).each do |collection|
94       if @sourcedata[collection.uuid]
95         @sourcedata[collection.uuid][:collection] = collection
96       end
97     end
98   end
99
100   protected
101   class FileStreamer
102     def initialize(opts={})
103       @opts = opts
104     end
105     def each
106       return unless @opts[:uuid] && @opts[:file]
107       env = Hash[ENV].
108         merge({
109                 'ARVADOS_API_HOST' =>
110                 $arvados_api_client.arvados_v1_base.
111                 sub(/\/arvados\/v1/, '').
112                 sub(/^https?:\/\//, ''),
113                 'ARVADOS_API_TOKEN' =>
114                 @opts[:arvados_api_token],
115                 'ARVADOS_API_HOST_INSECURE' =>
116                 Rails.configuration.arvados_insecure_https ? 'true' : 'false'
117               })
118       IO.popen([env, 'arv-get', "#{@opts[:uuid]}/#{@opts[:file]}"],
119                'rb') do |io|
120         while buf = io.read(2**20)
121           yield buf
122         end
123       end
124       Rails.logger.warn("#{@opts[:uuid]}/#{@opts[:file]}: $?") if $? != 0
125     end
126   end
127 end