Merge branch 'master' into 15572-new-install-docs
[arvados.git] / services / api / app / controllers / arvados / v1 / virtual_machines_controller.rb
index b0853021a5e3ad27fa6fb20517298d2d6a192f47..cb637c2fdacf8aa859c0107ba5d55bdef6b711f4 100644 (file)
@@ -1,58 +1,59 @@
+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
 class Arvados::V1::VirtualMachinesController < ApplicationController
-  skip_before_filter(:require_auth_scope_all,
-                     :only => [:logins, :get_all_logins])
-  before_filter(:admin_required,
-                :only => [:logins, :get_all_logins])
-  before_filter(:find_object_by_uuid, :only => :logins)
-  before_filter(:require_auth_scope_for_get_all_logins,
+  skip_before_action :find_object_by_uuid, :only => :get_all_logins
+  skip_before_action :render_404_if_no_object, :only => :get_all_logins
+  before_action(:admin_required,
                 :only => [:logins, :get_all_logins])
 
+  # Get all login permissons (user uuid, login account, SSH key) for a
+  # single VM
   def logins
-    get_all_logins
+    render_logins_for VirtualMachine.where(uuid: @object.uuid)
   end
 
+  # Get all login permissons for all VMs
   def get_all_logins
+    render_logins_for VirtualMachine
+  end
+
+  protected
+
+  def render_logins_for vm_query
+    @response = []
+    @vms = vm_query.eager_load :login_permissions
     @users = {}
-    User.includes(:authorized_keys).all.each do |u|
+    User.eager_load(:authorized_keys).
+      where('users.uuid in (?)',
+            @vms.map { |vm| vm.login_permissions.map(&:tail_uuid) }.flatten.uniq).
+      each do |u|
       @users[u.uuid] = u
     end
-    @response = []
-    @vms = VirtualMachine.includes(:login_permissions)
-    if @object
-      @vms = @vms.where('uuid=?', @object.uuid)
-    else
-      @vms = @vms.all
-    end
     @vms.each do |vm|
       vm.login_permissions.each do |perm|
         user_uuid = perm.tail_uuid
-        @users[user_uuid].andand.authorized_keys.each do |ak|
-          username = perm.properties.andand['username']
-          if username
-            @response << {
-              username: username,
-              hostname: vm.hostname,
-              public_key: ak.public_key,
-              user_uuid: user_uuid,
-              virtual_machine_uuid: vm.uuid,
-              authorized_key_uuid: ak.uuid
-            }
-          end
+        next if not @users[user_uuid]
+        next if perm.properties['username'].blank?
+        aks = @users[user_uuid].authorized_keys
+        if aks.empty?
+          # We'll emit one entry, with no public key.
+          aks = [nil]
+        end
+        aks.each do |ak|
+          @response << {
+            username: perm.properties['username'],
+            hostname: vm.hostname,
+            groups: (perm.properties['groups'].to_a rescue []),
+            public_key: ak ? ak.public_key : nil,
+            user_uuid: user_uuid,
+            virtual_machine_uuid: vm.uuid,
+            authorized_key_uuid: ak ? ak.uuid : nil,
+          }
         end
       end
     end
-    render json: { kind: "arvados#HashList", items: @response }
-  end
-
-  protected
-
-  def require_auth_scope_for_get_all_logins
-    if @object
-      # Client wants all logins for a single VM.
-      require_auth_scope(['all', arvados_v1_virtual_machine_url(@object.uuid)])
-    else
-      # ...for a non-existent VM, or all VMs.
-      require_auth_scope(['all'])
-    end
+    send_json kind: "arvados#HashList", items: @response
   end
 end