From 23d96df630689d122c023d76ec1d40d7688d2c96 Mon Sep 17 00:00:00 2001 From: mguetlein Date: Wed, 19 Jan 2011 15:59:12 +0100 Subject: extend authorization and rdf serialization for validation --- lib/authorization.rb | 48 ++++++++++++++++---- lib/dataset.rb | 7 +-- lib/error.rb | 11 +++++ lib/helper.rb | 25 ++++++----- lib/opentox-ruby.rb | 3 +- lib/overwrite.rb | 10 +++-- lib/policy.rb | 10 +++++ lib/serializer.rb | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/to-html.rb | 3 +- 9 files changed, 213 insertions(+), 28 deletions(-) create mode 100644 lib/error.rb (limited to 'lib') diff --git a/lib/authorization.rb b/lib/authorization.rb index f9499e6..c33f712 100644 --- a/lib/authorization.rb +++ b/lib/authorization.rb @@ -132,6 +132,20 @@ module OpenTox end end + # Lists policies alongside with affected uris + # @param [String] subjectid + # @return [Hash] keys: all policies of the subjectid owner, values: uris affected by those policies + def self.list_policy_uris( subjectid ) + names = list_policies(subjectid) + policies = {} + names.each do |n| + p = OpenTox::Policies.new + p.load_xml( list_policy(n, subjectid) ) + policies[n] = p.uris + end + policies + end + #Returns the owner (who created the first policy) of an URI # @param [String, String]uri,subjectid # return [String, nil]owner,nil returns owner of the URI @@ -271,21 +285,37 @@ module OpenTox return true end - #Checks (if subjectid is valid) if a policy exist and create default policy if not + # Checks (if subjectid is valid) if a policy exist and create default policy if not + # @param [String] uri + # @param [String] subjectid + # @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else def self.check_policy(uri, subjectid) + return true unless uri and subjectid token_valid = OpenTox::Authorization.is_token_valid(subjectid) LOGGER.debug "OpenTox::Authorization.check_policy with uri: #{uri}, subjectid: #{subjectid} is valid: #{token_valid}" - if uri and token_valid - if !uri_has_policy(uri, subjectid) - return send_policy(uri, subjectid) - else - LOGGER.debug "OpenTox::Authorization.check_policy URI: #{uri} has already a Policy." + # check if subjectid is valid + unless token_valid + # abort if invalid + LOGGER.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}" + return false + end + + if !uri_has_policy(uri, subjectid) + # if no policy exists, create a policy, return result of send policy + send_policy(uri, subjectid) + else + LOGGER.debug "OpenTox::Authorization.check_policy URI: #{uri} has already a Policy." + # if policy exists check for POST rights + if authorize(uri, "POST", subjectid) + true + else + LOGGER.error "OpenTox::Authorization.check_policy, already exists, but no POST-authorization with subjectid: #{subjectid}" + false end end - true - end + end - end + end end diff --git a/lib/dataset.rb b/lib/dataset.rb index d45c821..ae86f5f 100644 --- a/lib/dataset.rb +++ b/lib/dataset.rb @@ -253,11 +253,12 @@ module OpenTox # @param [Array] compounds List of compound URIs # @param [Array] features List of feature URIs # @param [Hash] metadata Hash containing the metadata for the new dataset + # @param [String] subjectid # @return [OpenTox::Dataset] newly created dataset, already saved - def split( compounds, features, metadata) + def split( compounds, features, metadata, subjectid=nil) LOGGER.debug "split dataset using "+compounds.size.to_s+"/"+@compounds.size.to_s+" compounds" raise "no new compounds selected" unless compounds and compounds.size>0 - dataset = OpenTox::Dataset.create + dataset = OpenTox::Dataset.create(CONFIG[:services]["opentox-dataset"],subjectid) if features.size==0 compounds.each{ |c| dataset.add_compound(c) } else @@ -270,7 +271,7 @@ module OpenTox end end dataset.add_metadata(metadata) - dataset.save + dataset.save(subjectid) dataset end diff --git a/lib/error.rb b/lib/error.rb new file mode 100644 index 0000000..87e1a5d --- /dev/null +++ b/lib/error.rb @@ -0,0 +1,11 @@ +module OpenTox + + class NotFoundError < RuntimeError + + end + + class BadRequestError < RuntimeError + + end + +end \ No newline at end of file diff --git a/lib/helper.rb b/lib/helper.rb index 965b4ad..bb0279e 100644 --- a/lib/helper.rb +++ b/lib/helper.rb @@ -3,22 +3,24 @@ helpers do # Authentification def protected!(subjectid) if env["session"] - flash[:notice] = "You don't have access to this section: " and \ - redirect back and \ - return unless authorized?(subjectid) + unless authorized?(subjectid) + flash[:notice] = "You don't have access to this section: " + redirect back + end elsif !env["session"] && subjectid - throw(:halt, [401, "Not authorized.\n"]) and \ - redirect back and \ - return unless authorized?(subjectid) + unless authorized?(subjectid) + throw(:halt, [401, "Not authorized.\n"]) + redirect back + end + else + throw(:halt, [401, "Not authorized.\n"]) unless authorized?(subjectid) end - throw(:halt, [401, "Not authorized.\n"]) and \ - return unless authorized?(subjectid) end def authorized?(subjectid) if CONFIG[:authorization][:authorize_request].include?(request.env['REQUEST_METHOD']) ret = OpenTox::Authorization.authorize("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}", request.env['REQUEST_METHOD'], subjectid) - LOGGER.debug "OpenTox helpers OpenTox::Authorization authorized? method: #{request.env['REQUEST_METHOD']} , URI: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}, subjectid: #{subjectid} with return #{ret}." + LOGGER.debug "OpenTox helpers OpenTox::Authorization authorized? method: #{request.env['REQUEST_METHOD']}, URI: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}, subjectid: #{subjectid} with return #{ret}." return ret end if CONFIG[:authorization][:authenticate_request].include?(env['REQUEST_METHOD']) @@ -49,7 +51,7 @@ helpers do end before do - unless unprotected_requests or CONFIG[:authorization][:free_request].include?(env['REQUEST_METHOD']) + unless !AA_SERVER or unprotected_requests or CONFIG[:authorization][:free_request].include?(env['REQUEST_METHOD']) begin subjectid = session[:subjectid] if session[:subjectid] subjectid = params[:subjectid] if params[:subjectid] and !check_subjectid(subjectid) @@ -60,7 +62,8 @@ before do LOGGER.debug "OpenTox ruby api wrapper: helper before filter: NO subjectid for URI: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}" subjectid = "" end - protected!(subjectid) if AA_SERVER + @subjectid = subjectid + protected!(subjectid) end end diff --git a/lib/opentox-ruby.rb b/lib/opentox-ruby.rb index fb3803b..fc1732d 100644 --- a/lib/opentox-ruby.rb +++ b/lib/opentox-ruby.rb @@ -8,6 +8,7 @@ rescue LoadError puts "Please install Openbabel with 'rake openbabel:install' in the compound component" end -['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature', 'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html'].each do |lib| +['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature', + 'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html', 'error' ].each do |lib| require lib end diff --git a/lib/overwrite.rb b/lib/overwrite.rb index ffeba21..720ed77 100644 --- a/lib/overwrite.rb +++ b/lib/overwrite.rb @@ -1,7 +1,11 @@ # class overwrites aka monkey patches -# hack: store sinatra in global var to make url_for and halt methods accessible +# hack: store sinatra instance in global var $url_provider to make url_for and halt methods accessible before { - $sinatra = self unless $sinatra + raise "should not happen, url provider already differently initialized "+ + $url_provider.request.host.to_s+" != "+self.request.host.to_s if + $url_provider and $url_provider.request.host!=self.request.host and + $url_provider.request.script_name!=self.request.script_name + $url_provider = self # stupid internet explorer does not ask for text/html, add this manually request.env['HTTP_ACCEPT'] += ";text/html" if request.env["HTTP_USER_AGENT"]=~/MSIE/ } @@ -91,7 +95,7 @@ class OTLogger < Logger end def format(msg) - pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace+" :: "+($sinatra ? $sinatra.request.env['REMOTE_ADDR'] : nil).to_s + pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace end def debug(msg) diff --git a/lib/policy.rb b/lib/policy.rb index 0ef8298..08bf6ed 100644 --- a/lib/policy.rb +++ b/lib/policy.rb @@ -32,6 +32,11 @@ module OpenTox end return true end + + # @return [Array] set of arrays affected by policies + def uris + @policies.collect{ |k,v| v.uris }.flatten.uniq + end #loads a default policy template in policies instance def load_default_policy(user, uri, group="member") @@ -190,6 +195,11 @@ module OpenTox @subjects[name] = Subject.new(name, type, value) end + # @return [Array] set of uris affected by policy + def uris + @rules.collect{ |k,v| v.uri }.uniq + end + #rule inside a policy class Rule diff --git a/lib/serializer.rb b/lib/serializer.rb index 495702a..03c2639 100644 --- a/lib/serializer.rb +++ b/lib/serializer.rb @@ -26,6 +26,15 @@ module OpenTox OT.Algorithm => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , OT.Parameter => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , OT.Task => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + #classes for validation + OT.Validation => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.ClassificationStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.ConfusionMatrix => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.ConfusionMatrixCell => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.ClassValueStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.RegressionStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.Crossvalidation => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , + OT.CrossvalidationInfo => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } , OT.compound => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , OT.feature => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , @@ -34,6 +43,22 @@ module OpenTox OT.values => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , OT.algorithm => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , OT.parameters => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + #object props for validation# + OT.model => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.trainingDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.predictionFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.predictionDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.crossvalidation => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.testTargetDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.testDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.classificationStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.confusionMatrix => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.confusionMatrixCell => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.classValueStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.regressionStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.validation => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.crossvalidationInfo => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , + OT.dataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } , DC.title => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , DC.identifier => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , @@ -47,6 +72,47 @@ module OpenTox OT.hasStatus => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , OT.resultURI => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , OT.percentageCompleted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + # annotation props for validation + OT.numUnpredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.crossvalidationFold => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numInstances => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numWithoutClass => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.percentWithoutClass => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.percentUnpredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.confusionMatrixActual => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.confusionMatrixPredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.confusionMatrixValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numIncorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.percentCorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numCorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.accuracy => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.trueNegativeRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.truePositiveRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.falseNegativeRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.falsePositiveRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numTrueNegatives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numTruePositives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numFalseNegatives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numFalsePositives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.classValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.precision => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.areaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.weightedAreaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.fMeasure => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.percentIncorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.validationType => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.realRuntime => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.sampleCorrelationCoefficient => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.targetVarianceActual => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.targetVariancePredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.meanAbsoluteError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.sumSquaredError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.rootMeanSquaredError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.rSquare => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.stratified => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.numFolds => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.randomSeed => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , + OT.reportType => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } , OT.hasSource => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } , OT.value => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } , @@ -121,6 +187,64 @@ module OpenTox @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Task }] } add_metadata uri, metadata end + + # Add a resource defined by resource_class and content + # (see documentation of add_content for example) + # @param [String] uri of resource + # @param [String] resource class, e.g. OT.Validation + # @param [Hash] content as hash + def add_resource(uri, resource_class, content) + @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => resource_class }] } + @@content_id = 1 + add_content uri, content + end + + private + @@content_id = 1 + + # Recursiv function to add content + # @example + # { DC.description => "bla", + # OT.similar_resources => [ "http://uri1", "http://uri2" ], + # OT.matrixCells => + # [ { RDF.type => OT.MatrixCell, OT.cellIndex=1 OT.cellValue => "xy" }, + # { RDF.type => OT.MatrixCell, OT.cellIndex=2 OT.cellValue => "z" } ], + # OT.info => { RDF.type => OT.ImportantInfo, + # DC.description => "blub" } + # } + # @param [String] uri + # @param [Hash] content as hash, uri must already have been added to @object + def add_content(uri, hash) + raise "content is no hash: "+hash.class.to_s unless hash.is_a?(Hash) + hash.each do |u,v| + if v.is_a? Hash + # value is again a hash, i.e. a new owl class is added + # first make sure type (==class) is set + type = v[RDF.type] + raise "type missing for "+u.to_s+" content:\n"+v.inspect unless type + raise "class unknown "+type.to_s+" (for "+u.to_s+")" unless @object.has_key?(type) + # create new node and add to current uri + genid = "_:#{type.split('#')[-1]}#{@@content_id}" + @@content_id += 1 + @object[uri] = {} unless @object[uri] + @object[uri][u] = [{ "type" => "bnode", "value" => genid }] + # add content to new class + add_hash(genid,v) + elsif v.is_a? Array + # value is an array, i.e. a list of values with property is added + v.each{ |vv| add_hash( uri, { u => vv } ) } + else # v.is_a? String + # simple string value + @object[uri] = {} unless @object[uri] + @object[uri][u] = [] unless @object[uri][u] + raise "property unknown "+u.to_s if !@object.has_key?(u) and u!=RDF.type + # use << to allow different values for one property + @object[uri][u] << {"type" => type(v), "value" => v } + end + end + end + + public # Add metadata # @param [Hash] metadata diff --git a/lib/to-html.rb b/lib/to-html.rb index 1bc1496..e9764ef 100755 --- a/lib/to-html.rb +++ b/lib/to-html.rb @@ -27,7 +27,8 @@ module OpenTox # @return [String] html page def self.text_to_html( text, related_links=nil, description=nil, post_params=nil ) - title = $sinatra.url_for($sinatra.request.env['PATH_INFO'], :full) if $sinatra + # TODO add title as parameter + title = nil #$sinatra.url_for($sinatra.request.env['PATH_INFO'], :full) if $sinatra html = < -- cgit v1.2.3