13111: Merge branch 'master' into 12308-go-fuse
[arvados.git] / services / api / app / models / arvados_model.rb
index 457b1bf1d5891ee5ca27dc41630c6025ad4da2a2..05deba7bc153b50f5af256dd7a3cc97f1e942454 100644 (file)
@@ -254,66 +254,58 @@ class ArvadosModel < ActiveRecord::Base
 
     # Collect the UUIDs of the authorized users.
     sql_table = kwargs.fetch(:table_name, table_name)
-    include_trashed = kwargs.fetch(:include_trashed, 0)
+    include_trash = kwargs.fetch(:include_trash, false)
 
     sql_conds = []
     user_uuids = users_list.map { |u| u.uuid }
 
-    User.install_view('permission')
+    exclude_trashed_records = if !include_trash and (sql_table == "groups" or sql_table == "collections") then
+                                # Only include records that are not explicitly trashed
+                                "AND #{sql_table}.is_trashed = false"
+                              else
+                                ""
+                              end
 
-    # Check if any of the users are admin.
     if users_list.select { |u| u.is_admin }.any?
-      # For admins, only filter on "trashed"
-      # sql_conds += ["#{sql_table}.uuid in (SELECT target_uuid
-      #             FROM permission_view
-      #             WHERE trashed in (:include_trashed)
-      #             GROUP BY user_uuid, target_uuid)"]
-
-      # if self.column_names.include? 'owner_uuid'
-      #   sql_conds[0] += "AND #{sql_table}.owner_uuid in (SELECT target_uuid
-      #             FROM permission_view
-      #             WHERE trashed in (:include_trashed)
-      #             GROUP BY user_uuid, target_uuid)"
-      # end
-      return where({})
-    else
-      # Match any object (evidently a group or user) whose UUID is
-      # listed explicitly in user_uuids.
-      sql_conds += ["#{sql_table}.uuid in (:user_uuids)"]
-
-      # Match any object whose owner is listed explicitly in
-      # user_uuids.
-      sql_conds += ["#{sql_table}.owner_uuid IN (:user_uuids)"]
-
-      # At least read permission from user_uuid to target_uuid of object
-      sql_conds += ["#{sql_table}.uuid in (SELECT target_uuid
-                  FROM permission_view
-                  WHERE user_uuid in (:user_uuids) and perm_level >= 1 and trashed = (:include_trashed)
-                  GROUP BY user_uuid, target_uuid)"]
-
-      if self.column_names.include? 'owner_uuid'
-        # At least read permission from user_uuid to target_uuid that owns object
-        sql_conds += ["#{sql_table}.owner_uuid in (SELECT target_uuid
-                  FROM permission_view
-                  WHERE user_uuid in (:user_uuids) and
-                    target_owner_uuid IS NOT NULL and
-                    perm_level >= 1 and trashed = (:include_trashed)
-                  GROUP BY user_uuid, target_uuid)"]
+      if !include_trash
+        if sql_table != "api_client_authorizations"
+          # Exclude rows where the owner is trashed
+          sql_conds.push "NOT EXISTS(SELECT 1 "+
+                  "FROM #{PERMISSION_VIEW} "+
+                  "WHERE trashed = 1 AND "+
+                  "(#{sql_table}.owner_uuid = target_uuid)) "+
+                  exclude_trashed_records
+        end
       end
+    else
+      trashed_check = if !include_trash then
+                        "AND trashed = 0"
+                      else
+                        ""
+                      end
+
+      owner_check = if sql_table != "api_client_authorizations" and sql_table != "groups" then
+                      "OR (target_uuid = #{sql_table}.owner_uuid AND target_owner_uuid IS NOT NULL)"
+                    else
+                      ""
+                    end
+
+      sql_conds.push "EXISTS(SELECT 1 FROM #{PERMISSION_VIEW} "+
+                     "WHERE user_uuid IN (:user_uuids) AND perm_level >= 1 #{trashed_check} AND (target_uuid = #{sql_table}.uuid #{owner_check})) "+
+                     exclude_trashed_records
 
       if sql_table == "links"
         # Match any permission link that gives one of the authorized
         # users some permission _or_ gives anyone else permission to
         # view one of the authorized users.
-        sql_conds += ["(#{sql_table}.link_class in (:permission_link_classes) AND "+
-                      "(#{sql_table}.head_uuid IN (:user_uuids) OR #{sql_table}.tail_uuid IN (:user_uuids)))"]
+        sql_conds.push "(#{sql_table}.link_class IN (:permission_link_classes) AND "+
+                       "(#{sql_table}.head_uuid IN (:user_uuids) OR #{sql_table}.tail_uuid IN (:user_uuids)))"
       end
     end
 
-    where(sql_conds.join(' OR '),
-          user_uuids: user_uuids,
-          permission_link_classes: ['permission', 'resources'],
-          include_trashed: include_trashed)
+    self.where(sql_conds.join(' OR '),
+                    user_uuids: user_uuids,
+                    permission_link_classes: ['permission', 'resources'])
   end
 
   def save_with_unique_name!
@@ -373,13 +365,14 @@ class ArvadosModel < ActiveRecord::Base
 
   def self.full_text_searchable_columns
     self.columns.select do |col|
-      col.type == :string or col.type == :text
+      [:string, :text, :jsonb].include?(col.type)
     end.map(&:name)
   end
 
   def self.full_text_tsvector
     parts = full_text_searchable_columns.collect do |column|
-      "coalesce(#{column},'')"
+      cast = serialized_attributes[column] ? '::text' : ''
+      "coalesce(#{column}#{cast},'')"
     end
     "to_tsvector('english', #{parts.join(" || ' ' || ")})"
   end
@@ -749,7 +742,7 @@ class ArvadosModel < ActiveRecord::Base
     if self == ArvadosModel
       # If called directly as ArvadosModel.find_by_uuid rather than via subclass,
       # delegate to the appropriate subclass based on the given uuid.
-      self.resource_class_for_uuid(uuid).unscoped.find_by_uuid(uuid)
+      self.resource_class_for_uuid(uuid).find_by_uuid(uuid)
     else
       super
     end