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