require 'rubygems' require 'rest_client' require 'zip' require 'zip/zipfilesystem' require 'zip/zip' require 'open-uri' require 'digest/sha2' require 'openssl' require 'base64' require 'json' module Factor module Client class Client attr_accessor :host FACTOR_HOST = ENV["FACTOR_HOST"] || "factor.io" def initialize(host=FACTOR_HOST) @host=host end def login_token(token) @token=token end def create_credential(service,name,value,secret=nil,organization=nil) # this is a PUT not POST because it is technically editing, not creating a new one credential = {:service=>service,:name=>name,:value=>value} if secret payload=value sha256= Digest::SHA2.new(256) encrypter = OpenSSL::Cipher.new("AES-256-CFB") encrypter.encrypt encrypter.key=Base64.encode64(sha256.digest(secret)) encrypted = Base64.encode64(encrypter.update(value) + encrypter.final) credential[:value]=encrypted credential[:encrypted]=true end path = !!organization ? "organizations/#{organization}/credentials" : "credentials" rest_post(path,credential) end def get_credentials() rest_get("credentials") end def delete_credential(service,name) rest_delete("credentials",{:service=>service,:name=>name}) end # untested def create_workflow(key,definition,organization=nil) path = !!organization ? "organizations/#{organization}/workflows" : "workflows" rest_post(path,{:workflow=>{:name=>key,:definition=>definition}}) end def get_workflows() rest_get("workflows") end def delete_workflow(workflow_name) rest_delete("workflows/#{workflow_name}") end def start_workflow(workflow_name) rest_get("workflows/#{workflow_name}/state") end def stop_workflow(workflow_name) rest_delete("workflows/#{workflow_name}/state") end def call_workflow(workflow_name,params) rest_get("workflows/#{workflow_name}/call",params) end # channels def create_channel(path,definition_file,organization=nil) file=zip(File.expand_path(path)) definition = File.read(definition_file) path = !!organization ? "organizations/#{organization}/channels" : "channels" rest_post(path,{:zip=>file,:channel=>{:definition=>definition}}) end def get_channels() rest_get("channels") end def delete_channel(channel_name) rest_delete("channels/#{channel_name}") end private def zip(directory) path=directory.dup path.sub!(%r[/$],'') zip_path = File.join(path,"..",File.basename(path))+'.zip' FileUtils.rm zip_path, :force=>true Zip::ZipFile.open(zip_path, 'w') do |zip| Dir["#{path}/**/**"].reject{|f|f==zip_path}.each do |file| zip.add(file.sub(path+'/',''),file) end end File.open(zip_path,'r') end def rest_get(path,params={}) params["auth_token"]=@token param_string=params.map{|key,value| "#{key}=#{value}"}.join("&") response=RestClient.get("http://#{@host}/#{path}.json?#{param_string}") JSON.parse(response) end def rest_put(path,params={}) params["auth_token"]=@token response=RestClient.put("http://#{@host}/#{path}.json",params) JSON.parse(response) end def rest_post(path,params={}) response=RestClient.post("http://#{@host}/#{path}.json?auth_token=#{@token}",params) JSON.parse(response) end def rest_delete(path,params={}) params["auth_token"]=@token param_string=params.map{|key,value| "#{key}=#{value}"}.join("&") response=RestClient.delete("http://#{@host}/#{path}.json?#{param_string}") JSON.parse(response) end end end end