Diff
Modified: branches/api/Rakefile (2921 => 2924)
--- trunk/Rakefile 2012-01-26 13:24:17 UTC (rev 2921)
+++ branches/api/Rakefile 2012-02-03 11:28:38 UTC (rev 2924)
@@ -176,3 +176,16 @@
end
end
+desc 'Dump REST spreadsheet to yaml'
+task "myexp:api:yaml" do
+ require File.dirname(__FILE__) + '/config/environment'
+
+ tables = TABLES.clone
+
+ tables.keys.each do |key|
+ tables[key] = tables[key][:data]
+ end
+
+ puts tables.to_yaml
+end
+
Deleted: branches/api/app/controllers/api_controller.rb (2921 => 2924)
--- trunk/app/controllers/api_controller.rb 2012-01-26 13:24:17 UTC (rev 2921)
+++ branches/api/app/controllers/api_controller.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -1,80 +0,0 @@
-# myExperiment: app/controllers/api.rb
-#
-# Copyright (c) 2007 University of Manchester and the University of Southampton.
-# See license.txt for details.
-
-require 'rexml/document'
-require 'base64'
-require 'lib/rest'
-
-class ApiController < ApplicationController
-
- def process_request
-
- # all responses from the API are in XML
- response.content_type = "application/xml"
-
- user = current_user
-
- auth = request.env["HTTP_AUTHORIZATION"]
-
- if auth and auth.starts_with?("Basic ")
- credentials = Base64.decode64(auth.sub(/^Basic /, '')).split(':')
- user = User.authenticate(credentials[0], credentials[1])
-
- return rest_response(401, :reason => "Failed to authenticate") if user.nil?
-
- end
-
- method = request.method.to_s.upcase
- uri = params[:uri]
-
- # logger.info "current token: #{current_token.inspect}"
- # logger.info "current user: #{user.id}"
- # logger.info "method: #{method}"
- # logger.info "uri: #{uri}"
-
- return rest_response(400) if TABLES['REST'][:data][uri].nil?
- return rest_response(400) if TABLES['REST'][:data][uri][method].nil?
-
- rules = TABLES['REST'][:data][uri][method]
-
- # validate id and version query options
-
- case rules['Allow id']
- when 'required'
- return rest_response(400, :reason => "Must specify an id") if request.query_parameters['id'].nil?
- when 'no'
- return rest_response(400, :reason => "Cannot specify an id") if request.query_parameters['id']
- end
-
- case rules['Allow version']
- when 'required'
- return rest_response(400, :reason => "Must specify a version") if request.query_parameters['version'].nil?
- when 'no'
- return rest_response(400, :reason => "Cannot specify a version") if request.query_parameters['version']
- end
-
- # key check - if an oauth access token is in use, this means that we must
- # only allow requests where explicit permission has been given
-
- if current_token
- requested_permission = "#{method} #{uri}"
- permission_found = false
-
- current_token.client_application.permissions.each do |permission|
- permission_found = true if permission.for == requested_permission
- end
-
- return rest_response(403, :reason => "OAuth token does not grant sufficient permission for this action") if permission_found == false
- end
-
- case rules['Type']
- when 'index'; doc = rest_index_request(params[:uri], params[:format], rules, user, request.query_parameters)
- when 'crud'; doc = rest_crud_request(params[:uri], params[:format], rules, user, request.query_parameters)
- when 'call'; doc = rest_call_request(params[:uri], params[:format], rules, user, request.query_parameters)
- else; return rest_response(500, :reason => "Unknown REST table type")
- end
- end
-end
-
Copied: branches/api/app/controllers/api_controller.rb (from rev 2923, trunk/app/controllers/api_controller.rb) (0 => 2924)
--- branches/api/app/controllers/api_controller.rb (rev 0)
+++ branches/api/app/controllers/api_controller.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -0,0 +1,107 @@
+# myExperiment: app/controllers/api.rb
+#
+# Copyright (c) 2007 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+require 'base64'
+require 'lib/rest'
+
+class ApiController < ApplicationController
+
+ def process_request
+
+ rest_response = process_request_aux
+
+ case params[:format]
+
+ when "xml"
+ response.content_type = "application/xml"
+ render(:xml => rest_response[:xml].to_s, :status => rest_response[:status])
+ when "json"
+ response.content_type = "application/json"
+ render(:text => produce_json(rest_response[:xml]))
+ end
+ end
+
+private
+
+ def produce_json(doc)
+
+ def aux(element)
+ result = {}
+
+ debugger
+ element.
+
+ result
+ end
+
+ aux(doc.root).to_json
+ end
+
+ def process_request_aux
+
+ user = current_user
+
+ auth = request.env["HTTP_AUTHORIZATION"]
+
+ if auth and auth.starts_with?("Basic ")
+ credentials = Base64.decode64(auth.sub(/^Basic /, '')).split(':')
+ user = User.authenticate(credentials[0], credentials[1])
+
+ return rest_response(401, :reason => "Failed to authenticate") if user.nil?
+
+ end
+
+ method = request.method.to_s.upcase
+ uri = params[:uri]
+
+ # logger.info "current token: #{current_token.inspect}"
+ # logger.info "current user: #{user.id}"
+ # logger.info "method: #{method}"
+ # logger.info "uri: #{uri}"
+
+ return rest_response(400) if TABLES['REST'][:data][uri].nil?
+ return rest_response(400) if TABLES['REST'][:data][uri][method].nil?
+
+ rules = TABLES['REST'][:data][uri][method]
+
+ # validate id and version query options
+
+ case rules['Allow id']
+ when 'required'
+ return rest_response(400, :reason => "Must specify an id") if request.query_parameters['id'].nil?
+ when 'no'
+ return rest_response(400, :reason => "Cannot specify an id") if request.query_parameters['id']
+ end
+
+ case rules['Allow version']
+ when 'required'
+ return rest_response(400, :reason => "Must specify a version") if request.query_parameters['version'].nil?
+ when 'no'
+ return rest_response(400, :reason => "Cannot specify a version") if request.query_parameters['version']
+ end
+
+ # key check - if an oauth access token is in use, this means that we must
+ # only allow requests where explicit permission has been given
+
+ if current_token
+ requested_permission = "#{method} #{uri}"
+ permission_found = false
+
+ current_token.client_application.permissions.each do |permission|
+ permission_found = true if permission.for == requested_permission
+ end
+
+ return rest_response(403, :reason => "OAuth token does not grant sufficient permission for this action") if permission_found == false
+ end
+
+ case rules['Type']
+ when 'index'; rest_index_request(params[:uri], params[:format], rules, user, request.query_parameters)
+ when 'crud'; rest_crud_request(params[:uri], params[:format], rules, user, request.query_parameters)
+ when 'call'; rest_call_request(params[:uri], params[:format], rules, user, request.query_parameters)
+ else; rest_response(500, :reason => "Unknown REST table type")
+ end
+ end
+end
+
Deleted: branches/api/app/models/curation_event.rb (2921 => 2924)
--- trunk/app/models/curation_event.rb 2012-01-26 13:24:17 UTC (rev 2921)
+++ branches/api/app/models/curation_event.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -1,44 +0,0 @@
-# myExperiment: app/models/curation_event.rb
-#
-# Copyright (c) 2009 University of Manchester and the University of Southampton.
-# See license.txt for details.
-
-class CurationEvent < ActiveRecord::Base
-
- belongs_to :user
- belongs_to :object, :polymorphic => true
-
- format_attribute :details
-
- validates_presence_of :user, :category
-
- def self.curation_score(events)
-
- score = 0
-
- events.each do|event|
-
- case event.category
- when 'example'
- score += 40
- when 'test'
- score += 0
- when 'component'
- score += 45
- when 'whole solution'
- score += 50
- when 'tutorial'
- score += 30
- when 'obsolete'
- score += 20
- when 'incomplete'
- score += 10
- when 'junk'
- score -= 50
- end
- end
-
- score
- end
-end
-
Copied: branches/api/app/models/curation_event.rb (from rev 2922, trunk/app/models/curation_event.rb) (0 => 2924)
--- branches/api/app/models/curation_event.rb (rev 0)
+++ branches/api/app/models/curation_event.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -0,0 +1,48 @@
+# myExperiment: app/models/curation_event.rb
+#
+# Copyright (c) 2009 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class CurationEvent < ActiveRecord::Base
+
+ belongs_to :user
+ belongs_to :object, :polymorphic => true
+
+ format_attribute :details
+
+ validates_presence_of :user, :category
+
+ def label
+ category
+ end
+
+ def self.curation_score(events)
+
+ score = 0
+
+ events.each do|event|
+
+ case event.category
+ when 'example'
+ score += 40
+ when 'test'
+ score += 0
+ when 'component'
+ score += 45
+ when 'whole solution'
+ score += 50
+ when 'tutorial'
+ score += 30
+ when 'obsolete'
+ score += 20
+ when 'incomplete'
+ score += 10
+ when 'junk'
+ score -= 50
+ end
+ end
+
+ score
+ end
+end
+
Modified: branches/api/config/tables.xml
(Binary files differ)
Deleted: branches/api/lib/rest.rb (2921 => 2924)
--- trunk/lib/rest.rb 2012-01-26 13:24:17 UTC (rev 2921)
+++ branches/api/lib/rest.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -1,2146 +0,0 @@
-# myExperiment: lib/rest.rb
-#
-# Copyright (c) 2007 University of Manchester and the University of Southampton.
-# See license.txt for details.
-
-require 'lib/conf'
-require 'lib/excel_xml'
-require 'xml/libxml'
-require 'uri'
-
-include LibXML
-
-API_VERSION = "0.1"
-
-TABLES = parse_excel_2003_xml(File.read('config/tables.xml'),
-
- { 'Model' => { :indices => [ 'REST Entity' ],
- :lists => [ 'REST Attribute', 'Encoding', 'Accessor',
- 'Create', 'Read', 'Update', 'Read by default',
- 'List Element Name', 'List Element Accessor',
- 'Example', 'Versioned', 'Key type',
- 'Limited to user', 'Permission', 'Index filter' ] },
-
- 'REST' => { :indices => [ 'URI', 'Method' ] }
- } )
-
-# Temporary removals
-
-TABLES["REST"][:data]["job"].delete("POST")
-TABLES["REST"][:data]["messages"].delete("GET")
-
-def rest_routes(map)
- TABLES['REST'][:data].keys.each do |uri|
- TABLES['REST'][:data][uri].keys.each do |method|
- formats = []
-
- formats << "xml" if TABLES['REST'][:data][uri][method]["XML"]
- formats << "rdf" if TABLES['REST'][:data][uri][method]["RDF"]
-
- formats.each do |format|
- map.connect "#{uri}.#{format}", :controller => 'api', :action ="" 'process_request', :uri => uri, :format => format
- end
- end
- end
-end
-
-def rest_response(code, args = {})
-
- if code == 401
- response.headers['WWW-Authenticate'] = "Basic realm=\"#{Conf.sitename} REST API\""
- end
-
- if code == 307
- response.headers['Location'] = args[:location]
- end
-
- message = "Unknown Error"
-
- case code
- when 200: message = "OK"
- when 307: message = "Temporary Redirect"
- when 400: message = "Bad Request"
- when 401: message = "Unauthorized"
- when 403: message = "Forbidden"
- when 404: message = "Not Found"
- when 500: message = "Internal Server Error"
- end
-
- if (code >= 300) && (code < 400)
-
- doc = ""
-
- else
-
- error = LibXML::XML::Node.new('error')
- error["code" ] = code.to_s
- error["message"] = message
-
- doc = LibXML::XML::Document.new
- doc.root = error
-
- if args[:object]
- args[:object].errors.full_messages.each do |message|
- reason = LibXML::XML::Node.new('reason')
- reason << message
- doc.root << reason
- end
- end
-
- if args[:reason]
- reason = LibXML::XML::Node.new('reason')
- reason << args[:reason]
- doc.root << reason
- end
- end
-
- render(:xml => doc.to_s, :status => "#{code} #{message}")
-end
-
-def resource_preview_url(ob, type)
- url = ""
- url.path << "/versions/#{ob.current_version}" if ob.respond_to?('current_version')
- url.path << "/previews/#{type}"
- url.to_s
-end
-
-def model_entity_to_rest_entity(model_entity)
- TABLES['Model'][:data].each do |k,v|
- return k if v['Model Entity'] == model_entity
- end
-
- nil
-end
-
-def rest_get_element(ob, user, rest_entity, rest_attribute, query, elements)
-
- # puts "rest_get_element: #{rest_entity} / #{rest_attribute}"
-
- model_data = TABLES['Model'][:data][rest_entity]
-
- i = model_data['REST Attribute'].index(rest_attribute)
-
- # is this attributed limited to a particular user?
-
- limited_to_user = model_data['Limited to user'][i]
-
- if not limited_to_user.nil?
- if limited_to_user == 'self'
- limited_ob = ob
- else
- limited_ob = eval("ob.#{limited_to_user}")
- end
-
- return nil if limited_ob != user
- end
-
- permission = model_data['Permission'][i]
-
- if permission
- return nil if !Authorization.is_authorized?(permission, nil, ob, user)
- end
-
- unless query['all_elements'] == 'yes'
- return nil if elements and not elements.index(model_data['REST Attribute'][i])
- return nil if not elements and model_data['Read by default'][i] == 'no'
- end
-
- if (model_data['Read'][i] == 'yes')
-
- accessor = model_data['Accessor'][i]
-
- text = ''
- attrs = {}
-
- case model_data['Encoding'][i]
-
- when 'list', 'item as list'
-
- list_element = LibXML::XML::Node.new(model_data['REST Attribute'][i])
-
- attrs.each do |key,value|
- list_element[key] = value
- end
-
- collection = eval("ob.#{model_data['Accessor'][i]}")
-
- collection = [collection] if model_data['Encoding'][i] == 'item as list'
-
- # filter out things that the user cannot see
- collection = collection.select do |c|
- not c.respond_to?('contribution') or Authorization.is_authorized?("view", nil, c, user)
- end
-
- collection.each do |item|
-
- item_attrs = { }
-
- next if item.nil?
-
- item_uri = rest_resource_uri(item)
-
- item_attrs['resource'] = item_uri if item_uri
- item_attrs['uri'] = rest_access_uri(item)
-
- list_element_accessor = model_data['List Element Accessor'][i]
- list_element_text = list_element_accessor ? eval("item.#{model_data['List Element Accessor'][i]}") : item
-
- if list_element_text
- if list_element_text.instance_of?(String)
- el = LibXML::XML::Node.new(model_data['List Element Name'][i])
-
- item_attrs.each do |key,value|
- el[key] = value
- end
-
- el << list_element_text.to_s if list_element_text
-
- list_element << el
- else
- list_element << rest_reference(list_element_text, query)
- end
- end
- end
-
- list_element
-
- when 'xml'
-
- if query['version'] and model_data['Versioned'][i] == 'yes'
- text = eval("ob.find_version(#{query['version']}).#{accessor}")
- else
- text = eval("ob.#{accessor}")
- end
-
- text
-
- when 'url'
-
- element = LibXML::XML::Node.new(model_data['REST Attribute'][i])
-
- element << eval("#{model_data['Accessor'][i]}(ob)")
-
- element
-
- when 'call'
-
- eval("#{model_data['Accessor'][i]}(ob, user, query)")
-
- when 'item'
-
- el = LibXML::XML::Node.new(model_data['REST Attribute'][i])
-
- item = eval("ob.#{model_data['Accessor'][i]}")
-
- if item != nil
- resource_uri = rest_resource_uri(item)
- el['resource'] = resource_uri if resource_uri
- el['uri'] = rest_access_uri(item)
- el << item.label if item.respond_to?(:label) && item.label
- end
-
- el
-
- else
-
- if model_data['Encoding'][i] == 'preview'
-
- text = resource_preview_url(ob, model_data['Accessor'][i])
-
- else
-
- text = ""
-
- if accessor
- if query['version'] and model_data['Versioned'][i] == 'yes'
- text = eval("ob.find_version(#{query['version']}).#{accessor}").to_s
- else
-
- val = eval("ob.#{accessor}")
-
- if val.class == ActiveSupport::TimeWithZone
- text = val.time().to_s
- else
- text = val.to_s
- end
- end
- end
-
- if model_data['Encoding'][i] == 'base64'
- text = Base64.encode64(text)
- attrs = { 'type' => 'binary', 'encoding' => 'base64' }
- end
- end
-
- # puts "ATTRIBUTE = #{model_data['REST Attribute'][i]}, ATTRS = #{attrs.inspect}, text = #{text.inspect}"
-
- el = LibXML::XML::Node.new(model_data['REST Attribute'][i])
-
- attrs.each do |key,value|
- el[key] = value if value
- end
-
- el << text
- el
- end
- end
-end
-
-def rest_get_request(ob, req_uri, user, uri, entity_name, query)
-
- if query['version']
- return rest_response(400, :reason => "Object does not support versioning") unless ob.respond_to?('versions')
- return rest_response(404, :reason => "Specified version does not exist") if query['version'].to_i < 1
- end
-
- elements = query['elements'] ? query['elements'].split(',') : nil
-
- doc = LibXML::XML::Document.new()
- root = LibXML::XML::Node.new(entity_name)
- doc.root = root
-
- root['uri' ] = rest_access_uri(ob)
- root['resource' ] = uri if uri
- root['api-version'] = API_VERSION if query['api_version'] == 'yes'
-
- if ob.respond_to?('versions')
- if query['version']
- root['version'] = query['version']
- else
- root['version'] = ob.current_version.to_s
- end
- end
-
- data = ""
-
- rest_entity = data['REST Entity']
-
- TABLES['Model'][:data][rest_entity]['REST Attribute'].each do |rest_attribute|
- data = "" user, rest_entity, rest_attribute, query, elements)
- root << data unless data.nil?
- end
-
- render(:xml => doc.to_s)
-end
-
-def rest_crud_request(req_uri, format, rules, user, query)
-
- rest_name = rules['REST Entity']
- model_name = rules['Model Entity']
-
- ob = eval(model_name.camelize).find_by_id(params[:id].to_i)
-
- return rest_response(404, :reason => "Object not found") if ob.nil?
-
- perm_ob = ob
-
- perm_ob = ob.send(rules['Permission object']) if rules['Permission object']
-
- case rules['Permission']
- when 'public'; # do nothing
- when 'view'; return rest_response(401, :reason => "Not authorised") if not Authorization.is_authorized?("show", nil, perm_ob, user)
- when 'owner'; return rest_response(401, :reason => "Not authorised") if logged_in?.nil? or object_owner(perm_ob) != user
- end
-
- rest_get_request(ob, params[:uri], user, eval("rest_resource_uri(ob)"), rest_name, query)
-end
-
-def find_paginated_auth(args, num, page, filters, user, &blk)
-
- def aux(args, num, page, filters, user)
-
- results = yield(args, num, page)
-
- return nil if results.nil?
-
- failures = 0
-
- results.select do |result|
-
- selected = Authorization.is_authorized?('view', nil, result, user)
-
- if selected
- filters.each do |attribute, bits|
-
- lhs = eval("result.#{bits[:accessor]}")
- rhs = bits[:value]
-
- lhs = lhs.downcase if lhs.class == String
- rhs = rhs.downcase if rhs.class == String
-
- selected = false unless lhs == rhs
- end
- end
-
- selected
- end
- end
-
- # 'upto' is the number of results needed to fulfil the request
-
- upto = num * page
-
- results = []
- current_page = 1
-
- # if this isn't the first page, do a single request to fetch all the pages
- # up to possibly fulfil the request
-
- if (page > 1)
- results = aux(args, upto, 1, filters, user, &blk)
- current_page = page + 1
- end
-
- while (results.length < upto)
-
- results_page = aux(args, num, current_page, filters, user, &blk)
-
- if results_page.nil?
- break
- else
- results += results_page
- current_page += 1
- end
- end
-
- range = results[num * (page - 1)..(num * page) - 1]
- range = [] if range.nil?
- range
-end
-
-def rest_index_request(req_uri, format, rules, user, query)
-
- rest_name = rules['REST Entity']
- model_name = rules['Model Entity']
-
- default_limit = 25
- default_page = 1
-
- max_limit = 100
- min_limit = 1
-
- limit = query['num'] ? query['num'].to_i : default_limit
- page = query['page'] ? query['page'].to_i : default_page
-
- limit = min_limit if limit < min_limit
- limit = max_limit if limit > max_limit
-
- page = 1 if page < 1
-
- model = TABLES["Model"][:data][TABLES["REST"][:data][req_uri]["GET"]["REST Entity"]]
-
- # detect filters
-
- filters = {}
-
- (0..model["REST Attribute"].length - 1).each do |i|
-
- if model["Index filter"][i]
-
- attribute = model["REST Attribute"][i]
- filter_name = attribute.gsub("-", "_")
-
- if query[filter_name]
-
- filter = { :accessor => model["Accessor"][i] }
-
- if model["Encoding"][i] == 'item' || model["Encoding"][i] == 'item as list'
- filter[:value] = get_resource_from_uri(query[filter_name], user)
- else
- filter[:value] = query[filter_name]
- end
-
- filters[attribute] = filter
- end
- end
- end
-
- if query['tag']
- tag = Tag.find_by_name(query['tag'])
-
- if tag
- obs = (tag.taggings.select do |t| t.taggable_type == model_name.camelize end).map do |t| t.taggable end
- else
- obs = []
- end
- else
-
- sort = 'id'
- order = 'ASC'
- conditions = model_index_conditions(model_name)
-
- case query['sort']
- when 'created'; sort = 'created_at' if eval(model_name.camelize).new.respond_to?('created_at')
- when 'updated'; sort = 'updated_at' if eval(model_name.camelize).new.respond_to?('updated_at')
- when 'title'; sort = 'title' if eval(model_name.camelize).new.respond_to?('title')
- when 'name'; sort = 'name' if eval(model_name.camelize).new.respond_to?('name')
- end
-
- order = 'DESC' if query['order'] == 'reverse'
-
- find_args = { :order => "#{sort} #{order}" }
-
- find_args[:conditions] = conditions if conditions
-
- obs = find_paginated_auth( { :model => model_name.camelize, :find_args => find_args }, limit, page, filters, user) { |args, size, page|
-
- find_args = args[:find_args].clone
- find_args[:page] = { :size => size, :current => page }
-
- results = eval(args[:model]).find(:all, find_args)
-
- results unless results.page > results.page_count
- }
- end
-
- produce_rest_list(req_uri, rules, query, obs, rest_name.pluralize, [], user)
-end
-
-def produce_rest_list(req_uri, rules, query, obs, tag, attributes, user)
-
- root = LibXML::XML::Node.new(tag)
-
- root['api-version'] = API_VERSION if query['api_version'] == 'yes'
-
- attributes.each do |k,v|
- root[k] = v
- end
-
- elements = query['elements'] ? query['elements'].split(',') : nil
-
- obs.each do |ob|
-
- el = rest_reference(ob, query, !elements.nil?)
-
- if elements
-
- rest_entity = model_entity_to_rest_entity(ob.class.name)
-
- TABLES['Model'][:data][rest_entity]['REST Attribute'].each do |rest_attribute|
- data = "" user, rest_entity, rest_attribute, query, elements)
- el << data unless data.nil?
- end
- end
-
- root << el
- end
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- render(:xml => doc.to_s)
-end
-
-def object_owner(ob)
- return User.find(ob.to) if ob.class == Message
- return ob.user if ob.respond_to?("user")
- return ob.owner if ob.respond_to?("owner")
-end
-
-def model_index_conditions(model_name)
- case model_name
- when 'user'; return 'users.activated_at IS NOT NULL'
- end
-end
-
-def rest_resource_uri(ob)
-
- case ob.class.name
- when 'Workflow'; return workflow_url(ob)
- when 'Blob'; return blob_url(ob)
- when 'Network'; return network_url(ob)
- when 'User'; return user_url(ob)
- when 'Review'; return workflow_review_url(ob.reviewable, ob)
- when 'Comment'; return "#{rest_resource_uri(ob.commentable)}/comments/#{ob.id}"
- when 'Bookmark'; return nil
- when 'Blog'; return blog_url(ob)
- when 'BlogPost'; return blog_blog_post_url(ob.blog, ob)
- when 'Rating'; return "#{rest_resource_uri(ob.rateable)}/ratings/#{ob.id}"
- when 'Tag'; return tag_url(ob)
- when 'Picture'; return user_picture_url(ob.owner, ob)
- when 'Message'; return message_url(ob)
- when 'Citation'; return workflow_citation_url(ob.workflow, ob)
- when 'Announcement'; return announcement_url(ob)
- when 'Pack'; return pack_url(ob)
- when 'Experiment'; return experiment_url(ob)
- when 'TavernaEnactor'; return runner_url(ob)
- when 'Job'; return experiment_job_url(ob.experiment, ob)
- when 'PackContributableEntry'; return ob.contributable ? rest_resource_uri(ob.contributable) : nil
- when 'PackRemoteEntry'; return ob.uri
- when 'ContentType'; return content_type_url(ob)
- when 'License'; return license_url(ob)
- when 'CurationEvent'; return nil
- 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 'Workflow::Version'; return "#{rest_resource_uri(ob.workflow)}?version=#{ob.version}"
- end
-
- raise "Class not processed in rest_resource_uri: #{ob.class.to_s}"
-end
-
-def rest_access_uri(ob)
-
- base = "#{request.protocol}#{request.host_with_port}"
-
- case ob.class.name
- when 'Workflow'; return "#{base}/workflow.xml?id=#{ob.id}"
- when 'Blob'; return "#{base}/file.xml?id=#{ob.id}"
- when 'Network'; return "#{base}/group.xml?id=#{ob.id}"
- when 'User'; return "#{base}/user.xml?id=#{ob.id}"
- when 'Review'; return "#{base}/review.xml?id=#{ob.id}"
- when 'Comment'; return "#{base}/comment.xml?id=#{ob.id}"
- when 'Bookmark'; return "#{base}/favourite.xml?id=#{ob.id}"
- when 'Blog'; return "#{base}/blog.xml?id=#{ob.id}"
- when 'BlogPost'; return "#{base}/blog-post.xml?id=#{ob.id}"
- when 'Rating'; return "#{base}/rating.xml?id=#{ob.id}"
- when 'Tag'; return "#{base}/tag.xml?id=#{ob.id}"
- when 'Picture'; return "#{base}/picture.xml?id=#{ob.id}"
- when 'Message'; return "#{base}/message.xml?id=#{ob.id}"
- when 'Citation'; return "#{base}/citation.xml?id=#{ob.id}"
- when 'Announcement'; return "#{base}/announcement.xml?id=#{ob.id}"
- when 'Pack'; return "#{base}/pack.xml?id=#{ob.id}"
- when 'Experiment'; return "#{base}/experiment.xml?id=#{ob.id}"
- when 'TavernaEnactor'; return "#{base}/runner.xml?id=#{ob.id}"
- when 'Job'; return "#{base}/job.xml?id=#{ob.id}"
- when 'Download'; return "#{base}/download.xml?id=#{ob.id}"
- when 'PackContributableEntry'; return "#{base}/internal-pack-item.xml?id=#{ob.id}"
- when 'PackRemoteEntry'; return "#{base}/external-pack-item.xml?id=#{ob.id}"
- when 'Tagging'; return "#{base}/tagging.xml?id=#{ob.id}"
- when 'ContentType'; return "#{base}/type.xml?id=#{ob.id}"
- when 'License'; return "#{base}/license.xml?id=#{ob.id}"
- when 'CurationEvent'; return "#{base}/curation-event.xml?id=#{ob.id}"
- when 'Ontology'; return "#{base}/ontology.xml?id=#{ob.id}"
- when 'Predicate'; return "#{base}/predicate.xml?id=#{ob.id}"
- when 'Relationship'; return "#{base}/relationship.xml?id=#{ob.id}"
-
- when 'Creditation'; return "#{base}/credit.xml?id=#{ob.id}"
- when 'Attribution'; return nil
-
- when 'Workflow::Version'; return "#{base}/workflow.xml?id=#{ob.workflow.id}&version=#{ob.version}"
- end
-
- raise "Class not processed in rest_access_uri: #{ob.class.to_s}"
-end
-
-def rest_object_tag_text(ob)
-
- case ob.class.name
- when 'User'; return 'user'
- when 'Workflow'; return 'workflow'
- when 'Blob'; return 'file'
- when 'Network'; return 'group'
- when 'Rating'; return 'rating'
- when 'Creditation'; return 'credit'
- when 'Citation'; return 'citation'
- when 'Announcement'; return 'announcement'
- when 'Tag'; return 'tag'
- when 'Tagging'; return 'tagging'
- when 'Pack'; return 'pack'
- when 'Experiment'; return 'experiment'
- when 'Download'; return 'download'
- when 'PackContributableEntry'; return rest_object_tag_text(ob.contributable)
- when 'PackRemoteEntry'; return 'external'
- when 'Workflow::Version'; return 'workflow'
- when 'Comment'; return 'comment'
- when 'Bookmark'; return 'favourite'
- when 'ContentType'; return 'type'
- when 'License'; return 'license'
- when 'CurationEvent'; return 'curation-event'
- when 'Ontology'; return 'ontology'
- when 'Predicate'; return 'predicate'
- when 'Relationship'; return 'relationship'
- end
-
- return 'object'
-end
-
-def rest_object_label_text(ob)
-
- case ob.class.name
- when 'User'; return ob.name
- when 'Workflow'; return ob.title
- when 'Blob'; return ob.title
- when 'Network'; return ob.title
- when 'Rating'; return ob.rating.to_s
- when 'Creditation'; return ''
- when 'Citation'; return ob.title
- when 'Announcement'; return ob.title
- when 'Tag'; return ob.name
- when 'Tagging'; return ob.tag.name
- when 'Pack'; return ob.title
- when 'Experiment'; return ob.title
- when 'Download'; return ''
- when 'PackContributableEntry'; return rest_object_label_text(ob.contributable)
- when 'PackRemoteEntry'; return ob.title
- when 'Workflow::Version'; return ob.title
- when 'ContentType'; return ob.title
- when 'License'; return ob.title
- when 'CurationEvent'; return ob.category
- when 'Ontology'; return ob.title
- when 'Predicate'; return ob.title
- when 'Relationship'; return ''
- end
-
- return ''
-end
-
-def rest_reference(ob, query, skip_text = false)
-
- el = LibXML::XML::Node.new(rest_object_tag_text(ob))
-
- resource_uri = rest_resource_uri(ob)
-
- el['resource'] = resource_uri if resource_uri
- el['uri' ] = rest_access_uri(ob)
- el['version' ] = ob.current_version.to_s if ob.respond_to?('current_version')
-
- el << rest_object_label_text(ob) if !skip_text
-
- el
-end
-
-def parse_resource_uri(str)
-
- base_uri = URI.parse("#{Conf.base_uri}/")
- uri = base_uri.merge(str)
- is_local = base_uri.host == uri.host and base_uri.port == uri.port
-
- return [Workflow, $1, is_local] if uri.path =~ /^\/workflows\/([\d]+)$/
- return [Blob, $1, is_local] if uri.path =~ /^\/files\/([\d]+)$/
- return [Network, $1, is_local] if uri.path =~ /^\/groups\/([\d]+)$/
- return [User, $1, is_local] if uri.path =~ /^\/users\/([\d]+)$/
- return [Review, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/reviews\/([\d]+)$/
- return [Comment, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/comments\/([\d]+)$/
- return [Blog, $1, is_local] if uri.path =~ /^\/blogs\/([\d]+)$/
- return [BlogPost, $1, is_local] if uri.path =~ /^\/blogs\/[\d]+\/blog_posts\/([\d]+)$/
- return [Tag, $1, is_local] if uri.path =~ /^\/tags\/([\d]+)$/
- return [Picture, $1, is_local] if uri.path =~ /^\/users\/[\d]+\/pictures\/([\d]+)$/
- return [Message, $1, is_local] if uri.path =~ /^\/messages\/([\d]+)$/
- return [Citation, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/citations\/([\d]+)$/
- return [Announcement, $1, is_local] if uri.path =~ /^\/announcements\/([\d]+)$/
- return [Pack, $1, is_local] if uri.path =~ /^\/packs\/([\d]+)$/
- return [Experiment, $1, is_local] if uri.path =~ /^\/experiments\/([\d]+)$/
- return [TavernaEnactor, $1, is_local] if uri.path =~ /^\/runners\/([\d]+)$/
- return [Job, $1, is_local] if uri.path =~ /^\/jobs\/([\d]+)$/
- return [Download, $1, is_local] if uri.path =~ /^\/downloads\/([\d]+)$/
- return [Ontology, $1, is_local] if uri.path =~ /^\/ontologies\/([\d]+)$/
- return [Predicate, $1, is_local] if uri.path =~ /^\/predicates\/([\d]+)$/
-
- nil
-
-end
-
-def get_resource_from_uri(uri, user)
-
- cl, id, local = parse_resource_uri(uri)
-
- return nil if cl.nil? || local == false
-
- resource = cl.find_by_id(id)
-
- return nil if !Authorization.is_authorized?('view', nil, resource, user)
-
- resource
-end
-
-def resolve_resource_node(resource_node, user = nil, permission = nil)
-
- return nil if resource_node.nil?
-
- attr = resource_node.find_first('@resource')
-
- return nil if attr.nil?
-
- resource_uri = attr.value
-
- resource_bits = parse_resource_uri(resource_uri)
-
- return nil if resource_bits.nil?
-
- resource = resource_bits[0].find_by_id(resource_bits[1].to_i)
-
- return nil if resource.nil?
-
- if permission
- return nil if !Authorization.is_authorized?(permission, nil, resource, user)
- end
-
- resource
-end
-
-def obtain_rest_resource(type, id, version, user, permission = nil)
-
- resource = eval(type).find_by_id(id)
-
- if resource.nil?
- rest_response(404, :reason => "Couldn't find a #{type} with id #{id}")
- return nil
- end
-
- if version
- if resource.versions.last.version != version.to_i
- resource = resource.find_version(version)
- end
- end
-
- if resource.nil?
- rest_response(404, :reason => "#{type} #{id} does not have a version #{version}")
- return nil
- end
-
- if permission
- if !Authorization.is_authorized?(permission, nil, resource, user)
- rest_response(401, :reason => "Not authorised for #{type} #{id}")
- return nil
- end
- end
-
- resource
-end
-
-def rest_access_redirect(opts = {})
-
- return rest_response(400, :reason => "Resource was not specified") if opts[:query]['resource'].nil?
-
- bits = parse_resource_uri(opts[:query]['resource'])
-
- return rest_response(404, :reason => "Didn't understand the format of the specified resource") if bits.nil?
-
- ob = bits[0].find_by_id(bits[1])
-
- return rest_response(404, :reason => "The specified resource does not exist") if ob.nil?
-
- return rest_response(401, :reason => "Not authorised for the specified resource") if !Authorization.is_authorized?('view', nil, ob, opts[:user])
-
- rest_response(307, :location => rest_access_uri(ob))
-end
-
-def create_default_policy(user)
- Policy.new(:contributor => user, :name => 'auto', :share_mode => 7, :update_mode => 6)
-end
-
-def update_permissions(ob, permissions)
-
- share_mode = 7
- update_mode = 6
-
- # clear out any permission records for this contributable
-
- ob.contribution.policy.permissions.each do |p|
- p.destroy
- end
-
- # process permission elements
-
- if permissions
- permissions.find('permission').each do |permission|
-
- # handle public privileges
-
- if permission.find_first('category/text()').to_s == 'public'
-
- privileges = {}
-
- permission.find('privilege').each do |el|
- privileges[el['type']] = true
- end
-
- if privileges["view"] && privileges["download"]
- share_mode = 0
- elsif privileges["view"]
- share_mode = 2
- else
- share_mode = 7
- end
- end
- end
- end
-
- ob.contribution.policy.update_attributes(:share_mode => share_mode,
- :update_mode => update_mode)
-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.is_authorized_for_type?('create', 'Workflow', opts[:user], nil)
- if opts[:query]['id']
- ob = obtain_rest_resource('Workflow', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- ob = Workflow.new(:contributor => opts[:user])
- end
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Workflow', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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
-
- 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
-
- # 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 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
-
- success = if (action == 'create' and opts[:query]['id'])
- ob.save_as_new_version(revision_comment)
- else
- ob.save
- 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?
-
- if ob.contribution.policy.nil?
- ob.contribution.policy = create_default_policy(opts[:user])
- ob.contribution.save
- end
-
- update_permissions(ob, permissions)
- end
- end
-
- ob = ob.versioned_resource if ob.respond_to?("versioned_resource")
-
- rest_get_request(ob, "workflow", opts[:user],
- rest_resource_uri(ob), "workflow", { "id" => ob.id.to_s })
-end
-
-def post_workflow(opts)
- workflow_aux('create', opts)
-end
-
-def put_workflow(opts)
- workflow_aux('update', 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.is_authorized_for_type?('create', 'Blob', opts[:user], nil)
- ob = Blob.new(:contributor => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Blob', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- 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')
- content_type = parse_element(data, :text, '/file/content-type')
- content = parse_element(data, :binary, '/file/content')
-
- 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
-
- # 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
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
-
- if ob.contribution.policy.nil?
- ob.contribution.policy = create_default_policy(opts[:user])
- ob.contribution.save
- end
-
- update_permissions(ob, permissions)
- end
-
- rest_get_request(ob, "file", opts[:user],
- rest_resource_uri(ob), "file", { "id" => ob.id.to_s })
-end
-
-def post_file(opts)
- file_aux('create', opts)
-end
-
-def put_file(opts)
- file_aux('update', 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.is_authorized_for_type?('create', 'Pack', opts[:user], nil)
- ob = Pack.new(:contributor => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Pack', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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')
-
- # build the contributable
-
- ob.title = title if title
- ob.description = description if description
-
- if not ob.save
- return rest_response(400, :object => ob)
- end
-
- if ob.contribution.policy.nil?
- ob.contribution.policy = create_default_policy(opts[:user])
- ob.contribution.save
- end
-
- update_permissions(ob, permissions)
- end
-
- rest_get_request(ob, "pack", opts[:user],
- rest_resource_uri(ob), "pack", { "id" => ob.id.to_s })
-end
-
-def post_pack(opts)
- pack_aux('create', opts)
-end
-
-def put_pack(opts)
- pack_aux('update', 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.is_authorized_for_type?('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.is_authorized?('edit', nil, pack, opts[:user])
-
- ob = PackRemoteEntry.new(:user => opts[:user],
- :pack => pack,
- :title => title,
- :uri => uri,
- :alternate_uri => alternate_uri,
- :comment => comment)
-
- when 'read', 'update', 'destroy':
-
- ob = 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.is_authorized?('edit', nil, ob.pack, opts[:user])
- end
-
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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, "external-pack-item", opts[:user],
- rest_resource_uri(ob), "external-pack-item", { "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('update', 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')
- end
-
- # Obtain object
-
- case action
- when 'create':
-
- return rest_response(401, :reason => "Not authorised to create an internal pack item") unless Authorization.is_authorized_for_type?('create', 'PackContributableEntry', 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.is_authorized?('edit', nil, pack, opts[:user])
-
- ob = PackContributableEntry.new(:user => opts[:user],
- :pack => pack,
- :contributable => item,
- :comment => comment)
-
- when 'read', 'update', 'destroy':
-
- ob = obtain_rest_resource('PackContributableEntry', 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.is_authorized?('edit', nil, ob.pack, opts[:user])
- end
-
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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, "internal-pack-item", opts[:user],
- rest_resource_uri(ob), "internal-pack-item", { "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('update', 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.is_authorized?('edit', nil, experiment, opts[:user])
-# return rest_response(400) if runner.nil? or not Authorization.is_authorized?('download', nil, runner, opts[:user])
-# return rest_response(400) if runnable.nil? or not Authorization.is_authorized?('view', nil, 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 == ""
-
- find_paginated_auth( { :query => query, :models => models }, num, page, [], user) { |args, size, page|
-
- q = args[:query]
- models = args[:models]
-
- search_result = models[0].multi_solr_search(q, :limit => size, :offset => size * (page - 1), :models => models)
- search_result.results unless search_result.total < (size * (page - 1))
- }
-end
-
-def search(opts)
-
- search_query = opts[:query]['query']
-
- # Start of curation hack
-
- if search_query[0..1].downcase == 'c:' && opts[:user] &&
- Conf.curators.include?(opts[:user].username)
-
- bits = search_query.match("^c:([a-z]*) ([0-9]+)-([0-9]+)$")
-
- if bits.length == 4
-
- case bits[1]
- when 'workflows': model = Workflow
- when 'files': model = Blob
- when 'packs': model = Pack
- else return rest_response(400, :reason => "Unknown category '#{bits[1]}'")
- end
-
- obs = model.find(:all, :conditions => ['id >= ? AND id <= ?', bits[2], bits[3]])
-
- obs = (obs.select do |c| c.respond_to?('contribution') == false or Authorization.is_authorized?("view", nil, c, opts[:user]) end)
-
- return produce_rest_list(opts[:req_uri], opts[:rules], opts[:query], obs, 'search', {}, opts[:user])
- end
- end
-
- # End of curation hack
-
- models = [User, Workflow, Blob, Network, Pack]
-
- # parse type option
-
- if opts[:query]['type']
-
- models = []
-
- opts[:query]['type'].split(',').each do |type|
- case type
- when 'user'; models.push(User)
- when 'workflow'; models.push(Workflow)
- when 'file'; models.push(Blob)
- when 'group'; models.push(Network)
- when 'pack'; models.push(Pack)
-
- else return rest_response(400, :reason => "Unknown search type '#{type}'")
- end
- end
- end
-
- num = 25
-
- if opts[:query]['num']
- num = opts[:query]['num'].to_i
- end
-
- num = 25 if num < 0
- num = 100 if num > 100
-
- page = opts[:query]['page'] ? opts[:query]['page'].to_i : 1
-
- page = 1 if page < 1
-
- attributes = {}
- attributes['query'] = search_query
- attributes['type'] = opts[:query]['type'] if models.length == 1
-
- begin
- obs = paginated_search_index(search_query, models, num, page, opts[:user])
- produce_rest_list(opts[:req_uri], opts[:rules], opts[:query], obs, 'search', attributes, opts[:user])
- rescue
- rest_response(400, :reason => "Invalid search query")
- 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
-
- render(:xml => doc.to_s)
-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
-
- render(:xml => doc.to_s)
-end
-
-def workflow_count(opts)
-
- workflows = Workflow.find(:all).select do |w|
- Authorization.is_authorized?('view', nil, w, opts[:user])
- end
-
- root = LibXML::XML::Node.new('workflow-count')
- root << workflows.length.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- render(:xml => doc.to_s)
-end
-
-def pack_count(opts)
-
- packs = Pack.find(:all).select do |p|
- Authorization.is_authorized?('view', nil, p, opts[:user])
- end
-
- root = LibXML::XML::Node.new('pack-count')
- root << packs.length.to_s
-
- doc = LibXML::XML::Document.new
- doc.root = root
-
- render(:xml => doc.to_s)
-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
-
- render(:xml => doc.to_s)
-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.is_authorized?("index", nil, 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
-
- render(:xml => doc.to_s)
-end
-
-def whoami_redirect(opts)
- if opts[:user].class == User
- case opts[:format]
- when "xml": rest_response(307, :location => rest_access_uri(opts[:user]))
- when "rdf": rest_response(307, :location => formatted_user_url(:id => opts[:user].id, :format => 'rdf'))
- end
- else
- rest_response(401, :reason => "Not logged in")
- end
-end
-
-def parse_element(doc, kind, query)
- case kind
- when :text
- if doc.find_first(query)
-
- enc = doc.find_first(query)['encoding']
- el = doc.find_first("#{query}")
- text = doc.find_first("#{query}/text()")
-
- if el
- if enc == 'base64'
- return Base64::decode64(text.to_s)
- else
- return text.to_s
- end
- end
- end
- when :binary
- el = doc.find_first("#{query}")
- text = doc.find_first("#{query}/text()")
- return Base64::decode64(text.to_s) if el
- when :resource
- return resolve_resource_node(doc.find_first(query))
- end
-end
-
-# Avatar handling (to show default avatar when none present)
-
-def effective_avatar(ob, user, query)
-
- picture = ob.profile.picture
-
- if picture
- result = rest_reference(picture, query, true)
- result.name = "avatar"
- result
- else
- result = LibXML::XML::Node.new('avatar')
- result['resource'] = Conf.base_uri + '/images/avatar.png'
- result
- end
-end
-
-# Privileges
-
-def effective_privileges(ob, user, query)
-
- privileges = LibXML::XML::Node.new('privileges')
-
- ['view', 'download', 'edit'].each do |type|
- if Authorization.is_authorized?(type, nil, ob, user)
- privilege = LibXML::XML::Node.new('privilege')
- privilege['type'] = type
-
- privileges << privilege
- end
- end
-
- privileges
-end
-
-# Comments
-
-def comment_aux(action, opts)
-
- # Obtain object
-
- case action
- when 'create':
- return rest_response(401, :reason => "Not authorised to create a comment") unless Authorization.is_authorized_for_type?('create', 'Comment', opts[:user], nil)
-
- ob = Comment.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Comment', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- comment = parse_element(data, :text, '/comment/comment')
- subject = parse_element(data, :resource, '/comment/subject')
-
- 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.is_authorized_for_type?(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_save
-
- return rest_get_request(ob, "comment", opts[:user], rest_resource_uri(ob),
- "comment", { "id" => ob.id.to_s })
- end
-
- # End of curation hack
-
- return rest_response(400, :object => ob) unless ob.save
- end
-
- rest_get_request(ob, "comment", opts[:user], rest_resource_uri(ob), "comment", { "id" => ob.id.to_s })
-end
-
-def post_comment(opts)
- comment_aux('create', opts)
-end
-
-def put_comment(opts)
- comment_aux('update', opts)
-end
-
-def delete_comment(opts)
- comment_aux('destroy', opts)
-end
-
-# Favourites
-
-def favourite_aux(action, opts)
-
- # Obtain object
-
- case action
- when 'create':
- return rest_response(401, :reason => "Not authorised to create a favourite") unless Authorization.is_authorized_for_type?('create', 'Bookmark', opts[:user], nil)
-
- ob = Bookmark.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Bookmark', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- target = parse_element(data, :resource, '/favourite/object')
-
- 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.is_authorized_for_type?(action, 'Bookmark', opts[:user], target)
- ob.bookmarkable = target
- end
-
- return rest_response(400, :object => ob) unless ob.save
- end
-
- rest_get_request(ob, "favourite", opts[:user], rest_resource_uri(ob), "favourite", { "id" => ob.id.to_s })
-end
-
-def post_favourite(opts)
- favourite_aux('create', opts)
-end
-
-def put_favourite(opts)
- favourite_aux('update', opts)
-end
-
-def delete_favourite(opts)
- favourite_aux('destroy', opts)
-end
-
-# Ratings
-
-def rating_aux(action, opts)
-
- # Obtain object
-
- case action
- when 'create':
- return rest_response(401, :reason => "Not authorised to create a rating") unless Authorization.is_authorized_for_type?('create', 'Rating', opts[:user], nil)
-
- ob = Rating.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Rating', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- rating = parse_element(data, :text, '/rating/rating')
- subject = parse_element(data, :resource, '/rating/subject')
-
- 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.is_authorized_for_type?(action, 'Rating', opts[:user], subject)
- ob.rateable = subject
- end
-
- return rest_response(400, :object => ob) unless ob.save
- end
-
- rest_get_request(ob, "rating", opts[:user], rest_resource_uri(ob), "rating", { "id" => ob.id.to_s })
-end
-
-def post_rating(opts)
- rating_aux('create', opts)
-end
-
-def put_rating(opts)
- rating_aux('update', opts)
-end
-
-def delete_rating(opts)
- rating_aux('destroy', opts)
-end
-
-# Taggings
-
-def tagging_aux(action, opts)
-
- # Obtain object
-
- case action
- when 'create':
- return rest_response(401, :reason => "Not authorised to create a tagging") unless Authorization.is_authorized_for_type?('create', 'Tagging', opts[:user], nil)
-
- ob = Tagging.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Tagging', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return if ob.nil? # appropriate rest response already given
-
- if action == "destroy"
-
- ob.destroy
-
- else
-
- data = ""
-
- subject = parse_element(data, :resource, '/tagging/subject')
- label = parse_element(data, :text, '/tagging/label')
- tag = parse_element(data, :resource, '/tagging/tag')
-
- 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.is_authorized_for_type?(action, 'Rating', opts[:user], subject)
- ob.taggable = subject
- end
-
- return rest_response(400, :object => ob) unless ob.save
- end
-
- rest_get_request(ob, "tagging", opts[:user], rest_resource_uri(ob), "tagging", { "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.is_authorized_for_type?('create', 'Ontology', opts[:user], nil)
- ob = Ontology.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Ontology', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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, "ontology", opts[:user],
- rest_resource_uri(ob), "ontology", { "id" => ob.id.to_s })
-end
-
-def post_ontology(opts)
- ontology_aux('create', opts)
-end
-
-def put_ontology(opts)
- ontology_aux('update', 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.is_authorized_for_type?('create', 'Predicate', opts[:user], ontology)
- ob = Predicate.new
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Predicate', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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, "predicate", opts[:user],
- rest_resource_uri(ob), "predicate", { "id" => ob.id.to_s })
-end
-
-def post_predicate(opts)
- predicate_aux('create', opts)
-end
-
-def put_predicate(opts)
- predicate_aux('update', 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.is_authorized_for_type?('create', 'Relationship', opts[:user], context)
- ob = Relationship.new(:user => opts[:user])
- when 'read', 'update', 'destroy':
- ob = obtain_rest_resource('Relationship', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
- else
- raise "Invalid action '#{action}'"
- end
-
- return 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, "relationship", opts[:user],
- rest_resource_uri(ob), "relationship", { "id" => ob.id.to_s })
-end
-
-def post_relationship(opts)
- relationship_aux('create', opts)
-end
-
-def put_relationship(opts)
- relationship_aux('update', opts)
-end
-
-def delete_relationship(opts)
- relationship_aux('destroy', opts)
-end
-
-# Call dispatcher
-
-def rest_call_request(req_uri, format, rules, user, query)
- begin
- eval("#{rules['Function']}(:req_uri => req_uri, :format => format, :rules => rules, :user => user, :query => query)")
- rescue
- return rest_response(500)
- end
-end
-
Copied: branches/api/lib/rest.rb (from rev 2923, trunk/lib/rest.rb) (0 => 2924)
--- branches/api/lib/rest.rb (rev 0)
+++ branches/api/lib/rest.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -0,0 +1,2144 @@
+# myExperiment: lib/rest.rb
+#
+# Copyright (c) 2007 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+require 'lib/conf'
+require 'lib/excel_xml'
+require 'xml/libxml'
+require 'uri'
+
+include LibXML
+
+API_VERSION = "0.1"
+
+TABLES = parse_excel_2003_xml(File.read('config/tables.xml'),
+
+ { 'Model' => { :indices => [ 'REST Entity' ],
+ :lists => [ 'REST Attribute', 'Encoding', 'Accessor',
+ 'Create', 'Read', 'Update', 'Read by default',
+ 'List Element Name', 'List Element Accessor',
+ 'Example', 'Versioned', 'Key type',
+ 'Limited to user', 'Permission', 'Index filter' ] },
+
+ 'REST' => { :indices => [ 'URI', 'Method' ] }
+ } )
+
+# Temporary removals
+
+TABLES["REST"][:data]["job"].delete("POST")
+TABLES["REST"][:data]["messages"].delete("GET")
+
+def rest_routes(map)
+ TABLES['REST'][:data].keys.each do |uri|
+ TABLES['REST'][:data][uri].keys.each do |method|
+ formats = []
+
+ formats << "xml" if TABLES['REST'][:data][uri][method]["XML"]
+ formats << "json" if TABLES['REST'][:data][uri][method]["JSON"]
+ formats << "rdf" if TABLES['REST'][:data][uri][method]["RDF"]
+
+ formats.each do |format|
+ map.connect "#{uri}.#{format}", :controller => 'api', :action ="" 'process_request', :uri => uri, :format => format
+ end
+ end
+ end
+end
+
+def rest_response(code, args = {})
+
+ if code == 401
+ response.headers['WWW-Authenticate'] = "Basic realm=\"#{Conf.sitename} REST API\""
+ end
+
+ if code == 307
+ response.headers['Location'] = args[:location]
+ end
+
+ message = "Unknown Error"
+
+ case code
+ when 200: message = "OK"
+ when 307: message = "Temporary Redirect"
+ when 400: message = "Bad Request"
+ when 401: message = "Unauthorized"
+ when 403: message = "Forbidden"
+ when 404: message = "Not Found"
+ when 500: message = "Internal Server Error"
+ end
+
+ if (code >= 300) && (code < 400)
+
+ doc = ""
+
+ else
+
+ error = LibXML::XML::Node.new('error')
+ error["code" ] = code.to_s
+ error["message"] = message
+
+ doc = LibXML::XML::Document.new
+ doc.root = error
+
+ if args[:object]
+ args[:object].errors.full_messages.each do |message|
+ reason = LibXML::XML::Node.new('reason')
+ reason << message
+ doc.root << reason
+ end
+ end
+
+ if args[:reason]
+ reason = LibXML::XML::Node.new('reason')
+ reason << args[:reason]
+ doc.root << reason
+ end
+ end
+
+ { :xml => doc.to_s, :status => "#{code} #{message}" }
+end
+
+def resource_preview_url(ob, type)
+ url = ""
+ url.path << "/versions/#{ob.current_version}" if ob.respond_to?('current_version')
+ url.path << "/previews/#{type}"
+ url.to_s
+end
+
+def model_entity_to_rest_entity(model_entity)
+ TABLES['Model'][:data].each do |k,v|
+ return k if v['Model Entity'] == model_entity
+ end
+
+ nil
+end
+
+def rest_get_element(ob, user, rest_entity, rest_attribute, query, elements)
+
+ # puts "rest_get_element: #{rest_entity} / #{rest_attribute}"
+
+ model_data = TABLES['Model'][:data][rest_entity]
+
+ i = model_data['REST Attribute'].index(rest_attribute)
+
+ # is this attributed limited to a particular user?
+
+ limited_to_user = model_data['Limited to user'][i]
+
+ if not limited_to_user.nil?
+ if limited_to_user == 'self'
+ limited_ob = ob
+ else
+ limited_ob = eval("ob.#{limited_to_user}")
+ end
+
+ return nil if limited_ob != user
+ end
+
+ permission = model_data['Permission'][i]
+
+ if permission
+ return nil if !Authorization.is_authorized?(permission, nil, ob, user)
+ end
+
+ unless query['all_elements'] == 'yes'
+ return nil if elements and not elements.index(model_data['REST Attribute'][i])
+ return nil if not elements and model_data['Read by default'][i] == 'no'
+ end
+
+ if (model_data['Read'][i] == 'yes')
+
+ accessor = model_data['Accessor'][i]
+
+ text = ''
+ attrs = {}
+
+ case model_data['Encoding'][i]
+
+ when 'list', 'item as list'
+
+ list_element = LibXML::XML::Node.new(model_data['REST Attribute'][i])
+
+ attrs.each do |key,value|
+ list_element[key] = value
+ end
+
+ collection = eval("ob.#{model_data['Accessor'][i]}")
+
+ collection = [collection] if model_data['Encoding'][i] == 'item as list'
+
+ # filter out things that the user cannot see
+ collection = collection.select do |c|
+ not c.respond_to?('contribution') or Authorization.is_authorized?("view", nil, c, user)
+ end
+
+ collection.each do |item|
+
+ item_attrs = { }
+
+ next if item.nil?
+
+ item_uri = rest_resource_uri(item)
+
+ item_attrs['resource'] = item_uri if item_uri
+ item_attrs['uri'] = rest_access_uri(item)
+
+ list_element_accessor = model_data['List Element Accessor'][i]
+ list_element_text = list_element_accessor ? eval("item.#{model_data['List Element Accessor'][i]}") : item
+
+ if list_element_text
+ if list_element_text.instance_of?(String)
+ el = LibXML::XML::Node.new(model_data['List Element Name'][i])
+
+ item_attrs.each do |key,value|
+ el[key] = value
+ end
+
+ el << list_element_text.to_s if list_element_text
+
+ list_element << el
+ else
+ list_element << rest_reference(list_element_text, query)
+ end
+ end
+ end
+
+ list_element
+
+ when 'xml'
+
+ if query['version'] and model_data['Versioned'][i] == 'yes'
+ text = eval("ob.find_version(#{query['version']}).#{accessor}")
+ else
+ text = eval("ob.#{accessor}")
+ end
+
+ text
+
+ when 'url'
+
+ element = LibXML::XML::Node.new(model_data['REST Attribute'][i])
+
+ element << eval("#{model_data['Accessor'][i]}(ob)")
+
+ element
+
+ when 'call'
+
+ eval("#{model_data['Accessor'][i]}(ob, user, query)")
+
+ when 'item'
+
+ el = LibXML::XML::Node.new(model_data['REST Attribute'][i])
+
+ item = eval("ob.#{model_data['Accessor'][i]}")
+
+ if item != nil
+ resource_uri = rest_resource_uri(item)
+ el['resource'] = resource_uri if resource_uri
+ el['uri'] = rest_access_uri(item)
+ el << item.label if item.respond_to?(:label) && item.label
+ end
+
+ el
+
+ else
+
+ if model_data['Encoding'][i] == 'preview'
+
+ text = resource_preview_url(ob, model_data['Accessor'][i])
+
+ else
+
+ text = ""
+
+ if accessor
+ if query['version'] and model_data['Versioned'][i] == 'yes'
+ text = eval("ob.find_version(#{query['version']}).#{accessor}").to_s
+ else
+
+ val = eval("ob.#{accessor}")
+
+ if val.class == ActiveSupport::TimeWithZone
+ text = val.time().to_s
+ else
+ text = val.to_s
+ end
+ end
+ end
+
+ if model_data['Encoding'][i] == 'base64'
+ text = Base64.encode64(text)
+ attrs = { 'type' => 'binary', 'encoding' => 'base64' }
+ end
+ end
+
+ # puts "ATTRIBUTE = #{model_data['REST Attribute'][i]}, ATTRS = #{attrs.inspect}, text = #{text.inspect}"
+
+ el = LibXML::XML::Node.new(model_data['REST Attribute'][i])
+
+ attrs.each do |key,value|
+ el[key] = value if value
+ end
+
+ el << text
+ el
+ end
+ end
+end
+
+def rest_get_request(ob, req_uri, user, uri, entity_name, query)
+
+ if query['version']
+ return rest_response(400, :reason => "Object does not support versioning") unless ob.respond_to?('versions')
+ return rest_response(404, :reason => "Specified version does not exist") if query['version'].to_i < 1
+ end
+
+ elements = query['elements'] ? query['elements'].split(',') : nil
+
+ doc = LibXML::XML::Document.new()
+ root = LibXML::XML::Node.new(entity_name)
+ doc.root = root
+
+ root['uri' ] = rest_access_uri(ob)
+ root['resource' ] = uri if uri
+ root['api-version'] = API_VERSION if query['api_version'] == 'yes'
+
+ if ob.respond_to?('versions')
+ if query['version']
+ root['version'] = query['version']
+ else
+ root['version'] = ob.current_version.to_s
+ end
+ end
+
+ data = ""
+
+ rest_entity = data['REST Entity']
+
+ TABLES['Model'][:data][rest_entity]['REST Attribute'].each do |rest_attribute|
+ data = "" user, rest_entity, rest_attribute, query, elements)
+ root << data unless data.nil?
+ end
+
+ { :xml => doc }
+end
+
+def rest_crud_request(req_uri, format, rules, user, query)
+
+ rest_name = rules['REST Entity']
+ model_name = rules['Model Entity']
+
+ ob = eval(model_name.camelize).find_by_id(params[:id].to_i)
+
+ return rest_response(404, :reason => "Object not found") if ob.nil?
+
+ perm_ob = ob
+
+ perm_ob = ob.send(rules['Permission object']) if rules['Permission object']
+
+ case rules['Permission']
+ when 'public'; # do nothing
+ when 'view'; return rest_response(401, :reason => "Not authorised") if not Authorization.is_authorized?("show", nil, perm_ob, user)
+ when 'owner'; return rest_response(401, :reason => "Not authorised") if logged_in?.nil? or object_owner(perm_ob) != user
+ end
+
+ rest_get_request(ob, params[:uri], user, eval("rest_resource_uri(ob)"), rest_name, query)
+end
+
+def find_paginated_auth(args, num, page, filters, user, &blk)
+
+ def aux(args, num, page, filters, user)
+
+ results = yield(args, num, page)
+
+ return nil if results.nil?
+
+ failures = 0
+
+ results.select do |result|
+
+ selected = Authorization.is_authorized?('view', nil, result, user)
+
+ if selected
+ filters.each do |attribute, bits|
+
+ lhs = eval("result.#{bits[:accessor]}")
+ rhs = bits[:value]
+
+ lhs = lhs.downcase if lhs.class == String
+ rhs = rhs.downcase if rhs.class == String
+
+ selected = false unless lhs == rhs
+ end
+ end
+
+ selected
+ end
+ end
+
+ # 'upto' is the number of results needed to fulfil the request
+
+ upto = num * page
+
+ results = []
+ current_page = 1
+
+ # if this isn't the first page, do a single request to fetch all the pages
+ # up to possibly fulfil the request
+
+ if (page > 1)
+ results = aux(args, upto, 1, filters, user, &blk)
+ current_page = page + 1
+ end
+
+ while (results.length < upto)
+
+ results_page = aux(args, num, current_page, filters, user, &blk)
+
+ if results_page.nil?
+ break
+ else
+ results += results_page
+ current_page += 1
+ end
+ end
+
+ range = results[num * (page - 1)..(num * page) - 1]
+ range = [] if range.nil?
+ range
+end
+
+def rest_index_request(req_uri, format, rules, user, query)
+
+ rest_name = rules['REST Entity']
+ model_name = rules['Model Entity']
+
+ default_limit = 25
+ default_page = 1
+
+ max_limit = 100
+ min_limit = 1
+
+ limit = query['num'] ? query['num'].to_i : default_limit
+ page = query['page'] ? query['page'].to_i : default_page
+
+ limit = min_limit if limit < min_limit
+ limit = max_limit if limit > max_limit
+
+ page = 1 if page < 1
+
+ model = TABLES["Model"][:data][TABLES["REST"][:data][req_uri]["GET"]["REST Entity"]]
+
+ # detect filters
+
+ filters = {}
+
+ (0..model["REST Attribute"].length - 1).each do |i|
+
+ if model["Index filter"][i]
+
+ attribute = model["REST Attribute"][i]
+ filter_name = attribute.gsub("-", "_")
+
+ if query[filter_name]
+
+ filter = { :accessor => model["Accessor"][i] }
+
+ if model["Encoding"][i] == 'item' || model["Encoding"][i] == 'item as list'
+ filter[:value] = get_resource_from_uri(query[filter_name], user)
+ else
+ filter[:value] = query[filter_name]
+ end
+
+ filters[attribute] = filter
+ end
+ end
+ end
+
+ if query['tag']
+ tag = Tag.find_by_name(query['tag'])
+
+ if tag
+ obs = (tag.taggings.select do |t| t.taggable_type == model_name.camelize end).map do |t| t.taggable end
+ else
+ obs = []
+ end
+ else
+
+ sort = 'id'
+ order = 'ASC'
+ conditions = model_index_conditions(model_name)
+
+ case query['sort']
+ when 'created'; sort = 'created_at' if eval(model_name.camelize).new.respond_to?('created_at')
+ when 'updated'; sort = 'updated_at' if eval(model_name.camelize).new.respond_to?('updated_at')
+ when 'title'; sort = 'title' if eval(model_name.camelize).new.respond_to?('title')
+ when 'name'; sort = 'name' if eval(model_name.camelize).new.respond_to?('name')
+ end
+
+ order = 'DESC' if query['order'] == 'reverse'
+
+ find_args = { :order => "#{sort} #{order}" }
+
+ find_args[:conditions] = conditions if conditions
+
+ obs = find_paginated_auth( { :model => model_name.camelize, :find_args => find_args }, limit, page, filters, user) { |args, size, page|
+
+ find_args = args[:find_args].clone
+ find_args[:page] = { :size => size, :current => page }
+
+ results = eval(args[:model]).find(:all, find_args)
+
+ results unless results.page > results.page_count
+ }
+ end
+
+ produce_rest_list(req_uri, rules, query, obs, rest_name.pluralize, [], user)
+end
+
+def produce_rest_list(req_uri, rules, query, obs, tag, attributes, user)
+
+ root = LibXML::XML::Node.new(tag)
+
+ root['api-version'] = API_VERSION if query['api_version'] == 'yes'
+
+ attributes.each do |k,v|
+ root[k] = v
+ end
+
+ elements = query['elements'] ? query['elements'].split(',') : nil
+
+ obs.each do |ob|
+
+ el = rest_reference(ob, query, !elements.nil?)
+
+ if elements
+
+ rest_entity = model_entity_to_rest_entity(ob.class.name)
+
+ TABLES['Model'][:data][rest_entity]['REST Attribute'].each do |rest_attribute|
+ data = "" user, rest_entity, rest_attribute, query, elements)
+ el << data unless data.nil?
+ end
+ end
+
+ root << el
+ end
+
+ doc = LibXML::XML::Document.new
+ doc.root = root
+
+ { :xml => doc }
+end
+
+def object_owner(ob)
+ return User.find(ob.to) if ob.class == Message
+ return ob.user if ob.respond_to?("user")
+ return ob.owner if ob.respond_to?("owner")
+end
+
+def model_index_conditions(model_name)
+ case model_name
+ when 'user'; return 'users.activated_at IS NOT NULL'
+ end
+end
+
+def rest_resource_uri(ob)
+
+ case ob.class.name
+ when 'Workflow'; return workflow_url(ob)
+ when 'Blob'; return blob_url(ob)
+ when 'Network'; return network_url(ob)
+ when 'User'; return user_url(ob)
+ when 'Review'; return workflow_review_url(ob.reviewable, ob)
+ when 'Comment'; return "#{rest_resource_uri(ob.commentable)}/comments/#{ob.id}"
+ when 'Bookmark'; return nil
+ when 'Blog'; return blog_url(ob)
+ when 'BlogPost'; return blog_blog_post_url(ob.blog, ob)
+ when 'Rating'; return "#{rest_resource_uri(ob.rateable)}/ratings/#{ob.id}"
+ when 'Tag'; return tag_url(ob)
+ when 'Picture'; return user_picture_url(ob.owner, ob)
+ when 'Message'; return message_url(ob)
+ when 'Citation'; return workflow_citation_url(ob.workflow, ob)
+ when 'Announcement'; return announcement_url(ob)
+ when 'Pack'; return pack_url(ob)
+ when 'Experiment'; return experiment_url(ob)
+ when 'TavernaEnactor'; return runner_url(ob)
+ when 'Job'; return experiment_job_url(ob.experiment, ob)
+ when 'PackContributableEntry'; return ob.contributable ? rest_resource_uri(ob.contributable) : nil
+ when 'PackRemoteEntry'; return ob.uri
+ when 'ContentType'; return content_type_url(ob)
+ when 'License'; return license_url(ob)
+ when 'CurationEvent'; return nil
+ 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 'Workflow::Version'; return "#{rest_resource_uri(ob.workflow)}?version=#{ob.version}"
+ end
+
+ raise "Class not processed in rest_resource_uri: #{ob.class.to_s}"
+end
+
+def rest_access_uri(ob)
+
+ base = "#{request.protocol}#{request.host_with_port}"
+
+ case ob.class.name
+ when 'Workflow'; return "#{base}/workflow.xml?id=#{ob.id}"
+ when 'Blob'; return "#{base}/file.xml?id=#{ob.id}"
+ when 'Network'; return "#{base}/group.xml?id=#{ob.id}"
+ when 'User'; return "#{base}/user.xml?id=#{ob.id}"
+ when 'Review'; return "#{base}/review.xml?id=#{ob.id}"
+ when 'Comment'; return "#{base}/comment.xml?id=#{ob.id}"
+ when 'Bookmark'; return "#{base}/favourite.xml?id=#{ob.id}"
+ when 'Blog'; return "#{base}/blog.xml?id=#{ob.id}"
+ when 'BlogPost'; return "#{base}/blog-post.xml?id=#{ob.id}"
+ when 'Rating'; return "#{base}/rating.xml?id=#{ob.id}"
+ when 'Tag'; return "#{base}/tag.xml?id=#{ob.id}"
+ when 'Picture'; return "#{base}/picture.xml?id=#{ob.id}"
+ when 'Message'; return "#{base}/message.xml?id=#{ob.id}"
+ when 'Citation'; return "#{base}/citation.xml?id=#{ob.id}"
+ when 'Announcement'; return "#{base}/announcement.xml?id=#{ob.id}"
+ when 'Pack'; return "#{base}/pack.xml?id=#{ob.id}"
+ when 'Experiment'; return "#{base}/experiment.xml?id=#{ob.id}"
+ when 'TavernaEnactor'; return "#{base}/runner.xml?id=#{ob.id}"
+ when 'Job'; return "#{base}/job.xml?id=#{ob.id}"
+ when 'Download'; return "#{base}/download.xml?id=#{ob.id}"
+ when 'PackContributableEntry'; return "#{base}/internal-pack-item.xml?id=#{ob.id}"
+ when 'PackRemoteEntry'; return "#{base}/external-pack-item.xml?id=#{ob.id}"
+ when 'Tagging'; return "#{base}/tagging.xml?id=#{ob.id}"
+ when 'ContentType'; return "#{base}/type.xml?id=#{ob.id}"
+ when 'License'; return "#{base}/license.xml?id=#{ob.id}"
+ when 'CurationEvent'; return "#{base}/curation-event.xml?id=#{ob.id}"
+ when 'Ontology'; return "#{base}/ontology.xml?id=#{ob.id}"
+ when 'Predicate'; return "#{base}/predicate.xml?id=#{ob.id}"
+ when 'Relationship'; return "#{base}/relationship.xml?id=#{ob.id}"
+
+ when 'Creditation'; return "#{base}/credit.xml?id=#{ob.id}"
+ when 'Attribution'; return nil
+
+ when 'Workflow::Version'; return "#{base}/workflow.xml?id=#{ob.workflow.id}&version=#{ob.version}"
+ end
+
+ raise "Class not processed in rest_access_uri: #{ob.class.to_s}"
+end
+
+def rest_object_tag_text(ob)
+
+ case ob.class.name
+ when 'User'; return 'user'
+ when 'Workflow'; return 'workflow'
+ when 'Blob'; return 'file'
+ when 'Network'; return 'group'
+ when 'Rating'; return 'rating'
+ when 'Creditation'; return 'credit'
+ when 'Citation'; return 'citation'
+ when 'Announcement'; return 'announcement'
+ when 'Tag'; return 'tag'
+ when 'Tagging'; return 'tagging'
+ when 'Pack'; return 'pack'
+ when 'Experiment'; return 'experiment'
+ when 'Download'; return 'download'
+ when 'PackContributableEntry'; return rest_object_tag_text(ob.contributable)
+ when 'PackRemoteEntry'; return 'external'
+ when 'Workflow::Version'; return 'workflow'
+ when 'Comment'; return 'comment'
+ when 'Bookmark'; return 'favourite'
+ when 'ContentType'; return 'type'
+ when 'License'; return 'license'
+ when 'CurationEvent'; return 'curation-event'
+ when 'Ontology'; return 'ontology'
+ when 'Predicate'; return 'predicate'
+ when 'Relationship'; return 'relationship'
+ end
+
+ return 'object'
+end
+
+def rest_object_label_text(ob)
+
+ case ob.class.name
+ when 'User'; return ob.name
+ when 'Workflow'; return ob.title
+ when 'Blob'; return ob.title
+ when 'Network'; return ob.title
+ when 'Rating'; return ob.rating.to_s
+ when 'Creditation'; return ''
+ when 'Citation'; return ob.title
+ when 'Announcement'; return ob.title
+ when 'Tag'; return ob.name
+ when 'Tagging'; return ob.tag.name
+ when 'Pack'; return ob.title
+ when 'Experiment'; return ob.title
+ when 'Download'; return ''
+ when 'PackContributableEntry'; return rest_object_label_text(ob.contributable)
+ when 'PackRemoteEntry'; return ob.title
+ when 'Workflow::Version'; return ob.title
+ when 'ContentType'; return ob.title
+ when 'License'; return ob.title
+ when 'CurationEvent'; return ob.category
+ when 'Ontology'; return ob.title
+ when 'Predicate'; return ob.title
+ when 'Relationship'; return ''
+ end
+
+ return ''
+end
+
+def rest_reference(ob, query, skip_text = false)
+
+ el = LibXML::XML::Node.new(rest_object_tag_text(ob))
+
+ resource_uri = rest_resource_uri(ob)
+
+ el['resource'] = resource_uri if resource_uri
+ el['uri' ] = rest_access_uri(ob)
+ el['version' ] = ob.current_version.to_s if ob.respond_to?('current_version')
+
+ el << rest_object_label_text(ob) if !skip_text
+
+ el
+end
+
+def parse_resource_uri(str)
+
+ base_uri = URI.parse("#{Conf.base_uri}/")
+ uri = base_uri.merge(str)
+ is_local = base_uri.host == uri.host and base_uri.port == uri.port
+
+ return [Workflow, $1, is_local] if uri.path =~ /^\/workflows\/([\d]+)$/
+ return [Blob, $1, is_local] if uri.path =~ /^\/files\/([\d]+)$/
+ return [Network, $1, is_local] if uri.path =~ /^\/groups\/([\d]+)$/
+ return [User, $1, is_local] if uri.path =~ /^\/users\/([\d]+)$/
+ return [Review, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/reviews\/([\d]+)$/
+ return [Comment, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/comments\/([\d]+)$/
+ return [Blog, $1, is_local] if uri.path =~ /^\/blogs\/([\d]+)$/
+ return [BlogPost, $1, is_local] if uri.path =~ /^\/blogs\/[\d]+\/blog_posts\/([\d]+)$/
+ return [Tag, $1, is_local] if uri.path =~ /^\/tags\/([\d]+)$/
+ return [Picture, $1, is_local] if uri.path =~ /^\/users\/[\d]+\/pictures\/([\d]+)$/
+ return [Message, $1, is_local] if uri.path =~ /^\/messages\/([\d]+)$/
+ return [Citation, $1, is_local] if uri.path =~ /^\/[^\/]+\/[\d]+\/citations\/([\d]+)$/
+ return [Announcement, $1, is_local] if uri.path =~ /^\/announcements\/([\d]+)$/
+ return [Pack, $1, is_local] if uri.path =~ /^\/packs\/([\d]+)$/
+ return [Experiment, $1, is_local] if uri.path =~ /^\/experiments\/([\d]+)$/
+ return [TavernaEnactor, $1, is_local] if uri.path =~ /^\/runners\/([\d]+)$/
+ return [Job, $1, is_local] if uri.path =~ /^\/jobs\/([\d]+)$/
+ return [Download, $1, is_local] if uri.path =~ /^\/downloads\/([\d]+)$/
+ return [Ontology, $1, is_local] if uri.path =~ /^\/ontologies\/([\d]+)$/
+ return [Predicate, $1, is_local] if uri.path =~ /^\/predicates\/([\d]+)$/
+
+ nil
+
+end
+
+def get_resource_from_uri(uri, user)
+
+ cl, id, local = parse_resource_uri(uri)
+
+ return nil if cl.nil? || local == false
+
+ resource = cl.find_by_id(id)
+
+ return nil if !Authorization.is_authorized?('view', nil, resource, user)
+
+ resource
+end
+
+def resolve_resource_node(resource_node, user = nil, permission = nil)
+
+ return nil if resource_node.nil?
+
+ attr = resource_node.find_first('@resource')
+
+ return nil if attr.nil?
+
+ resource_uri = attr.value
+
+ resource_bits = parse_resource_uri(resource_uri)
+
+ return nil if resource_bits.nil?
+
+ resource = resource_bits[0].find_by_id(resource_bits[1].to_i)
+
+ return nil if resource.nil?
+
+ if permission
+ return nil if !Authorization.is_authorized?(permission, nil, resource, user)
+ end
+
+ resource
+end
+
+def obtain_rest_resource(type, id, version, user, permission = nil)
+
+ resource = eval(type).find_by_id(id)
+
+ if resource.nil?
+ return [nil, rest_response(404, :reason => "Couldn't find a #{type} with id #{id}")]
+ end
+
+ if version
+ if resource.versions.last.version != version.to_i
+ resource = resource.find_version(version)
+ end
+ end
+
+ if resource.nil?
+ return [nil, rest_response(404, :reason => "#{type} #{id} does not have a version #{version}")]
+ end
+
+ if permission
+ if !Authorization.is_authorized?(permission, nil, resource, user)
+ return [nil, rest_response(401, :reason => "Not authorised for #{type} #{id}")]
+ end
+ end
+
+ [resource, nil]
+end
+
+def rest_access_redirect(opts = {})
+
+ return rest_response(400, :reason => "Resource was not specified") if opts[:query]['resource'].nil?
+
+ bits = parse_resource_uri(opts[:query]['resource'])
+
+ return rest_response(404, :reason => "Didn't understand the format of the specified resource") if bits.nil?
+
+ ob = bits[0].find_by_id(bits[1])
+
+ return rest_response(404, :reason => "The specified resource does not exist") if ob.nil?
+
+ return rest_response(401, :reason => "Not authorised for the specified resource") if !Authorization.is_authorized?('view', nil, ob, opts[:user])
+
+ rest_response(307, :location => rest_access_uri(ob))
+end
+
+def create_default_policy(user)
+ Policy.new(:contributor => user, :name => 'auto', :share_mode => 7, :update_mode => 6)
+end
+
+def update_permissions(ob, permissions)
+
+ share_mode = 7
+ update_mode = 6
+
+ # clear out any permission records for this contributable
+
+ ob.contribution.policy.permissions.each do |p|
+ p.destroy
+ end
+
+ # process permission elements
+
+ if permissions
+ permissions.find('permission').each do |permission|
+
+ # handle public privileges
+
+ if permission.find_first('category/text()').to_s == 'public'
+
+ privileges = {}
+
+ permission.find('privilege').each do |el|
+ privileges[el['type']] = true
+ end
+
+ if privileges["view"] && privileges["download"]
+ share_mode = 0
+ elsif privileges["view"]
+ share_mode = 2
+ else
+ share_mode = 7
+ end
+ end
+ end
+ end
+
+ ob.contribution.policy.update_attributes(:share_mode => share_mode,
+ :update_mode => update_mode)
+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.is_authorized_for_type?('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 'read', 'update', '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
+
+ 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
+
+ # 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 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
+
+ success = if (action == 'create' and opts[:query]['id'])
+ ob.save_as_new_version(revision_comment)
+ else
+ ob.save
+ 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?
+
+ if ob.contribution.policy.nil?
+ ob.contribution.policy = create_default_policy(opts[:user])
+ ob.contribution.save
+ end
+
+ update_permissions(ob, permissions)
+ end
+ end
+
+ ob = ob.versioned_resource if ob.respond_to?("versioned_resource")
+
+ rest_get_request(ob, "workflow", opts[:user],
+ rest_resource_uri(ob), "workflow", { "id" => ob.id.to_s })
+end
+
+def post_workflow(opts)
+ workflow_aux('create', opts)
+end
+
+def put_workflow(opts)
+ workflow_aux('update', 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.is_authorized_for_type?('create', 'Blob', opts[:user], nil)
+ ob = Blob.new(:contributor => opts[:user])
+ when 'read', 'update', '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"
+
+ 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')
+ content_type = parse_element(data, :text, '/file/content-type')
+ content = parse_element(data, :binary, '/file/content')
+
+ 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
+
+ # 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
+
+ if not ob.save
+ return rest_response(400, :object => ob)
+ end
+
+ if ob.contribution.policy.nil?
+ ob.contribution.policy = create_default_policy(opts[:user])
+ ob.contribution.save
+ end
+
+ update_permissions(ob, permissions)
+ end
+
+ rest_get_request(ob, "file", opts[:user],
+ rest_resource_uri(ob), "file", { "id" => ob.id.to_s })
+end
+
+def post_file(opts)
+ file_aux('create', opts)
+end
+
+def put_file(opts)
+ file_aux('update', 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.is_authorized_for_type?('create', 'Pack', opts[:user], nil)
+ ob = Pack.new(:contributor => opts[:user])
+ when 'read', 'update', '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')
+
+ # build the contributable
+
+ ob.title = title if title
+ ob.description = description if description
+
+ if not ob.save
+ return rest_response(400, :object => ob)
+ end
+
+ if ob.contribution.policy.nil?
+ ob.contribution.policy = create_default_policy(opts[:user])
+ ob.contribution.save
+ end
+
+ update_permissions(ob, permissions)
+ end
+
+ rest_get_request(ob, "pack", opts[:user],
+ rest_resource_uri(ob), "pack", { "id" => ob.id.to_s })
+end
+
+def post_pack(opts)
+ pack_aux('create', opts)
+end
+
+def put_pack(opts)
+ pack_aux('update', 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.is_authorized_for_type?('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.is_authorized?('edit', nil, pack, opts[:user])
+
+ ob = PackRemoteEntry.new(:user => opts[:user],
+ :pack => pack,
+ :title => title,
+ :uri => uri,
+ :alternate_uri => alternate_uri,
+ :comment => comment)
+
+ when 'read', 'update', '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.is_authorized?('edit', nil, 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, "external-pack-item", opts[:user],
+ rest_resource_uri(ob), "external-pack-item", { "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('update', 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')
+ end
+
+ # Obtain object
+
+ case action
+ when 'create':
+
+ return rest_response(401, :reason => "Not authorised to create an internal pack item") unless Authorization.is_authorized_for_type?('create', 'PackContributableEntry', 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.is_authorized?('edit', nil, pack, opts[:user])
+
+ ob = PackContributableEntry.new(:user => opts[:user],
+ :pack => pack,
+ :contributable => item,
+ :comment => comment)
+
+ when 'read', 'update', 'destroy':
+
+ ob, error = obtain_rest_resource('PackContributableEntry', 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.is_authorized?('edit', nil, 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.comment = comment if comment
+
+ if not ob.save
+ return rest_response(400, :object => ob)
+ end
+ end
+
+ rest_get_request(ob, "internal-pack-item", opts[:user],
+ rest_resource_uri(ob), "internal-pack-item", { "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('update', 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.is_authorized?('edit', nil, experiment, opts[:user])
+# return rest_response(400) if runner.nil? or not Authorization.is_authorized?('download', nil, runner, opts[:user])
+# return rest_response(400) if runnable.nil? or not Authorization.is_authorized?('view', nil, 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 == ""
+
+ find_paginated_auth( { :query => query, :models => models }, num, page, [], user) { |args, size, page|
+
+ q = args[:query]
+ models = args[:models]
+
+ search_result = models[0].multi_solr_search(q, :limit => size, :offset => size * (page - 1), :models => models)
+ search_result.results unless search_result.total < (size * (page - 1))
+ }
+end
+
+def search(opts)
+
+ search_query = opts[:query]['query']
+
+ # Start of curation hack
+
+ if search_query[0..1].downcase == 'c:' && opts[:user] &&
+ Conf.curators.include?(opts[:user].username)
+
+ bits = search_query.match("^c:([a-z]*) ([0-9]+)-([0-9]+)$")
+
+ if bits.length == 4
+
+ case bits[1]
+ when 'workflows': model = Workflow
+ when 'files': model = Blob
+ when 'packs': model = Pack
+ else return rest_response(400, :reason => "Unknown category '#{bits[1]}'")
+ end
+
+ obs = model.find(:all, :conditions => ['id >= ? AND id <= ?', bits[2], bits[3]])
+
+ obs = (obs.select do |c| c.respond_to?('contribution') == false or Authorization.is_authorized?("view", nil, c, opts[:user]) end)
+
+ return produce_rest_list(opts[:req_uri], opts[:rules], opts[:query], obs, 'search', {}, opts[:user])
+ end
+ end
+
+ # End of curation hack
+
+ models = [User, Workflow, Blob, Network, Pack]
+
+ # parse type option
+
+ if opts[:query]['type']
+
+ models = []
+
+ opts[:query]['type'].split(',').each do |type|
+ case type
+ when 'user'; models.push(User)
+ when 'workflow'; models.push(Workflow)
+ when 'file'; models.push(Blob)
+ when 'group'; models.push(Network)
+ when 'pack'; models.push(Pack)
+
+ else return rest_response(400, :reason => "Unknown search type '#{type}'")
+ end
+ end
+ end
+
+ num = 25
+
+ if opts[:query]['num']
+ num = opts[:query]['num'].to_i
+ end
+
+ num = 25 if num < 0
+ num = 100 if num > 100
+
+ page = opts[:query]['page'] ? opts[:query]['page'].to_i : 1
+
+ page = 1 if page < 1
+
+ attributes = {}
+ attributes['query'] = search_query
+ attributes['type'] = opts[:query]['type'] if models.length == 1
+
+ begin
+ obs = paginated_search_index(search_query, models, num, page, opts[:user])
+ produce_rest_list(opts[:req_uri], opts[:rules], opts[:query], obs, 'search', attributes, opts[:user])
+ rescue
+ rest_response(400, :reason => "Invalid search query")
+ 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.is_authorized?('view', nil, 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.is_authorized?('view', nil, 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.is_authorized?("index", nil, 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]
+ when "xml": rest_response(307, :location => rest_access_uri(opts[:user]))
+ when "rdf": rest_response(307, :location => formatted_user_url(:id => opts[:user].id, :format => 'rdf'))
+ end
+ else
+ rest_response(401, :reason => "Not logged in")
+ end
+end
+
+def parse_element(doc, kind, query)
+ case kind
+ when :text
+ if doc.find_first(query)
+
+ enc = doc.find_first(query)['encoding']
+ el = doc.find_first("#{query}")
+ text = doc.find_first("#{query}/text()")
+
+ if el
+ if enc == 'base64'
+ return Base64::decode64(text.to_s)
+ else
+ return text.to_s
+ end
+ end
+ end
+ when :binary
+ el = doc.find_first("#{query}")
+ text = doc.find_first("#{query}/text()")
+ return Base64::decode64(text.to_s) if el
+ when :resource
+ return resolve_resource_node(doc.find_first(query))
+ end
+end
+
+# Avatar handling (to show default avatar when none present)
+
+def effective_avatar(ob, user, query)
+
+ picture = ob.profile.picture
+
+ if picture
+ result = rest_reference(picture, query, true)
+ result.name = "avatar"
+ result
+ else
+ result = LibXML::XML::Node.new('avatar')
+ result['resource'] = Conf.base_uri + '/images/avatar.png'
+ result
+ end
+end
+
+# Privileges
+
+def effective_privileges(ob, user, query)
+
+ privileges = LibXML::XML::Node.new('privileges')
+
+ ['view', 'download', 'edit'].each do |type|
+ if Authorization.is_authorized?(type, nil, ob, user)
+ privilege = LibXML::XML::Node.new('privilege')
+ privilege['type'] = type
+
+ privileges << privilege
+ end
+ end
+
+ privileges
+end
+
+# Comments
+
+def comment_aux(action, opts)
+
+ # Obtain object
+
+ case action
+ when 'create':
+ return rest_response(401, :reason => "Not authorised to create a comment") unless Authorization.is_authorized_for_type?('create', 'Comment', opts[:user], nil)
+
+ ob = Comment.new(:user => opts[:user])
+ when 'read', 'update', '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
+
+ data = ""
+
+ comment = parse_element(data, :text, '/comment/comment')
+ subject = parse_element(data, :resource, '/comment/subject')
+
+ 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.is_authorized_for_type?(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_save
+
+ return rest_get_request(ob, "comment", opts[:user], rest_resource_uri(ob),
+ "comment", { "id" => ob.id.to_s })
+ end
+
+ # End of curation hack
+
+ return rest_response(400, :object => ob) unless ob.save
+ end
+
+ rest_get_request(ob, "comment", opts[:user], rest_resource_uri(ob), "comment", { "id" => ob.id.to_s })
+end
+
+def post_comment(opts)
+ comment_aux('create', opts)
+end
+
+def put_comment(opts)
+ comment_aux('update', opts)
+end
+
+def delete_comment(opts)
+ comment_aux('destroy', opts)
+end
+
+# Favourites
+
+def favourite_aux(action, opts)
+
+ # Obtain object
+
+ case action
+ when 'create':
+ return rest_response(401, :reason => "Not authorised to create a favourite") unless Authorization.is_authorized_for_type?('create', 'Bookmark', opts[:user], nil)
+
+ ob = Bookmark.new(:user => opts[:user])
+ when 'read', 'update', '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
+
+ data = ""
+
+ target = parse_element(data, :resource, '/favourite/object')
+
+ 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.is_authorized_for_type?(action, 'Bookmark', opts[:user], target)
+ ob.bookmarkable = target
+ end
+
+ return rest_response(400, :object => ob) unless ob.save
+ end
+
+ rest_get_request(ob, "favourite", opts[:user], rest_resource_uri(ob), "favourite", { "id" => ob.id.to_s })
+end
+
+def post_favourite(opts)
+ favourite_aux('create', opts)
+end
+
+def put_favourite(opts)
+ favourite_aux('update', opts)
+end
+
+def delete_favourite(opts)
+ favourite_aux('destroy', opts)
+end
+
+# Ratings
+
+def rating_aux(action, opts)
+
+ # Obtain object
+
+ case action
+ when 'create':
+ return rest_response(401, :reason => "Not authorised to create a rating") unless Authorization.is_authorized_for_type?('create', 'Rating', opts[:user], nil)
+
+ ob = Rating.new(:user => opts[:user])
+ when 'read', 'update', '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
+
+ data = ""
+
+ rating = parse_element(data, :text, '/rating/rating')
+ subject = parse_element(data, :resource, '/rating/subject')
+
+ 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.is_authorized_for_type?(action, 'Rating', opts[:user], subject)
+ ob.rateable = subject
+ end
+
+ return rest_response(400, :object => ob) unless ob.save
+ end
+
+ rest_get_request(ob, "rating", opts[:user], rest_resource_uri(ob), "rating", { "id" => ob.id.to_s })
+end
+
+def post_rating(opts)
+ rating_aux('create', opts)
+end
+
+def put_rating(opts)
+ rating_aux('update', opts)
+end
+
+def delete_rating(opts)
+ rating_aux('destroy', opts)
+end
+
+# Taggings
+
+def tagging_aux(action, opts)
+
+ # Obtain object
+
+ case action
+ when 'create':
+ return rest_response(401, :reason => "Not authorised to create a tagging") unless Authorization.is_authorized_for_type?('create', 'Tagging', opts[:user], nil)
+
+ ob = Tagging.new(:user => opts[:user])
+ when 'read', 'update', '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
+
+ data = ""
+
+ subject = parse_element(data, :resource, '/tagging/subject')
+ label = parse_element(data, :text, '/tagging/label')
+ tag = parse_element(data, :resource, '/tagging/tag')
+
+ 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.is_authorized_for_type?(action, 'Rating', opts[:user], subject)
+ ob.taggable = subject
+ end
+
+ return rest_response(400, :object => ob) unless ob.save
+ end
+
+ rest_get_request(ob, "tagging", opts[:user], rest_resource_uri(ob), "tagging", { "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.is_authorized_for_type?('create', 'Ontology', opts[:user], nil)
+ ob = Ontology.new(:user => opts[:user])
+ when 'read', 'update', '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, "ontology", opts[:user],
+ rest_resource_uri(ob), "ontology", { "id" => ob.id.to_s })
+end
+
+def post_ontology(opts)
+ ontology_aux('create', opts)
+end
+
+def put_ontology(opts)
+ ontology_aux('update', 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.is_authorized_for_type?('create', 'Predicate', opts[:user], ontology)
+ ob = Predicate.new
+ when 'read', 'update', '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, "predicate", opts[:user],
+ rest_resource_uri(ob), "predicate", { "id" => ob.id.to_s })
+end
+
+def post_predicate(opts)
+ predicate_aux('create', opts)
+end
+
+def put_predicate(opts)
+ predicate_aux('update', 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.is_authorized_for_type?('create', 'Relationship', opts[:user], context)
+ ob = Relationship.new(:user => opts[:user])
+ when 'read', 'update', '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, "relationship", opts[:user],
+ rest_resource_uri(ob), "relationship", { "id" => ob.id.to_s })
+end
+
+def post_relationship(opts)
+ relationship_aux('create', opts)
+end
+
+def put_relationship(opts)
+ relationship_aux('update', opts)
+end
+
+def delete_relationship(opts)
+ relationship_aux('destroy', opts)
+end
+
+# Call dispatcher
+
+def rest_call_request(req_uri, format, rules, user, query)
+ begin
+ eval("#{rules['Function']}(:req_uri => req_uri, :format => format, :rules => rules, :user => user, :query => query)")
+ rescue
+ return rest_response(500)
+ end
+end
+
Deleted: branches/api/test/functional/api_controller_test.rb (2921 => 2924)
--- trunk/test/functional/api_controller_test.rb 2012-01-26 13:24:17 UTC (rev 2921)
+++ branches/api/test/functional/api_controller_test.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -1,945 +0,0 @@
-require File.dirname(__FILE__) + '/../test_helper'
-require 'api_controller'
-require 'xml/libxml'
-require 'lib/rest'
-
-include ActionView::Helpers::UrlHelper
-include ActionController::UrlWriter
-
-class ApiControllerTest < ActionController::TestCase
-
- def setup
- @controller = ApiController.new
- @request = TestRequestWithQuery.new
- @response = ActionController::TestResponse.new
- end
-
- fixtures :workflows, :users, :content_types, :licenses, :ontologies, :predicates, :packs
-
- def test_workflows
-
- existing_workflows = Workflow.find(:all)
-
- login_as(:john)
-
- title = "Unique tags"
- title2 = "Unique tags again"
- license_type = "by-sa"
- content_type = "application/vnd.taverna.scufl+xml"
- description = "A workflow description."
-
- content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
-
- # post a workflow
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>#{title}</title>
- <description>#{description}</description>
- <license-type>#{license_type}</license-type>
- <content-type>#{content_type}</content-type>
- <content>#{content}</content>
- </workflow>")
-
- assert_response(:success)
-
- extra_workflows = Workflow.find(:all) - existing_workflows
-
- assert_equal(extra_workflows.length, 1)
-
- @workflow_id = extra_workflows.first.id
-
- # get the workflow
-
- response = rest_request(:get, 'workflow', nil, "id" => @workflow_id,
- "elements" => "title,description,license-type,content-type,content")
-
- assert_response(:success)
-
- assert_equal(title, response.find_first('/workflow/title').inner_xml)
- assert_equal(description, response.find_first('/workflow/description').inner_xml)
- assert_equal(license_type, response.find_first('/workflow/license-type').inner_xml)
- assert_equal(content_type, response.find_first('/workflow/content-type').inner_xml)
- assert_equal(content, response.find_first('/workflow/content').inner_xml)
-
- # it's private default, so make sure that another user can't get the
- # workflow
-
- setup
- login_as(:jane)
-
- rest_request(:get, 'workflow', nil, "id" => @workflow_id)
-
- assert_response(:unauthorized)
-
- # update the workflow
-
- setup
- login_as(:john)
-
- rest_request(:put, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>#{title2}</title>
- </workflow>", "id" => @workflow_id)
-
- assert_response(:success)
-
- # get the updated workflow
-
- response = rest_request(:get, 'workflow', nil, "id" => @workflow_id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title2, response.find_first('/workflow/title').inner_xml)
- assert_equal(description, response.find_first('/workflow/description').inner_xml)
-
- # delete the workflow
-
- rest_request(:delete, 'workflow', nil, "id" => @workflow_id)
-
- assert_response(:success)
-
- # try to get the deleted workflow
-
- rest_request(:get, 'workflow', nil, "id" => @workflow_id)
-
- assert_response(:not_found)
- end
-
- def test_files
-
- existing_files = Blob.find(:all)
-
- login_as(:john)
-
- title = "Test file title"
- title2 = "Updated test file title"
- license_type = "by-sa"
- content_type = "text/plain"
- description = "A description of the test file."
-
- content = Base64.encode64("This is the content of this test file.")
-
- # post a file
-
- rest_request(:post, 'file', "<?xml version='1.0'?>
- <file>
- <title>#{title}</title>
- <description>#{description}</description>
- <license-type>#{license_type}</license-type>
- <content-type>#{content_type}</content-type>
- <content>#{content}</content>
- </file>")
-
- assert_response(:success)
-
- extra_files = Blob.find(:all) - existing_files
-
- assert_equal(extra_files.length, 1)
-
- file = extra_files.first
-
- # get the file
-
- response = rest_request(:get, 'file', nil, "id" => file.id,
- "elements" => "title,description,license-type,content-type,content")
-
- assert_response(:success)
-
- assert_equal(title, response.find_first('/file/title').inner_xml)
- assert_equal(description, response.find_first('/file/description').inner_xml)
- assert_equal(license_type, response.find_first('/file/license-type').inner_xml)
- assert_equal(content_type, response.find_first('/file/content-type').inner_xml)
- assert_equal(content, response.find_first('/file/content').inner_xml)
-
- # it's private default, so make sure that another user can't get the
- # file
-
- setup
- login_as(:jane)
-
- rest_request(:get, 'file', nil, "id" => file.id)
-
- assert_response(:unauthorized)
-
- # update the file
-
- setup
- login_as(:john)
-
- rest_request(:put, 'file', "<?xml version='1.0'?>
- <file>
- <title>#{title2}</title>
- </file>", "id" => file.id)
-
- assert_response(:success)
-
- # get the updated file
-
- response = rest_request(:get, 'file', nil, "id" => file.id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title2, response.find_first('/file/title').inner_xml)
- assert_equal(description, response.find_first('/file/description').inner_xml)
-
- # delete the file
-
- rest_request(:delete, 'file', nil, "id" => file.id)
-
- assert_response(:success)
-
- # try to get the deleted file
-
- rest_request(:get, 'file', nil, "id" => file.id)
-
- assert_response(:not_found)
- end
-
- def test_packs
-
- existing_packs = Pack.find(:all)
-
- login_as(:john)
-
- title = "A pack"
- title2 = "An updated pack"
- description = "A pack description."
-
- # post a pack
-
- rest_request(:post, 'pack', "<?xml version='1.0'?>
- <pack>
- <title>#{title}</title>
- <description>#{description}</description>
- <permissions>
- <permission>
- <category>public</category>
- <privilege type='view'/>
- <privilege type='download'/>
- </permission>
- </permissions>
- </pack>")
-
- assert_response(:success)
-
- extra_packs = Pack.find(:all) - existing_packs
-
- assert_equal(extra_packs.length, 1)
-
- @pack_id = extra_packs.first.id
-
- # get the pack
-
- response = rest_request(:get, 'pack', nil, "id" => @pack_id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title, response.find_first('/pack/title').inner_xml)
- assert_equal(description, response.find_first('/pack/description').inner_xml)
-
- # make sure that another user can get the pack, since it's supposed to be
- # public
-
- setup;
- login_as(:jane)
-
- rest_request(:get, 'pack', nil, "id" => @pack_id)
-
- assert_response(:success)
-
- # update the pack
-
- setup
- login_as(:john)
-
- rest_request(:put, 'pack', "<?xml version='1.0'?>
- <pack>
- <title>#{title2}</title>
- </pack>", "id" => @pack_id)
-
- assert_response(:success)
-
- # get the updated pack
-
- response = rest_request(:get, 'pack', nil, "id" => @pack_id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title2, response.find_first('/pack/title').inner_xml)
- assert_equal(description, response.find_first('/pack/description').inner_xml)
-
- # add an internal pack item
-
- existing_internal_pack_items = PackContributableEntry.find(:all)
-
- pack_uri = rest_resource_uri(Pack.find(@pack_id))
- workflow_uri = rest_resource_uri(Workflow.find(1))
- comment1 = "It's an internal pack item."
- comment2 = "It's an updated internal pack item."
-
- rest_request(:post, 'internal-pack-item', "<?xml version='1.0'?>
- <internal-pack-item>
- <pack resource='#{pack_uri}'/>
- <item resource='#{workflow_uri}'/>
- <comment>#{comment1}</comment>
- </internal-pack-item>")
-
- assert_response(:success)
-
- extra_internal_pack_items = PackContributableEntry.find(:all) - existing_internal_pack_items
-
- assert_equal(extra_internal_pack_items.length, 1)
-
- @internal_pack_item_id = extra_internal_pack_items.first.id
-
- # get the internal pack item
-
- response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
-
- assert_response(:success)
-
- assert_equal(pack_uri, response.find_first('/internal-pack-item/pack/@resource').value)
- assert_equal(workflow_uri, response.find_first('/internal-pack-item/item/*/@resource').value)
- assert_equal(comment1, response.find_first('/internal-pack-item/comment').inner_xml)
-
- # update the internal pack item
-
- rest_request(:put, 'internal-pack-item', "<?xml version='1.0'?>
- <internal-pack-item>
- <comment>#{comment2}</comment>
- </internal-pack-item>", "id" => @internal_pack_item_id)
-
- assert_response(:success)
-
- # get the updated internal pack item
-
- response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
-
- assert_response(:success)
-
- assert_equal(comment2, response.find_first('/internal-pack-item/comment').inner_xml)
-
- # delete the internal pack item
-
- rest_request(:delete, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
-
- assert_response(:success)
-
- # try to get the deleted internal pack item
-
- response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
-
- assert_response(:not_found)
-
- # add an external pack item
-
- existing_external_pack_items = PackRemoteEntry.find(:all)
-
- external_uri = "http://example.com/"
- alternate_uri = "http://example.com/alternate"
- comment3 = "It's an external pack item."
- comment4 = "It's an updated external pack item."
- title = "Title for the external pack item."
-
- rest_request(:post, 'external-pack-item', "<?xml version='1.0'?>
- <external-pack-item>
- <pack resource='#{pack_uri}'/>
- <title>#{title}</title>
- <uri>#{external_uri}</uri>
- <alternate-uri>#{alternate_uri}</alternate-uri>
- <comment>#{comment3}</comment>
- </external-pack-item>")
-
- assert_response(:success)
-
- extra_external_pack_items = PackRemoteEntry.find(:all) - existing_external_pack_items
-
- assert_equal(extra_external_pack_items.length, 1)
-
- @external_pack_item_id = extra_external_pack_items.first.id
-
- # get the external pack item
-
- response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id,
- "elements" => "pack,title,uri,alternate-uri,comment")
-
- assert_response(:success)
-
- assert_equal(pack_uri, response.find_first('/external-pack-item/pack/@resource').value)
- assert_equal(external_uri, response.find_first('/external-pack-item/uri').inner_xml)
- assert_equal(alternate_uri, response.find_first('/external-pack-item/alternate-uri').inner_xml)
- assert_equal(comment3, response.find_first('/external-pack-item/comment').inner_xml)
-
- # update the external pack item
-
- rest_request(:put, 'external-pack-item', "<?xml version='1.0'?>
- <external-pack-item>
- <comment>#{comment4}</comment>
- </external-pack-item>", "id" => @external_pack_item_id)
-
- assert_response(:success)
-
- # get the updated external pack item
-
- response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id)
-
- assert_response(:success)
-
- assert_equal(comment4, response.find_first('/external-pack-item/comment').inner_xml)
-
- # delete the external pack item
-
- rest_request(:delete, 'external-pack-item', nil, "id" => @external_pack_item_id)
-
- assert_response(:success)
-
- # try to get the deleted external pack item
-
- response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id)
-
- assert_response(:not_found)
-
- # delete the pack
-
- rest_request(:delete, 'pack', nil, "id" => @pack_id)
-
- assert_response(:success)
-
- # try to get the deleted pack
-
- rest_request(:get, 'pack', nil, "id" => @pack_id)
-
- assert_response(:not_found)
- end
-
- def test_comments
-
- login_as(:john)
-
- # post a workflow to test with
-
- content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
-
- existing_workflows = Workflow.find(:all)
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>Unique tags</title>
- <description>A workflow description.</description>
- <license-type>by-sa</license-type>
- <content-type>application/vnd.taverna.scufl+xml</content-type>
- <content>#{content}</content>
- </workflow>")
-
- assert_response(:success)
-
- extra_workflows = Workflow.find(:all) - existing_workflows
-
- assert_equal(extra_workflows.length, 1)
-
- workflow = extra_workflows.first
- workflow_url = rest_resource_uri(workflow)
-
- # post a comment
-
- comment_text = "a test comment"
- comment_text2 = "an updated test comment"
-
- existing_comments = Comment.find(:all)
-
- rest_request(:post, 'comment', "<?xml version='1.0'?>
- <comment>
- <comment>#{comment_text}</comment>
- <subject resource='#{workflow_url}'/>
- </comment>")
-
- assert_response(:success)
-
- extra_comments = Comment.find(:all) - existing_comments
-
- assert_equal(extra_comments.length, 1)
-
- comment = extra_comments.first
-
- # update the comment (which should fail)
-
- rest_request(:put, 'comment', "<?xml version='1.0'?>
- <comment>
- <comment>#{comment_text2}</comment>
- </comment>", "id" => comment.id)
-
- assert_response(:unauthorized)
-
- # delete the comment
-
- rest_request(:delete, 'comment', nil, "id" => comment.id)
-
- assert_response(:success)
-
- # try to get the deleted comment
-
- rest_request(:get, 'comment', nil, "id" => comment.id)
-
- assert_response(:not_found)
- end
-
- def test_ratings
-
- login_as(:john)
-
- # post a workflow to test with
-
- content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
-
- existing_workflows = Workflow.find(:all)
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>Unique tags</title>
- <description>A workflow description.</description>
- <license-type>by-sa</license-type>
- <content-type>application/vnd.taverna.scufl+xml</content-type>
- <content>#{content}</content>
- </workflow>")
-
- assert_response(:success)
-
- extra_workflows = Workflow.find(:all) - existing_workflows
-
- assert_equal(extra_workflows.length, 1)
-
- workflow = extra_workflows.first
- workflow_url = rest_resource_uri(workflow)
-
- # post a rating
-
- existing_ratings = Rating.find(:all)
-
- rest_request(:post, 'rating', "<?xml version='1.0'?>
- <rating>
- <rating>4</rating>
- <subject resource='#{workflow_url}'/>
- </rating>")
-
- assert_response(:success)
-
- extra_ratings = Rating.find(:all) - existing_ratings
-
- assert_equal(extra_ratings.length, 1)
-
- rating = extra_ratings.first
-
- assert_equal(rating.user, users(:john));
- assert_equal(rating.rateable, workflow);
- assert_equal(rating.rating, 4);
-
- # update the rating (which should fail)
-
- rest_request(:put, 'rating', "<?xml version='1.0'?>
- <rating>
- <rating>3</rating>
- </rating>", "id" => rating.id)
-
- assert_response(:success)
-
- rating.reload
-
- assert_equal(rating.rating, 3);
-
- # delete the rating
-
- rest_request(:delete, 'rating', nil, "id" => rating.id)
-
- assert_response(:success)
-
- # try to get the deleted rating
-
- rest_request(:get, 'rating', nil, "id" => rating.id)
-
- assert_response(:not_found)
- end
-
- def test_favourites
-
- login_as(:john)
-
- # post a workflow to test with
-
- content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
-
- existing_workflows = Workflow.find(:all)
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>Unique tags</title>
- <description>A workflow description.</description>
- <license-type>by-sa</license-type>
- <content-type>application/vnd.taverna.scufl+xml</content-type>
- <content>#{content}</content>
- </workflow>")
-
- assert_response(:success)
-
- extra_workflows = Workflow.find(:all) - existing_workflows
-
- assert_equal(extra_workflows.length, 1)
-
- workflow = extra_workflows.first
- workflow_url = rest_resource_uri(workflow)
-
- # post a favourite
-
- existing_favourites = Bookmark.find(:all)
-
- rest_request(:post, 'favourite', "<?xml version='1.0'?>
- <favourite>
- <object resource='#{workflow_url}'/>
- </favourite>")
-
- assert_response(:success)
-
- extra_favourites = Bookmark.find(:all) - existing_favourites
-
- assert_equal(extra_favourites.length, 1)
-
- favourite = extra_favourites.first
-
- # delete the favourite
-
- rest_request(:delete, 'favourite', nil, "id" => favourite.id)
-
- assert_response(:success)
-
- # try to get the deleted favourite
-
- rest_request(:get, 'favourite', nil, "id" => favourite.id)
-
- assert_response(:not_found)
- end
-
- def test_taggings
-
- login_as(:john)
-
- # post a workflow to test with
-
- content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
-
- existing_workflows = Workflow.find(:all)
-
- rest_request(:post, 'workflow', "<?xml version='1.0'?>
- <workflow>
- <title>Unique tags</title>
- <description>A workflow description.</description>
- <license-type>by-sa</license-type>
- <content-type>application/vnd.taverna.scufl+xml</content-type>
- <content>#{content}</content>
- </workflow>")
-
- assert_response(:success)
-
- extra_workflows = Workflow.find(:all) - existing_workflows
-
- assert_equal(extra_workflows.length, 1)
-
- workflow = extra_workflows.first
- workflow_url = rest_resource_uri(workflow)
-
- # post a tagging
-
- existing_taggings = Tagging.find(:all)
-
- rest_request(:post, 'tagging', "<?xml version='1.0'?>
- <tagging>
- <subject resource='#{workflow_url}'/>
- <label>my test tag</label>
- </tagging>")
-
- assert_response(:success)
-
- extra_taggings = Tagging.find(:all) - existing_taggings
-
- assert_equal(extra_taggings.length, 1)
-
- tagging = extra_taggings.first
-
- assert_equal(tagging.user, users(:john));
- assert_equal(tagging.taggable, workflow);
- assert_equal(tagging.label, 'my test tag');
-
- # update the tagging (which should fail)
-
- rest_request(:put, 'tagging', "<?xml version='1.0'?>
- <tagging>
- <label>fail</label>
- </tagging>", "id" => tagging.id)
-
- assert_response(400)
-
- # delete the tagging
-
- rest_request(:delete, 'tagging', nil, "id" => tagging.id)
-
- assert_response(:success)
-
- # try to get the deleted tagging
-
- rest_request(:get, 'tagging', nil, "id" => tagging.id)
-
- assert_response(:not_found)
- end
-
- def test_ontologies
-
- existing_ontologies = Ontology.find(:all)
-
- login_as(:john)
-
- title = "Test ontology title"
- title2 = "Updated test ontology title"
- uri = "http://example.com/ontology"
- prefix = "test prefix"
- description = "A description of the ontology."
-
- # post an ontology
-
- rest_request(:post, 'ontology', "<?xml version='1.0'?>
- <ontology>
- <title>#{title}</title>
- <description>#{description}</description>
- <uri>#{uri}</uri>
- <prefix>#{prefix}</prefix>
- </ontology>")
-
- assert_response(:success)
-
- extra_ontologies = Ontology.find(:all) - existing_ontologies
-
- assert_equal(extra_ontologies.length, 1)
-
-
-
- # get the ontology
-
- response = rest_request(:get, 'ontology', nil, "id" => ontology.id,
- "elements" => "title,description,uri,prefix")
-
- assert_response(:success)
-
- assert_equal(title, response.find_first('/ontology/title').inner_xml)
- assert_equal(description, response.find_first('/ontology/description').inner_xml)
- assert_equal(uri, response.find_first('/ontology/uri').inner_xml)
- assert_equal(prefix, response.find_first('/ontology/prefix').inner_xml)
-
- # update the ontology
-
- rest_request(:put, 'ontology', "<?xml version='1.0'?>
- <ontology>
- <title>#{title2}</title>
- </ontology>", "id" => ontology.id)
-
- assert_response(:success)
-
- # get the updated ontology
-
- response = rest_request(:get, 'ontology', nil, "id" => ontology.id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title2, response.find_first('/ontology/title').inner_xml)
- assert_equal(description, response.find_first('/ontology/description').inner_xml)
-
- # delete the ontology
-
- rest_request(:delete, 'ontology', nil, "id" => ontology.id)
-
- assert_response(:success)
-
- # try to get the deleted ontology
-
- rest_request(:get, 'ontology', nil, "id" => ontology.id)
-
- assert_response(:not_found)
- end
-
- def test_predicates
-
- existing_predicates = Predicate.find(:all)
-
- login_as(:john)
-
- title = "Test predicate title"
- title2 = "Updated test predicate title"
-
-
- phrase = "test phrase"
- description = "A description of the predicate."
- description_html = "<p>A description of the predicate.</p>"
- equivalent_to = "test equivalent_to"
-
- # post a predicate
-
- rest_request(:post, 'predicate', "<?xml version='1.0'?>
- <predicate>
- <title>#{title}</title>
- <ontology resource='#{ontology_url}'/>
- <phrase>#{phrase}</phrase>
- <description>#{description}</description>
- <equivalent-to>#{equivalent_to}</equivalent-to>
- </predicate>")
-
- assert_response(:success)
-
- extra_predicates = Predicate.find(:all) - existing_predicates
-
- assert_equal(extra_predicates.length, 1)
-
- predicate = extra_predicates.first
-
- # get the predicate
-
- response = rest_request(:get, 'predicate', nil, "id" => predicate.id,
- "elements" => "title,description,phrase,equivalent-to")
-
- assert_response(:success)
-
- assert_equal(title, response.find_first('/predicate/title').inner_xml)
- assert_equal(description, response.find_first('/predicate/description').inner_xml)
- assert_equal(phrase, response.find_first('/predicate/phrase').inner_xml)
- assert_equal(equivalent_to, response.find_first('/predicate/equivalent-to').inner_xml)
-
- # update the predicate
-
- rest_request(:put, 'predicate', "<?xml version='1.0'?>
- <predicate>
- <title>#{title2}</title>
- </predicate>", "id" => predicate.id)
-
- assert_response(:success)
-
- # get the updated predicate
-
- response = rest_request(:get, 'predicate', nil, "id" => predicate.id,
- "elements" => "title,description")
-
- assert_response(:success)
-
- assert_equal(title2, response.find_first('/predicate/title').inner_xml)
- assert_equal(description, response.find_first('/predicate/description').inner_xml)
-
- # delete the predicate
-
- rest_request(:delete, 'predicate', nil, "id" => predicate.id)
-
- assert_response(:success)
-
- # try to get the deleted predicate
-
- rest_request(:get, 'predicate', nil, "id" => predicate.id)
-
- assert_response(:not_found)
- end
-
- def test_relationships
-
- existing_relationships = Relationship.find(:all)
-
- login_as(:john)
-
- subject_url = rest_resource_uri(workflows(:workflow_branch_choice))
- predicate_url = rest_resource_uri(predicates(:test_predicate_1))
- objekt_url = rest_resource_uri(workflows(:workflow_dilbert))
- context_url = rest_resource_uri(packs(:pack_1))
-
- # post a relationship
-
- rest_request(:post, 'relationship', "<?xml version='1.0'?>
- <relationship>
- <subject resource='#{subject_url}'/>
- <predicate resource='#{predicate_url}'/>
- <object resource='#{objekt_url}'/>
- <context resource='#{context_url}'/>
- </relationship>")
-
- assert_response(:success)
-
- extra_relationships = Relationship.find(:all) - existing_relationships
-
- assert_equal(extra_relationships.length, 1)
-
- relationship = extra_relationships.first
-
- # get the relationship
-
- response = rest_request(:get, 'relationship', nil, "id" => relationship.id,
- "elements" => "user,subject,predicate,object,context")
-
- assert_response(:success)
-
- assert_equal(subject_url, response.find_first('/relationship/subject/*/@resource').value)
- assert_equal(predicate_url, response.find_first('/relationship/predicate/@resource').value)
- assert_equal(objekt_url, response.find_first('/relationship/object/*/@resource').value)
- assert_equal(context_url, response.find_first('/relationship/context/*/@resource').value)
-
- # delete the relationship
-
- rest_request(:delete, 'relationship', nil, "id" => relationship.id)
-
- assert_response(:success)
-
- # try to get the deleted relationship
-
- rest_request(:get, 'relationship', nil, "id" => relationship.id)
-
- assert_response(:not_found)
- end
-
- private
-
- def rest_request(method, uri, data = "" query = {})
-
- @request.query_parameters!(query) if query
-
- @request.env['RAW_POST_DATA'] = data if data
-
- # puts "Sending: #{data.inspect}"
-
- case method
- when :get; get(:process_request, { :uri => uri } )
- when :post; post(:process_request, { :uri => uri } )
- when :put; put(:process_request, { :uri => uri } )
- when :delete; delete(:process_request, { :uri => uri } )
- end
-
- # puts "Response: #{LibXML::XML::Parser.string(@response.body).parse.root.to_s}"
-
- LibXML::XML::Parser.string(@response.body).parse
- end
-end
-
-# Custom version of the TestRequest, so that I can set the query parameters of
-# a request.
-
-class TestRequestWithQuery < ActionController::TestRequest
-
- def query_parameters!(hash)
- @custom_query_parameters = hash
- end
-
-
- def recycle!
- super
-
- if @custom_query_parameters
- self.query_parameters = @custom_query_parameters
- @custom_query_parameters = nil
- end
- end
-end
-
Copied: branches/api/test/functional/api_controller_test.rb (from rev 2923, trunk/test/functional/api_controller_test.rb) (0 => 2924)
--- branches/api/test/functional/api_controller_test.rb (rev 0)
+++ branches/api/test/functional/api_controller_test.rb 2012-02-03 11:28:38 UTC (rev 2924)
@@ -0,0 +1,945 @@
+require File.dirname(__FILE__) + '/../test_helper'
+require 'api_controller'
+require 'xml/libxml'
+require 'lib/rest'
+
+include ActionView::Helpers::UrlHelper
+include ActionController::UrlWriter
+
+class ApiControllerTest < ActionController::TestCase
+
+ def setup
+ @controller = ApiController.new
+ @request = TestRequestWithQuery.new
+ @response = ActionController::TestResponse.new
+ end
+
+ fixtures :workflows, :users, :content_types, :licenses, :ontologies, :predicates, :packs
+
+ def test_workflows
+
+ existing_workflows = Workflow.find(:all)
+
+ login_as(:john)
+
+ title = "Unique tags"
+ title2 = "Unique tags again"
+ license_type = "by-sa"
+ content_type = "application/vnd.taverna.scufl+xml"
+ description = "A workflow description."
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+
+ # post a workflow
+
+ rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>#{title}</title>
+ <description>#{description}</description>
+ <license-type>#{license_type}</license-type>
+ <content-type>#{content_type}</content-type>
+ <content>#{content}</content>
+ </workflow>")
+
+ assert_response(:success)
+
+ extra_workflows = Workflow.find(:all) - existing_workflows
+
+ assert_equal(extra_workflows.length, 1)
+
+ @workflow_id = extra_workflows.first.id
+
+ # get the workflow
+
+ response = rest_request(:get, 'workflow', nil, "id" => @workflow_id,
+ "elements" => "title,description,license-type,content-type,content")
+
+ assert_response(:success)
+
+ assert_equal(title, response.find_first('/workflow/title').inner_xml)
+ assert_equal(description, response.find_first('/workflow/description').inner_xml)
+ assert_equal(license_type, response.find_first('/workflow/license-type').inner_xml)
+ assert_equal(content_type, response.find_first('/workflow/content-type').inner_xml)
+ assert_equal(content, response.find_first('/workflow/content').inner_xml)
+
+ # it's private default, so make sure that another user can't get the
+ # workflow
+
+ setup
+ login_as(:jane)
+
+ rest_request(:get, 'workflow', nil, "id" => @workflow_id)
+
+ assert_response(:unauthorized)
+
+ # update the workflow
+
+ setup
+ login_as(:john)
+
+ rest_request(:put, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>#{title2}</title>
+ </workflow>", "id" => @workflow_id)
+
+ assert_response(:success)
+
+ # get the updated workflow
+
+ response = rest_request(:get, 'workflow', nil, "id" => @workflow_id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title2, response.find_first('/workflow/title').inner_xml)
+ assert_equal(description, response.find_first('/workflow/description').inner_xml)
+
+ # delete the workflow
+
+ rest_request(:delete, 'workflow', nil, "id" => @workflow_id)
+
+ assert_response(:success)
+
+ # try to get the deleted workflow
+
+ rest_request(:get, 'workflow', nil, "id" => @workflow_id)
+
+ assert_response(:not_found)
+ end
+
+ def test_files
+
+ existing_files = Blob.find(:all)
+
+ login_as(:john)
+
+ title = "Test file title"
+ title2 = "Updated test file title"
+ license_type = "by-sa"
+ content_type = "text/plain"
+ description = "A description of the test file."
+
+ content = Base64.encode64("This is the content of this test file.")
+
+ # post a file
+
+ rest_request(:post, 'file', "<?xml version='1.0'?>
+ <file>
+ <title>#{title}</title>
+ <description>#{description}</description>
+ <license-type>#{license_type}</license-type>
+ <content-type>#{content_type}</content-type>
+ <content>#{content}</content>
+ </file>")
+
+ assert_response(:success)
+
+ extra_files = Blob.find(:all) - existing_files
+
+ assert_equal(extra_files.length, 1)
+
+ file = extra_files.first
+
+ # get the file
+
+ response = rest_request(:get, 'file', nil, "id" => file.id,
+ "elements" => "title,description,license-type,content-type,content")
+
+ assert_response(:success)
+
+ assert_equal(title, response.find_first('/file/title').inner_xml)
+ assert_equal(description, response.find_first('/file/description').inner_xml)
+ assert_equal(license_type, response.find_first('/file/license-type').inner_xml)
+ assert_equal(content_type, response.find_first('/file/content-type').inner_xml)
+ assert_equal(content, response.find_first('/file/content').inner_xml)
+
+ # it's private default, so make sure that another user can't get the
+ # file
+
+ setup
+ login_as(:jane)
+
+ rest_request(:get, 'file', nil, "id" => file.id)
+
+ assert_response(:unauthorized)
+
+ # update the file
+
+ setup
+ login_as(:john)
+
+ rest_request(:put, 'file', "<?xml version='1.0'?>
+ <file>
+ <title>#{title2}</title>
+ </file>", "id" => file.id)
+
+ assert_response(:success)
+
+ # get the updated file
+
+ response = rest_request(:get, 'file', nil, "id" => file.id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title2, response.find_first('/file/title').inner_xml)
+ assert_equal(description, response.find_first('/file/description').inner_xml)
+
+ # delete the file
+
+ rest_request(:delete, 'file', nil, "id" => file.id)
+
+ assert_response(:success)
+
+ # try to get the deleted file
+
+ rest_request(:get, 'file', nil, "id" => file.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_packs
+
+ existing_packs = Pack.find(:all)
+
+ login_as(:john)
+
+ title = "A pack"
+ title2 = "An updated pack"
+ description = "A pack description."
+
+ # post a pack
+
+ rest_request(:post, 'pack', "<?xml version='1.0'?>
+ <pack>
+ <title>#{title}</title>
+ <description>#{description}</description>
+ <permissions>
+ <permission>
+ <category>public</category>
+ <privilege type='view'/>
+ <privilege type='download'/>
+ </permission>
+ </permissions>
+ </pack>")
+
+ assert_response(:success)
+
+ extra_packs = Pack.find(:all) - existing_packs
+
+ assert_equal(extra_packs.length, 1)
+
+ @pack_id = extra_packs.first.id
+
+ # get the pack
+
+ response = rest_request(:get, 'pack', nil, "id" => @pack_id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title, response.find_first('/pack/title').inner_xml)
+ assert_equal(description, response.find_first('/pack/description').inner_xml)
+
+ # make sure that another user can get the pack, since it's supposed to be
+ # public
+
+ setup;
+ login_as(:jane)
+
+ rest_request(:get, 'pack', nil, "id" => @pack_id)
+
+ assert_response(:success)
+
+ # update the pack
+
+ setup
+ login_as(:john)
+
+ rest_request(:put, 'pack', "<?xml version='1.0'?>
+ <pack>
+ <title>#{title2}</title>
+ </pack>", "id" => @pack_id)
+
+ assert_response(:success)
+
+ # get the updated pack
+
+ response = rest_request(:get, 'pack', nil, "id" => @pack_id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title2, response.find_first('/pack/title').inner_xml)
+ assert_equal(description, response.find_first('/pack/description').inner_xml)
+
+ # add an internal pack item
+
+ existing_internal_pack_items = PackContributableEntry.find(:all)
+
+ pack_uri = rest_resource_uri(Pack.find(@pack_id))
+ workflow_uri = rest_resource_uri(Workflow.find(1))
+ comment1 = "It's an internal pack item."
+ comment2 = "It's an updated internal pack item."
+
+ rest_request(:post, 'internal-pack-item', "<?xml version='1.0'?>
+ <internal-pack-item>
+ <pack resource='#{pack_uri}'/>
+ <item resource='#{workflow_uri}'/>
+ <comment>#{comment1}</comment>
+ </internal-pack-item>")
+
+ assert_response(:success)
+
+ extra_internal_pack_items = PackContributableEntry.find(:all) - existing_internal_pack_items
+
+ assert_equal(extra_internal_pack_items.length, 1)
+
+ @internal_pack_item_id = extra_internal_pack_items.first.id
+
+ # get the internal pack item
+
+ response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
+
+ assert_response(:success)
+
+ assert_equal(pack_uri, response.find_first('/internal-pack-item/pack/@resource').value)
+ assert_equal(workflow_uri, response.find_first('/internal-pack-item/item/*/@resource').value)
+ assert_equal(comment1, response.find_first('/internal-pack-item/comment').inner_xml)
+
+ # update the internal pack item
+
+ rest_request(:put, 'internal-pack-item', "<?xml version='1.0'?>
+ <internal-pack-item>
+ <comment>#{comment2}</comment>
+ </internal-pack-item>", "id" => @internal_pack_item_id)
+
+ assert_response(:success)
+
+ # get the updated internal pack item
+
+ response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
+
+ assert_response(:success)
+
+ assert_equal(comment2, response.find_first('/internal-pack-item/comment').inner_xml)
+
+ # delete the internal pack item
+
+ rest_request(:delete, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
+
+ assert_response(:success)
+
+ # try to get the deleted internal pack item
+
+ response = rest_request(:get, 'internal-pack-item', nil, "id" => @internal_pack_item_id)
+
+ assert_response(:not_found)
+
+ # add an external pack item
+
+ existing_external_pack_items = PackRemoteEntry.find(:all)
+
+ external_uri = "http://example.com/"
+ alternate_uri = "http://example.com/alternate"
+ comment3 = "It's an external pack item."
+ comment4 = "It's an updated external pack item."
+ title = "Title for the external pack item."
+
+ rest_request(:post, 'external-pack-item', "<?xml version='1.0'?>
+ <external-pack-item>
+ <pack resource='#{pack_uri}'/>
+ <title>#{title}</title>
+ <uri>#{external_uri}</uri>
+ <alternate-uri>#{alternate_uri}</alternate-uri>
+ <comment>#{comment3}</comment>
+ </external-pack-item>")
+
+ assert_response(:success)
+
+ extra_external_pack_items = PackRemoteEntry.find(:all) - existing_external_pack_items
+
+ assert_equal(extra_external_pack_items.length, 1)
+
+ @external_pack_item_id = extra_external_pack_items.first.id
+
+ # get the external pack item
+
+ response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id,
+ "elements" => "pack,title,uri,alternate-uri,comment")
+
+ assert_response(:success)
+
+ assert_equal(pack_uri, response.find_first('/external-pack-item/pack/@resource').value)
+ assert_equal(external_uri, response.find_first('/external-pack-item/uri').inner_xml)
+ assert_equal(alternate_uri, response.find_first('/external-pack-item/alternate-uri').inner_xml)
+ assert_equal(comment3, response.find_first('/external-pack-item/comment').inner_xml)
+
+ # update the external pack item
+
+ rest_request(:put, 'external-pack-item', "<?xml version='1.0'?>
+ <external-pack-item>
+ <comment>#{comment4}</comment>
+ </external-pack-item>", "id" => @external_pack_item_id)
+
+ assert_response(:success)
+
+ # get the updated external pack item
+
+ response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id)
+
+ assert_response(:success)
+
+ assert_equal(comment4, response.find_first('/external-pack-item/comment').inner_xml)
+
+ # delete the external pack item
+
+ rest_request(:delete, 'external-pack-item', nil, "id" => @external_pack_item_id)
+
+ assert_response(:success)
+
+ # try to get the deleted external pack item
+
+ response = rest_request(:get, 'external-pack-item', nil, "id" => @external_pack_item_id)
+
+ assert_response(:not_found)
+
+ # delete the pack
+
+ rest_request(:delete, 'pack', nil, "id" => @pack_id)
+
+ assert_response(:success)
+
+ # try to get the deleted pack
+
+ rest_request(:get, 'pack', nil, "id" => @pack_id)
+
+ assert_response(:not_found)
+ end
+
+ def test_comments
+
+ login_as(:john)
+
+ # post a workflow to test with
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+
+ existing_workflows = Workflow.find(:all)
+
+ rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>Unique tags</title>
+ <description>A workflow description.</description>
+ <license-type>by-sa</license-type>
+ <content-type>application/vnd.taverna.scufl+xml</content-type>
+ <content>#{content}</content>
+ </workflow>")
+
+ assert_response(:success)
+
+ extra_workflows = Workflow.find(:all) - existing_workflows
+
+ assert_equal(extra_workflows.length, 1)
+
+ workflow = extra_workflows.first
+ workflow_url = rest_resource_uri(workflow)
+
+ # post a comment
+
+ comment_text = "a test comment"
+ comment_text2 = "an updated test comment"
+
+ existing_comments = Comment.find(:all)
+
+ rest_request(:post, 'comment', "<?xml version='1.0'?>
+ <comment>
+ <comment>#{comment_text}</comment>
+ <subject resource='#{workflow_url}'/>
+ </comment>")
+
+ assert_response(:success)
+
+ extra_comments = Comment.find(:all) - existing_comments
+
+ assert_equal(extra_comments.length, 1)
+
+ comment = extra_comments.first
+
+ # update the comment (which should fail)
+
+ rest_request(:put, 'comment', "<?xml version='1.0'?>
+ <comment>
+ <comment>#{comment_text2}</comment>
+ </comment>", "id" => comment.id)
+
+ assert_response(:unauthorized)
+
+ # delete the comment
+
+ rest_request(:delete, 'comment', nil, "id" => comment.id)
+
+ assert_response(:success)
+
+ # try to get the deleted comment
+
+ rest_request(:get, 'comment', nil, "id" => comment.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_ratings
+
+ login_as(:john)
+
+ # post a workflow to test with
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+
+ existing_workflows = Workflow.find(:all)
+
+ rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>Unique tags</title>
+ <description>A workflow description.</description>
+ <license-type>by-sa</license-type>
+ <content-type>application/vnd.taverna.scufl+xml</content-type>
+ <content>#{content}</content>
+ </workflow>")
+
+ assert_response(:success)
+
+ extra_workflows = Workflow.find(:all) - existing_workflows
+
+ assert_equal(extra_workflows.length, 1)
+
+ workflow = extra_workflows.first
+ workflow_url = rest_resource_uri(workflow)
+
+ # post a rating
+
+ existing_ratings = Rating.find(:all)
+
+ rest_request(:post, 'rating', "<?xml version='1.0'?>
+ <rating>
+ <rating>4</rating>
+ <subject resource='#{workflow_url}'/>
+ </rating>")
+
+ assert_response(:success)
+
+ extra_ratings = Rating.find(:all) - existing_ratings
+
+ assert_equal(extra_ratings.length, 1)
+
+ rating = extra_ratings.first
+
+ assert_equal(rating.user, users(:john));
+ assert_equal(rating.rateable, workflow);
+ assert_equal(rating.rating, 4);
+
+ # update the rating (which should fail)
+
+ rest_request(:put, 'rating', "<?xml version='1.0'?>
+ <rating>
+ <rating>3</rating>
+ </rating>", "id" => rating.id)
+
+ assert_response(:success)
+
+ rating.reload
+
+ assert_equal(rating.rating, 3);
+
+ # delete the rating
+
+ rest_request(:delete, 'rating', nil, "id" => rating.id)
+
+ assert_response(:success)
+
+ # try to get the deleted rating
+
+ rest_request(:get, 'rating', nil, "id" => rating.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_favourites
+
+ login_as(:john)
+
+ # post a workflow to test with
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+
+ existing_workflows = Workflow.find(:all)
+
+ rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>Unique tags</title>
+ <description>A workflow description.</description>
+ <license-type>by-sa</license-type>
+ <content-type>application/vnd.taverna.scufl+xml</content-type>
+ <content>#{content}</content>
+ </workflow>")
+
+ assert_response(:success)
+
+ extra_workflows = Workflow.find(:all) - existing_workflows
+
+ assert_equal(extra_workflows.length, 1)
+
+ workflow = extra_workflows.first
+ workflow_url = rest_resource_uri(workflow)
+
+ # post a favourite
+
+ existing_favourites = Bookmark.find(:all)
+
+ rest_request(:post, 'favourite', "<?xml version='1.0'?>
+ <favourite>
+ <object resource='#{workflow_url}'/>
+ </favourite>")
+
+ assert_response(:success)
+
+ extra_favourites = Bookmark.find(:all) - existing_favourites
+
+ assert_equal(extra_favourites.length, 1)
+
+ favourite = extra_favourites.first
+
+ # delete the favourite
+
+ rest_request(:delete, 'favourite', nil, "id" => favourite.id)
+
+ assert_response(:success)
+
+ # try to get the deleted favourite
+
+ rest_request(:get, 'favourite', nil, "id" => favourite.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_taggings
+
+ login_as(:john)
+
+ # post a workflow to test with
+
+ content = Base64.encode64(File.read('test/fixtures/files/workflow_dilbert.xml'))
+
+ existing_workflows = Workflow.find(:all)
+
+ rest_request(:post, 'workflow', "<?xml version='1.0'?>
+ <workflow>
+ <title>Unique tags</title>
+ <description>A workflow description.</description>
+ <license-type>by-sa</license-type>
+ <content-type>application/vnd.taverna.scufl+xml</content-type>
+ <content>#{content}</content>
+ </workflow>")
+
+ assert_response(:success)
+
+ extra_workflows = Workflow.find(:all) - existing_workflows
+
+ assert_equal(extra_workflows.length, 1)
+
+ workflow = extra_workflows.first
+ workflow_url = rest_resource_uri(workflow)
+
+ # post a tagging
+
+ existing_taggings = Tagging.find(:all)
+
+ rest_request(:post, 'tagging', "<?xml version='1.0'?>
+ <tagging>
+ <subject resource='#{workflow_url}'/>
+ <label>my test tag</label>
+ </tagging>")
+
+ assert_response(:success)
+
+ extra_taggings = Tagging.find(:all) - existing_taggings
+
+ assert_equal(extra_taggings.length, 1)
+
+ tagging = extra_taggings.first
+
+ assert_equal(tagging.user, users(:john));
+ assert_equal(tagging.taggable, workflow);
+ assert_equal(tagging.label, 'my test tag');
+
+ # update the tagging (which should fail)
+
+ rest_request(:put, 'tagging', "<?xml version='1.0'?>
+ <tagging>
+ <label>fail</label>
+ </tagging>", "id" => tagging.id)
+
+ assert_response(400)
+
+ # delete the tagging
+
+ rest_request(:delete, 'tagging', nil, "id" => tagging.id)
+
+ assert_response(:success)
+
+ # try to get the deleted tagging
+
+ rest_request(:get, 'tagging', nil, "id" => tagging.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_ontologies
+
+ existing_ontologies = Ontology.find(:all)
+
+ login_as(:john)
+
+ title = "Test ontology title"
+ title2 = "Updated test ontology title"
+ uri = "http://example.com/ontology"
+ prefix = "test prefix"
+ description = "A description of the ontology."
+
+ # post an ontology
+
+ rest_request(:post, 'ontology', "<?xml version='1.0'?>
+ <ontology>
+ <title>#{title}</title>
+ <description>#{description}</description>
+ <uri>#{uri}</uri>
+ <prefix>#{prefix}</prefix>
+ </ontology>")
+
+ assert_response(:success)
+
+ extra_ontologies = Ontology.find(:all) - existing_ontologies
+
+ assert_equal(extra_ontologies.length, 1)
+
+
+
+ # get the ontology
+
+ response = rest_request(:get, 'ontology', nil, "id" => ontology.id,
+ "elements" => "title,description,uri,prefix")
+
+ assert_response(:success)
+
+ assert_equal(title, response.find_first('/ontology/title').inner_xml)
+ assert_equal(description, response.find_first('/ontology/description').inner_xml)
+ assert_equal(uri, response.find_first('/ontology/uri').inner_xml)
+ assert_equal(prefix, response.find_first('/ontology/prefix').inner_xml)
+
+ # update the ontology
+
+ rest_request(:put, 'ontology', "<?xml version='1.0'?>
+ <ontology>
+ <title>#{title2}</title>
+ </ontology>", "id" => ontology.id)
+
+ assert_response(:success)
+
+ # get the updated ontology
+
+ response = rest_request(:get, 'ontology', nil, "id" => ontology.id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title2, response.find_first('/ontology/title').inner_xml)
+ assert_equal(description, response.find_first('/ontology/description').inner_xml)
+
+ # delete the ontology
+
+ rest_request(:delete, 'ontology', nil, "id" => ontology.id)
+
+ assert_response(:success)
+
+ # try to get the deleted ontology
+
+ rest_request(:get, 'ontology', nil, "id" => ontology.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_predicates
+
+ existing_predicates = Predicate.find(:all)
+
+ login_as(:john)
+
+ title = "Test predicate title"
+ title2 = "Updated test predicate title"
+
+
+ phrase = "test phrase"
+ description = "A description of the predicate."
+ description_html = "<p>A description of the predicate.</p>"
+ equivalent_to = "test equivalent_to"
+
+ # post a predicate
+
+ rest_request(:post, 'predicate', "<?xml version='1.0'?>
+ <predicate>
+ <title>#{title}</title>
+ <ontology resource='#{ontology_url}'/>
+ <phrase>#{phrase}</phrase>
+ <description>#{description}</description>
+ <equivalent-to>#{equivalent_to}</equivalent-to>
+ </predicate>")
+
+ assert_response(:success)
+
+ extra_predicates = Predicate.find(:all) - existing_predicates
+
+ assert_equal(extra_predicates.length, 1)
+
+ predicate = extra_predicates.first
+
+ # get the predicate
+
+ response = rest_request(:get, 'predicate', nil, "id" => predicate.id,
+ "elements" => "title,description,phrase,equivalent-to")
+
+ assert_response(:success)
+
+ assert_equal(title, response.find_first('/predicate/title').inner_xml)
+ assert_equal(description, response.find_first('/predicate/description').inner_xml)
+ assert_equal(phrase, response.find_first('/predicate/phrase').inner_xml)
+ assert_equal(equivalent_to, response.find_first('/predicate/equivalent-to').inner_xml)
+
+ # update the predicate
+
+ rest_request(:put, 'predicate', "<?xml version='1.0'?>
+ <predicate>
+ <title>#{title2}</title>
+ </predicate>", "id" => predicate.id)
+
+ assert_response(:success)
+
+ # get the updated predicate
+
+ response = rest_request(:get, 'predicate', nil, "id" => predicate.id,
+ "elements" => "title,description")
+
+ assert_response(:success)
+
+ assert_equal(title2, response.find_first('/predicate/title').inner_xml)
+ assert_equal(description, response.find_first('/predicate/description').inner_xml)
+
+ # delete the predicate
+
+ rest_request(:delete, 'predicate', nil, "id" => predicate.id)
+
+ assert_response(:success)
+
+ # try to get the deleted predicate
+
+ rest_request(:get, 'predicate', nil, "id" => predicate.id)
+
+ assert_response(:not_found)
+ end
+
+ def test_relationships
+
+ existing_relationships = Relationship.find(:all)
+
+ login_as(:john)
+
+ subject_url = rest_resource_uri(workflows(:workflow_branch_choice))
+ predicate_url = rest_resource_uri(predicates(:test_predicate_1))
+ objekt_url = rest_resource_uri(workflows(:workflow_dilbert))
+ context_url = rest_resource_uri(packs(:pack_1))
+
+ # post a relationship
+
+ rest_request(:post, 'relationship', "<?xml version='1.0'?>
+ <relationship>
+ <subject resource='#{subject_url}'/>
+ <predicate resource='#{predicate_url}'/>
+ <object resource='#{objekt_url}'/>
+ <context resource='#{context_url}'/>
+ </relationship>")
+
+ assert_response(:success)
+
+ extra_relationships = Relationship.find(:all) - existing_relationships
+
+ assert_equal(extra_relationships.length, 1)
+
+ relationship = extra_relationships.first
+
+ # get the relationship
+
+ response = rest_request(:get, 'relationship', nil, "id" => relationship.id,
+ "elements" => "user,subject,predicate,object,context")
+
+ assert_response(:success)
+
+ assert_equal(subject_url, response.find_first('/relationship/subject/*/@resource').value)
+ assert_equal(predicate_url, response.find_first('/relationship/predicate/@resource').value)
+ assert_equal(objekt_url, response.find_first('/relationship/object/*/@resource').value)
+ assert_equal(context_url, response.find_first('/relationship/context/*/@resource').value)
+
+ # delete the relationship
+
+ rest_request(:delete, 'relationship', nil, "id" => relationship.id)
+
+ assert_response(:success)
+
+ # try to get the deleted relationship
+
+ rest_request(:get, 'relationship', nil, "id" => relationship.id)
+
+ assert_response(:not_found)
+ end
+
+ private
+
+ def rest_request(method, uri, data = "" query = {})
+
+ @request.query_parameters!(query) if query
+
+ @request.env['RAW_POST_DATA'] = data if data
+
+ # puts "Sending: #{data.inspect}"
+
+ case method
+ when :get; get(:process_request, { :uri => uri, :format => "xml" } )
+ when :post; post(:process_request, { :uri => uri, :format => "xml" } )
+ when :put; put(:process_request, { :uri => uri, :format => "xml" } )
+ when :delete; delete(:process_request, { :uri => uri, :format => "xml" } )
+ end
+
+ # puts "Response: #{LibXML::XML::Parser.string(@response.body).parse.root.to_s}"
+
+ LibXML::XML::Parser.string(@response.body).parse
+ end
+end
+
+# Custom version of the TestRequest, so that I can set the query parameters of
+# a request.
+
+class TestRequestWithQuery < ActionController::TestRequest
+
+ def query_parameters!(hash)
+ @custom_query_parameters = hash
+ end
+
+
+ def recycle!
+ super
+
+ if @custom_query_parameters
+ self.query_parameters = @custom_query_parameters
+ @custom_query_parameters = nil
+ end
+ end
+end
+