X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/6f6235983d91e0b9fb5660d0a2825f510bbdac73..0b4f867ef14af38c07b910643fbe8cc6a93e6bb6:/apps/workbench/app/models/arvados_api_client.rb diff --git a/apps/workbench/app/models/arvados_api_client.rb b/apps/workbench/app/models/arvados_api_client.rb index 040af43abd..7574cf665b 100644 --- a/apps/workbench/app/models/arvados_api_client.rb +++ b/apps/workbench/app/models/arvados_api_client.rb @@ -6,6 +6,8 @@ class ArvadosApiClient end class InvalidApiResponseException < StandardError end + class AccessForbiddenException < StandardError + end @@profiling_enabled = Rails.configuration.profiling_enabled @@discovery = nil @@ -13,7 +15,14 @@ class ArvadosApiClient # An API client object suitable for handling API requests on behalf # of the current thread. def self.new_or_current - Thread.current[:arvados_api_client] ||= new + # If this thread doesn't have an API client yet, *or* this model + # has been reloaded since the existing client was created, create + # a new client. Otherwise, keep using the latest client created in + # the current thread. + unless Thread.current[:arvados_api_client].andand.class == self + Thread.current[:arvados_api_client] = new + end + Thread.current[:arvados_api_client] end def initialize *args @@ -36,16 +45,16 @@ class ArvadosApiClient end end - api_token = Thread.current[:arvados_api_token] - api_token ||= '' - resources_kind = class_kind(resources_kind).pluralize if resources_kind.is_a? Class url = "#{self.arvados_v1_base}/#{resources_kind}#{action}" # Clean up /arvados/v1/../../discovery/v1 to /discovery/v1 url.sub! '/arvados/v1/../../', '/' - query = {"api_token" => api_token} + query = { + 'api_token' => Thread.current[:arvados_api_token] || '', + 'reader_tokens' => (Thread.current[:reader_tokens] || []).to_json, + } if !data.nil? data.each do |k,v| if v.is_a? String or v.nil? @@ -64,12 +73,12 @@ class ArvadosApiClient if @@profiling_enabled query["_profile"] = "true" end - + header = {"Accept" => "application/json"} - profile_checkpoint { "Prepare request #{url} #{query[:uuid]} #{query[:where]}" } + profile_checkpoint { "Prepare request #{url} #{query[:uuid]} #{query[:where]} #{query[:filters]}" } msg = @client_mtx.synchronize do - @api_client.post(url, + @api_client.post(url, query, header: header) end @@ -80,7 +89,7 @@ class ArvadosApiClient end json = msg.content - + begin resp = Oj.load(json, :symbol_keys => true) rescue Oj::ParseError @@ -92,7 +101,11 @@ class ArvadosApiClient if msg.status_code != 200 errors = resp[:errors] errors = errors.join("\n\n") if errors.is_a? Array - raise "#{errors} [API: #{msg.status_code}]" + if msg.status_code == 403 + raise AccessForbiddenException.new "#{errors} [API: #{msg.status_code}]" + else + raise "#{errors} [API: #{msg.status_code}]" + end end if resp[:_profile] Rails.logger.info "API client: " \ @@ -102,7 +115,7 @@ class ArvadosApiClient resp end - def self.patch_paging_vars(ary, items_available, offset, limit) + def self.patch_paging_vars(ary, items_available, offset, limit, links=nil) if items_available (class << ary; self; end).class_eval { attr_accessor :items_available } ary.items_available = items_available @@ -114,14 +127,22 @@ class ArvadosApiClient if limit (class << ary; self; end).class_eval { attr_accessor :limit } ary.limit = limit - end + end + if links + (class << ary; self; end).class_eval { attr_accessor :links } + ary.links = links + end ary end def unpack_api_response(j, kind=nil) if j.is_a? Hash and j[:items].is_a? Array and j[:kind].match(/(_list|List)$/) ary = j[:items].collect { |x| unpack_api_response x, x[:kind] } - self.class.patch_paging_vars(ary, j[:items_available], j[:offset], j[:limit]) + links = ArvadosResourceList.new Link + links.results = (j[:links] || []).collect do |x| + unpack_api_response x, x[:kind] + end + self.class.patch_paging_vars(ary, j[:items_available], j[:offset], j[:limit], links) elsif j.is_a? Hash and (kind || j[:kind]) oclass = self.kind_class(kind || j[:kind]) if oclass