+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
+require 'safe_json'
+
class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
accept_attribute_as_json :scopes, Array
- before_filter :current_api_client_is_trusted
- before_filter :admin_required, :only => :create_system_auth
- skip_before_filter :render_404_if_no_object, :only => :create_system_auth
+ before_action :current_api_client_is_trusted, :except => [:current]
+ before_action :admin_required, :only => :create_system_auth
+ skip_before_action :render_404_if_no_object, :only => [:create_system_auth, :current]
+ skip_before_action :find_object_by_uuid, :only => [:create_system_auth, :current]
def self._create_system_auth_requires_parameters
{
scopes: {type: 'array', required: false}
}
end
+
def create_system_auth
@object = ApiClientAuthorization.
new(user_id: system_user.id,
api_client_id: params[:api_client_id] || current_api_client.andand.id,
created_by_ip_address: remote_ip,
- scopes: Oj.load(params[:scopes] || '["all"]'))
+ scopes: SafeJSON.load(params[:scopes] || '["all"]'))
@object.save!
show
end
super
end
+ def current
+ @object = Thread.current[:api_client_authorization].dup
+ if params[:remote]
+ # Client is validating a salted token. Don't return the unsalted
+ # secret!
+ @object.api_token = nil
+ end
+ show
+ end
+
protected
def default_orders
val.is_a?(String) && (attr == 'uuid' || attr == 'api_token')
}
end
- @objects = model_class.where('user_id=?', current_user.id)
+ if current_api_client_authorization.andand.api_token != Rails.configuration.SystemRootToken
+ @objects = model_class.where('user_id=?', current_user.id)
+ end
if wanted_scopes.compact.any?
# We can't filter on scopes effectively using AR/postgres.
# Instead we get the entire result set, do our own filtering on
@offset = 0
super
wanted_scopes.compact.each do |scope_list|
- sorted_scopes = scope_list.sort
- @objects = @objects.select { |auth| auth.scopes.sort == sorted_scopes }
+ if @objects.respond_to?(:where) && scope_list.length < 2
+ @objects = @objects.
+ where('scopes in (?)',
+ [scope_list.to_yaml, SafeJSON.dump(scope_list)])
+ else
+ if @objects.respond_to?(:where)
+ # Eliminate rows with scopes=['all'] before doing the
+ # expensive filter. They are typically the majority of
+ # rows, and they obviously won't match given
+ # scope_list.length>=2, so loading them all into
+ # ActiveRecord objects is a huge waste of time.
+ @objects = @objects.
+ where('scopes not in (?)',
+ [['all'].to_yaml, SafeJSON.dump(['all'])])
+ end
+ sorted_scopes = scope_list.sort
+ @objects = @objects.select { |auth| auth.scopes.sort == sorted_scopes }
+ end
end
@limit = @request_limit
@offset = @request_offset
def find_object_by_uuid
uuid_param = params[:uuid] || params[:id]
- if (uuid_param != current_api_client_authorization.andand.uuid and
- not Thread.current[:api_client].andand.is_trusted)
+ if (uuid_param != current_api_client_authorization.andand.uuid &&
+ !Thread.current[:api_client].andand.is_trusted)
return forbidden
end
@limit = 1