X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/56d8ed80ce834a051be71d2bcf76a346b7bc7f0b..a151147d22130c4d9e0f89989ce43db2cec325ed:/services/api/app/controllers/arvados/v1/collections_controller.rb diff --git a/services/api/app/controllers/arvados/v1/collections_controller.rb b/services/api/app/controllers/arvados/v1/collections_controller.rb index d81f441168..05da5fef03 100644 --- a/services/api/app/controllers/arvados/v1/collections_controller.rb +++ b/services/api/app/controllers/arvados/v1/collections_controller.rb @@ -1,21 +1,73 @@ class Arvados::V1::CollectionsController < ApplicationController def create - # It's not an error for a client to re-register a manifest that we - # already know about. - @object = model_class.new resource_attrs - begin - @object.save! - rescue ActiveRecord::RecordNotUnique - logger.debug resource_attrs.inspect - if resource_attrs[:manifest_text] and resource_attrs[:uuid] - @existing_object = model_class. - where('uuid=? and manifest_text=?', - resource_attrs[:uuid], - resource_attrs[:manifest_text]). - first - @object = @existing_object || @object + # Collections are owned by system_user. Creating a collection has + # two effects: The collection is added if it doesn't already + # exist, and a "permission" Link is added (if one doesn't already + # exist) giving the current user (or specified owner_uuid) + # permission to read it. + owner_uuid = resource_attrs.delete(:owner_uuid) || current_user.uuid + owner_kind = if owner_uuid.match(/-(\w+)-/)[1] == User.uuid_prefix + 'arvados#user' + else + 'arvados#group' + end + unless current_user.can? write: owner_uuid + raise ArvadosModel::PermissionDeniedError + end + act_as_system_user do + @object = model_class.new resource_attrs.reject { |k,v| k == :owner_uuid } + begin + @object.save! + rescue ActiveRecord::RecordNotUnique + logger.debug resource_attrs.inspect + if resource_attrs[:manifest_text] and resource_attrs[:uuid] + @existing_object = model_class. + where('uuid=? and manifest_text=?', + resource_attrs[:uuid], + resource_attrs[:manifest_text]). + first + @object = @existing_object || @object + end + end + + if @object + link_attrs = { + owner_uuid: owner_uuid, + link_class: 'permission', + name: 'can_read', + head_kind: 'arvados#collection', + head_uuid: @object.uuid, + tail_kind: owner_kind, + tail_uuid: owner_uuid + } + ActiveRecord::Base.transaction do + if Link.where(link_attrs).empty? + Link.create! link_attrs + end + end end end show end + + protected + + def find_object_by_uuid + super + if !@object and !params[:uuid].match(/^[0-9a-f]+\+\d+$/) + # Normalize the given uuid and search again. + hash_part = params[:uuid].match(/^([0-9a-f]*)/)[1] + collection = Collection.where('uuid like ?', hash_part + '+%').first + if collection + # We know the collection exists, and what its real uuid is in + # the database. Now, throw out @objects and repeat the usual + # lookup procedure. (Returning the collection at this point + # would bypass permission checks.) + @objects = nil + @where = { uuid: collection.uuid } + find_objects_for_index + @object = @objects.first + end + end + end end