do not render attributes of non-owned objects with x-editable
[arvados.git] / apps / workbench / app / models / arvados_api_client.rb
1 class ArvadosApiClient
2   class NotLoggedInException < StandardError
3   end
4   class InvalidApiResponseException < StandardError
5   end
6   def api(resources_kind, action, data=nil)
7     arvados_api_token = Thread.current[:arvados_api_token]
8     arvados_api_token = '' if arvados_api_token.nil?
9     dataargs = ['--data-urlencode',
10                 "api_token=#{arvados_api_token}",
11                 '--header',
12                 'Accept:application/json']
13     if !data.nil?
14       data.each do |k,v|
15         dataargs << '--data-urlencode'
16         if v.is_a? String or v.nil?
17           dataargs << "#{k}=#{v}"
18         elsif v == true or v == false
19           dataargs << "#{k}=#{v ? 1 : 0}"
20         else
21           dataargs << "#{k}=#{JSON.dump(v)}"
22         end
23       end
24     else
25       dataargs << '--data-urlencode' << '_method=GET'
26     end
27     json = nil
28     resources_kind = class_kind(resources_kind).pluralize if resources_kind.is_a? Class
29     url = "#{self.arvados_v1_base}/#{resources_kind}#{action}"
30     IO.popen([ENV,
31               'curl',
32               "-s#{'k' if Rails.configuration.arvados_insecure_https}",
33               *dataargs,
34               url],
35              'r') do |io|
36       json = io.read
37     end
38     begin
39       resp = Oj.load(json, :symbol_keys => true)
40     rescue Oj::ParseError
41       raise InvalidApiResponseException.new json
42     end
43     if resp[:errors]
44       if resp[:errors][0] == 'Not logged in'
45         raise NotLoggedInException.new
46       else
47         errors = resp[:errors]
48         errors = errors.join("\n\n") if errors.is_a? Array
49         raise "API errors:\n\n#{errors}\n"
50       end
51     end
52     resp
53   end
54
55   def unpack_api_response(j, kind=nil)
56     if j.is_a? Hash and j[:items].is_a? Array and j[:kind].match(/(_list|List)$/)
57       j[:items].collect { |x| unpack_api_response x, j[:kind] }
58     elsif j.is_a? Hash and (kind || j[:kind])
59       oclass = self.kind_class(kind || j[:kind])
60       if oclass
61         j.keys.each do |k|
62           childkind = j["#{k.to_s}_kind".to_sym]
63           if childkind
64             j[k] = self.unpack_api_response(j[k], childkind)
65           end
66         end
67         oclass.new.private_reload(j)
68       else
69         j
70       end
71     else
72       j
73     end
74   end
75
76   def arvados_login_url(params={})
77     if Rails.configuration.respond_to? :arvados_login_base
78       uri = Rails.configuration.arvados_login_base
79     else
80       uri = self.arvados_v1_base.sub(%r{/arvados/v\d+.*}, '/login')
81     end
82     if params.size > 0
83       uri += '?' << params.collect { |k,v|
84         CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s)
85       }.join('&')
86     end
87   end
88
89   def arvados_logout_url(params={})
90     arvados_login_url(params).sub('/login','/logout')
91   end
92
93   def arvados_v1_base
94     Rails.configuration.arvados_v1_base
95   end
96
97   def arvados_schema
98     @arvados_schema ||= api 'schema', ''
99   end
100
101   def kind_class(kind)
102     kind.match(/^arvados\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
103   end
104
105   def class_kind(resource_class)
106     resource_class.to_s.underscore
107   end
108 end