opentox-client 0.0.1pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/LICENSE +674 -0
- data/README.markdown +17 -0
- data/Rakefile +11 -0
- data/lib/algorithm.rb +15 -0
- data/lib/authorization.rb +392 -0
- data/lib/compound.rb +170 -0
- data/lib/dataset.rb +318 -0
- data/lib/error.rb +106 -0
- data/lib/model.rb +14 -0
- data/lib/opentox-client.rb +32 -0
- data/lib/opentox.rb +145 -0
- data/lib/otlogger.rb +45 -0
- data/lib/overwrite.rb +90 -0
- data/lib/policy.rb +261 -0
- data/lib/rest-client-wrapper.rb +47 -0
- data/lib/task.rb +123 -0
- data/lib/templates/default_guest_policy.xml +53 -0
- data/lib/templates/default_policy.xml +53 -0
- data/opentox-client.gemspec +27 -0
- data/test/compound.rb +52 -0
- data/test/data/CPDBAS_v5c_1547_29Apr2008part.sdf +13553 -0
- data/test/data/EPAFHM.csv +618 -0
- data/test/data/EPAFHM.mini.csv +21 -0
- data/test/data/ISSCAN-multi.csv +59 -0
- data/test/data/cpdb_100.csv +101 -0
- data/test/data/hamster_carcinogenicity.csv +86 -0
- data/test/data/hamster_carcinogenicity.mini.csv +11 -0
- data/test/data/hamster_carcinogenicity.sdf +2805 -0
- data/test/data/hamster_carcinogenicity.xls +0 -0
- data/test/data/hamster_carcinogenicity.yaml +352 -0
- data/test/data/hamster_carcinogenicity_with_errors.csv +88 -0
- data/test/data/kazius.csv +4069 -0
- data/test/data/multi_cell_call.csv +1067 -0
- data/test/data/multicolumn.csv +5 -0
- data/test/dataset.rb +53 -0
- data/test/error.rb +35 -0
- data/test/feature.rb +36 -0
- data/test/task.rb +85 -0
- metadata +144 -0
data/lib/opentox.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# defaults to stderr, may be changed to file output (e.g in opentox-service)
|
2
|
+
$logger = OTLogger.new(STDERR)
|
3
|
+
$logger.level = Logger::DEBUG
|
4
|
+
|
5
|
+
module OpenTox
|
6
|
+
|
7
|
+
attr_accessor :uri, :subjectid, :rdf, :response
|
8
|
+
|
9
|
+
# Ruby interface
|
10
|
+
|
11
|
+
# Create a new OpenTox object (does not load data from service)
|
12
|
+
# @param [optional,String] URI
|
13
|
+
# @param [optional,String] subjectid
|
14
|
+
# @return [OpenTox] OpenTox object
|
15
|
+
def initialize uri=nil, subjectid=nil
|
16
|
+
@uri = uri.to_s.chomp
|
17
|
+
@subjectid = subjectid
|
18
|
+
@rdf = RDF::Graph.new
|
19
|
+
end
|
20
|
+
|
21
|
+
# Load metadata from service
|
22
|
+
def pull
|
23
|
+
kind_of?(OpenTox::Dataset) ? uri = File.join(@uri,"metadata") : uri = @uri
|
24
|
+
# TODO generic method for all formats
|
25
|
+
parse_rdfxml RestClientWrapper.get(uri,{},{:accept => $default_rdf, :subjectid => @subjectid})
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get object metadata
|
29
|
+
# @return [Hash] Metadata
|
30
|
+
def metadata
|
31
|
+
pull if @rdf.empty?
|
32
|
+
metadata = {}
|
33
|
+
@rdf.query([RDF::URI.new(@uri),nil,nil]).collect do |statement|
|
34
|
+
metadata[statement.predicate] ||= []
|
35
|
+
metadata[statement.predicate] << statement.object
|
36
|
+
end
|
37
|
+
metadata
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get metadata values
|
41
|
+
# @param [RDF] Key from RDF Vocabularies
|
42
|
+
# @return [Array] Values for supplied key
|
43
|
+
def [](key)
|
44
|
+
pull if @rdf.empty?
|
45
|
+
@rdf.query([RDF::URI.new(@uri),key,nil]).collect{|statement| statement.object}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Save object at service
|
49
|
+
def save
|
50
|
+
#TODO: dynamic assignment
|
51
|
+
post self.to_rdfxml, { :content_type => $default_rdf}
|
52
|
+
end
|
53
|
+
|
54
|
+
RDF_FORMATS.each do |format|
|
55
|
+
|
56
|
+
# rdf parse methods for all formats e.g. parse_rdfxml
|
57
|
+
send :define_method, "parse_#{format}".to_sym do |rdf|
|
58
|
+
@rdf = RDF::Graph.new
|
59
|
+
RDF::Reader.for(format).new(rdf) do |reader|
|
60
|
+
reader.each_statement{ |statement| @rdf << statement }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# rdf serialization methods for all formats e.g. to_rdfxml
|
65
|
+
send :define_method, "to_#{format}".to_sym do
|
66
|
+
rdf = RDF::Writer.for(format).buffer do |writer|
|
67
|
+
@rdf.each{|statement| writer << statement}
|
68
|
+
end
|
69
|
+
rdf
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# REST API
|
74
|
+
def get headers={}
|
75
|
+
headers[:subjectid] ||= @subjectid
|
76
|
+
headers[:accept] ||= 'application/rdf+xml'
|
77
|
+
@response = RestClientWrapper.get @uri, {}, headers
|
78
|
+
end
|
79
|
+
|
80
|
+
def post payload={}, headers={}
|
81
|
+
headers[:subjectid] ||= @subjectid
|
82
|
+
headers[:accept] ||= 'application/rdf+xml'
|
83
|
+
@response = RestClientWrapper.post(@uri.to_s, payload, headers)
|
84
|
+
end
|
85
|
+
|
86
|
+
def put payload={}, headers={}
|
87
|
+
headers[:subjectid] ||= @subjectid
|
88
|
+
headers[:accept] ||= 'application/rdf+xml'
|
89
|
+
@response = RestClientWrapper.put(@uri.to_s, payload, headers)
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete headers={}
|
93
|
+
headers[:subjectid] ||= @subjectid
|
94
|
+
@response = RestClientWrapper.delete(@uri.to_s,nil,headers)
|
95
|
+
end
|
96
|
+
|
97
|
+
# class methods
|
98
|
+
module ClassMethods
|
99
|
+
|
100
|
+
def all service_uri, subjectid=nil
|
101
|
+
uris = RestClientWrapper.get(service_uri, {}, :accept => 'text/uri-list').split("\n").compact
|
102
|
+
uris.collect{|uri| URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid)}
|
103
|
+
end
|
104
|
+
|
105
|
+
def create service_uri, subjectid=nil
|
106
|
+
uri = RestClientWrapper.post(service_uri, {}, {:accept => 'text/uri-list', :subjectid => subjectid})
|
107
|
+
URI.task?(service_uri) ? from_uri(uri, subjectid, false) : from_uri(uri, subjectid)
|
108
|
+
end
|
109
|
+
|
110
|
+
def from_file service_uri, filename, subjectid=nil
|
111
|
+
file = File.new filename
|
112
|
+
from_uri RestClientWrapper.post(service_uri, {:file => file}, {:subjectid => subjectid, :content_type => file.mime_type, :accept => "text/uri-list"}), subjectid
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def from_uri uri, subjectid=nil, wait=true
|
117
|
+
|
118
|
+
uri.chomp!
|
119
|
+
# TODO add waiting task
|
120
|
+
if URI.task? uri and wait
|
121
|
+
t = OpenTox::Task.new(uri)
|
122
|
+
t.wait
|
123
|
+
uri = t.resultURI
|
124
|
+
end
|
125
|
+
|
126
|
+
# guess class from uri, this is potentially unsafe, but polling metadata from large uri lists is way too slow (and not all service provide RDF.type in their metadata)
|
127
|
+
result = CLASSES.collect{|s| s if uri =~ /#{s.downcase}/}.compact
|
128
|
+
internal_server_error "Cannot determine class from URI: '#{uri}.\nCandidate classes are #{result.inspect}" unless result.size == 1
|
129
|
+
klass = result.first
|
130
|
+
# initialize with/without subjectid
|
131
|
+
subjectid ? eval("#{self}.new(\"#{uri}\", #{subjectid})") : eval("#{self}.new(\"#{uri}\")")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# create default OpenTox classes
|
136
|
+
CLASSES.each do |klass|
|
137
|
+
c = Class.new do
|
138
|
+
include OpenTox
|
139
|
+
extend OpenTox::ClassMethods
|
140
|
+
end
|
141
|
+
OpenTox.const_set klass,c
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
data/lib/otlogger.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class OTLogger < Logger
|
2
|
+
|
3
|
+
def pwd
|
4
|
+
path = Dir.pwd.to_s
|
5
|
+
index = path.rindex(/\//)
|
6
|
+
return path if index==nil
|
7
|
+
path[(index+1)..-1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def trace()
|
11
|
+
lines = caller(0)
|
12
|
+
n = 2
|
13
|
+
line = lines[n]
|
14
|
+
|
15
|
+
while (line =~ /error.rb/ or line =~ /create/ or line =~ /#{File.basename(__FILE__)}/)
|
16
|
+
n += 1
|
17
|
+
line = lines[n]
|
18
|
+
end
|
19
|
+
|
20
|
+
index = line.rindex(/\/.*\.rb/)
|
21
|
+
return line if index==nil
|
22
|
+
line[index..-1]
|
23
|
+
end
|
24
|
+
|
25
|
+
def format(msg)
|
26
|
+
pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace
|
27
|
+
end
|
28
|
+
|
29
|
+
def debug(msg)
|
30
|
+
super format(msg)
|
31
|
+
end
|
32
|
+
|
33
|
+
def info(msg)
|
34
|
+
super format(msg)
|
35
|
+
end
|
36
|
+
|
37
|
+
def warn(msg)
|
38
|
+
super format(msg)
|
39
|
+
end
|
40
|
+
|
41
|
+
def error(msg)
|
42
|
+
super format(msg)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/overwrite.rb
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
class String
|
2
|
+
def underscore
|
3
|
+
self.gsub(/::/, '/').
|
4
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
5
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
6
|
+
tr("-", "_").
|
7
|
+
downcase
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module URI
|
12
|
+
|
13
|
+
def self.compound? uri
|
14
|
+
uri =~ /compound/ and URI.valid? uri
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.task? uri
|
18
|
+
uri =~ /task/ and URI.valid? uri
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.dataset? uri, subjectid=nil
|
22
|
+
uri =~ /dataset/ and URI.accessible? uri, subjectid=nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.model? uri, subjectid=nil
|
26
|
+
uri =~ /model/ and URI.accessible? uri, subjectid=nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.accessible? uri, subjectid=nil
|
30
|
+
if URI.task? uri or URI.compound? uri
|
31
|
+
# just try to get a response, valid tasks may return codes > 400
|
32
|
+
Net::HTTP.get_response(URI.parse(uri))
|
33
|
+
true
|
34
|
+
else
|
35
|
+
Net::HTTP.get_response(URI.parse(uri)).code.to_i < 400
|
36
|
+
end
|
37
|
+
rescue
|
38
|
+
false
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.valid? uri
|
42
|
+
u = URI::parse(uri)
|
43
|
+
u.scheme!=nil and u.host!=nil
|
44
|
+
rescue URI::InvalidURIError
|
45
|
+
false
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
class File
|
51
|
+
def mime_type
|
52
|
+
`file -ib #{self.path}`.chomp
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# overwrite backtick operator to catch system errors
|
57
|
+
module Kernel
|
58
|
+
|
59
|
+
# Override raises an error if _cmd_ returns a non-zero exit status.
|
60
|
+
# Returns stdout if _cmd_ succeeds. Note that these are simply concatenated; STDERR is not inline.
|
61
|
+
def ` cmd
|
62
|
+
stdout, stderr = ''
|
63
|
+
status = Open4::popen4(cmd) do |pid, stdin_stream, stdout_stream, stderr_stream|
|
64
|
+
stdout = stdout_stream.read
|
65
|
+
stderr = stderr_stream.read
|
66
|
+
end
|
67
|
+
raise stderr.strip if !status.success?
|
68
|
+
return stdout
|
69
|
+
rescue Exception
|
70
|
+
internal_server_error $!
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :system!, :system
|
74
|
+
|
75
|
+
def system cmd
|
76
|
+
`#{cmd}`
|
77
|
+
return true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Array
|
82
|
+
def short_backtrace
|
83
|
+
short = []
|
84
|
+
each do |c|
|
85
|
+
break if c =~ /sinatra\/base/
|
86
|
+
short << c
|
87
|
+
end
|
88
|
+
short.join("\n")
|
89
|
+
end
|
90
|
+
end
|
data/lib/policy.rb
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
module OpenTox
|
2
|
+
require "rexml/document"
|
3
|
+
|
4
|
+
#Module for policy-processing
|
5
|
+
# @see also http://www.opentox.org/dev/apis/api-1.2/AA for opentox API specs
|
6
|
+
# Class Policies corresponds to <policies> container of an xml-policy-fle
|
7
|
+
class Policies
|
8
|
+
|
9
|
+
attr_accessor :name, :policies
|
10
|
+
|
11
|
+
def initialize()
|
12
|
+
@policies = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
#create new policy instance with name
|
16
|
+
# @param [String]name of the policy
|
17
|
+
def new_policy(name)
|
18
|
+
@policies[name] = Policy.new(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
#drop a specific policy in a policies instance
|
22
|
+
# @param [String]name of the policy
|
23
|
+
# @return [Boolean]
|
24
|
+
def drop_policy(name)
|
25
|
+
return true if @policies.delete(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
#drop all policies in a policies instance
|
29
|
+
def drop_policies
|
30
|
+
@policies.each do |name, policy|
|
31
|
+
drop_policy(name)
|
32
|
+
end
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Array] set of arrays affected by policies
|
37
|
+
def uris
|
38
|
+
@policies.collect{ |k,v| v.uris }.flatten.uniq
|
39
|
+
end
|
40
|
+
|
41
|
+
#drop all policies in a policies instance
|
42
|
+
def names
|
43
|
+
out = []
|
44
|
+
@policies.each do |name, policy|
|
45
|
+
out << name
|
46
|
+
end
|
47
|
+
return out
|
48
|
+
end
|
49
|
+
|
50
|
+
#loads a default policy template in policies instance
|
51
|
+
def load_default_policy(user, uri, group="member")
|
52
|
+
template = case user
|
53
|
+
when "guest", "anonymous" then "default_guest_policy"
|
54
|
+
else "default_policy"
|
55
|
+
end
|
56
|
+
xml = File.read(File.join(File.dirname(__FILE__), "templates/#{template}.xml"))
|
57
|
+
self.load_xml(xml)
|
58
|
+
datestring = Time.now.strftime("%Y-%m-%d-%H-%M-%S-x") + rand(1000).to_s
|
59
|
+
|
60
|
+
@policies["policy_user"].name = "policy_user_#{user}_#{datestring}"
|
61
|
+
@policies["policy_user"].rules["rule_user"].uri = uri
|
62
|
+
@policies["policy_user"].rules["rule_user"].name = "rule_user_#{user}_#{datestring}"
|
63
|
+
@policies["policy_user"].subjects["subject_user"].name = "subject_user_#{user}_#{datestring}"
|
64
|
+
@policies["policy_user"].subjects["subject_user"].value = "uid=#{user},ou=people,dc=opentox,dc=org"
|
65
|
+
@policies["policy_user"].subject_group = "subjects_user_#{user}_#{datestring}"
|
66
|
+
|
67
|
+
@policies["policy_group"].name = "policy_group_#{group}_#{datestring}"
|
68
|
+
@policies["policy_group"].rules["rule_group"].uri = uri
|
69
|
+
@policies["policy_group"].rules["rule_group"].name = "rule_group_#{group}_#{datestring}"
|
70
|
+
@policies["policy_group"].subjects["subject_group"].name = "subject_group_#{group}_#{datestring}"
|
71
|
+
@policies["policy_group"].subjects["subject_group"].value = "cn=#{group},ou=groups,dc=opentox,dc=org"
|
72
|
+
@policies["policy_group"].subject_group = "subjects_#{group}_#{datestring}"
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
|
76
|
+
#loads a xml template
|
77
|
+
def load_xml(xml)
|
78
|
+
rexml = REXML::Document.new(xml)
|
79
|
+
rexml.elements.each("Policies/Policy") do |pol| #Policies
|
80
|
+
policy_name = pol.attributes["name"]
|
81
|
+
new_policy(policy_name)
|
82
|
+
#@policies[policy_name] = Policy.new(policy_name)
|
83
|
+
rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Rule") do |r| #Rules
|
84
|
+
rule_name = r.attributes["name"]
|
85
|
+
uri = rexml.elements["Policies/Policy[@name='#{policy_name}']/Rule[@name='#{rule_name}']/ResourceName"].attributes["name"]
|
86
|
+
@policies[policy_name].rules[rule_name] = @policies[policy_name].new_rule(rule_name, uri)
|
87
|
+
rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Rule[@name='#{rule_name}']/AttributeValuePair") do |attribute_pairs|
|
88
|
+
action=nil; value=nil;
|
89
|
+
attribute_pairs.each_element do |elem|
|
90
|
+
action = elem.attributes["name"] if elem.attributes["name"]
|
91
|
+
value = elem.text if elem.text
|
92
|
+
end
|
93
|
+
if action and value
|
94
|
+
case action
|
95
|
+
when "GET"
|
96
|
+
@policies[policy_name].rules[rule_name].get = value
|
97
|
+
when "POST"
|
98
|
+
@policies[policy_name].rules[rule_name].post = value
|
99
|
+
when "PUT"
|
100
|
+
@policies[policy_name].rules[rule_name].put = value
|
101
|
+
when "DELETE"
|
102
|
+
@policies[policy_name].rules[rule_name].delete = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Subjects") do |subjects| #Subjects
|
108
|
+
@policies[policy_name].subject_group = subjects.attributes["name"]
|
109
|
+
rexml.elements.each("Policies/Policy[@name='#{policy_name}']/Subjects[@name='#{@policies[policy_name].subject_group}']/Subject") do |s| #Subject
|
110
|
+
subject_name = s.attributes["name"]
|
111
|
+
subject_type = s.attributes["type"]
|
112
|
+
subject_value = rexml.elements["Policies/Policy[@name='#{policy_name}']/Subjects[@name='#{@policies[policy_name].subject_group}']/Subject[@name='#{subject_name}']/AttributeValuePair/Value"].text
|
113
|
+
@policies[policy_name].new_subject(subject_name, subject_type, subject_value) if subject_name and subject_type and subject_value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
#generates xml from policies instance
|
120
|
+
def to_xml
|
121
|
+
doc = REXML::Document.new()
|
122
|
+
doc << REXML::DocType.new("Policies", "PUBLIC \"-//Sun Java System Access Manager7.1 2006Q3\n Admin CLI DTD//EN\" \"jar://com/sun/identity/policy/policyAdmin.dtd\"")
|
123
|
+
doc.add_element(REXML::Element.new("Policies"))
|
124
|
+
|
125
|
+
@policies.each do |name, pol|
|
126
|
+
policy = REXML::Element.new("Policy")
|
127
|
+
policy.attributes["name"] = pol.name
|
128
|
+
policy.attributes["referralPolicy"] = false
|
129
|
+
policy.attributes["active"] = true
|
130
|
+
@policies[name].rules.each do |r,rl|
|
131
|
+
rule = @policies[name].rules[r]
|
132
|
+
out_rule = REXML::Element.new("Rule")
|
133
|
+
out_rule.attributes["name"] = rule.name
|
134
|
+
servicename = REXML::Element.new("ServiceName")
|
135
|
+
servicename.attributes["name"]="iPlanetAMWebAgentService"
|
136
|
+
out_rule.add_element(servicename)
|
137
|
+
rescourcename = REXML::Element.new("ResourceName")
|
138
|
+
rescourcename.attributes["name"] = rule.uri
|
139
|
+
out_rule.add_element(rescourcename)
|
140
|
+
|
141
|
+
["get","post","delete","put"].each do |act|
|
142
|
+
if rule.method(act).call
|
143
|
+
attribute = REXML::Element.new("Attribute")
|
144
|
+
attribute.attributes["name"] = act.upcase
|
145
|
+
attributevaluepair = REXML::Element.new("AttributeValuePair")
|
146
|
+
attributevaluepair.add_element(attribute)
|
147
|
+
attributevalue = REXML::Element.new("Value")
|
148
|
+
attributevaluepair.add_element(attributevalue)
|
149
|
+
attributevalue.add_text REXML::Text.new(rule.method(act).call)
|
150
|
+
out_rule.add_element(attributevaluepair)
|
151
|
+
|
152
|
+
end
|
153
|
+
end
|
154
|
+
policy.add_element(out_rule)
|
155
|
+
end
|
156
|
+
|
157
|
+
subjects = REXML::Element.new("Subjects")
|
158
|
+
subjects.attributes["name"] = pol.subject_group
|
159
|
+
subjects.attributes["description"] = ""
|
160
|
+
@policies[name].subjects.each do |subj, subjs|
|
161
|
+
subject = REXML::Element.new("Subject")
|
162
|
+
subject.attributes["name"] = pol.subjects[subj].name
|
163
|
+
subject.attributes["type"] = pol.subjects[subj].type
|
164
|
+
subject.attributes["includeType"] = "inclusive"
|
165
|
+
attributevaluepair = REXML::Element.new("AttributeValuePair")
|
166
|
+
attribute = REXML::Element.new("Attribute")
|
167
|
+
attribute.attributes["name"] = "Values"
|
168
|
+
attributevaluepair.add_element(attribute)
|
169
|
+
attributevalue = REXML::Element.new("Value")
|
170
|
+
attributevalue.add_text REXML::Text.new(pol.subjects[subj].value)
|
171
|
+
attributevaluepair.add_element(attributevalue)
|
172
|
+
subject.add_element(attributevaluepair)
|
173
|
+
subjects.add_element(subject)
|
174
|
+
end
|
175
|
+
policy.add_element(subjects)
|
176
|
+
doc.root.add_element(policy)
|
177
|
+
end
|
178
|
+
out = ""
|
179
|
+
doc.write(out, 2)
|
180
|
+
return out
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
#single policy in a policies instance
|
186
|
+
class Policy
|
187
|
+
|
188
|
+
attr_accessor :name, :rules, :subject_group, :subjects
|
189
|
+
|
190
|
+
def initialize(name)
|
191
|
+
@name = name
|
192
|
+
@rules = {}
|
193
|
+
@subject_group = ""
|
194
|
+
@subjects = {}
|
195
|
+
end
|
196
|
+
|
197
|
+
#create a new rule instance for the policy
|
198
|
+
def new_rule(name, uri)
|
199
|
+
@rules[name] = Rule.new(name, uri)
|
200
|
+
end
|
201
|
+
|
202
|
+
#create a new subject instance for the policy
|
203
|
+
def new_subject(name, type, value)
|
204
|
+
@subjects[name] = Subject.new(name, type, value)
|
205
|
+
end
|
206
|
+
|
207
|
+
# @return [Array] set of uris affected by policy
|
208
|
+
def uris
|
209
|
+
@rules.collect{ |k,v| v.uri }.uniq
|
210
|
+
end
|
211
|
+
|
212
|
+
#rule inside a policy
|
213
|
+
class Rule
|
214
|
+
|
215
|
+
attr_accessor :name, :uri, :get, :post, :put, :delete
|
216
|
+
|
217
|
+
def initialize(name, uri)
|
218
|
+
@name = name
|
219
|
+
@uri = uri
|
220
|
+
end
|
221
|
+
|
222
|
+
def rename(new, old)
|
223
|
+
self[new] = self.delete(old)
|
224
|
+
self[new].name = new
|
225
|
+
end
|
226
|
+
|
227
|
+
def get=(value)
|
228
|
+
@get = check_value(value, @get)
|
229
|
+
end
|
230
|
+
|
231
|
+
def post=(value)
|
232
|
+
@post = check_value(value, @post)
|
233
|
+
end
|
234
|
+
|
235
|
+
def delete=(value)
|
236
|
+
@delete = check_value(value, @delete)
|
237
|
+
end
|
238
|
+
|
239
|
+
def put=(value)
|
240
|
+
@put = check_value(value, @put)
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
#checks if value is allow or deny. returns old value if not valid.
|
245
|
+
def check_value(new_value, old_value)
|
246
|
+
return (new_value=="allow" || new_value=="deny" || new_value==nil) ? new_value : old_value
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class Subject
|
251
|
+
|
252
|
+
attr_accessor :name, :type, :value
|
253
|
+
|
254
|
+
def initialize(name, type, value)
|
255
|
+
@name = name
|
256
|
+
@type = type
|
257
|
+
@value = value
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|