0

I'm trying to use ConnectWise API's in my Rails 3 application. I've built and tested an API using plain ruby and it's successful. Now I'm trying to add this script into lib/assets in my Rails app to run but It seems to be either not executing the script, or executing and failing without giving me any error output.

Here are the successful Ruby scripts:

CompanyApis Class:

require 'builder'
class CompanyApis
  def self.get_company
    cw_company_id = 21920
    integrator_company_id = 'COMPANY_ID'
    integrator_login_id = 'INTERGRATOR_LOGIN'
    integrator_password = 'INTEGRATOR PW'

    xml = Builder::XmlMarkup.new(:indent=>2)
    xml.instruct!
    xml.tag!('soap:Envelope',
             :'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
             :xmlns => 'http://connectwise.com'){
      xml.tag!('soap:Body'){
        xml.tag!('GetCompany'){
          xml.tag!('credentials'){
            xml.CompanyId(integrator_company_id)
            xml.IntegratorLoginId(integrator_login_id)
            xml.IntegratorPassword(integrator_password)
          }
          xml.id(cw_company_id)
        }
      }
    }
  end
end

CwIntegrator Class:

require 'net/https'
require 'uri'
require 'nokogiri'
require './company_api'

class CwIntegrator
  cw_company_id = 21920
  cw_hostname = 'cw.host.com'
  companyapi_url = "https://#{cw_hostname}/v4_6_release/apis/2.0/CompanyApi.asmx"
  uri = URI.parse(companyapi_url)

  # Use for proxying to Kali
  #proxy_addr = '172.16.1.149'
  #proxy_port = 8080

  request = Net::HTTP::Post.new(uri.path)
  request.add_field('Content-Type', 'text/xml; charset=utf-8')
  request.add_field('SOAPAction', 'http://connectwise.com/GetCompany')
  request.body = CompanyApis.get_company
  http = Net::HTTP.new(uri.host, uri.port)

  # Use for proxying to Kali
  #http = Net::HTTP.new(uri.host, uri.port, proxy_addr, proxy_port)

  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  response = http.start {|h| h.request(request)}
  company_info = []
  xml_doc = Nokogiri::XML(response.body).remove_namespaces!
  company_name = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/CompanyName').text
  company_street_addr = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/StreetLines/string')[0].text
  begin
    company_street_addr2 = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/StreetLines/string')[1].text
  end
  company_city = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/City').text
  company_state = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/State').text
  company_zip = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/Zip').text
  company_country = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/Country').text
  company_status = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/Status').text
  company_phone = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/PhoneNumber').text
  company_fax = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/FaxNumber').text
  company_www = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/WebSite').text

  company_info += [company_name: company_name, cw_company_id: cw_company_id, company_name: company_name,
                   company_street_addr: company_street_addr, company_street_addr2: company_street_addr2,
                   company_city: company_city, company_state: company_state, company_zip: company_zip,
                   company_country:company_country,company_status: company_status, company_phone: company_phone,
                   company_fax: company_fax, company_www: company_www]

  puts(company_info)
end

Running this script has this output:

ruby cw_integrator.rb {:company_name=>"Orlando Fake Co, LLC.", :cw_company_id=>21920, :company_street_addr=>"STREET ADDR.", :company_street_addr2=>"Suite 400", :company_city=>"Orlando", :company_state=>"FL", :company_zip=>"32839", :company_country=>"United States", :company_status=>"Active Gold TTS", :company_phone=>"5558765309", :company_fax=>"", :company_www=>"www.myweb.com"}

So to add this to the Rails app I've added two .rb files to lib/assets, cw_apis.rb and cw_get_company_integrator.rb. Here are their contents:

CwApis class:

#!/usr/bin/env ruby
require 'builder'
class CwApis
  def self.get_company_xml_request
    cw_integrator_account = CwIntegratorAccount.first
    integrator_company_id = cw_integrator_account.integrator_company_id
    integrator_login_id = cw_integrator_account.integrator_login_id
    integrator_password = cw_integrator_account.integrator_password

    xml = Builder::XmlMarkup.new(:indent=>2)
    xml.instruct!
    xml.tag!('soap:Envelope',
             :'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/',
             :xmlns => 'http://connectwise.com'){
      xml.tag!('soap:Body'){
        xml.tag!('GetCompany'){
          xml.tag!('credentials'){
            xml.CompanyId(integrator_company_id)
            xml.IntegratorLoginId(integrator_login_id)
            xml.IntegratorPassword(integrator_password)
          }
          xml.id(cw_integrator_account.cw_company_id)
        }
      }
    }
  end
