+ def find_object_by_uuid(with_lock: false)
+ if params[:id] && params[:id].match(/\D/)
+ params[:uuid] = params.delete :id
+ end
+ if action_name == 'get_permissions'
+ # get_permissions accepts a UUID for any kind of object.
+ @object = ArvadosModel::resource_class_for_uuid(params[:uuid])
+ .readable_by(*@read_users)
+ .where(uuid: params[:uuid])
+ .first
+ elsif !current_user
+ super(with_lock: with_lock)
+ else
+ # The usual permission-filtering index query is unnecessarily
+ # inefficient, and doesn't match all permission links that
+ # should be visible (see #18865). Instead, we look up the link
+ # by UUID, then check whether (a) its tail_uuid is the current
+ # user or (b) its head_uuid is an object the current_user
+ # can_manage.
+ model = Link
+ if with_lock && Rails.configuration.API.LockBeforeUpdate
+ model = model.lock
+ end
+ link = model.unscoped.where(uuid: params[:uuid]).first
+ if link && link.link_class != 'permission'
+ # Not a permission link. Re-fetch using generic
+ # permission-filtering query.
+ super(with_lock: with_lock)
+ elsif link && (current_user.uuid == link.tail_uuid ||
+ current_user.can?(manage: link.head_uuid))
+ # Permission granted.
+ @object = link
+ else
+ # Permission denied, i.e., link is invisible => 404.
+ @object = nil
+ end
+ end
+ end
+