opentox-ruby 0.0.2 → 1.0.0

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/README.markdown ADDED
@@ -0,0 +1,41 @@
1
+ opentox-ruby
2
+ ============
3
+
4
+ Ruby wrapper for the [OpenTox](http://www.opentox.org) REST API
5
+
6
+ Installation
7
+ ------------
8
+
9
+ opentox-ruby depends on many third party programs and libraries, which makes the setup complicated and error prone. For this reason we recommend to use the installer from [opentox-install](http://github.com/opentox/opentox-install). If you want to install manually you can find the necessary steps in the installation scripts.
10
+
11
+ Quickstart
12
+ ----------
13
+
14
+ This example shows how to create a lazar model and predict a compound, it assumes that you have access to a working installation of OpenTox services with corresponding settings in $HOME/.opentox/config. Run the following code in irb or from a ruby script:
15
+
16
+ require 'rubygems'
17
+ require 'opentox-ruby'
18
+
19
+ # Authenticate
20
+ subjectid = OpenTox::Authorization.authenticate(USER,PASSWORD)
21
+
22
+ # Upload a dataset
23
+ training_dataset = OpenTox::Dataset.create_from_csv_file(TRAINING_DATASET, subjectid)
24
+
25
+ # Create a prediction model
26
+ model_uri = OpenTox::Algorithm::Lazar.new.run({:dataset_uri => training_dataset.uri, :subjectid => subjectid}).to_s
27
+ lazar = OpenTox::Model::Lazar.find model_uri, subjectid
28
+
29
+ # Predict a compound
30
+ compound = OpenTox::Compound.from_smiles("c1ccccc1NN")
31
+ prediction_uri = lazar.run(:compound_uri => compound.uri, :subjectid => subjectid)
32
+ prediction = OpenTox::LazarPrediction.find(prediction_uri, subjectid)
33
+ puts prediction.to_yaml
34
+
35
+ [API documentation](http://rdoc.info/gems/opentox-ruby/1.0.0/frames)
36
+ -------------------------------------------------------------------
37
+
38
+ Copyright
39
+ ---------
40
+
41
+ Copyright (c) 2009-2011 Christoph Helma, Martin Guetlein, Micha Rautenberg, Andreas Maunz, David Vorgrimmler, Denis Gebele. See LICENSE for details.
data/Rakefile CHANGED
@@ -27,8 +27,11 @@ begin
27
27
  "yajl-ruby",
28
28
  "tmail",
29
29
  "rinruby",
30
+ "ohm",
31
+ "SystemTimer",
30
32
  "rjb"
31
33
  ].each { |dep| gem.add_dependency dep }
34
+ =begin
32
35
  [ "dm-core",
33
36
  'dm-serializer',
34
37
  'dm-timestamps',
@@ -37,6 +40,7 @@ begin
37
40
  "dm-mysql-adapter",
38
41
  "dm-validations",
39
42
  ].each {|dep| gem.add_dependency dep, ">= 1" }
43
+ =end
40
44
  gem.add_dependency "haml", ">=3"
41
45
  ['jeweler'].each { |dep| gem.add_development_dependency dep }
42
46
  gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 1.0.0
data/lib/algorithm.rb CHANGED
@@ -13,9 +13,10 @@ module OpenTox
13
13
 
14
14
  # Execute algorithm with parameters, please consult the OpenTox API and the webservice documentation for acceptable parameters
15
15
  # @param [optional,Hash] params Algorithm parameters
16
+ # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
16
17
  # @return [String] URI of new resource (dataset, model, ...)
17
- def run(params=nil)
18
- RestClientWrapper.post(@uri, {:accept => 'text/uri-list'}, params).to_s
18
+ def run(params=nil, waiting_task=nil)
19
+ RestClientWrapper.post(@uri, params, {:accept => 'text/uri-list'}, waiting_task).to_s
19
20
  end
20
21
 
21
22
  # Get OWL-DL representation in RDF/XML format
@@ -29,6 +30,18 @@ module OpenTox
29
30
  # Generic Algorithm class, should work with all OpenTox webservices
30
31
  class Generic
31
32
  include Algorithm
33
+
34
+ # Find Generic Opentox Algorithm via URI, and loads metadata, could raise NotFound/NotAuthorized error
35
+ # @param [String] uri Algorithm URI
36
+ # @return [OpenTox::Algorithm::Generic] Algorithm instance
37
+ def self.find(uri, subjectid=nil)
38
+ return nil unless uri
39
+ alg = Generic.new(uri)
40
+ alg.load_metadata( subjectid )
41
+ raise "cannot load algorithm metadata" if alg.metadata==nil or alg.metadata.size==0
42
+ alg
43
+ end
44
+
32
45
  end
33
46
 
34
47
  # Fminer algorithms (https://github.com/amaunz/fminer2)
@@ -0,0 +1,381 @@
1
+ module OpenTox
2
+
3
+ #Module for Authorization and Authentication
4
+ #@example Authentication
5
+ # require "opentox-ruby-api-wrapper"
6
+ # OpenTox::Authorization::AA_SERVER = "https://opensso.in-silico.ch" #if not set in .opentox/conf/[environment].yaml
7
+ # token = OpenTox::Authorization.authenticate("benutzer", "passwort")
8
+ #@see http://www.opentox.org/dev/apis/api-1.2/AA OpenTox A&A API 1.2 specification
9
+
10
+ module Authorization
11
+
12
+ #Helper Class AA to create and send default policies out of xml templates
13
+ #@example Creating a default policy to a URI
14
+ # aa=OpenTox::Authorization::AA.new(tok)
15
+ # xml=aa.get_xml('http://uri....')
16
+ # OpenTox::Authorization.create_policy(xml,tok)
17
+
18
+ class AA
19
+ attr_accessor :user, :subjectid, :policy
20
+
21
+ #Generates AA object - requires subjectid
22
+ # @param [String] subjectid
23
+ def initialize(subjectid)
24
+ @user = Authorization.get_user(subjectid)
25
+ @subjectid = subjectid
26
+ @policy = Policies.new()
27
+ end
28
+
29
+ #Cleans AA Policies and loads default xml file into policy attribute
30
+ #set uri and user, returns Policyfile(XML) for open-sso
31
+ # @param [String] URI to create a policy for
32
+ def get_xml(uri)
33
+ @policy.drop_policies
34
+ @policy.load_default_policy(@user, uri)
35
+ return @policy.to_xml
36
+ end
37
+
38
+ #Loads and sends Policyfile(XML) to open-sso server
39
+ # @param [String] URI to create a policy for
40
+ def send(uri)
41
+ xml = get_xml(uri)
42
+ ret = false
43
+ ret = Authorization.create_policy(xml, @subjectid)
44
+ LOGGER.debug "Policy send with subjectid: #{@subjectid}"
45
+ LOGGER.warn "Not created Policy is: #{xml}" if !ret
46
+ ret
47
+ end
48
+
49
+ end
50
+
51
+ #Returns the open-sso server set in the config file .opentox/config/[environment].yaml
52
+ # @return [String, nil] the openSSO server URI or nil
53
+ def self.server
54
+ return AA_SERVER
55
+ end
56
+
57
+ #Authentication against OpenSSO. Returns token. Requires Username and Password.
58
+ # @param [String, String]Username,Password
59
+ # @return [String, nil] gives subjectid or nil
60
+ def self.authenticate(user, pw)
61
+ return nil if !AA_SERVER
62
+ begin
63
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/authenticate")
64
+ out = resource.post(:username=>user, :password => pw).sub("token.id=","").sub("\n","")
65
+ return out
66
+ rescue
67
+ return nil
68
+ end
69
+ end
70
+
71
+ #Logout on opensso. Make token invalid. Requires token
72
+ # @param [String]subjectid the subjectid
73
+ # @return [Boolean] true if logout is OK
74
+ def self.logout(subjectid)
75
+ begin
76
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/logout")
77
+ resource.post(:subjectid => subjectid)
78
+ return true
79
+ rescue
80
+ return false
81
+ end
82
+ end
83
+
84
+ #Authorization against OpenSSO for a URI with request-method (action) [GET/POST/PUT/DELETE]
85
+ # @param [String,String,String]uri,action,subjectid
86
+ # @return [Boolean, nil] returns true, false or nil (if authorization-request fails).
87
+ def self.authorize(uri, action, subjectid)
88
+ return true if !AA_SERVER
89
+ begin
90
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/authorize")
91
+ return true if resource.post(:uri => uri, :action => action, :subjectid => subjectid) == "boolean=true\n"
92
+ rescue
93
+ return nil
94
+ end
95
+ end
96
+
97
+ #Checks if a token is a valid token
98
+ # @param [String]subjectid subjectid from openSSO session
99
+ # @return [Boolean] subjectid is valid or not.
100
+ def self.is_token_valid(subjectid)
101
+ return true if !AA_SERVER
102
+ begin
103
+ resource = RestClient::Resource.new("#{AA_SERVER}/auth/isTokenValid")
104
+ return true if resource.post(:tokenid => subjectid) == "boolean=true\n"
105
+ rescue
106
+ return false
107
+ end
108
+ end
109
+
110
+ #Returns array with all policies of the token owner
111
+ # @param [String]subjectid requires subjectid
112
+ # @return [Array, nil] returns an Array of policy names or nil if request fails
113
+ def self.list_policies(subjectid)
114
+ begin
115
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
116
+ out = resource.get(:subjectid => subjectid)
117
+ return out.split("\n")
118
+ rescue RestClient::InternalServerError => e
119
+ raise e.response
120
+ rescue
121
+ return nil
122
+ end
123
+ end
124
+
125
+ #Returns a policy in xml-format
126
+ # @param [String, String]policy,subjectid
127
+ # @return [String] XML of the policy
128
+ def self.list_policy(policy, subjectid)
129
+ begin
130
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
131
+ return resource.get(:subjectid => subjectid,:id => policy)
132
+ rescue
133
+ return nil
134
+ end
135
+ end
136
+
137
+ # Lists policies alongside with affected uris
138
+ # @param [String] subjectid
139
+ # @return [Hash] keys: all policies of the subjectid owner, values: uris affected by those policies
140
+ def self.list_policy_uris( subjectid )
141
+ names = list_policies(subjectid)
142
+ policies = {}
143
+ names.each do |n|
144
+ p = OpenTox::Policies.new
145
+ p.load_xml( list_policy(n, subjectid) )
146
+ policies[n] = p.uris
147
+ end
148
+ policies
149
+ end
150
+
151
+ #Returns the owner (who created the first policy) of an URI
152
+ # @param [String, String]uri,subjectid
153
+ # return [String, nil]owner,nil returns owner of the URI
154
+ def self.get_uri_owner(uri, subjectid)
155
+ begin
156
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
157
+ return resource.get(:uri => uri, :subjectid => subjectid).sub("\n","")
158
+ rescue
159
+ return nil
160
+ end
161
+ end
162
+
163
+ #Checks if a policy exists to a URI. Requires URI and token.
164
+ # @param [String, String]uri,subjectid
165
+ # return [Boolean]
166
+ def self.uri_has_policy(uri, subjectid)
167
+ owner = get_uri_owner(uri, subjectid)
168
+ return true if owner and owner != "null"
169
+ false
170
+ end
171
+
172
+ #List all policynames for a URI. Requires URI and token.
173
+ # @param [String, String]uri,subjectid
174
+ # return [Array, nil] returns an Array of policy names or nil if request fails
175
+ def self.list_uri_policies(uri, subjectid)
176
+ begin
177
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
178
+ out = resource.get(:uri => uri, :polnames => true, :subjectid => subjectid)
179
+ policies = []; notfirstline = false
180
+ out.split("\n").each do |line|
181
+ policies << line if notfirstline
182
+ notfirstline = true
183
+ end
184
+ return policies
185
+ rescue
186
+ return nil
187
+ end
188
+ end
189
+
190
+ #Sends a policy in xml-format to opensso server. Requires policy-xml and token.
191
+ # @param [String, String]policyxml,subjectid
192
+ # return [Boolean] returns true if policy is created
193
+ def self.create_policy(policy, subjectid)
194
+ begin
195
+ resource = RestClient::Resource.new("#{AA_SERVER}/Pol/opensso-pol")
196
+ LOGGER.debug "OpenTox::Authorization.create_policy policy: #{policy[168,43]} with token:" + subjectid.to_s + " length: " + subjectid.length.to_s
197
+ return true if resource.post(policy, :subjectid => subjectid, :content_type => "application/xml")
198
+ rescue
199
+ return false
200
+ end
201
+ end
202
+
203
+ #Deletes a policy
204
+ # @param [String, String]policyname,subjectid
205
+ # @return [Boolean,nil]
206
+ def self.delete_policy(policy, subjectid)
207
+ begin
208
+ resource = RestClient::Resource.new("#{AA_SERVER}/pol")
209
+ LOGGER.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}"
210
+ return true if resource.delete(:subjectid => subjectid, :id => policy)
211
+ rescue
212
+ return nil
213
+ end
214
+ end
215
+
216
+ #Returns array of all possible LDAP-Groups
217
+ # @param [String]subjectid
218
+ # @return [Array]
219
+ def self.list_groups(subjectid)
220
+ begin
221
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/search")
222
+ grps = resource.post(:admin => subjectid, :attributes_names => "objecttype", :attributes_values_objecttype => "group")
223
+ grps.split("\n").collect{|x| x.sub("string=","")}
224
+ rescue
225
+ []
226
+ end
227
+ end
228
+
229
+ #Returns array of the LDAP-Groups of an user
230
+ # @param [String]subjectid
231
+ # @return [Array] gives array of LDAP groups of a user
232
+ def self.list_user_groups(user, subjectid)
233
+ begin
234
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/read")
235
+ out = resource.post(:name => user, :admin => subjectid, :attributes_names => "group")
236
+ grps = []
237
+ out.split("\n").each do |line|
238
+ grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=")
239
+ end
240
+ return grps
241
+ rescue
242
+ []
243
+ end
244
+ end
245
+
246
+ #Returns the owner (user id) of a token
247
+ # @param [String]subjectid
248
+ # @return [String]user
249
+ def self.get_user(subjectid)
250
+ begin
251
+ resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/attributes")
252
+ out = resource.post(:subjectid => subjectid, :attributes_names => "uid")
253
+ user = ""; check = false
254
+ out.split("\n").each do |line|
255
+ if check
256
+ user = line.sub("userdetails.attribute.value=","") if line.include?("userdetails.attribute.value=")
257
+ check = false
258
+ end
259
+ check = true if line.include?("userdetails.attribute.name=uid")
260
+ end
261
+ return user
262
+ rescue
263
+ nil
264
+ end
265
+ end
266
+
267
+ #Send default policy with Authorization::AA class
268
+ # @param [String, String]URI,subjectid
269
+ def self.send_policy(uri, subjectid)
270
+ return true if !AA_SERVER
271
+ aa = Authorization::AA.new(subjectid)
272
+ ret = aa.send(uri)
273
+ LOGGER.debug "OpenTox::Authorization send policy for URI: #{uri} | subjectid: #{subjectid} - policy created: #{ret}"
274
+ ret
275
+ end
276
+
277
+ #Deletes all policies of an URI
278
+ # @param [String, String]URI,subjectid
279
+ # @return [Boolean]
280
+ def self.delete_policies_from_uri(uri, subjectid)
281
+ policies = list_uri_policies(uri, subjectid)
282
+ policies.each do |policy|
283
+ ret = delete_policy(policy, subjectid)
284
+ LOGGER.debug "OpenTox::Authorization delete policy: #{policy} - with result: #{ret}"
285
+ end
286
+ return true
287
+ end
288
+
289
+ # Checks (if subjectid is valid) if a policy exist and create default policy if not
290
+ # @param [String] uri
291
+ # @param [String] subjectid
292
+ # @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else
293
+ def self.check_policy(uri, subjectid)
294
+ return true unless uri and subjectid
295
+ token_valid = OpenTox::Authorization.is_token_valid(subjectid)
296
+ LOGGER.debug "OpenTox::Authorization.check_policy with uri: #{uri}, subjectid: #{subjectid} is valid: #{token_valid}"
297
+ # check if subjectid is valid
298
+ unless token_valid
299
+ # abort if invalid
300
+ LOGGER.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}"
301
+ return false
302
+ end
303
+
304
+ if !uri_has_policy(uri, subjectid)
305
+ # if no policy exists, create a policy, return result of send policy
306
+ send_policy(uri, subjectid)
307
+ else
308
+ # if policy exists check for POST rights
309
+ if authorize(uri, "POST", subjectid)
310
+ true
311
+ else
312
+ LOGGER.error "OpenTox::Authorization.check_policy, already exists, but no POST-authorization with subjectid: #{subjectid}"
313
+ false
314
+ end
315
+ end
316
+ true
317
+ end
318
+
319
+ class << self
320
+ alias :token_valid? :is_token_valid
321
+ end
322
+
323
+ # Check Authorization for a resource (identified via URI) with method and subjectid.
324
+ # @param [String] uri
325
+ # @param [String] request_method, should be GET, POST, PUT, DELETE
326
+ # @param [String] subjectid
327
+ # @return [Boolean] true if access granted, else otherwise
328
+ def self.authorized?(uri, request_method, subjectid)
329
+ if CONFIG[:authorization][:free_request].include?(request_method)
330
+ #LOGGER.debug "authorized? >>true<< (request is free), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
331
+ true
332
+ elsif OpenTox::Authorization.free_uri?(uri, request_method)
333
+ #LOGGER.debug "authorized? >>true<< (uris is free_uri), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
334
+ true
335
+ elsif CONFIG[:authorization][:authenticate_request].include?(request_method)
336
+ ret = OpenTox::Authorization.is_token_valid(subjectid)
337
+ LOGGER.debug "authorized? >>#{ret}<< (token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
338
+ ret
339
+ elsif OpenTox::Authorization.authorize_exception?(uri, request_method)
340
+ ret = OpenTox::Authorization.is_token_valid(subjectid)
341
+ LOGGER.debug "authorized? >>#{ret}<< (uris is authorize exception, token is in/valid), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
342
+ ret
343
+ elsif CONFIG[:authorization][:authorize_request].include?(request_method)
344
+ ret = OpenTox::Authorization.authorize(uri, request_method, subjectid)
345
+ LOGGER.debug "authorized? >>#{ret}<< (uri (not) authorized), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
346
+ ret
347
+ else
348
+ LOGGER.error "invalid request/uri method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
349
+ false
350
+ end
351
+ end
352
+
353
+ private
354
+ def self.free_uri?(uri, request_method)
355
+ if CONFIG[:authorization][:free_uris]
356
+ CONFIG[:authorization][:free_uris].each do |request_methods,uris|
357
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
358
+ uris.each do |u|
359
+ return true if u.match uri
360
+ end
361
+ end
362
+ end
363
+ end
364
+ return false
365
+ end
366
+
367
+ def self.authorize_exception?(uri, request_method)
368
+ if CONFIG[:authorization][:authorize_exceptions]
369
+ CONFIG[:authorization][:authorize_exceptions].each do |request_methods,uris|
370
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
371
+ uris.each do |u|
372
+ return true if u.match uri
373
+ end
374
+ end
375
+ end
376
+ end
377
+ return false
378
+ end
379
+
380
+ end
381
+ end