:none dispatcher only runs one job at a time.
[arvados.git] / services / api / app / models / arvados_model.rb
index 2817d69b55965b8eb23285b2164f16339894ea5f..2df6686f2883edd81adde92e9748b3fa95010614 100644 (file)
@@ -28,7 +28,7 @@ class ArvadosModel < ActiveRecord::Base
   # Note: This only returns permission links. It does not account for
   # permissions obtained via user.is_admin or
   # user.uuid==object.owner_uuid.
-  has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'", dependent: :destroy
+  has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'"
 
   class PermissionDeniedError < StandardError
     def http_status
@@ -91,6 +91,13 @@ class ArvadosModel < ActiveRecord::Base
     # Get rid of troublesome nils
     users_list.compact!
 
+    # Load optional keyword arguments, if they exist.
+    if users_list.last.is_a? Hash
+      kwargs = users_list.pop
+    else
+      kwargs = {}
+    end
+
     # Check if any of the users are admin.  If so, we're done.
     if users_list.select { |u| u.is_admin }.empty?
 
@@ -101,6 +108,7 @@ class ArvadosModel < ActiveRecord::Base
         collect { |uuid| sanitize(uuid) }.join(', ')
       sql_conds = []
       sql_params = []
+      sql_table = kwargs.fetch(:table_name, table_name)
       or_object_uuid = ''
 
       # This row is owned by a member of users_list, or owned by a group
@@ -113,25 +121,25 @@ class ArvadosModel < ActiveRecord::Base
       # to this row, or to the owner of this row (see join() below).
       permitted_uuids = "(SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (#{sanitized_uuid_list}))"
 
-      sql_conds += ["#{table_name}.owner_uuid in (?)",
-                    "#{table_name}.uuid in (?)",
-                    "#{table_name}.uuid IN #{permitted_uuids}"]
+      sql_conds += ["#{sql_table}.owner_uuid in (?)",
+                    "#{sql_table}.uuid in (?)",
+                    "#{sql_table}.uuid IN #{permitted_uuids}"]
       sql_params += [uuid_list, user_uuids]
 
-      if self == Link and users_list.any?
+      if sql_table == "links" and users_list.any?
         # This row is a 'permission' or 'resources' link class
         # The uuid for a member of users_list is referenced in either the head
         # or tail of the link
-        sql_conds += ["(#{table_name}.link_class in (#{sanitize 'permission'}, #{sanitize 'resources'}) AND (#{table_name}.head_uuid IN (?) OR #{table_name}.tail_uuid IN (?)))"]
+        sql_conds += ["(#{sql_table}.link_class in (#{sanitize 'permission'}, #{sanitize 'resources'}) AND (#{sql_table}.head_uuid IN (?) OR #{sql_table}.tail_uuid IN (?)))"]
         sql_params += [user_uuids, user_uuids]
       end
 
-      if self == Log and users_list.any?
+      if sql_table == "logs" and users_list.any?
         # Link head points to the object described by this row
-        sql_conds += ["#{table_name}.object_uuid IN #{permitted_uuids}"]
+        sql_conds += ["#{sql_table}.object_uuid IN #{permitted_uuids}"]
 
         # This object described by this row is owned by this user, or owned by a group readable by this user
-        sql_conds += ["#{table_name}.object_owner_uuid in (?)"]
+        sql_conds += ["#{sql_table}.object_owner_uuid in (?)"]
         sql_params += [uuid_list]
       end
 
@@ -192,7 +200,9 @@ class ArvadosModel < ActiveRecord::Base
       self.owner_uuid ||= current_user.uuid
     end
     if self.owner_uuid_changed?
-      if current_user.uuid == self.owner_uuid or
+      if new_record?
+        return true
+      elsif current_user.uuid == self.owner_uuid or
           current_user.can? write: self.owner_uuid
         # current_user is, or has :write permission on, the new owner
       else
@@ -262,19 +272,20 @@ class ArvadosModel < ActiveRecord::Base
     true
   end
 
-  def self.has_any_symbols? x
+  def self.has_symbols? x
     if x.is_a? Hash
       x.each do |k,v|
-        return true if has_any_symbols?(k) or has_any_symbols?(v)
+        return true if has_symbols?(k) or has_symbols?(v)
       end
+      false
     elsif x.is_a? Array
       x.each do |k|
-        return true if has_any_symbols?(k)
+        return true if has_symbols?(k)
       end
+      false
     else
-      return (x.class == Symbol)
+      (x.class == Symbol)
     end
-    false
   end
 
   def self.recursive_stringify x
@@ -304,7 +315,7 @@ class ArvadosModel < ActiveRecord::Base
       if attr.object_class
         if self.attributes[colname].class != attr.object_class
           self.errors.add colname.to_sym, "must be a #{attr.object_class.to_s}, not a #{self.attributes[colname].class.to_s}"
-        elsif self.class.has_any_symbols? attributes[colname]
+        elsif self.class.has_symbols? attributes[colname]
           self.errors.add colname.to_sym, "must not contain symbols: #{attributes[colname].inspect}"
         end
       end
@@ -312,13 +323,17 @@ class ArvadosModel < ActiveRecord::Base
   end
 
   def convert_serialized_symbols_to_strings
+    # ensure_serialized_attribute_type should prevent symbols from
+    # getting into the database in the first place. If someone managed
+    # to get them into the database (perhaps using an older version)
+    # we'll convert symbols to strings when loading from the
+    # database. (Otherwise, loading and saving an object with existing
+    # symbols in a serialized field will crash.)
     self.class.serialized_attributes.each do |colname, attr|
-      if attr.object_class == Hash
-        if self.class.has_any_symbols? attributes[colname]
-          attributes[colname] = self.class.recursive_stringify attributes[colname]
-          self.send(colname + '=',
-                    self.class.recursive_stringify(attributes[colname]))
-        end
+      if self.class.has_symbols? attributes[colname]
+        attributes[colname] = self.class.recursive_stringify attributes[colname]
+        self.send(colname + '=',
+                  self.class.recursive_stringify(attributes[colname]))
       end
     end
   end