Modified: trunk/lib/rest.rb (3683 => 3684)
--- trunk/lib/rest.rb 2013-09-06 13:07:03 UTC (rev 3683)
+++ trunk/lib/rest.rb 2013-09-06 13:31:58 UTC (rev 3684)
@@ -9,6 +9,7 @@
require 'uri'
require 'pivoting'
require 'will_paginate'
+Dir.glob(RAILS_ROOT + '/lib/api/resources/*') {|file| require file}
include LibXML
@@ -687,15 +688,12 @@
when 'Ontology'; return ontology_url(ob)
when 'Predicate'; return predicate_url(ob)
when 'Relationship'; return nil
-
when 'Creditation'; return nil
when 'Attribution'; return nil
when 'Tagging'; return nil
-
when 'WorkflowVersion'; return "#{rest_resource_uri(ob.workflow)}?version=#{ob.version}"
when 'BlobVersion'; return "#{rest_resource_uri(ob.blob)}?version=#{ob.version}"
when 'PackVersion'; return pack_version_url(ob, ob.version)
-
when 'Policy'; return policy_url(ob)
end
@@ -835,7 +833,7 @@
el
end
-def parse_resource_uri(str)
+def parse_resource_uri(str)
base_uri = URI.parse("#{Conf.base_uri}/")
uri = base_uri.merge(str)
@@ -1042,603 +1040,6 @@
end
end
-def workflow_aux(action, opts = {})
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a workflow") unless Authorization.check('create', Workflow, opts[:user], nil)
- if opts[:query]['id']
- ob, error = obtain_rest_resource('Workflow', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- ob = Workflow.new(:contributor => opts[:user])
- end
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Workflow', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- return rest_response(400, :reason => "Cannot delete individual versions") if opts[:query]['version']
-
- ob.destroy
-
- else
-
- data = ""
-
- title = parse_element(data, :text, '/workflow/title')
- description = parse_element(data, :text, '/workflow/description')
- license_type = parse_element(data, :text, '/workflow/license-type')
- type = parse_element(data, :text, '/workflow/type')
- content_type = parse_element(data, :text, '/workflow/content-type')
- content = parse_element(data, :binary, '/workflow/content')
- preview = parse_element(data, :binary, '/workflow/preview')
- svg = parse_element(data, :text, '/workflow/svg')
- revision_comment = parse_element(data, :text, '/workflow/revision-comment')
-
- permissions = data.find_first('/workflow/permissions')
-
- # build the contributable
-
- if license_type
- if license_type == ""
- ob.license = nil
- else
- ob.license = License.find_by_unique_name(license_type)
-
- if ob.license.nil?
- ob.errors.add("License type")
- return rest_response(400, :object => ob)
- end
- end
- end
-
- # handle workflow type
-
- if type
-
- ob.content_type = ContentType.find_by_title(type)
-
- if ob.content_type.nil?
- ob.errors.add("Type")
- return rest_response(400, :object => ob)
- end
-
- elsif content_type
-
- content_types = ContentType.find_all_by_mime_type(content_type)
-
- if content_types.length == 1
- ob.content_type = content_types.first
- else
- if content_types.empty?
- ob.errors.add("Content type")
- else
- ob.errors.add("Content type", "matches more than one registered content type")
- end
-
- return rest_response(400, :object => ob)
- end
- end
-
- ob.content_blob_id = ContentBlob.create(:data ="" content).id if content
-
- # Handle versioned metadata. Priority:
- #
- # 1st = elements in REST request
- # 2nd = extracted metadata from workflow processor
- # 3rd = values from previous version
-
- metadata = Workflow.extract_metadata(:type => ob.content_type.title, :data ="" content)
-
- if title
- ob.title = title
- elsif metadata["title"]
- ob.title = metadata["title"]
- end
-
- if description
- ob.body = description
- elsif metadata["description"]
- ob.body = metadata["description"]
- end
-
- # Handle the preview and svg images. If there's a preview supplied, use
- # it. Otherwise auto-generate one if we can.
-
- begin
- if preview.nil? and content
- metadata = Workflow.extract_metadata(:type => ob.content_type.title, :data ="" content)
- preview = metadata["image"].read if metadata["image"]
- end
-
- if preview
- ob.image = preview
- end
-
- if svg.nil? and content
- metadata = Workflow.extract_metadata(:type => ob.content_type.title, :data ="" content)
- svg = metadata["image"].read if metadata["image"]
- end
-
- if svg
- ob.svg = svg
- end
-
- rescue
- return rest_response(500, :reason => "Unable to extract metadata")
- end
-
- new_version = action == 'create' && opts[:query]['id'] != nil
- edit_version = action == 'edit' && opts[:query]['version'] != nil
-
- if new_version
- ob.preview = nil
- ob[:revision_comments] = revision_comment
- end
-
- success = ob.save
-
- if success
- case "#{action} #{new_version || edit_version}"
- when "create false"; Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob, :auth => ob)
- when "create true"; Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob.versions.last, :auth => ob)
- when "edit false"; Activity.create(:subject => opts[:user], :action ="" 'edit', :objekt => ob, :auth => ob)
- when "edit true"; Activity.create(:subject => opts[:user], :action ="" 'edit', :objekt => ob, :extra => ob.version, :auth => ob.workflow)
- end
- end
-
- return rest_response(400, :object => ob) unless success
-
- # Elements to update if we're not dealing with a workflow version
-
- if opts[:query]['version'].nil?
- update_permissions(ob, permissions, opts[:user])
- end
-
- # Extract internals and stuff
- if ob.is_a?(WorkflowVersion)
- ob.workflow.extract_metadata
- else
- ob.extract_metadata
- end
- end
-
- ob = ob.versioned_resource if ob.respond_to?("versioned_resource")
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_workflow(opts)
- workflow_aux('create', opts)
-end
-
-def put_workflow(opts)
- workflow_aux('edit', opts)
-end
-
-def delete_workflow(opts)
- workflow_aux('destroy', opts)
-end
-
-# file handling
-
-def file_aux(action, opts = {})
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a file") unless Authorization.check('create', Blob, opts[:user], nil)
- if opts[:query]['id']
- ob, error = obtain_rest_resource('Blob', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- ob = Blob.new(:contributor => opts[:user])
- end
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Blob', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- return rest_response(400, :reason => "Cannot delete individual versions") if opts[:query]['version']
-
- ob.destroy
-
- else
-
- data = ""
-
- title = parse_element(data, :text, '/file/title')
- description = parse_element(data, :text, '/file/description')
- license_type = parse_element(data, :text, '/file/license-type')
- type = parse_element(data, :text, '/file/type')
- filename = parse_element(data, :text, '/file/filename')
- content_type = parse_element(data, :text, '/file/content-type')
- content = parse_element(data, :binary, '/file/content')
- revision_comment = parse_element(data, :text, '/file/revision-comment')
-
- permissions = data.find_first('/file/permissions')
-
- # build the contributable
-
- ob.title = title if title
- ob.body = description if description
-
- if license_type
- if license_type == ""
- ob.license = nil
- else
- ob.license = License.find_by_unique_name(license_type)
-
- if ob.license.nil?
- ob.errors.add("License type")
- return rest_response(400, :object => ob)
- end
- end
- end
-
- # file name
-
- if filename && !filename.blank?
- ob.local_name = filename
- else
- if ob.local_name.blank?
- ob.errors.add("Filename", "missing")
- return rest_response(400, :object => ob)
- end
- end
-
- # handle type
-
- if type
-
- ob.content_type = ContentType.find_by_title(type)
-
- if ob.content_type.nil?
- ob.errors.add("Type")
- return rest_response(400, :object => ob)
- end
-
- elsif content_type
-
- content_types = ContentType.find_all_by_mime_type(content_type)
-
- if content_types.length == 1
- ob.content_type = content_types.first
- else
- if content_types.empty?
- ob.errors.add("Content type")
- else
- ob.errors.add("Content type", "matches more than one registered content type")
- end
-
- return rest_response(400, :object => ob)
- end
- end
-
- ob.content_blob = ContentBlob.new(:data ="" content) if content
-
- new_version = action == 'create' && opts[:query]['id'] != nil
- edit_version = action == 'edit' && opts[:query]['version'] != nil
-
- if new_version
- ob[:revision_comments] = revision_comment
- end
-
- success = ob.save
-
- if success
- case "#{action} #{new_version || edit_version}"
- when "create false"; Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob, :auth => ob)
- when "create true"; Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob.versions.last, :auth => ob)
- when "edit false"; Activity.create(:subject => opts[:user], :action ="" 'edit', :objekt => ob, :auth => ob)
- when "edit true"; Activity.create(:subject => opts[:user], :action ="" 'edit', :objekt => ob, :extra => ob.version, :auth => ob.blob)
- end
- end
-
- return rest_response(400, :object => ob) unless success
-
- if opts[:query]['version'].nil?
- update_permissions(ob, permissions, opts[:user])
- end
- end
-
- ob = ob.versioned_resource if ob.respond_to?("versioned_resource")
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_file(opts)
- file_aux('create', opts)
-end
-
-def put_file(opts)
- file_aux('edit', opts)
-end
-
-def delete_file(opts)
- file_aux('destroy', opts)
-end
-
-# pack handling
-
-def pack_aux(action, opts = {})
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a pack") unless Authorization.check('create', Pack, opts[:user], nil)
- if id = opts[:query]['id']
- ob = Pack.find_by_id(id)
- if ob.nil?
- return rest_response(404, :reason => "Couldn't find a Pack with id #{id}")
- else
- if Authorization.check('edit', ob, opts[:user])
- ob.snapshot!
- return rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
- else
- return rest_response(401, :reason => "Not authorised to snapshot pack #{id}")
- end
- end
- else
- ob = Pack.new(:contributor => opts[:user])
- end
-
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Pack', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- title = parse_element(data, :text, '/pack/title')
- description = parse_element(data, :text, '/pack/description')
-
- permissions = data.find_first('/pack/permissions')
-
- if license_type = parse_element(data, :text, '/pack/license-type')
- if license_type == ""
- ob.license = nil
- else
- ob.license = License.find_by_unique_name(license_type)
-
- if ob.license.nil?
- ob.errors.add("License type")
- return rest_response(400, :object => ob)
- end
- end
- end
-
- # build the contributable
-
- ob.title = title if title
- ob.description = description if description
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
-
- update_permissions(ob, permissions, opts[:user])
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_pack(opts)
- pack_aux('create', opts)
-end
-
-def put_pack(opts)
- pack_aux('edit', opts)
-end
-
-def delete_pack(opts)
- pack_aux('destroy', opts)
-end
-
-def external_pack_item_aux(action, opts = {})
-
- unless action == 'destroy'
-
- data = ""
-
- pack = parse_element(data, :resource, '/external-pack-item/pack')
- title = parse_element(data, :text, '/external-pack-item/title')
- uri = parse_element(data, :text, '/external-pack-item/uri')
- alternate_uri = parse_element(data, :text, '/external-pack-item/alternate-uri')
- comment = parse_element(data, :text, '/external-pack-item/comment')
- end
-
- # Obtain object
-
- case action
- when 'create';
-
- return rest_response(401, :reason => "Not authorised to create an external pack item") unless Authorization.check('create', PackRemoteEntry, opts[:user], pack)
- return rest_response(400, :reason => "Pack not found") if pack.nil?
- return rest_response(401, :reason => "Not authorised to change the specified pack") unless Authorization.check('edit', pack, opts[:user])
-
- ob = PackRemoteEntry.new(:user => opts[:user],
- :pack => pack,
- :title => title,
- :uri => uri,
- :alternate_uri => alternate_uri,
- :comment => comment)
-
- when 'view', 'edit', 'destroy';
-
- ob, error = obtain_rest_resource('PackRemoteEntry', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
-
- if ob
- return rest_response(401, :reason => "Not authorised to change the specified pack") unless Authorization.check('edit', ob.pack, opts[:user])
- end
-
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- ob.title = title if title
- ob.uri = uri if uri
- ob.alternate_uri = alternate_uri if alternate_uri
- ob.comment = comment if comment
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_external_pack_item(opts)
- external_pack_item_aux('create', opts)
-end
-
-def put_external_pack_item(opts)
- external_pack_item_aux('edit', opts)
-end
-
-def delete_external_pack_item(opts)
- external_pack_item_aux('destroy', opts)
-end
-
-def internal_pack_item_aux(action, opts = {})
-
- unless action == 'destroy'
-
- data = ""
-
- pack = parse_element(data, :resource, '/internal-pack-item/pack')
- item = parse_element(data, :resource, '/internal-pack-item/item')
- comment = parse_element(data, :text, '/internal-pack-item/comment')
-
- version_node = data.find_first('/internal-pack-item/item/@version')
- version = version_node ? version_node.value.to_i : nil
- end
-
- # Obtain object
-
- case action
- when 'create';
-
- return rest_response(401, :reason => "Not authorised to create an internal pack item") unless Authorization.check('create', PackContributableEntry, opts[:user], pack)
- return rest_response(400, :reason => "Pack not found") if pack.nil?
-
- ob = PackContributableEntry.new(:user => opts[:user],
- :pack => pack,
- :contributable => item,
- :comment => comment,
- :contributable_version => version)
-
- when 'view', 'edit', 'destroy';
-
- ob, error = obtain_rest_resource('PackContributableEntry', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
-
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- ob.comment = comment if comment
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_internal_pack_item(opts)
- internal_pack_item_aux('create', opts)
-end
-
-def put_internal_pack_item(opts)
- internal_pack_item_aux('edit', opts)
-end
-
-def delete_internal_pack_item(opts)
- internal_pack_item_aux('destroy', opts)
-end
-
-# def post_job(opts)
-#
-# title = params["job"]["title"]
-# description = params["job"]["description"]
-#
-# experiment_bits = parse_resource_uri(params["job"]["experiment"])
-# runner_bits = parse_resource_uri(params["job"]["runner"])
-# runnable_bits = parse_resource_uri(params["job"]["runnable"])
-#
-# return rest_response(400) if title.nil?
-# return rest_response(400) if description.nil?
-#
-# return rest_response(400) if experiment_bits.nil? or experiment_bits[0] != 'Experiment'
-# return rest_response(400) if runner_bits.nil? or runner_bits[0] != 'TavernaEnactor'
-# return rest_response(400) if runnable_bits.nil? or runnable_bits[0] != 'Workflow'
-#
-# experiment = Experiment.find_by_id(experiment_bits[1].to_i)
-# runner = TavernaEnactor.find_by_id(runner_bits[1].to_i)
-# runnable = Workflow.find_by_id(runnable_bits[1].to_i)
-#
-# return rest_response(400) if experiment.nil? or not Authorization.check('edit', experiment, opts[:user])
-# return rest_response(400) if runner.nil? or not Authorization.check('download', runner, opts[:user])
-# return rest_response(400) if runnable.nil? or not Authorization.check('view', runnable, opts[:user])
-#
-# puts "#{params[:job]}"
-#
-# job = Job.new(:title => title, :description => description, :runnable => runnable,
-# :experiment => experiment, :runner => runner, :user => opts[:user],
-# :runnable_version => runnable.current_version)
-#
-# inputs = { "Tags" => "aa,bb,aa,cc,aa" }
-#
-# job.inputs_data = inputs
-#
-# success = job.submit_and_run!
-#
-# return rest_response(500) if not success
-#
-# return "<yes/>"
-#
-# end
-
def paginated_search_index(query, models, num, page, user)
return [] if not Conf.solr_enable or query.nil? or query == ""
@@ -1734,123 +1135,6 @@
end
end
-def user_count(opts)
-
- users = User.find(:all).select do |user| user.activated? end
-
- root = LibXML::XML::Node.new('user-count')
- root << users.length.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- { :xml => doc }
-end
-
-def group_count(opts)
-
- root = LibXML::XML::Node.new('group-count')
- root << Network.count.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- { :xml => doc }
-end
-
-def workflow_count(opts)
-
- workflows = Workflow.find(:all).select do |w|
- Authorization.check('view', w, opts[:user])
- end
-
- root = LibXML::XML::Node.new('workflow-count')
- root << workflows.length.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- { :xml => doc }
-end
-
-def pack_count(opts)
-
- packs = Pack.find(:all).select do |p|
- Authorization.check('view', p, opts[:user])
- end
-
- root = LibXML::XML::Node.new('pack-count')
- root << packs.length.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- { :xml => doc }
-end
-
-def content_type_count(opts)
-
- root = LibXML::XML::Node.new('type-count')
- root << ContentType.count.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- { :xml => doc }
-end
-
-def get_tagged(opts)
-
- return rest_response(400, :reason => "Did not specify a tag") if opts[:query]['tag'].nil?
-
- tag = Tag.find_by_name(opts[:query]['tag'])
-
- obs = tag ? tag.tagged : []
-
- # filter out ones they are not allowed to get
- obs = (obs.select do |c| c.respond_to?('contribution') == false or Authorization.check("view", c, opts[:user]) end)
-
- produce_rest_list("tagged", opts[:rules], opts[:query], obs, 'tagged', [], opts[:user])
-end
-
-def tag_cloud(opts)
-
- num = 25
- type = nil
-
- if opts[:query]['num']
- if opts[:query]['num'] == 'all'
- num = nil
- else
- num = opts[:query]['num'].to_i
- end
- end
-
- if opts[:query]['type'] and opts[:query]['type'] != 'all'
- type = opts[:query]['type'].camelize
-
- type = 'Network' if type == 'Group'
- type = 'Blob' if type == 'File'
- end
-
- tags = Tag.find_by_tag_count(num, type)
-
- doc = LibXML::XML::Document.new()
-
- root = LibXML::XML::Node.new('tag-cloud')
- doc.root = root
-
- root['type'] = opts[:query]['type'] ? opts[:query]['type'] : 'all'
-
- tags.each do |tag|
- tag_node = rest_reference(tag, opts[:query])
- tag_node['count'] = tag.taggings_count.to_s
- root << tag_node
- end
-
- { :xml => doc }
-end
-
def whoami_redirect(opts)
if opts[:user].class == User
case opts[:format]
@@ -1987,590 +1271,18 @@
permissions
end
-# Comments
-
-def comment_aux(action, opts)
-
- unless action == "destroy"
-
- data = ""
-
- comment = parse_element(data, :text, '/comment/comment')
- subject = parse_element(data, :resource, '/comment/subject')
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a comment") unless Authorization.check('create', Comment, opts[:user], subject)
-
- ob = Comment.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Comment', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- ob.comment = comment if comment
-
- if subject
- return rest_response(400, :reason => "Specified resource does not support comments") unless [Blob, Network, Pack, Workflow].include?(subject.class)
- return rest_response(401, :reason => "Not authorised to add a comment to the specified resource") unless Authorization.check(action, Comment, opts[:user], subject)
- ob.commentable = subject
- end
-
- # Start of curation hack
-
- def match_tag_name(name)
-
- name.sub!(/^c:/, '')
-
- matches = []
-
- Conf.curation_types.each do |type|
- matches.push type if type.starts_with?(name)
- end
-
- return matches[0] if matches.length == 1
- end
-
- if comment[0..1].downcase == 'c:' && opts[:user] && subject &&
- Conf.curators.include?(opts[:user].username)
-
- comment = comment[2..-1].strip
-
- lines = comment.split("\n")
- events = []
- failed = false
-
- lines.each do |line|
-
- line.strip!
-
- bits = line.split(";")
-
- if bits.length > 1
- details = bits[1..-1].join(";")
- else
- details = nil
- end
-
- if bits.length > 0
- bits[0].split(",").each do |bit|
-
- bit.downcase!
- bit.strip!
-
- curation_type = match_tag_name(bit)
-
- if curation_type
- events.push(CurationEvent.new(:category => curation_type,
- :object => subject, :user => opts[:user], :details => details))
- else
- failed = true
- end
- end
- end
- end
-
- if failed
- return rest_response(400, :reason => 'Unrecognised curation term')
- end
-
- events.each do |event|
- event.save
- end
-
- subject.solr_index
-
- return rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
- end
-
- # End of curation hack
-
- success = ob.save
-
- if success
- case action
- when "create"; Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob)
- when "edit"; Activity.create(:subject => opts[:user], :action ="" 'edit', :objekt => ob)
- end
- end
-
- return rest_response(400, :object => ob) unless success
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_comment(opts)
- comment_aux('create', opts)
-end
-
-def put_comment(opts)
- comment_aux('edit', opts)
-end
-
-def delete_comment(opts)
- comment_aux('destroy', opts)
-end
-
-# Favourites
-
-def favourite_aux(action, opts)
-
- unless action == "destroy"
-
- data = ""
-
- target = parse_element(data, :resource, '/favourite/object')
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a favourite") unless Authorization.check('create', Bookmark, opts[:user], target)
-
- ob = Bookmark.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Bookmark', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- if target
- return rest_response(400, :reason => "Specified resource is not a valid favourite target") unless [Blob, Pack, Workflow].include?(target.class)
- return rest_response(401, :reason => "Not authorised to create the favourite") unless Authorization.check(action, Bookmark, opts[:user], target)
- ob.bookmarkable = target
- end
-
- success = ob.save
-
- if success
- Activity.create(:subject => current_user, :action ="" 'create', :objekt => ob)
- end
-
- return rest_response(400, :object => ob) unless success
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_favourite(opts)
- favourite_aux('create', opts)
-end
-
-def put_favourite(opts)
- favourite_aux('edit', opts)
-end
-
-def delete_favourite(opts)
- favourite_aux('destroy', opts)
-end
-
-# Ratings
-
-def rating_aux(action, opts)
-
- unless action == "destroy"
-
- data = ""
-
- rating = parse_element(data, :text, '/rating/rating')
- subject = parse_element(data, :resource, '/rating/subject')
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a rating") unless Authorization.check('create', Rating, opts[:user], subject)
-
- ob = Rating.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Rating', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- ob.rating = rating if rating
-
- if subject
- return rest_response(400, :reason => "Specified resource does not support ratings") unless [Blob, Network, Pack, Workflow].include?(subject.class)
- return rest_response(401, :reason => "Not authorised for the specified resource") unless Authorization.check(action, Rating, opts[:user], subject)
- ob.rateable = subject
- end
-
- success = ob.save
-
- if success
- Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob, :auth => subject)
- end
-
- return rest_response(400, :object => ob) unless success
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_rating(opts)
- rating_aux('create', opts)
-end
-
-def put_rating(opts)
- rating_aux('edit', opts)
-end
-
-def delete_rating(opts)
- rating_aux('destroy', opts)
-end
-
-# Taggings
-
-def tagging_aux(action, opts)
-
- unless action == "destroy"
-
- data = ""
-
- subject = parse_element(data, :resource, '/tagging/subject')
- label = parse_element(data, :text, '/tagging/label')
- tag = parse_element(data, :resource, '/tagging/tag')
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a tagging") unless Authorization.check('create', Tagging, opts[:user], subject)
-
- ob = Tagging.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Tagging', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- ob.label = label if label
- ob.tag = tag if tag
-
- if subject
- return rest_response(401, :reason => "Not authorised for the specified resource") unless Authorization.check(action, Tagging, opts[:user], subject)
- ob.taggable = subject
- end
-
- success = ob.save
-
- if success && action == "create"
- Activity.create(:subject => opts[:user], :action ="" 'create', :objekt => ob, :auth => subject)
- end
-
- return rest_response(400, :object => ob) unless success
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_tagging(opts)
- tagging_aux('create', opts)
-end
-
-def delete_tagging(opts)
- tagging_aux('destroy', opts)
-end
-
-# Ontologies
-
-def ontology_aux(action, opts)
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create an ontology") unless Authorization.check('create', Ontology, opts[:user], nil)
- ob = Ontology.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Ontology', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- title = parse_element(data, :text, '/ontology/title')
- description = parse_element(data, :text, '/ontology/description')
- uri = parse_element(data, :text, '/ontology/uri')
- prefix = parse_element(data, :text, '/ontology/prefix')
-
- # build the contributable
-
- ob.title = title if title
- ob.description = description if description
- ob.uri = uri if uri
- ob.prefix = prefix if prefix
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_ontology(opts)
- ontology_aux('create', opts)
-end
-
-def put_ontology(opts)
- ontology_aux('edit', opts)
-end
-
-def delete_ontology(opts)
- ontology_aux('destroy', opts)
-end
-
-# Predicates
-
-def predicate_aux(action, opts)
-
- if action != "destroy"
-
- data = ""
-
- title = parse_element(data, :text, '/predicate/title')
- :resource, '/predicate/ontology')
- description = parse_element(data, :text, '/predicate/description')
- phrase = parse_element(data, :text, '/predicate/phrase')
- equivalent_to = parse_element(data, :text, '/predicate/equivalent-to')
-
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a predicate") unless Authorization.check('create', Predicate, opts[:user], ontology)
- ob = Predicate.new
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Predicate', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- # build it
-
- ob.title = title if title
- ob.description = description if description
- ob.phrase = phrase if phrase
- ob.equivalent_to = equivalent_to if equivalent_to
- ob. if ontology
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_predicate(opts)
- predicate_aux('create', opts)
-end
-
-def put_predicate(opts)
- predicate_aux('edit', opts)
-end
-
-def delete_predicate(opts)
- predicate_aux('destroy', opts)
-end
-
-# Relationships
-
-def relationship_aux(action, opts)
-
- if action != "destroy"
-
- data = ""
-
- subject = parse_element(data, :resource, '/relationship/subject')
- predicate = parse_element(data, :resource, '/relationship/predicate')
- objekt = parse_element(data, :resource, '/relationship/object')
- context = parse_element(data, :resource, '/relationship/context')
- end
-
- # Obtain object
-
- case action
- when 'create';
- return rest_response(401, :reason => "Not authorised to create a relationship") unless Authorization.check('create', Relationship, opts[:user], context)
- ob = Relationship.new(:user => opts[:user])
- when 'view', 'edit', 'destroy';
- ob, error = obtain_rest_resource('Relationship', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return error if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- # build it
-
- ob.subject = subject if subject
- ob.predicate = predicate if predicate
- ob.objekt = objekt if objekt
- ob.context = context if context
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
- end
-
- rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
-end
-
-def post_relationship(opts)
- relationship_aux('create', opts)
-end
-
-def put_relationship(opts)
- relationship_aux('edit', opts)
-end
-
-def delete_relationship(opts)
- relationship_aux('destroy', opts)
-end
-
# Call dispatcher
def rest_call_request(opts)
begin
send(opts[:rules]['Function'], opts)
- rescue
+ rescue Exception => e
if Rails.env == "production"
+ logger.info e.message
+ logger.info e.backtrace.join("\n")
return rest_response(500)
else
raise
end
end
end
-
-# Component Querying
-def get_components(opts)
- return rest_response(404) if TripleStore.instance.nil?
-
- sparql_prefixes = CGI.unescape(opts[:query]["prefixes"] || '')
- sparql_query = CGI.unescape(opts[:query]["query"] || '')
-
- # Prevent subversion of SELECT template
- if sparql_prefixes.downcase.include?("select")
- return rest_response(400, :reason => "Invalid prefix syntax")
- end
-
- template = %(
- PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>
- PREFIX wfdesc:<http://purl.org/wf4ever/wfdesc#>
- PREFIX wf4ever:<http://purl.org/wf4ever/wf4ever#>
- #{sparql_prefixes}
-
- SELECT DISTINCT ?workflow_uri WHERE {
- GRAPH ?workflow_uri {
- ?w a wfdesc:Workflow .
- #{sparql_query}
- }
- })
-
- # Perform query
- begin
- sparql_results = TripleStore.instance.query(template)
- rescue Sesame::QueryException => e
- return rest_response(400, :reason => "SPARQL Error: #{e.message}")
- end
-
- # Remove results not from this host
- # TODO: do this in the query?
- base_uri = URI(Conf.base_uri)
- results = sparql_results.select do |r|
- r[:workflow_uri].host == base_uri.host && r[:workflow_uri].port == base_uri.port
- end
-
- # Find the workflows in the database
- results = results.map do |r|
- Workflow.find_by_id(r[:workflow_uri].request_uri.to_s.sub('/workflows/', '').to_i)
- end
-
- # Perform auth on workflow set
- results = results.select { |r| Authorization.check("view", r, opts[:user]) }
-
- # Render results
- produce_rest_list(opts[:uri], opts[:rules], opts[:query], results, "workflows", [], opts[:user])
-end
-
-def get_policies(opts)
- policies = []
-
- if opts[:user].is_a?(User)
- if opts[:query]["type"] == 'group'
- policies = opts[:user].group_policies
- else
- policies = opts[:user].policies + opts[:user].group_policies
- end
- end
-
- produce_rest_list(opts[:uri], opts[:rules], opts[:query], policies, "policies", [], opts[:user])
-end
Modified: trunk/test/functional/api_controller_test.rb (3683 => 3684)
--- trunk/test/functional/api_controller_test.rb 2013-09-06 13:07:03 UTC (rev 3683)
+++ trunk/test/functional/api_controller_test.rb 2013-09-06 13:31:58 UTC (rev 3684)
@@ -14,7 +14,7 @@
@response = ActionController::TestResponse.new
end
- fixtures :workflows, :users, :content_types, :licenses, :ontologies, :predicates, :packs
+ fixtures :workflows, :users, :content_types, :licenses, :ontologies, :predicates, :packs, :tags, :taggings
def test_workflows
@@ -1131,13 +1131,14 @@
assert_response(:not_found)
end
- # Component querying
+ # Components
- def test_basic_component_query # not a great test, but should pick up any major errors
+ test "can create components" do
login_as(:john)
# Check empty
- resp = rest_request(:get, 'components', nil, {'prefixes' => '', 'query' => ''})
+ TripleStore.instance.repo = {}
+ resp = rest_request(:get, 'components')
assert_response(:success)
assert_equal 0, resp.find('//workflow').size
@@ -1145,11 +1146,12 @@
license_type = "by-sa"
content_type = "application/vnd.taverna.t2flow+xml"
content = Base64.encode64(File.read('test/fixtures/files/image_to_tiff_migration.t2flow'))
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ family = packs(:component_family)
+ workflow_resp = rest_request(:post, 'component', "<?xml version='1.0'?>
<workflow>
<title>Test Component</title>
<description>123</description>
+ <component-family>#{polymorphic_url(family)}</component-family>
<license-type>#{license_type}</license-type>
<content-type>#{content_type}</content-type>
<content>#{content}</content>
@@ -1157,12 +1159,429 @@
assert_response(:success)
- # Check result returned
+ # Get the newly created component
+ uri = workflow_resp.find_first('//workflow')['resource']
+ component = Workflow.find(uri.split('/').last.to_i)
+
+ # Check it was added to the family
+ assert_includes family.contributable_entries.map { |e| e.contributable }, component
+
+ # Check it was tagged
+ assert component.component?
+
+ # Check it's retrievable
+ query_resp = rest_request(:get, 'components')
+ assert_response(:success)
+ assert_equal 1, query_resp.find('//workflow').size
+ assert_equal uri, query_resp.find_first('//workflow')['resource']
+ end
+
+ test "can't create component if family doesn't exist" do
+ login_as(:john)
+
+ # Upload a component workflow
+ license_type = "by-sa"
+ content_type = "application/vnd.taverna.t2flow+xml"
+ content = Base64.encode64(File.read('test/fixtures/files/image_to_tiff_migration.t2flow'))
+ assert_no_difference('Workflow.count') do
+ rest_request(:post, 'component', "<?xml version='1.0'?>
+ <workflow>
+ <title>Test Component</title>
+ <description>123</description>
+ <component-family>http://www.example.com/families/123</component-family>
+ <license-type>#{license_type}</license-type>
+ <content-type>#{content_type}</content-type>
+ <content>#{content}</content>
+ </workflow>")
+ end
+
+ assert_response(404)
+ end
+
+ test "can't create component if family url points to non-family resource" do
+ login_as(:john)
+
+ # Upload a component workflow
+ license_type = "by-sa"
+ content_type = "application/vnd.taverna.t2flow+xml"
+ content = Base64.encode64(File.read('test/fixtures/files/image_to_tiff_migration.t2flow'))
+ assert_no_difference('Workflow.count') do
+ rest_request(:post, 'component', "<?xml version='1.0'?>
+ <workflow>
+ <title>Test Component</title>
+ <description>123</description>
+ <component-family>#{polymorphic_url(packs(:pack_1))}</component-family>
+ <license-type>#{license_type}</license-type>
+ <content-type>#{content_type}</content-type>
+ <content>#{content}</content>
+ </workflow>")
+ end
+
+ assert_response(400)
+ end
+
+ test "can't create components in protected family" do
+ login_as(:jane)
+
+ # Upload a component workflow
+ license_type = "by-sa"
+ content_type = "application/vnd.taverna.t2flow+xml"
+ content = Base64.encode64(File.read('test/fixtures/files/image_to_tiff_migration.t2flow'))
+ family = packs(:protected_component_family)
+ assert_no_difference('Workflow.count') do
+ rest_request(:post, 'component', "<?xml version='1.0'?>
+ <workflow>
+ <title>Test Component</title>
+ <description>123</description>
+ <component-family>#{polymorphic_url(family)}</component-family>
+ <license-type>#{license_type}</license-type>
+ <content-type>#{content_type}</content-type>
+ <content>#{content}</content>
+ </workflow>")
+ end
+
+ assert_response(401)
+ end
+
+ test "can create component versions" do
+ login_as(:john)
+
+ # Set up
+ component = workflows(:component_workflow)
+ version_count = WorkflowVersion.count
+ # Put in triplestore
+ TripleStore.instance.repo = {}
+ TripleStore.instance.insert("", "<#{polymorphic_url(component)}>")
+
+ # Check its there
+ resp = rest_request(:get, 'components')
+ assert_response(:success)
+ assert_equal 1, resp.find('//workflow').size
+ assert_equal "", TripleStore.instance.repo["<#{polymorphic_url(component)}>"]
+
+ # Post new version
+ content = Base64.encode64(File.read('test/fixtures/files/image_to_tiff_migration.t2flow'))
+
+ workflow_resp = rest_request(:post, 'component', "<?xml version='1.0'?>
+ <workflow>
+ <title>Test Component II</title>
+ <description>456</description>
+ <content>#{content}</content>
+ </workflow>", {'id' => component.id})
+
+ assert_response(:success)
+
+ # Get the newly created component
+ uri = workflow_resp.find_first('//workflow')['resource']
+ component = Workflow.find(uri.split('/').last.to_i)
+
+ # Check the version was created
+ assert_equal version_count+1, WorkflowVersion.count
+ assert_equal 'Test Component II', component.title
+
+ # Check there's still only one component in the triplestore
+ query_resp = rest_request(:get, 'components')
+ assert_response(:success)
+ assert_equal 1, query_resp.find('//workflow').size
+ assert_equal uri, query_resp.find_first('//workflow')['resource']
+ assert_not_equal "", TripleStore.instance.repo["<#{polymorphic_url(component)}>"]
+ end
+
+ test "can query components by family" do
+ component_uri2 = polymorphic_url(workflows(:component_workflow2))
+ component_uri = polymorphic_url(workflows(:component_workflow))
+ private_component_uri = polymorphic_url(workflows(:private_component_workflow))
+ family_uri = polymorphic_url(packs(:component_family))
+
+ TripleStore.instance.repo = {}
+ TripleStore.instance.insert("", "<#{component_uri2}>") # Not in the family
+ TripleStore.instance.insert("", "<#{private_component_uri}>") # In the family, but not viewable
+ TripleStore.instance.insert("", "<#{component_uri}>") # In the family
+
+ # Should only return one result
+ resp = rest_request(:get, 'components', nil, {'component-family' => family_uri})
+ assert_response(:success)
+ assert_equal 3, TripleStore.instance.repo.keys.size
+ assert_equal 1, resp.find('//workflow').size
+ assert_equal component_uri, resp.find_first('//workflow')['resource']
+
+ # Clean up
+ TripleStore.instance.repo = {}
+ end
+
+ test "component query only returns local results" do
+ # Set up
+ login_as(:john)
+
+ uri = polymorphic_url(workflows(:component_workflow))
+
+ TripleStore.instance.repo = {}
+ TripleStore.instance.insert("", "<http://www.google.com/>")
+ TripleStore.instance.insert("", "<http://www.example.com/workflows/456>")
+ TripleStore.instance.insert("", "<#{uri}>")
+
+ # Should only return one result
resp = rest_request(:get, 'components', nil, {'prefixes' => '', 'query' => ''})
assert_response(:success)
+ assert_equal 3, TripleStore.instance.repo.keys.size
assert_equal 1, resp.find('//workflow').size
+ assert_equal uri, resp.find_first('//workflow')['resource']
+
+ # Clean up
+ TripleStore.instance.repo = {}
end
+ test "component query doesn't return private components" do
+ # Set up
+ TripleStore.instance.repo = {}
+ TripleStore.instance.insert("", "<#{polymorphic_url(workflows(:private_component_workflow))}>")
+
+ # Should only return one result
+ resp = rest_request(:get, 'components', nil, {'prefixes' => '', 'query' => ''})
+ assert_response(:success)
+ assert_equal 1, TripleStore.instance.repo.keys.size
+ assert_equal 0, resp.find('//workflow').size
+
+ # Clean up
+ TripleStore.instance.repo = {}
+ end
+
+ test "component query does return private components for authorized user" do
+ # Set up
+ login_as(:john)
+
+ uri = polymorphic_url(workflows(:private_component_workflow))
+
+ TripleStore.instance.repo = {}
+ TripleStore.instance.insert("", "<#{uri}>")
+
+ # Should only return one result
+ resp = rest_request(:get, 'components', nil, {'prefixes' => '', 'query' => ''})
+ assert_response(:success)
+ assert_equal 1, TripleStore.instance.repo.keys.size
+ assert_equal 1, resp.find('//workflow').size
+ assert_equal uri, resp.find_first('//workflow')['resource']
+
+ # Clean up
+ TripleStore.instance.repo = {}
+ end
+
+ test "can get list of component profiles" do
+ login_as(:john)
+
+ profile_count = Blob.all.select { |b| b.component_profile? }.size
+
+ resp = rest_request(:get, 'component-profiles')
+ assert_response(:success)
+
+ assert_equal profile_count, resp.find('//file').size
+ profiles = resp.find('//file').map { |f| Blob.find(f['resource'].split('/').last.to_i) }
+ assert_includes profiles, blobs(:component_profile)
+ end
+
+ test "can create component profile" do
+ login_as(:john)
+
+ # Get list of profiles first
+ resp = rest_request(:get, 'component-profiles')
+ assert_response(:success)
+ profile_count = resp.find('//file').size
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+ body = %(
+ <file>
+ <title>Component Profile</title>
+ <filename>profile.xml</filename>
+ <description>It's for components</description>
+ <content-type>application/vnd.taverna.component-profile+xml</content-type>
+ <content>#{content}</content>
+ <license-type>by-sa</license-type>
+ </file>
+ )
+
+ resp = rest_request(:post, 'component-profile', body)
+ assert_response(:success)
+
+ uri = resp.find_first('//file')['resource']
+ profile = ""
+ assert_not_nil profile
+ assert_includes profile.tags.map {|t| t.name }, 'component profile'
+
+ # Check new family returned in list
+ resp = rest_request(:get, 'component-profiles')
+ assert_response(:success)
+ assert_equal profile_count+1, resp.find('//file').size
+ assert_includes resp.find('//file').map {|f| f['resource']}, uri
+ end
+
+ test "can delete component profile that isn't used in any families" do
+ login_as(:john)
+
+ profile = ""
+
+ assert_difference('Blob.count', -1) do
+ rest_request(:delete, 'component-profile', nil, 'id' => profile.id)
+ end
+
+ assert_response(:success)
+ end
+
+ test "can't delete component profile that is used" do
+ login_as(:john)
+
+ profile = ""
+
+ assert_no_difference('Blob.count') do
+ rest_request(:delete, 'component-profile', nil, 'id' => profile.id)
+ end
+
+ assert_response(400)
+ end
+
+ test "can get list of component families" do
+ login_as(:john)
+
+ family_count = Pack.all.select { |p| p.component_family? }.size
+
+ resp = rest_request(:get, 'component-families')
+ assert_response(:success)
+
+ assert_equal family_count, resp.find('//pack').size
+ families = resp.find('//pack').map { |f| Pack.find(f['resource'].split('/').last.to_i) }
+ assert_includes families, packs(:component_family)
+ end
+
+ test "can create component family" do
+ login_as(:john)
+
+ family_count = Pack.all.select { |p| p.component_family? }.size
+
+ body = %(
+ <pack>
+ <title>A Component Family</title>
+ <description>It's for components</description>
+ <component-profile>#{polymorphic_url(blobs(:component_profile))}</component-profile>
+ <license-type>by-sa</license-type>
+ </pack>
+ )
+
+ resp = rest_request(:post, 'component-family', body)
+ assert_response(:success)
+
+ uri = resp.find_first('//pack')['resource']
+ family = Pack.find_by_id(uri.split('/').last.to_i)
+ assert_not_nil family
+ assert_includes family.tags.map {|t| t.name }, 'component family'
+
+ resp = rest_request(:get, 'component-families')
+ assert_response(:success)
+ assert_equal family_count+1, resp.find('//pack').size
+ assert_includes resp.find('//pack').map { |p| p['resource'] }, uri
+ end
+
+ test "can't create component family with missing profile uri" do
+ login_as(:john)
+
+ body = %(
+ <pack>
+ <title>A Component Family</title>
+ <description>It's for components</description>
+ <license-type>by-sa</license-type>
+ </pack>
+ )
+
+ assert_no_difference('Pack.count') do
+ rest_request(:post, 'component-family', body)
+ end
+
+ assert_response(400)
+ end
+
+ test "can't create component family with invalid profile uri" do
+ login_as(:john)
+
+ body = %(
+ <pack>
+ <title>A Component Family</title>
+ <description>It's for components</description>
+ <component-profile>http://www.example.com/profiles/241</component-profile>
+ <license-type>by-sa</license-type>
+ </pack>
+ )
+
+ assert_no_difference('Pack.count') do
+ rest_request(:post, 'component-family', body)
+ end
+
+ assert_response(404)
+ end
+
+
+ test "can't create component family with profile uri pointing to non-profile resources" do
+ login_as(:john)
+
+ body = %(
+ <pack>
+ <title>A Component Family</title>
+ <description>It's for components</description>
+ <component-profile>#{polymorphic_url(blobs(:picture))}</component-profile>
+ <license-type>by-sa</license-type>
+ </pack>
+ )
+
+ assert_no_difference('Pack.count') do
+ rest_request(:post, 'component-family', body)
+ end
+
+ assert_response(400)
+
+ body = %(
+ <pack>
+ <title>A Component Family</title>
+ <description>It's for components</description>
+ <component-profile>#{polymorphic_url(workflows(:workflow_dilbert))}</component-profile>
+ <license-type>by-sa</license-type>
+ </pack>
+ )
+
+ assert_no_difference('Pack.count') do
+ rest_request(:post, 'component-family', body)
+ end
+
+ assert_response(400)
+ end
+
+ test "can delete component family and components" do
+ login_as(:john)
+
+ family = packs(:protected_component_family)
+ component_count = family.contributable_entries.select { |e| e.contributable_type == 'Workflow' && e.contributable.component? }.size
+
+ assert_no_difference('Blob.count') do # Profile not deleted
+ assert_difference('Workflow.count', -component_count) do # Components deleted
+ assert_difference('Pack.count', -1) do # Family deleted
+ rest_request(:delete, 'component-family', nil, 'id' => family.id)
+ end
+ end
+ end
+
+ assert_response(:success)
+ end
+
+ test "can't delete component family containing other people's components" do
+ login_as(:john)
+
+ assert_no_difference('Blob.count') do
+ assert_no_difference('Workflow.count') do
+ assert_no_difference('Pack.count') do
+ rest_request(:delete, 'component-family', nil, 'id' => packs(:communal_component_family).id)
+ end
+ end
+ end
+
+ assert_response(401)
+ end
+
private
def rest_request(method, uri, data = "" query = {})