opentox-ruby 0.0.2 → 1.0.0

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