opentox-client 0.0.1pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|