Merge branch 'master' into 3114-copy-to-project
[arvados.git] / services / api / app / models / arvados_model.rb
index 41286fe0244de58126f76c4f044984056fe5b675..1247e365b1fd5f65e86993a75b412eb6c2743ea9 100644 (file)
@@ -52,13 +52,16 @@ class ArvadosModel < ActiveRecord::Base
 
   def self.searchable_columns operator
     textonly_operator = !operator.match(/[<=>]/)
-    self.columns.collect do |col|
-      if [:string, :text].index(col.type)
-        col.name
-      elsif !textonly_operator and [:datetime, :integer].index(col.type)
-        col.name
+    self.columns.select do |col|
+      case col.type
+      when :string, :text
+        true
+      when :datetime, :integer, :boolean
+        !textonly_operator
+      else
+        false
       end
-    end.compact
+    end.map(&:name)
   end
 
   def self.attribute_column attr
@@ -143,6 +146,12 @@ class ArvadosModel < ActiveRecord::Base
         sql_params += [uuid_list]
       end
 
+      if sql_table == "collections" and users_list.any?
+        # There is a 'name' link going from a readable group to the collection.
+        name_links = "(SELECT head_uuid FROM links WHERE link_class='name' AND tail_uuid IN (#{sanitized_uuid_list}))"
+        sql_conds += ["#{sql_table}.uuid IN #{name_links}"]
+      end
+
       # Link head points to this row, or to the owner of this row (the thing to be read)
       #
       # Link tail originates from this user, or a group that is readable by this
@@ -203,29 +212,25 @@ class ArvadosModel < ActiveRecord::Base
 
   def ensure_owner_uuid_is_permitted
     raise PermissionDeniedError if !current_user
-    if respond_to? :owner_uuid=
+    if new_record? and respond_to? :owner_uuid=
       self.owner_uuid ||= current_user.uuid
     end
-    if self.owner_uuid_changed?
-      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
-        logger.warn "User #{current_user.uuid} tried to change owner_uuid of #{self.class.to_s} #{self.uuid} to #{self.owner_uuid} but does not have permission to write to #{self.owner_uuid}"
-        raise PermissionDeniedError
-      end
-    end
-    if new_record?
-      return true
-    elsif current_user.uuid == self.owner_uuid_was or
+    # Verify permission to write to old owner (unless owner_uuid was
+    # nil -- or hasn't changed, in which case the following
+    # "permission to write to new owner" block will take care of us)
+    unless !owner_uuid_changed? or
+        owner_uuid_was.nil? or
+        current_user.uuid == self.owner_uuid_was or
         current_user.uuid == self.uuid or
         current_user.can? write: self.owner_uuid_was
-      # current user is, or has :write permission on, the previous owner
-      return true
-    else
-      logger.warn "User #{current_user.uuid} tried to modify #{self.class.to_s} #{self.uuid} but does not have permission to write #{self.owner_uuid_was}"
+      logger.warn "User #{current_user.uuid} tried to modify #{self.class.to_s} #{uuid} but does not have permission to write old owner_uuid #{owner_uuid_was}"
+      errors.add :owner_uuid, "cannot be changed without write permission on old owner"
+      raise PermissionDeniedError
+    end
+    # Verify permission to write to new owner
+    unless current_user == self or current_user.can? write: owner_uuid
+      logger.warn "User #{current_user.uuid} tried to modify #{self.class.to_s} #{uuid} but does not have permission to write new owner_uuid #{owner_uuid}"
+      errors.add :owner_uuid, "cannot be changed without write permission on new owner"
       raise PermissionDeniedError
     end
   end