# Collect the UUIDs of the authorized users.
sql_table = kwargs.fetch(:table_name, table_name)
include_trash = kwargs.fetch(:include_trash, false)
- query_on = kwargs.fetch(:query_on, self)
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?
if !include_trash
- # exclude rows that are explicitly trashed.
- if self.column_names.include? "owner_uuid"
- sql_conds += ["NOT EXISTS(SELECT 1
- FROM permission_view
- WHERE trashed = 1 AND
- (#{sql_table}.uuid = target_uuid OR #{sql_table}.owner_uuid = target_uuid))"]
- else
- sql_conds += ["NOT EXISTS(SELECT 1
- FROM permission_view
- WHERE trashed = 1 AND
- (#{sql_table}.uuid = target_uuid))"]
+ 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
- # Can read object (evidently a group or user) whose UUID is listed
- # explicitly in user_uuids.
- sql_conds += ["#{sql_table}.uuid IN (:user_uuids)"]
- trashed_check = if include_trash then "EXISTS" else "0 IN " end
- perm_check = "perm_level >= 1"
-
- if self.column_names.include? "owner_uuid"
- # to be readable:
- # row(s) exists granting readable permission to uuid or owner, and none are trashed
- sql_conds += ["#{trashed_check}(SELECT MAX(trashed) FROM permission_view "+
- "WHERE user_uuid IN (:user_uuids) AND #{perm_check} AND "+
- "(#{sql_table}.uuid = target_uuid OR (#{sql_table}.owner_uuid = target_uuid AND target_owner_uuid is NOT NULL)))"]
- # reader is owner, and item is not trashed
- not_trashed_check = if include_trash then
- ""
- else
- "AND 1 NOT IN (SELECT MAX(trashed) FROM permission_view "+
- "WHERE #{sql_table}.uuid = target_uuid OR #{sql_table}.owner_uuid = target_uuid)"
- end
- sql_conds += ["(#{sql_table}.owner_uuid IN (:user_uuids) #{not_trashed_check})"]
- else
- # to be readable:
- # * a non-trash row exists with readable permission uuid
- sql_conds += ["#{trashed_check}(SELECT MAX(trashed) FROM permission_view "+
- "WHERE user_uuid IN (:user_uuids) AND #{perm_check} AND "+
- "#{sql_table}.uuid = target_uuid) "]
- end
+ 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
- query_on.where(sql_conds.join(' OR '),
+ self.where(sql_conds.join(' OR '),
user_uuids: user_uuids,
permission_link_classes: ['permission', 'resources'])
end
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
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