diff options
author | rautenberg <rautenberg@in-silico.ch> | 2016-09-06 12:33:22 +0200 |
---|---|---|
committer | rautenberg <rautenberg@in-silico.ch> | 2016-09-06 12:33:22 +0200 |
commit | 4e173fe7a205907fe77a741c3d30a75de285b211 (patch) | |
tree | 457ecb17bcc19102cace9d840f83f2820901c0fa | |
parent | 8220c743b1ed446e9fd857c783375bbc094b60a5 (diff) |
clean code , add minimal authorization and authentication
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | api/api.json | 95 | ||||
-rw-r--r-- | lib/aa.rb | 82 | ||||
-rw-r--r-- | lib/compound.rb | 20 | ||||
-rw-r--r-- | lib/dataset.rb | 2 | ||||
-rw-r--r-- | lib/model.rb | 6 | ||||
-rw-r--r-- | lib/validation.rb | 16 | ||||
-rw-r--r-- | test/compound.rb | 2 |
8 files changed, 189 insertions, 36 deletions
@@ -1 +1 @@ -0.0.1
\ No newline at end of file +0.0.2 diff --git a/api/api.json b/api/api.json index e30ff98..4cd07c7 100644 --- a/api/api.json +++ b/api/api.json @@ -14,7 +14,7 @@ "url": "https://github.com/opentox/lazar-rest/blob/master/LICENSE" } }, - "host": "mr-test.in-silico.ch", + "host": "enm.in-silico.ch", "basePath": "/", "schemes": [ "https" @@ -720,7 +720,7 @@ "descriptor" ], "summary": "Descriptor calculation", - "description": "Calculate descriptors for a single compound as SMILES string or a CSV compound file <br> <strong>curl example:</strong> <pre>curl -Lk -X POST -i -H \"accept:application/json\" -F \"file=@../lazar/test/data/batch_prediction.csv;type=application/csv\" -F \"descriptor=Openbabel.HBA1,Openbabel.HBA2,JoeLib.LogP\" https://mr-test.in-silico.ch/algorithm/descriptor curl -Lk -X POST -i -H \"accept:application/json\" -F \"identifier=O=C1NC(=O)NC=C1\" -F \"descriptor=Openbabel.MW,JoeLib.LogP\" https://mr-test.in-silico.ch/algorithm/descriptor </pre> CSV compound file has to be comma separated with SMILES strings in the first column.", + "description": "Calculate descriptors for a single compound as SMILES string <br> <strong>curl example:</strong> <pre>curl -Lk -X POST -i -H \"accept:application/json\" -F \"identifier=O=C1NC(=O)NC=C1\" -F \"descriptor=Openbabel.MW,JoeLib.LogP\" https://enm.in-silico.ch/compound/descriptor </pre>.", "parameters": [ { "name": "accept", @@ -734,17 +734,10 @@ ] }, { - "name": "file", - "in": "formData", - "description": "CSV file of compounds", - "required": false, - "type": "file" - }, - { "name": "identifier", "in": "formData", "description": "SMILES identifier", - "required": false, + "required": true, "type": "string" }, { @@ -900,6 +893,84 @@ } } } + }, + "/aa/authenticate": { + "post": { + "tags": [ + "authentication" + ], + "description": "Authentication against OpenSSO. Returns token. Requires Username and Password.", + "operationId": "login", + "consumes": [ + "text/plain" + ], + "produces": [ + "text/plain" + ], + "parameters": [ + { + "in": "formData", + "name": "username", + "description": "username", + "required": true, + "type": "string" + }, + { + "in": "formData", + "name": "password", + "description": "password", + "required": true, + "type": "string", + "format": "password" + } + ], + "responses": { + "200": { + "$ref": "#/responses/200" + }, + "400": { + "$ref": "#/responses/400" + }, + "401": { + "$ref": "#/responses/401" + } + } + } + }, + "/aa/logout": { + "post": { + "description": "Devalidates a token. Requires Subjectid.", + "operationId": "logout", + "tags": [ + "authentication" + ], + "consumes": [ + "text/plain" + ], + "produces": [ + "text/plain" + ], + "parameters": [ + { + "in": "formData", + "name": "subjectid", + "description": "subjectid", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "$ref": "#/responses/200" + }, + "400": { + "$ref": "#/responses/400" + }, + "401": { + "$ref": "#/responses/401" + } + } + } } }, "parameters": { @@ -955,6 +1026,10 @@ "description": "Swagger API representation in JSON" }, { + "name": "authentication", + "description": "minimal Authentication service" + }, + { "name": "descriptor", "description": "Descriptor" }, diff --git a/lib/aa.rb b/lib/aa.rb new file mode 100644 index 0000000..6dfec4b --- /dev/null +++ b/lib/aa.rb @@ -0,0 +1,82 @@ +post "/aa/authenticate/?" do + mime_types = ["text/plain"] + bad_request_error "Mime type #{@accept} not supported here. Please request data as #{mime_types.join(', ')}." unless mime_types.include? @accept + bad_request_error "Please send formdata username." unless params[:username] + bad_request_error "Please send formdata password." unless params[:password] + case @accept + when "text/plain" + if OpenTox::Authorization.authenticate(params[:username], params[:password]) + return OpenTox::RestClientWrapper.subjectid + else + return nil + end + else + bad_request_error "'#{@accept}' is not a supported content type." + end +end + +post "/aa/logout/?" do + mime_types = ["text/plain"] + bad_request_error "Mime type #{@accept} not supported here. Please request data as #{mime_types.join(', ')}." unless mime_types.include? @accept + bad_request_error "Please send formdata subjectid." unless params[:subjectid] + case @accept + when "text/plain" + if OpenTox::Authorization.logout(params[:subjectid]) + return "Successfully logged out. \n" + else + return "Logout failed.\n" + end + else + bad_request_error "'#{@accept}' is not a supported content type." + end +end + +module OpenTox + + AA = "https://opensso.in-silico.ch" + + module Authorization + #Authentication against OpenSSO. Returns token. Requires Username and Password. + # @param user [String] Username + # @param pw [String] Password + # @return [Boolean] true if successful + def self.authenticate(user, pw) + begin + res = RestClientWrapper.post("#{AA}/auth/authenticate",{:username=>user, :password => pw},{:subjectid => ""}).sub("token.id=","").sub("\n","") + if is_token_valid(res) + RestClientWrapper.subjectid = res + return true + else + bad_request_error "Authentication failed #{res.inspect}" + end + rescue + bad_request_error "Authentication failed #{res.inspect}" + end + end + + #Logout on opensso. Make token invalid. Requires token + # @param [String] subjectid the subjectid + # @return [Boolean] true if logout is OK + def self.logout(subjectid=RestClientWrapper.subjectid) + begin + out = RestClientWrapper.post("#{AA}/auth/logout", :subjectid => subjectid) + return true unless is_token_valid(subjectid) + rescue + return false + end + return false + end + + #Checks if a token is a valid token + # @param [String]subjectid subjectid from openSSO session + # @return [Boolean] subjectid is valid or not. + def self.is_token_valid(subjectid=RestClientWrapper.subjectid) + begin + return true if RestClientWrapper.post("#{AA}/auth/isTokenValid",:tokenid => subjectid) == "boolean=true\n" + rescue #do rescue because openSSO throws 401 + return false + end + return false + end + end +end
\ No newline at end of file diff --git a/lib/compound.rb b/lib/compound.rb index fc4ec55..c8dd98c 100644 --- a/lib/compound.rb +++ b/lib/compound.rb @@ -5,23 +5,19 @@ get "/compound/descriptor/?:descriptor?" do case @accept when "application/json" - return "#{JSON.pretty_generate OpenTox::PhysChem::DESCRIPTORS} " unless params[:descriptor] - return {params[:descriptor] => OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]]}.to_json + return "#{JSON.pretty_generate PhysChem::DESCRIPTORS} " unless params[:descriptor] + return {params[:descriptor] => PhysChem::DESCRIPTORS[params[:descriptor]]}.to_json else - return OpenTox::PhysChem::DESCRIPTORS.collect{|k, v| "#{k}: #{v}\n"} unless params[:descriptor] - return OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]] + return PhysChem::DESCRIPTORS.collect{|k, v| "#{k}: #{v}\n"} unless params[:descriptor] + return PhysChem::DESCRIPTORS[params[:descriptor]] end end post "/compound/descriptor/?" do - bad_request_error "Missing Parameter " unless (params[:identifier] or params[:file]) and params[:descriptor] + bad_request_error "Missing Parameter " unless params[:identifier] && params[:descriptor] descriptor = params['descriptor'].split(',') - if params[:file] - data = OpenTox::Dataset.from_csv_file params[:file][:tempfile] - else - data = OpenTox::Compound.from_smiles params[:identifier] - end - d = Algorithm::Descriptor.physchem data, descriptor + compound = Compound.from_smiles params[:identifier] + d = compound.physchem descriptor csv = d.to_csv csv = "SMILES,#{params[:descriptor]}\n#{params[:identifier]},#{csv}" if params[:identifier] case @accept @@ -37,7 +33,7 @@ end get %r{/compound/(.+)} do |inchi| bad_request_error "Input parameter #{inchi} is not an InChI" unless inchi.match(/^InChI=/) - compound = OpenTox::Compound.from_inchi URI.unescape(inchi) + compound = Compound.from_inchi URI.unescape(inchi) response['Content-Type'] = @accept case @accept when "application/json" diff --git a/lib/dataset.rb b/lib/dataset.rb index 56f510f..ff16640 100644 --- a/lib/dataset.rb +++ b/lib/dataset.rb @@ -1,6 +1,6 @@ # Get all datasets get "/dataset/?" do - datasets = OpenTox::Dataset.all + datasets = Dataset.all case @accept when "text/uri-list" uri_list = datasets.collect{|dataset| uri("/dataset/#{dataset.id}")} diff --git a/lib/model.rb b/lib/model.rb index 6188cce..db0c190 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -3,7 +3,7 @@ # @param [Header] Accept one of text/uri-list, # @return [text/uri-list] list of all prediction models get "/model/?" do - models = OpenTox::Model::Prediction.all + models = Model::Prediction.all case @accept when "text/uri-list" uri_list = models.collect{|model| uri("/model/#{model.model_id}")} @@ -21,7 +21,7 @@ get "/model/?" do end get "/model/:id/?" do - model = OpenTox::Model::Lazar.find params[:id] + model = Model::Lazar.find params[:id] resource_not_found_error "Model with id: #{params[:id]} not found." unless model model[:URI] = uri("/model/#{model.id}") model[:neighbor_algorithm_parameters][:feature_dataset_uri] = uri("/dataset/#{model[:neighbor_algorithm_parameters][:feature_dataset_id]}") if model[:neighbor_algorithm_parameters][:feature_dataset_id] @@ -40,7 +40,7 @@ post "/model/:id/?" do @error_report = "Attention, '#{params[:identifier]}' is not a valid SMILES string." return @error_report end - model = OpenTox::Model::Lazar.find params[:id] + model = Model::Lazar.find params[:id] batch = {} compounds.each do |compound| prediction = model.predict(compound) diff --git a/lib/validation.rb b/lib/validation.rb index 5963c63..ce31c34 100644 --- a/lib/validation.rb +++ b/lib/validation.rb @@ -24,13 +24,13 @@ get "/validation/:validationtype/?" do bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype] case params[:validationtype] when "repeatedcrossvalidation" - validations = OpenTox::Validation::RepeatedCrossValidation.all + validations = Validation::RepeatedCrossValidation.all when "leaveoneout" - validations = OpenTox::Validation::LeaveOneOut.all + validations = Validation::LeaveOneOut.all when "crossvalidation" - validations = OpenTox::Validation::CrossValidation.all + validations = Validation::CrossValidation.all when "regressioncrossvalidation" - validations = OpenTox::Validation::RegressionCrossValidation.all + validations = Validation::RegressionCrossValidation.all end case @accept @@ -53,13 +53,13 @@ get "/validation/:validationtype/:id/?" do bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype] case params[:validationtype] when "repeatedcrossvalidation" - validation = OpenTox::Validation::RepeatedCrossValidation.find params[:id] + validation = Validation::RepeatedCrossValidation.find params[:id] when "leaveoneout" - validation = OpenTox::Validation::LeaveOneOut.find params[:id] + validation = Validation::LeaveOneOut.find params[:id] when "crossvalidation" - validation = OpenTox::Validation::CrossValidation.find params[:id] + validation = Validation::CrossValidation.find params[:id] when "regressioncrossvalidation" - validation = OpenTox::Validation::RegressionCrossValidation.find params[:id] + validation = Validation::RegressionCrossValidation.find params[:id] end resource_not_found_error "#{params[:validationtype]} with id: #{params[:id]} not found." unless validation diff --git a/test/compound.rb b/test/compound.rb index 5fac83d..cacd292 100644 --- a/test/compound.rb +++ b/test/compound.rb @@ -39,7 +39,7 @@ class CompoundTest < MiniTest::Test res = RestClientWrapper.get File.join($compound_uri, $compound[0]), {}, {:accept => "application/json"} assert_equal res.code, 200 js = JSON.parse res - assert_equal js["chemblid"], "CHEMBL581676" + assert_equal js["chemblid"], "CHEMBL277500" assert_equal js["names"].first, "BENZENE" assert_equal js["names"][6], "71-43-2" end |