Merge branch 'master' into 14874-protected-collection-properties
[arvados.git] / services / api / app / controllers / application_controller.rb
index 28da97f9eb5aa219ad963c5fc6e1b74a7de2c039..e07a5aca79b5a310d320c6901df9c5a82326465a 100644 (file)
@@ -42,9 +42,9 @@ class ApplicationController < ActionController::Base
   before_action :require_auth_scope, except: ERROR_ACTIONS
 
   before_action :catch_redirect_hint
+  before_action :load_required_parameters
   before_action(:find_object_by_uuid,
                 except: [:index, :create] + ERROR_ACTIONS)
-  before_action :load_required_parameters
   before_action :load_limit_offset_order_params, only: [:index, :contents]
   before_action :load_where_param, only: [:index, :contents]
   before_action :load_filters_param, only: [:index, :contents]
@@ -53,8 +53,6 @@ class ApplicationController < ActionController::Base
   before_action(:render_404_if_no_object,
                 except: [:index, :create] + ERROR_ACTIONS)
 
-  theme Rails.configuration.arvados_theme
-
   attr_writer :resource_attrs
 
   begin
@@ -83,14 +81,11 @@ class ApplicationController < ActionController::Base
 
   def default_url_options
     options = {}
-    if Rails.configuration.host
-      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
+    if Rails.configuration.Services.Controller.ExternalURL != URI("")
+      exturl = Rails.configuration.Services.Controller.ExternalURL
+      options[:host] = exturl.host
+      options[:port] = exturl.port
+      options[:protocol] = exturl.scheme
     end
     options
   end
@@ -170,6 +165,17 @@ class ApplicationController < ActionController::Base
 
   protected
 
+  def bool_param(pname)
+    if params.include?(pname)
+      if params[pname].is_a?(Boolean)
+        return params[pname]
+      else
+        logger.warn "Warning: received non-boolean parameter '#{pname}' on #{self.class.inspect}."
+      end
+    end
+    false
+  end
+
   def send_error(*args)
     if args.last.is_a? Hash
       err = args.pop
@@ -194,8 +200,8 @@ class ApplicationController < ActionController::Base
 
   def find_objects_for_index
     @objects ||= model_class.readable_by(*@read_users, {
-      :include_trash => (params[:include_trash] || 'untrash' == action_name),
-      :include_old_versions => params[:include_old_versions]
+      :include_trash => (bool_param(:include_trash) || 'untrash' == action_name),
+      :include_old_versions => bool_param(:include_old_versions)
     })
     apply_where_limit_order_params
   end
@@ -242,7 +248,7 @@ class ApplicationController < ActionController::Base
               conditions[0] << " and #{ar_table_name}.#{attr} in (?)"
               conditions << value
             end
-          elsif value.is_a? String or value.is_a? Fixnum or value == true or value == false
+          elsif value.is_a? String or value.is_a? Integer or value == true or value == false
             conditions[0] << " and #{ar_table_name}.#{attr}=?"
             conditions << value
           elsif value.is_a? Hash
@@ -306,7 +312,7 @@ class ApplicationController < ActionController::Base
       limit_query.each do |record|
         new_limit += 1
         read_total += record.read_length.to_i
-        if read_total >= Rails.configuration.max_index_database_read
+        if read_total >= Rails.configuration.API.MaxIndexDatabaseRead
           new_limit -= 1 if new_limit > 1
           @limit = new_limit
           break
@@ -323,10 +329,12 @@ class ApplicationController < ActionController::Base
   def resource_attrs
     return @attrs if @attrs
     @attrs = params[resource_name]
-    if @attrs.is_a? String
+    if @attrs.nil?
+      @attrs = {}
+    elsif @attrs.is_a? String
       @attrs = Oj.strict_load @attrs, symbol_keys: true
     end
-    unless @attrs.is_a? Hash
+    unless [Hash, ActionController::Parameters].include? @attrs.class
       message = "No #{resource_name}"
       if resource_name.index('_')
         message << " (or #{resource_name.camelcase(:lower)})"
@@ -417,8 +425,7 @@ class ApplicationController < ActionController::Base
   end
 
   def disable_api_methods
-    if Rails.configuration.disable_api_methods.
-        include?(controller_name + "." + action_name)
+    if Rails.configuration.API.DisabledAPIs.include?(controller_name + "." + action_name)
       send_error("Disabled", status: 404)
     end
   end
@@ -472,11 +479,21 @@ class ApplicationController < ActionController::Base
   end
 
   def load_json_value(hash, key, must_be_class=nil)
-    if hash[key].is_a? String
-      hash[key] = SafeJSON.load(hash[key])
-      if must_be_class and !hash[key].is_a? must_be_class
-        raise TypeError.new("parameter #{key.to_s} must be a #{must_be_class.to_s}")
-      end
+    return if hash[key].nil?
+
+    val = hash[key]
+    if val.is_a? ActionController::Parameters
+      val = val.to_unsafe_hash
+    elsif val.is_a? String
+      val = SafeJSON.load(val)
+      hash[key] = val
+    end
+    # When assigning a Hash to an ActionController::Parameters and then
+    # retrieve it, we get another ActionController::Parameters instead of
+    # a Hash. This doesn't happen with other types. This is why 'val' is
+    # being used to do type checking below.
+    if must_be_class and !val.is_a? must_be_class
+      raise TypeError.new("parameter #{key.to_s} must be a #{must_be_class.to_s}")
     end
   end
 
@@ -486,7 +503,7 @@ class ApplicationController < ActionController::Base
   accept_attribute_as_json :properties, Hash
   accept_attribute_as_json :info, Hash
   def accept_attribute_as_json(attr, must_be_class)
-    if params[resource_name] and resource_attrs.is_a? Hash
+    if params[resource_name] and [Hash, ActionController::Parameters].include?(resource_attrs.class)
       if resource_attrs[attr].is_a? Hash
         # Convert symbol keys to strings (in hashes provided by
         # resource_attrs)