16683: Check that remote cluster id is presumed valid, add test
[arvados.git] / services / api / app / models / link.rb
index bf21cf4b672263b784d24b4f2cfcb00d65c0b195..bf107f575cc39c03637d12001a3c7639106815b9 100644 (file)
@@ -6,7 +6,11 @@ class Link < ArvadosModel
   include HasUuid
   include KindAndEtag
   include CommonApiTemplate
-  serialize :properties, Hash
+
+  # Posgresql JSONB columns should NOT be declared as serialized, Rails 5
+  # already know how to properly treat them.
+  attribute :properties, :jsonbHash, default: {}
+
   before_create :permission_to_attach_to_objects
   before_update :permission_to_attach_to_objects
   after_update :maybe_invalidate_permissions_cache
@@ -38,6 +42,28 @@ class Link < ArvadosModel
 
   protected
 
+  def check_readable_uuid attr, attr_value
+    if attr == 'tail_uuid' &&
+       !attr_value.nil? &&
+       self.link_class == 'permission' &&
+       attr_value[0..4] != Rails.configuration.ClusterID &&
+       ApiClientAuthorization.remote_host(uuid_prefix: attr_value[0..4]) &&
+       ArvadosModel::resource_class_for_uuid(attr_value) == User
+      # Permission link tail is a remote user (the user permissions
+      # are being granted to), so bypass the standard check that a
+      # referenced object uuid is readable by current user.
+      #
+      # We could do a call to the remote cluster to check if the user
+      # in tail_uuid exists.  This would detect copy-and-paste errors,
+      # but add another way for the request to fail, and I don't think
+      # it would improve security.  It doesn't seem to be worth the
+      # complexity tradeoff.
+      true
+    else
+      super
+    end
+  end
+
   def permission_to_attach_to_objects
     # Anonymous users cannot write links
     return false if !current_user
@@ -50,6 +76,11 @@ class Link < ArvadosModel
 
     head_obj = ArvadosModel.find_by_uuid(head_uuid)
 
+    if head_obj.nil?
+      errors.add(:head_uuid, "does not exist")
+      return false
+    end
+
     # No permission links can be pointed to past collection versions
     return false if head_obj.is_a?(Collection) && head_obj.current_version_uuid != head_uuid
 
@@ -68,7 +99,7 @@ class Link < ArvadosModel
       # permissions for head_uuid and tail_uuid, and invalidate the
       # cache for only those users. (This would require a browseable
       # cache.)
-      User.invalidate_permissions_cache db_current_time.to_i
+      User.invalidate_permissions_cache
     end
   end
 
@@ -98,5 +129,4 @@ class Link < ArvadosModel
       super
     end
   end
-
 end