X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/1e3f8ceebd90058e902494fae84b1fd57ac6693b..aeb966ee09166bf074ea19a4a2dd5045ca795a98:/services/api/app/controllers/application_controller.rb diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb index a627bf4a46..7a9b7a67e5 100644 --- a/services/api/app/controllers/application_controller.rb +++ b/services/api/app/controllers/application_controller.rb @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0 require 'safe_json' +require 'request_error' module ApiTemplateOverride def allowed_to_render?(fieldset, field, model, options) @@ -77,14 +78,21 @@ class ApplicationController < ActionController::Base @distinct = nil @response_resource_name = nil @attrs = nil + @extra_included = nil end def default_url_options + options = {} if Rails.configuration.host - {:host => Rails.configuration.host} - else - {} + options[:host] = Rails.configuration.host + end + if Rails.configuration.port + options[:port] = Rails.configuration.port + end + if Rails.configuration.protocol + options[:protocol] = Rails.configuration.protocol end + options end def index @@ -137,7 +145,7 @@ class ApplicationController < ActionController::Base def render_error(e) logger.error e.inspect - if e.respond_to? :backtrace and e.backtrace + if !e.is_a? RequestError and (e.respond_to? :backtrace and e.backtrace) logger.error e.backtrace.collect { |x| x + "\n" }.join('') end if (@object.respond_to? :errors and @@ -156,6 +164,10 @@ class ApplicationController < ActionController::Base send_error("Path not found", status: 404) end + def render_accepted + send_json ({accepted: true}), status: 202 + end + protected def send_error(*args) @@ -181,7 +193,10 @@ class ApplicationController < ActionController::Base end def find_objects_for_index - @objects ||= model_class.readable_by(*@read_users, {:include_trash => (params[:include_trash] || 'untrash' == action_name)}) + @objects ||= model_class.readable_by(*@read_users, { + :include_trash => (params[:include_trash] || 'untrash' == action_name), + :include_old_versions => params[:include_old_versions] + }) apply_where_limit_order_params end @@ -336,29 +351,22 @@ class ApplicationController < ActionController::Base # If there are too many reader tokens, assume the request is malicious # and ignore it. if request.get? and params[:reader_tokens] and - params[:reader_tokens].size < 100 + params[:reader_tokens].size < 100 + secrets = params[:reader_tokens].map { |t| + if t.is_a? String and t.starts_with? "v2/" + t.split("/")[2] + else + t + end + } @read_auths += ApiClientAuthorization .includes(:user) .where('api_token IN (?) AND (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)', - params[:reader_tokens]) - .all + secrets) + .to_a end @read_auths.select! { |auth| auth.scopes_allow_request? request } - - # Use a salted token as a reader token for /groups/ and /users/current - if params[:remote] && ( - request.path.start_with?('/arvados/v1/groups') || - request.path.start_with?('/arvados/v1/users/current')) - auth = ApiClientAuthorization. - validate(token: Thread.current[:supplied_token], - remote: params[:remote]) - if auth && auth.user - Thread.current[:user] = auth.user - @read_auths << auth - end - end - @read_users = @read_auths.map(&:user).uniq end @@ -379,7 +387,7 @@ class ApplicationController < ActionController::Base end def require_auth_scope - if @read_auths.empty? + unless current_user && @read_auths.any? { |auth| auth.user.andand.uuid == current_user.uuid } if require_login != false send_error("Forbidden", status: 403) end @@ -395,7 +403,9 @@ class ApplicationController < ActionController::Base req_id = "req-" + Random::DEFAULT.rand(2**128).to_s(36)[0..19] end response.headers['X-Request-Id'] = Thread.current[:request_id] = req_id - yield + Rails.logger.tagged(req_id) do + yield + end Thread.current[:request_id] = nil end @@ -416,7 +426,7 @@ class ApplicationController < ActionController::Base def set_cors_headers response.headers['Access-Control-Allow-Origin'] = '*' response.headers['Access-Control-Allow-Methods'] = 'GET, HEAD, PUT, POST, DELETE' - response.headers['Access-Control-Allow-Headers'] = 'Authorization' + response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type' response.headers['Access-Control-Max-Age'] = '86486400' end @@ -505,12 +515,15 @@ class ApplicationController < ActionController::Base :limit => @limit, :items => @objects.as_api_response(nil, {select: @select}) } + if @extra_included + list[:included] = @extra_included.as_api_response(nil, {select: @select}) + end case params[:count] when nil, '', 'exact' if @objects.respond_to? :except list[:items_available] = @objects. except(:limit).except(:offset). - count(:id, distinct: true) + distinct.count(:id) end when 'none' else @@ -564,10 +577,20 @@ class ApplicationController < ActionController::Base location: "query", required: false, default: false - } + }, + cluster_id: { + type: 'string', + description: "Create object on a remote federated cluster instead of the current one.", + location: "query", + required: false, + }, } end + def self._update_requires_parameters + {} + end + def self._index_requires_parameters { filters: { type: 'array', required: false }, @@ -578,6 +601,12 @@ class ApplicationController < ActionController::Base limit: { type: 'integer', required: false, default: DEFAULT_LIMIT }, offset: { type: 'integer', required: false, default: 0 }, count: { type: 'string', required: false, default: 'exact' }, + cluster_id: { + type: 'string', + description: "List objects on a remote federated cluster instead of the current one.", + location: "query", + required: false, + }, } end