end

And CwGetCompanyIntegrator Class:

#!/usr/bin/env ruby
require 'net/https'
require 'uri'
require 'nokogiri'
require 'assets/cw_apis'

class CwGetCompanyIntegrator
  cw_integrator_account = CwIntegratorAccount.first
  cw_hostname = cw_integrator_account.cw_hostname
  company_api_url = "https://#{cw_hostname}/v4_6_release/apis/2.0/CompanyApi.asmx"
  uri = URI.parse(company_api_url)

  request = Net::HTTP::Post.new(uri.path)
  request.add_field('Content-Type', 'text/xml; charset=utf-8')
  request.add_field('SOAPAction', 'http://connectwise.com/GetCompany')
  request.body = CwApis.get_company_xml_request
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL
  response = http.start {|h| h.request(request)}
  xml_doc = Nokogiri::XML(response.body).remove_namespaces!

  company_name = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/CompanyName').text
  company_street_addr = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/StreetLines/string')[0].text
  begin
    company_street_addr2 = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/StreetLines/string')[1].text
  end
  company_city = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/City').text
  company_state = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/State').text
  company_zip = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/Zip').text
  company_country = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/DefaultAddress/Country').text
  company_status = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/Status').text
  company_phone = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/PhoneNumber').text
  company_fax = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/FaxNumber').text
  company_www = xml_doc.xpath('//Envelope/Body/GetCompanyResponse/GetCompanyResult/WebSite').text

  CompanyInfosController.create!(cw_company_id: cw_integrator_account.cw_company_id, company_name: company_name,
                                 company_street_addr: company_street_addr, company_street_addr2: company_street_addr2,
                                 company_city: company_city, company_state: company_state, company_zip: company_zip,
                                 company_country:company_country, company_status: company_status, company_phone: company_phone,
                                 company_fax: company_fax, company_www: company_www)
end

I'm trying to execute the CwGetCompanyIntegrator class in my CwIntegratorAccountsController.

Here is the code inside the create action from the CwIntegratorAccountsController I've omitted index, show, new, edit, update, and destroy:

require 'assets/cw_get_company_integrator'

class CwIntegratorAccountsController < ApplicationController
  skip_before_filter :require_company, :only => [:create,:new]

  # GET /cw_integrator_accounts
  # GET /cw_integrator_accounts.json

  def create
    unless CwIntegratorAccount.count >= 1
      @cw_integrator_account = CwIntegratorAccount.new(params[:cw_integrator_account])

      respond_to do |format|
        if @cw_integrator_account.save

          # Run the CW Integrator
          CwGetCompanyIntegrator
          format.html { redirect_to root_url, notice: 'cw_integrator success' }
          #format.json { render json: @cw_integrator_account, status: :created, location: @cw_integrator_account }
        else
          format.html { render action: 'new' }
          format.json { render json: @cw_integrator_account.errors, status: :unprocessable_entity }
        end
      end
    end
  end
end

I know that I'm getting past the if @cw_integrator_account.save, and CwGetCompanyIntegrator because I'm getting the redirect (and see it in the logs) from format.html { redirect_to root_url, notice: 'cw_integrator success' }, but the CwGetCompanyIntegrator is not erring or executing (properly any way).

What is the proper way to make this class execute?

insecure-IT
  • 2,068
  • 4
  • 18
  • 26

1 Answers1

3
  1. lib is not autoloaded by default. You need to add it to the autoload path - see Auto-loading lib files in Rails 4

  2. In addition, lib/assets is used by the Asset Pipeline. You should create a different folder for your classes.

  3. Your code in CwGetCompanyIntegrator needs to be wrapped in a method, like the following block which you'd call using CwGetCompanyIntegrator.call

    class CwGetCompanyIntegrator
      def self.call
        # execute code here
      end
    end
    
Community
  • 1
  • 1
fylooi
  • 3,840
  • 14
  • 24