14260: Container auth tokens must have the container uuid in the 4th position
[arvados.git] / services / api / app / controllers / arvados / v1 / api_client_authorizations_controller.rb
index 76acc701fd30194972b1f5491659f76ae8f7862e..826ced1cf8c1c3945503b7d79f4865928fb7beb3 100644 (file)
@@ -1,3 +1,9 @@
+# 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]
@@ -16,7 +22,7 @@ class Arvados::V1::ApiClientAuthorizationsController < ApplicationController
       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.strict_load(params[:scopes] || '["all"]'))
+          scopes: SafeJSON.load(params[:scopes] || '["all"]'))
     @object.save!
     show
   end
@@ -88,8 +94,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