Merge branch '16809-s3-v4-signature'
[arvados.git] / services / api / app / controllers / arvados / v1 / api_client_authorizations_controller.rb
index 334538ba1336598715be35c7ef9c62da92da0b7a..59e359232e834fbeb1f12a9c6daec6c52168debd 100644 (file)
@@ -1,11 +1,15 @@
+# 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, :except => [:current]
-  before_filter :admin_required, :only => :create_system_auth
-  skip_before_filter :render_404_if_no_object, :only => [:create_system_auth, :current]
-  skip_before_filter :find_object_by_uuid, :only => [:create_system_auth, :current]
+  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
     {
@@ -77,7 +81,9 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
         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
@@ -90,8 +96,24 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
       @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
@@ -102,8 +124,8 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
 
   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