+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: AGPL-3.0
+
require 'has_uuid'
require 'record_filters'
require 'serializers'
kwargs = {}
end
- # Check if any of the users are admin. If so, we're done.
- if users_list.select { |u| u.is_admin }.any?
- return self
- end
-
# Collect the UUIDs of the authorized users.
- user_uuids = users_list.map { |u| u.uuid }
-
- # Collect the UUIDs of all groups readable by any of the
- # authorized users. If one of these (or the UUID of one of the
- # authorized users themselves) is an object's owner_uuid, that
- # object is readable.
- owner_uuids = user_uuids + users_list.flat_map { |u| u.groups_i_can(:read) }
- owner_uuids.uniq!
-
- sql_conds = []
sql_table = kwargs.fetch(:table_name, table_name)
+ include_trash = kwargs.fetch(:include_trash, false)
+ query_on = kwargs.fetch(:query_on, self)
- # Match any object (evidently a group or user) whose UUID is
- # listed explicitly in owner_uuids.
- sql_conds += ["#{sql_table}.uuid in (:owner_uuids)"]
+ sql_conds = []
+ user_uuids = users_list.map { |u| u.uuid }
- # Match any object whose owner is listed explicitly in
- # owner_uuids.
- sql_conds += ["#{sql_table}.owner_uuid IN (:owner_uuids)"]
+ User.install_view('permission')
- # Match the head of any permission link whose tail is listed
- # explicitly in owner_uuids.
- sql_conds += ["#{sql_table}.uuid IN (SELECT head_uuid FROM links WHERE link_class='permission' AND tail_uuid IN (:owner_uuids))"]
+ # Check if any of the users are admin.
+ if users_list.select { |u| u.is_admin }.any?
+ if !include_trash
+ # exclude rows that are trashed.
+ if self.column_names.include? "owner_uuid"
+ sql_conds += ["NOT EXISTS(SELECT target_uuid
+ 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 target_uuid
+ FROM permission_view
+ WHERE trashed = 1 AND
+ (#{sql_table}.uuid = target_uuid))"]
+ end
+ end
+ else
+ trash_clause = if !include_trash then "trashed = 0 AND" else "" end
+
+ # Can read object (evidently a group or user) whose UUID is listed
+ # explicitly in user_uuids.
+ sql_conds += ["#{sql_table}.uuid IN (:user_uuids)"]
+
+ direct_permission_check = "EXISTS(SELECT 1 FROM permission_view
+ WHERE user_uuid IN (:user_uuids) AND perm_level >= 1 AND #{trash_clause}
+ (#{sql_table}.uuid = target_uuid))"
+
+ if self.column_names.include? "owner_uuid"
+ # if an explicit permission row exists for the uuid in question, apply
+ # the "direct_permission_check"
+ # if not, check for permission to read the owner instead
+ sql_conds += ["CASE
+ WHEN EXISTS(select 1 FROM permission_view where target_uuid = #{sql_table}.uuid)
+ THEN #{direct_permission_check}
+ ELSE EXISTS(SELECT 1 FROM permission_view
+ WHERE user_uuid IN (:user_uuids) AND perm_level >= 1 AND #{trash_clause}
+ (#{sql_table}.owner_uuid = target_uuid AND target_owner_uuid is NOT NULL))
+ END"]
+ # Can also read if one of the users is the owner of the object.
+ trash_clause = if !include_trash
+ "1 NOT IN (SELECT trashed
+ FROM permission_view
+ WHERE #{sql_table}.uuid = target_uuid) AND"
+ else
+ ""
+ end
+ sql_conds += ["(#{trash_clause} #{sql_table}.owner_uuid IN (:user_uuids))"]
+ else
+ sql_conds += [direct_permission_check]
+ end
- 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)))"]
+ 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)))"]
+ end
end
- where(sql_conds.join(' OR '),
- owner_uuids: owner_uuids,
- user_uuids: user_uuids,
- permission_link_classes: ['permission', 'resources'])
+ query_on.where(sql_conds.join(' OR '),
+ user_uuids: user_uuids,
+ permission_link_classes: ['permission', 'resources'])
end
def save_with_unique_name!