Commit 65175efc authored by Jose Ernesto Suarez's avatar Jose Ernesto Suarez

Se mueve todo el modulo Wedoops

parent 0e4138c5
example_id | status | run_time | example_id | status | run_time |
----------------------------- | ------ | --------------- | ----------------------------- | ------ | --------------- |
./spec/zoholib_spec.rb[1:1] | passed | 0.00183 seconds | ./spec/zoholib_spec.rb[1:1] | passed | 0.00261 seconds |
./spec/zoholib_spec.rb[1:2] | passed | 0.00144 seconds | ./spec/zoholib_spec.rb[1:2] | passed | 0.00141 seconds |
./spec/zoholib_spec.rb[1:3:1] | passed | 0.00112 seconds | ./spec/zoholib_spec.rb[1:3:1] | passed | 0.00125 seconds |
./spec/zoholib_spec.rb[1:3:2] | passed | 0.0012 seconds | ./spec/zoholib_spec.rb[1:3:2] | passed | 0.00011 seconds |
./spec/zoholib_spec.rb[1:3:3] | passed | 0.00009 seconds | ./spec/zoholib_spec.rb[1:3:3] | passed | 0.00008 seconds |
./spec/zoholib_spec.rb[1:3:4] | passed | 0.0002 seconds | ./spec/zoholib_spec.rb[1:3:4] | passed | 0.00016 seconds |
./spec/zoholib_spec.rb[1:3:5] | passed | 0.00022 seconds | ./spec/zoholib_spec.rb[1:3:5] | passed | 0.00017 seconds |
...@@ -14,20 +14,22 @@ require 'zoholib/zoho_client' ...@@ -14,20 +14,22 @@ require 'zoholib/zoho_client'
## ##
# This library is used for access Zoho # This library is used for access Zoho
module Zoholib module Wedoops
class << self module Zoholib
attr_accessor :configuration class << self
end attr_accessor :configuration
end
def self.configuration
@configuration ||= Configuration.new def self.configuration
end @configuration ||= Configuration.new
end
def self.reset
@configuration = Configuration.new def self.reset
end @configuration = Configuration.new
end
def self.configure
yield(configuration) def self.configure
yield(configuration)
end
end end
end end
...@@ -4,93 +4,94 @@ require 'json' ...@@ -4,93 +4,94 @@ require 'json'
require 'logger' require 'logger'
require 'date' require 'date'
module Wedoops
module Zoholib
class AdamoClient
module Zoholib def initialize(options={})
class AdamoClient @logger = Logger.new(STDOUT)
@http = HTTP
.use(logging: {logger: @logger})
.timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache",
"accept" => "application/json",
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0",
"x-apikey" => "Af8cbSpgkAReYqBs66DHJUkf2MJW3d9JDFVJhWe4U5haD")
end
def initialize(options={}) def cobertura_project
@logger = Logger.new(STDOUT) count=2
@http = HTTP url = "https://coverage-dump.adamo.es/v1/cobertura-project/#{count}?limit=500"
.use(logging: {logger: @logger}) return HTTP.use(logging: {logger: @logger})
.timeout(connect: 15, read: 30) .timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache", .headers("cache-control" => "no-cache",
"accept" => "application/json", "accept" => "application/json",
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0", "postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0",
"x-apikey" => "Af8cbSpgkAReYqBs66DHJUkf2MJW3d9JDFVJhWe4U5haD") "x-apikey" => "Af8cbSpgkAReYqBs66DHJUkf2MJW3d9JDFVJhWe4U5haD").get(url)
end end
def cobertura_project def cobertura
count=2 page=1
url = "https://coverage-dump.adamo.es/v1/cobertura-project/#{count}?limit=500" limit=50000
return HTTP.use(logging: {logger: @logger}) #date=Date.parse("06-04-2020").strftime("%Y%m%d")
.timeout(connect: 15, read: 30) date=Date.today.prev_day.strftime("%Y%m%d")
.headers("cache-control" => "no-cache", resultado_final=Array.new
"accept" => "application/json", r=Array.new
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0", loop do
"x-apikey" => "Af8cbSpgkAReYqBs66DHJUkf2MJW3d9JDFVJhWe4U5haD").get(url) print "#{page} "
end
url= "https://coverage-dump.adamo.es/v1/cobertura/#{page}?limit=#{limit}&date=#{date}"
#.use(logging: {logger: @logger})
resultado= HTTP.timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache",
"accept" => "application/json",
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0",
"x-apikey" => "zYkWN38SYH6hr2Ixq75xvDENl6hrYOvxx0FxLvPD7BUe6").get(url)
r= JSON.parse(resultado, symbolize_names: true)
resultado_final.concat(r)
page+=1
print "(#{r.size}/#{resultado_final.size}),"
break if r.size < limit || page >2
end
puts resultado_final.size
return resultado_final
end
def cobertura def projects
page=1 page=1
limit=50000 limit=50000
#date=Date.parse("06-04-2020").strftime("%Y%m%d") #date=Date.today.prev_day.strftime("%Y%m%d")
date=Date.today.prev_day.strftime("%Y%m%d") date=Date.parse("01-01-2011").strftime("%Y%m%d")
resultado_final=Array.new resultado_final=Array.new
r=Array.new r=Array.new
loop do loop do
print "#{page} " print "#{page} "
url= "https://coverage-dump.adamo.es/v1/cobertura-project/#{page}?limit=#{limit}&date=#{date}"
url= "https://coverage-dump.adamo.es/v1/cobertura/#{page}?limit=#{limit}&date=#{date}" #.use(logging: {logger: @logger})
#.use(logging: {logger: @logger}) resultado= HTTP.timeout(connect: 15, read: 30)
resultado= HTTP.timeout(connect: 15, read: 30) .headers("cache-control" => "no-cache",
.headers("cache-control" => "no-cache", "accept" => "application/json",
"accept" => "application/json", "postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0",
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0", "x-apikey" => "zYkWN38SYH6hr2Ixq75xvDENl6hrYOvxx0FxLvPD7BUe6").get(url)
"x-apikey" => "zYkWN38SYH6hr2Ixq75xvDENl6hrYOvxx0FxLvPD7BUe6").get(url) r= JSON.parse(resultado, symbolize_names: true)
r= JSON.parse(resultado, symbolize_names: true) resultado_final.concat(r)
resultado_final.concat(r) page+=1
page+=1 print "(#{r.size}/#{resultado_final.size}),"
print "(#{r.size}/#{resultado_final.size})," break if r.size < limit || page >2
break if r.size < limit || page >2 end
end puts resultado_final.size
puts resultado_final.size return resultado_final
return resultado_final end
end
def projects private
page=1
limit=50000
#date=Date.today.prev_day.strftime("%Y%m%d")
date=Date.parse("01-01-2011").strftime("%Y%m%d")
resultado_final=Array.new
r=Array.new
loop do
print "#{page} "
url= "https://coverage-dump.adamo.es/v1/cobertura-project/#{page}?limit=#{limit}&date=#{date}"
#.use(logging: {logger: @logger})
resultado= HTTP.timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache",
"accept" => "application/json",
"postman-token" => "8b126eb1-0de6-4a10-d78d-1fb417fb23b0",
"x-apikey" => "zYkWN38SYH6hr2Ixq75xvDENl6hrYOvxx0FxLvPD7BUe6").get(url)
r= JSON.parse(resultado, symbolize_names: true)
resultado_final.concat(r)
page+=1
print "(#{r.size}/#{resultado_final.size}),"
break if r.size < limit || page >2
end
puts resultado_final.size
return resultado_final
end
private def get_params(url,payload)
@http.get(url, :params => payload)
end
def get_params(url,payload) def get(url)
@http.get(url, :params => payload) @http.get(url)
end end
end
def get(url) end
@http.get(url)
end
end
end end
\ No newline at end of file
...@@ -3,122 +3,123 @@ ...@@ -3,122 +3,123 @@
#En algun momento tenemos que abrir un navegador #En algun momento tenemos que abrir un navegador
require 'launchy' require 'launchy'
require 'socket' require 'socket'
module Wedoops
module Zoholib
class AuthorizationRequest < ZohoRequest
module Zoholib # Sin en algun momento se quiere evitar el encode de URL
class AuthorizationRequest < ZohoRequest # he aqui un truco
# En esta ocasion lo gastamos porque los scopes vienen separados por una coma que hace que falle
query_string_normalizer proc { |query|
query.map do |key, value|
[value].flatten.map {|v| "#{key}=#{v}"}.join('&')
end.join('&')
}
# Sin en algun momento se quiere evitar el encode de URL def initialize(options={})
# he aqui un truco #build_url(options)
# En esta ocasion lo gastamos porque los scopes vienen separados por una coma que hace que falle @logger = ::Logger.new(STDOUT)
query_string_normalizer proc { |query| @options = Hash.new
query.map do |key, value| options.merge!({response_type: 'code',access_type: 'offline',redirect_uri: 'http://localhost:8000/auth/callback'})
[value].flatten.map {|v| "#{key}=#{v}"}.join('&') @grant_token = options[:grant_token]
end.join('&') #@options.merge!(grant_token: options[:grant_token] )
} options.delete(:grant_token)
#Al iniciar este objeto estas opciones solo tienen sentido en query
@options.merge!(query: options)
@logged_in = false
end
def initialize(options={}) def authorize(options={})
#build_url(options) unless @options[:refresh_token].nil?
@logger = ::Logger.new(STDOUT) @logger.warn "Refresh token already exists! Ignoring call"
@options = Hash.new return @options
options.merge!({response_type: 'code',access_type: 'offline',redirect_uri: 'http://localhost:8000/auth/callback'}) end
@grant_token = options[:grant_token] #El prompt consent obliga a mostrar la pantalla de consent
#@options.merge!(grant_token: options[:grant_token] ) # de esta manera se consigue que devuelva siempre el
options.delete(:grant_token) # refresh token que es valido para siempre
#Al iniciar este objeto estas opciones solo tienen sentido en query if options.has_key?(:force_prompt)
@options.merge!(query: options) #Si esta opcion la establecemos a true entonces se forzara el consent
@logged_in = false @options[:query].merge!(prompt:"consent") if options[:force_prompt]
end end
#pp @options
get_grant_token if @grant_token.nil?
tokens = get_grant_request
#pp tokens
raise "Unknown error! I cannot find the refresh_token! try to force prompt" if tokens[:refresh_token].nil?
@options.merge!(tokens)
# Decido devolver tokens unicamente, dejo aqui los comentarios antiguos
def authorize(options={}) # #Ya no necesitamos estas opciones dentro de query, las sacamos fuera
unless @options[:refresh_token].nil? # # Para devolverselas a nuestro padre
@logger.warn "Refresh token already exists! Ignoring call" # @options.merge!(@options[:query])
return @options # @options.delete(:query)
end # # El code solo tiene un uso y caducal al minuto, asi que
#El prompt consent obliga a mostrar la pantalla de consent # # Lo eliminamos tambien
# de esta manera se consigue que devuelva siempre el # @options.delete(:code)
# refresh token que es valido para siempre
if options.has_key?(:force_prompt) @options.delete(:follow_redirects)
#Si esta opcion la establecemos a true entonces se forzara el consent return tokens
@options[:query].merge!(prompt:"consent") if options[:force_prompt]
end end
#pp @options
get_grant_token if @grant_token.nil?
tokens = get_grant_request
#pp tokens
raise "Unknown error! I cannot find the refresh_token! try to force prompt" if tokens[:refresh_token].nil?
@options.merge!(tokens)
# Decido devolver tokens unicamente, dejo aqui los comentarios antiguos
# #Ya no necesitamos estas opciones dentro de query, las sacamos fuera def read_socket(port=8000)
# # Para devolverselas a nuestro padre @logger.info "Reading socket response"
# @options.merge!(@options[:query]) server = TCPServer.new port
# @options.delete(:query) while session = server.accept
# # El code solo tiene un uso y caducal al minuto, asi que request = session.gets
# # Lo eliminamos tambien match = /code=\d{4}\.\w{32}\.\w{32}/.match(request)
# @options.delete(:code) if match
code = match.to_s.split("=").last
@options.delete(:follow_redirects) end
return tokens session.print "HTTP/1.1 200\r\n" # 1
end session.print "Content-Type: text/html\r\n" # 2
session.print "\r\n" # 3
session.print "Thank you! The time is #{Time.now}" #4
def read_socket(port=8000) session.close
@logger.info "Reading socket response" break
server = TCPServer.new port end
while session = server.accept server.close
request = session.gets return code
match = /code=\d{4}\.\w{32}\.\w{32}/.match(request) end
if match
code = match.to_s.split("=").last
end
session.print "HTTP/1.1 200\r\n" # 1
session.print "Content-Type: text/html\r\n" # 2
session.print "\r\n" # 3
session.print "Thank you! The time is #{Time.now}" #4
session.close def get_grant_token
break # Ejecuta lo descrito en el paso 2 del ZOHO OAUTH https://www.zoho.com/crm/developer/docs/api/auth-request.html
# Para recibir el codigo que nos permitira generar los tokens
# Atencion, este metodo abre un navegador para autorizar y un socket en el puerto 8000 para recibir el codigo tras
# la aceptacion de permisos
@options.merge!(follow_redirects: false)
response=self.class.get('/auth', @options)
# puts "RESPONSE CODE:#{response.code}"
if response.code >= 300 && response.code < 400
redirect_url = response.headers['location']
Launchy.open(redirect_url)
grant_token=read_socket
@logger.info "GRANT TOKEN: #{grant_token}"
@grant_token = grant_token
return true
end
raise "Unable to get the grant token!"
end end
server.close
return code
end
def get_grant_token def get_grant_request
# Ejecuta lo descrito en el paso 2 del ZOHO OAUTH https://www.zoho.com/crm/developer/docs/api/auth-request.html # Prepara la llamada descrita en el paso 3 del ZOHO OAUTH https://www.zoho.com/crm/developer/docs/api/access-refresh.html
# Para recibir el codigo que nos permitira generar los tokens # Para recibir access_token y refresh_token
# Atencion, este metodo abre un navegador para autorizar y un socket en el puerto 8000 para recibir el codigo tras raise "Unable to get a grant request without grant token!" if @grant_token.nil?
# la aceptacion de permisos options_grant_request = @options.dup
@options.merge!(follow_redirects: false) options_grant_request.delete(:grant_token)
response=self.class.get('/auth', @options) options_grant_request.delete(:follow_redirects)
# puts "RESPONSE CODE:#{response.code}" options_grant_request[:query].delete(:response_type)
if response.code >= 300 && response.code < 400 options_grant_request[:query].delete(:scope)
redirect_url = response.headers['location'] options_grant_request[:query].delete(:access_type)
Launchy.open(redirect_url) options_grant_request[:query].merge!(code: @grant_token)
grant_token=read_socket grant_request=Zoholib::GrantRequest.new(options_grant_request)
@logger.info "GRANT TOKEN: #{grant_token}" result=grant_request.token
@grant_token = grant_token # pp result
return true raise "Error #{result[:error]}" unless result[:error].nil?
return result
end end
raise "Unable to get the grant token!"
end
def get_grant_request
# Prepara la llamada descrita en el paso 3 del ZOHO OAUTH https://www.zoho.com/crm/developer/docs/api/access-refresh.html
# Para recibir access_token y refresh_token
raise "Unable to get a grant request without grant token!" if @grant_token.nil?
options_grant_request = @options.dup
options_grant_request.delete(:grant_token)
options_grant_request.delete(:follow_redirects)
options_grant_request[:query].delete(:response_type)
options_grant_request[:query].delete(:scope)
options_grant_request[:query].delete(:access_type)
options_grant_request[:query].merge!(code: @grant_token)
grant_request=Zoholib::GrantRequest.new(options_grant_request)
result=grant_request.token
# pp result
raise "Error #{result[:error]}" unless result[:error].nil?
return result
end end
end end
end end
\ No newline at end of file
...@@ -5,53 +5,54 @@ require 'logger' ...@@ -5,53 +5,54 @@ require 'logger'
require 'date' require 'date'
require 'savon' require 'savon'
module Wedoops
module Zoholib module Zoholib
class B12Client class B12Client
def initialize(options={}) def initialize(options={})
@logger = Logger.new(STDOUT) @logger = Logger.new(STDOUT)
initialize_client initialize_client
@client.call(:lead) @client.call(:lead)
end end
def send_lead(lead) def send_lead(lead)
@logger.info("Sending lead: #{lead[:idvar]} tlf:#{lead[:Telefono]}") @logger.info("Sending lead: #{lead[:idvar]} tlf:#{lead[:Telefono]}")
#pp lead #pp lead
#puts ":.................:" #puts ":.................:"
begin begin
response = @client.call(:lead) do response = @client.call(:lead) do
message(lead) message(lead)
end
rescue Exception => e
@logger.error("Error sending the lead: #{e.message}")
return nil
end end
rescue Exception => e begin
@logger.error("Error sending the lead: #{e.message}") b12_id = response.body[:lead_response][:return]
return nil unless b12_id.match(/^\d*$/)
end raise "Error de B12, envio #{lead[:idvar]} tlf:#{lead[:Telefono]} duplicado (#{b12_id})" if b12_id == "-1"
begin raise "Error interno de B12, error #{b12_id} recibido"
b12_id = response.body[:lead_response][:return] end
unless b12_id.match(/^\d*$/) rescue Exception => e
raise "Error de B12, envio #{lead[:idvar]} tlf:#{lead[:Telefono]} duplicado (#{b12_id})" if b12_id == "-1" @logger.error("Error getting the LEAD ID: #{e.message}")
raise "Error interno de B12, error #{b12_id} recibido" return nil
end end
rescue Exception => e return b12_id
@logger.error("Error getting the LEAD ID: #{e.message}")
return nil
end end
return b12_id
end
private private
def initialize_client def initialize_client
@client = Savon.client do @client = Savon.client do
wsdl 'http://panel.digitalion.com/wss/cobalt.lead.php?wsdl' wsdl 'http://panel.digitalion.com/wss/cobalt.lead.php?wsdl'
pretty_print_xml true pretty_print_xml true
#convert_request_keys_to :camelcase #convert_request_keys_to :camelcase
log false log false
log_level :info log_level :info
end
end end
end
end
end end
end end
\ No newline at end of file
# frozen_string_literal: true # frozen_string_literal: true
module Wedoops
module Zoholib
##
# This class permits the configuration of the Valenciaport Access.
# Is neccesary the WDSL URLs for the login and transport endpoint
# as well the array with the different credentials wich will be used
class Configuration
attr_accessor :client_id, :client_secret, :scope, :refresh_token
module Zoholib def initialize
## @client_id = nil
# This class permits the configuration of the Valenciaport Access. @client_secret = nil
# Is neccesary the WDSL URLs for the login and transport endpoint @scope = nil
# as well the array with the different credentials wich will be used @refresh_token = nil
class Configuration end
attr_accessor :client_id, :client_secret, :scope, :refresh_token
def initialize
@client_id = nil
@client_secret = nil
@scope = nil
@refresh_token = nil
end
end
end end
end end
\ No newline at end of file
#require './lib/zoho_request' #require './lib/zoho_request'
module Zoholib module Wedoops
class GrantRequest < ZohoRequest module Zoholib
class GrantRequest < ZohoRequest
#base_uri "https://accounts.zoho.com/oauth/v2/token" #base_uri "https://accounts.zoho.com/oauth/v2/token"
#headers: {"Authorization" => "Token token=\"111\""} #headers: {"Authorization" => "Token token=\"111\""}
def initialize(options={}) def initialize(options={})
@logger = ::Logger.new(STDOUT) @logger = ::Logger.new(STDOUT)
@logged_in = false @logged_in = false
@options = options @options = options
end end
def token(options={}) def token(options={})
# Esta funcion se llama desde Zoholib::AuthorizationRequest # Esta funcion se llama desde Zoholib::AuthorizationRequest
# Ejecuta lo descrito en https://www.zoho.com/crm/developer/docs/api/access-refresh.html # Ejecuta lo descrito en https://www.zoho.com/crm/developer/docs/api/access-refresh.html
@options[:query].merge!(grant_type: "authorization_code") @options[:query].merge!(grant_type: "authorization_code")
@options.merge!(:logger => @logger) @options.merge!(:logger => @logger)
response=self.class.post('/token',@options) response=self.class.post('/token',@options)
JSON.parse(response.body,symbolize_names: true) JSON.parse(response.body,symbolize_names: true)
end end
end
end end
end end
\ No newline at end of file
#require './lib/zoho_request' #require './lib/zoho_request'
module Zoholib module Wedoops
class RefreshRequest < ZohoRequest module Zoholib
class RefreshRequest < ZohoRequest
# Sin en algun momento se quiere evitar el encode de URL # Sin en algun momento se quiere evitar el encode de URL
# he aqui un truco # he aqui un truco
#query_string_normalizer proc { |query|
# query.map do |key, value|
# [value].flatten.map {|v| "#{key}=#{v}"}.join('&')
# end.join('&')
# }
def initialize(options={}) #query_string_normalizer proc { |query|
options.merge!(grant_type: "refresh_token") # query.map do |key, value|
@options={:query => options} # [value].flatten.map {|v| "#{key}=#{v}"}.join('&')
end # end.join('&')
# }
def initialize(options={})
options.merge!(grant_type: "refresh_token")
@options={:query => options}
end
def get_token
self.class.post("/token",@options)
end
def get_token
self.class.post("/token",@options)
end end
end end
end end
\ No newline at end of file
module Zoholib module Wedoops
module Zoho module Zoholib
class Response class Response
......
# frozen_string_literal: true # frozen_string_literal: true
module Wedoops
module Zoholib module Zoholib
VERSION = '0.0.1b' VERSION = '0.0.1b'
end end
end
\ No newline at end of file
...@@ -7,167 +7,168 @@ require 'httparty' ...@@ -7,167 +7,168 @@ require 'httparty'
#require './lib/authorization_request' #require './lib/authorization_request'
module Wedoops
module Zoholib module Zoholib
class ZohoBasicClient class ZohoBasicClient
include HTTParty include HTTParty
base_uri 'https://www.zohoapis.com/crm/v2/' base_uri 'https://www.zohoapis.com/crm/v2/'
def initialize(options={}) def initialize(options={})
#Es un cliennte basico que trabaja a partir de refresh_tokens #Es un cliennte basico que trabaja a partir de refresh_tokens
@logger = ::Logger.new(STDOUT) @logger = ::Logger.new(STDOUT)
@logged_in = false
@options = options
@token = nil
end
def login
unless @options.has_key?(:refresh_token)
#En estos casos necesito mi refresh_token primero
auth_request=Zoholib::AuthorizationRequest.new(@options)
# Ojo esta opcion fuerza que siempre salga la pantalla
# de credenciales
result=auth_request.authorize({force_prompt: true})
@options.merge!(result)
#El refresh token habria que persisitirlo para
#evitar tener que cogerlo de nuevo
end
request= Zoholib::RefreshRequest.new(@options)
response=request.get_token
@logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
response = JSON.parse(response.to_s, symbolize_names: true)
unless response[:access_token].nil?
@logged_in = true
@token = response[:access_token]
else
@logged_in = false @logged_in = false
@options = options
@token = nil @token = nil
end end
return @logged_in
end
def read_all(url,params={}) def login
# ojo, maxrecords no tiene en cuenta cuantos registros se descaargan unless @options.has_key?(:refresh_token)
# en cada ocasion por lo que puede devolver registros de mas #En estos casos necesito mi refresh_token primero
# como resto de la llamada anterior auth_request=Zoholib::AuthorizationRequest.new(@options)
page=1 # Ojo esta opcion fuerza que siempre salga la pantalla
maxrecords=-1 # de credenciales
result = Hash.new result=auth_request.authorize({force_prompt: true})
result[:data] = Array.new @options.merge!(result)
params.delete(:page) if params.has_key?(:page) #El refresh token habria que persisitirlo para
if params.has_key?(:max_records) #evitar tener que cogerlo de nuevo
maxrecords = params[:max_records] end
params.delete(:max_records) request= Zoholib::RefreshRequest.new(@options)
end response=request.get_token
loop do @logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
params.merge!(page: page)
response=read(url,params) response = JSON.parse(response.to_s, symbolize_names: true)
if response[:info][:more_records] == true unless response[:access_token].nil?
page+=1 @logged_in = true
result[:data].concat(response[:data]) @token = response[:access_token]
break if maxrecords > 0 && result[:data].size >= maxrecords
else else
break @logged_in = false
@token = nil
end end
return @logged_in
end end
return result
end
def read(url,params=nil) def read_all(url,params={})
self.login unless @logged_in # ojo, maxrecords no tiene en cuenta cuantos registros se descaargan
options = {} # en cada ocasion por lo que puede devolver registros de mas
options[:query] = params unless params.nil? # como resto de la llamada anterior
options.merge!(build_header) page=1
maxrecords=-1
result = Hash.new
result[:data] = Array.new
params.delete(:page) if params.has_key?(:page)
if params.has_key?(:max_records)
maxrecords = params[:max_records]
params.delete(:max_records)
end
loop do
params.merge!(page: page)
response=read(url,params)
if response[:info][:more_records] == true
page+=1
result[:data].concat(response[:data])
break if maxrecords > 0 && result[:data].size >= maxrecords
else
break
end
end
return result
end
response=self.class.get("/#{url}",options) def read(url,params=nil)
@logger.debug("#{__method__}:#{response.request.last_uri.to_s}") self.login unless @logged_in
response = JSON.parse(response.to_s, symbolize_names: true) options = {}
return response options[:query] = params unless params.nil?
end options.merge!(build_header)
def write(url,data) response=self.class.get("/#{url}",options)
raise "Invalid JSON!" unless valid_json?(data) @logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
self.login unless @logged_in response = JSON.parse(response.to_s, symbolize_names: true)
options = {} return response
#Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion] end
options[:body]=data
options.merge!(build_header)
response=self.class.post("/#{url}",options)
@logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
response = JSON.parse(response.to_s, symbolize_names: true)
end
def update(url,data) def write(url,data)
raise "Invalid JSON!" unless valid_json?(data) raise "Invalid JSON!" unless valid_json?(data)
self.login unless @logged_in self.login unless @logged_in
options = {} options = {}
#Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion] #Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion]
options[:body]=data options[:body]=data
options.merge!(build_header) options.merge!(build_header)
response=self.class.put("/#{url}",options) response=self.class.post("/#{url}",options)
@logger.debug("#{__method__}:#{response.request.last_uri.to_s}") @logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
response = JSON.parse(response.to_s, symbolize_names: true) response = JSON.parse(response.to_s, symbolize_names: true)
end end
def query(coql) def update(url,data)
self.login unless @logged_in raise "Invalid JSON!" unless valid_json?(data)
options = {} self.login unless @logged_in
#Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion] options = {}
options[:body] = {:select_query => coql}.to_json #Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion]
# options[:query]={scope:"ZohoCRM.coql.READ,ZohoCRM.modules.all"} options[:body]=data
options[:logger]=@logger options.merge!(build_header)
options.merge!(build_header)
response=self.class.post("/coql",options) response=self.class.put("/#{url}",options)
#response=self.class.post("/coql?scope=ZohoCRM.modules.ALL,ZohoCRM.coql.read",options) @logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
@logger.debug("#{__method__}:#{response.request.last_uri.to_s}") response = JSON.parse(response.to_s, symbolize_names: true)
response = JSON.parse(response.to_s, symbolize_names: true) end
end
def query_all(coql,params={}) def query(coql)
# ojo, maxrecords no tiene en cuenta cuantos registros se descaargan self.login unless @logged_in
# en cada ocasion por lo que puede devolver registros de mas options = {}
# como resto de la llamada anterior #Ojo, aqui tal vez deberiamos coprobar que viene con la forma :data => [:coleccion]
page=1 options[:body] = {:select_query => coql}.to_json
maxrecords=-1 # options[:query]={scope:"ZohoCRM.coql.READ,ZohoCRM.modules.all"}
result = Hash.new options[:logger]=@logger
result[:data] = Array.new options.merge!(build_header)
params.delete(:page) if params.has_key?(:page) response=self.class.post("/coql",options)
if params.has_key?(:max_records) #response=self.class.post("/coql?scope=ZohoCRM.modules.ALL,ZohoCRM.coql.read",options)
maxrecords = params[:max_records] @logger.debug("#{__method__}:#{response.request.last_uri.to_s}")
params.delete(:max_records) response = JSON.parse(response.to_s, symbolize_names: true)
end end
loop do
params.merge!(page: page) def query_all(coql,params={})
response=self.query(coql) # ojo, maxrecords no tiene en cuenta cuantos registros se descaargan
return response if response[:status] == "error" # en cada ocasion por lo que puede devolver registros de mas
if response[:info][:more_records] == true # como resto de la llamada anterior
page+=1 page=1
result[:data].concat(response[:data]) maxrecords=-1
break if maxrecords > 0 && result[:data].size >= maxrecords result = Hash.new
else result[:data] = Array.new
break params.delete(:page) if params.has_key?(:page)
if params.has_key?(:max_records)
maxrecords = params[:max_records]
params.delete(:max_records)
end
loop do
params.merge!(page: page)
response=self.query(coql)
return response if response[:status] == "error"
if response[:info][:more_records] == true
page+=1
result[:data].concat(response[:data])
break if maxrecords > 0 && result[:data].size >= maxrecords
else
break
end
@logger.debug("#{result[:data].size} records")
@logger.debug("#{result[:data].last} ")
end end
@logger.debug("#{result[:data].size} records") return result
@logger.debug("#{result[:data].last} ")
end end
return result
end
private private
def build_header def build_header
{:headers => { "Authorization" => "Zoho-oauthtoken #{@token}"}} {:headers => { "Authorization" => "Zoho-oauthtoken #{@token}"}}
end end
def valid_json?(json) def valid_json?(json)
JSON.parse(json) JSON.parse(json)
return true return true
rescue JSON::ParserError => e rescue JSON::ParserError => e
return false return false
end end
end end
end end
end
\ No newline at end of file
...@@ -7,619 +7,620 @@ require 'date' ...@@ -7,619 +7,620 @@ require 'date'
require 'httparty' require 'httparty'
#include ERB::Util #include ERB::Util
module Wedoops
module Zoholib module Zoholib
class ZohoClient < ERB class ZohoClient < ERB
attr_accessor :token, :scope, :auth_type, :client_id, :redirect_uri, :code attr_accessor :token, :scope, :auth_type, :client_id, :redirect_uri, :code
def initialize(options={}) def initialize(options={})
@auth_type=nil @auth_type=nil
@user=nil @user=nil
@pass=nil @pass=nil
@scope=nil @scope=nil
@life_token=nil @life_token=nil
@client_id=nil @client_id=nil
@client_secret=nil @client_secret=nil
@code=nil @code=nil
@grant_type=nil @grant_type=nil
@access_token=nil @access_token=nil
@refresh_token=nil @refresh_token=nil
@api_domain=nil @api_domain=nil
@toke_type=nil @toke_type=nil
@expires_in=nil @expires_in=nil
@zapikey=nil @zapikey=nil
@redirect_uri=nil @redirect_uri=nil
@logger = Logger.new(STDOUT) @logger = Logger.new(STDOUT)
raise "Error constructing the class!" unless initialize_options(options) raise "Error constructing the class!" unless initialize_options(options)
@http = HTTP @http = HTTP
.use(logging: {logger: @logger})
.timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache")
# .accept(:json)
@logger.info("Initialized")
end
def get_code
url="https://accounts.zoho.com/oauth/v2/auth?scope=#{@scope}&client_id=#{@client_id}&response_type=code&access_type=offline&redirect_uri=#{@redirect_uri}"
@logger.info(url)
@logger.info("#> Sending request....")
HTTP.follow
.use(logging: {logger: @logger}) .use(logging: {logger: @logger})
.timeout(connect: 15, read: 30) .timeout(connect: 15, read: 30)
.headers("cache-control" => "no-cache") .headers("cache-control" => "no-cache")
# .accept(:json) .get(url)
@logger.info("Initialized") end
def token
#Dependiendo del tipo de autenticacion devolvere un tipo de token
case check_mode
when "apikey"
return @zapikey
when "oauth"
return @access_token
when "auth-token"
return @life_token
else
raise "Seems uninitialized!"
end
return nil
end
def token?
valid_token?
end
def grant_token!(token)
#Actualizo el codigo del grant token desde un callback de oauth probablemente
raise "Invalid token #{token}" unless /^\w{4}.\w{32}.\w{32}$/.match(token)
@logger.info("Grant Token updated! #{token}")
@code = token
get_refresh_token
persist_token
true
end
end def refresh_token!
raise "Unsupported mode" unless check_mode == "oauth"
def get_code #if @refresh_token.nil?
url="https://accounts.zoho.com/oauth/v2/auth?scope=#{@scope}&client_id=#{@client_id}&response_type=code&access_type=offline&redirect_uri=#{@redirect_uri}" # @logger.info("@refresh_token nulo, vamos a actualizar")
@logger.info(url) # get_refresh_token
@logger.info("#> Sending request....") # @logger.info("Actualizado el refresh token! ->#{@refresh_token}<-")
HTTP.follow #end
.use(logging: {logger: @logger})
.timeout(connect: 15, read: 30) #En este supuesto acabo de inicializar con los basico de Oauth
.headers("cache-control" => "no-cache") # y quiero traerme la informacion con @code de un fichero
.get(url) @logger.info("------------> Carga 1")
end load_previous_token if token.nil?
@logger.info("TOKEN: #{token}")
def token @logger.info("auth_token: #{@auth_token}")
#Dependiendo del tipo de autenticacion devolvere un tipo de token @logger.info("CODE: #{@code}")
case check_mode show_current_options
when "apikey" @logger.info "Show VALID TOKEM DIRA:"
return @zapikey
when "oauth" if token?
return @access_token @logger.info("DICE QUE GUAY")
when "auth-token" else
return @life_token @logger.info("DICE QUE NO")
else #get_refresh_token
raise "Seems uninitialized!" # refresh_oauth_token
end end
return nil
end
def token?
valid_token?
end
def grant_token!(token)
#Actualizo el codigo del grant token desde un callback de oauth probablemente
raise "Invalid token #{token}" unless /^\w{4}.\w{32}.\w{32}$/.match(token)
@logger.info("Grant Token updated! #{token}")
@code = token
get_refresh_token
persist_token
true
end
def refresh_token!
raise "Unsupported mode" unless check_mode == "oauth"
#if @refresh_token.nil?
# @logger.info("@refresh_token nulo, vamos a actualizar")
# get_refresh_token
# @logger.info("Actualizado el refresh token! ->#{@refresh_token}<-")
#end
#En este supuesto acabo de inicializar con los basico de Oauth if token.nil?
# y quiero traerme la informacion con @code de un fichero @logger.info("TOken sigue siendo nulo")
@logger.info("------------> Carga 1") if @code.nil?
load_previous_token if token.nil? @logger.info("------------> Carga 2!!!!")
@logger.info("TOKEN: #{token}") #Tal vez habria que implementar un mecanismo para traer nuevos codes
@logger.info("auth_token: #{@auth_token}") raise "Unable to load it!!!" unless load_previous_token
@logger.info("CODE: #{@code}") end
show_current_options # Si tengo un code debe ser que aun no se ha gastado
@logger.info "Show VALID TOKEM DIRA:" if get_authorization_token
@logger.info("Token refrescado #{@access_token}")
@http.headers("Authorization" => "Zoho-oauthtoken #{token}")
# Al persistirlo estamos grabando el refresh_token
#persist_token
#A la salida lo dejamos en blanco ya que no va a ser valido
#@refresh_token = nil
persist_token
return true
else
@logger.error("No ha sido posible refrescar el token")
return false
end
else
@logger.info("NO se refresca el token dado que todavia lo tenemos! #{token} : )")
true
end
end
def renew_life_token!(force=false)
raise "Unsupported mode" unless check_mode == "auth-token"
update_life_token!(force)
end
def execute(function,params=nil)
salida = case function
when "holamundo"
execute_function("https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60")
when "holamundo2"
execute_function("https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute",{
auth_type: "apikey",
zapikey: "1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60"})
# ?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60")
when "getJSON"
execute_function("https://www.zohoapis.com/crm/v2/functions/getjson/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60")
when "getJSONParams"
execute_function("https://www.zohoapis.com/crm/v2/functions/getjsonparams/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60",params)
when "call"
#just standard function
#https://crm.zoho.com/crm/v2/functions/{api_name_of_function}/actions/execute?auth_type=apikey&zapikey={zapikey}
execute_function("https://crm.zoho.com/crm/v2/functions/{api_name_of_function}/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60")
when "read_api"
execute_function("https://www.zohoapis.com/crm/v2/Modules/")
when "adamo_address"
result=Array.new
(0..4).each do |page|
puts "Zoho-oauthtoken #{token}"
url="https://www.zohoapis.com/crm/v2/Adamo_Addresses?page=#{page}&sort_by=Adamo_ID"
#temp= HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").get(url)
temp=HTTParty.get(url,format: :json,:headers => {"Authorization" => "Zoho-oauthtoken #{token}"})
puts "......."
pp temp.body
puts "......"
result << temp
end
return result
when "get_settings"
url= "https://www.zohoapis.com/crm/v2/settings/modules"
params={:scope => @scope}
return get_params(url,params)
else
puts "Unknown function"
end
if token? return normalize_output(salida)
@logger.info("DICE QUE GUAY")
else
@logger.info("DICE QUE NO")
#get_refresh_token
# refresh_oauth_token
end end
if token.nil? def execute_oauth(function)
@logger.info("TOken sigue siendo nulo") url="https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute?auth_type=oauth"
if @code.nil? end
@logger.info("------------> Carga 2!!!!")
#Tal vez habria que implementar un mecanismo para traer nuevos codes def valid_json?(string)
raise "Unable to load it!!!" unless load_previous_token !!JSON.parse(string)
rescue JSON::ParserError
false
end
private
def execute_function(url,params=nil)
# Ejecutamos una funcion GET con los parametors dados
# payload = {
# limit: 20,
# authtoken: @life_token,
# scope: "creatorapi",
# }
execute_url = url
payload = params
get_params(execute_url, params)
end
def get_refresh_token
@logger.info("#{__method__} con @refresh_token = #{@refresh_token} y grant_token (@code) = #{@code}")
#Proceso OAUTH para recibir un nuevo refresh_token para poder refrescar el token
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}"
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token&code=#{@code}&redirect_uri=http://localhost:8000/auth/callback"
url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}&redirect_uri=#{@redirect_uri}"
res=post(url)
resultado = JSON.parse(res,:symbolize_names => true)
if resultado.has_key?(:error)
#pp resultado
@logger.error("Se ha detectado un error solicitando el refresh token. Arakiri.")
raise resultado[:error]
end end
# Si tengo un code debe ser que aun no se ha gastado puts "-------RESULTADO DE GET REFRESH TOKEN----"
if get_authorization_token pp resultado
@logger.info("Token refrescado #{@access_token}") puts "..........."
@http.headers("Authorization" => "Zoho-oauthtoken #{token}") @refresh_token = resultado[:refresh_token]
# Al persistirlo estamos grabando el refresh_token @token_type = resultado[:token_type]
#persist_token @api_domain = resultado[:api_domain]
#A la salida lo dejamos en blanco ya que no va a ser valido @access_token = resultado[:access_token]
#@refresh_token = nil @expires_in = (Time.new + resultado[:expires_in]).to_datetime
persist_token persist_token
return true return true
else
@logger.error("No ha sido posible refrescar el token")
return false
end
else
@logger.info("NO se refresca el token dado que todavia lo tenemos! #{token} : )")
true
end end
end
def get_authorization_token
def renew_life_token!(force=false) @logger.info("#{__method__} con @refresh_token = #{@refresh_token} y grant_token (@code) = #{@code}")
raise "Unsupported mode" unless check_mode == "auth-token" #Proceso OAUTH para recibir un nuevo refresh_token para poder refrescar el token
update_life_token!(force)
end #url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}"
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token&code=#{@code}&redirect_uri=http://localhost:8000/auth/callback"
def execute(function,params=nil) url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}&redirect_uri=#{@redirect_uri}"
salida = case function res=post(url)
when "holamundo" resultado = JSON.parse(res,:symbolize_names => true)
execute_function("https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60") if resultado.has_key?(:error)
when "holamundo2" #pp resultado
execute_function("https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute",{ @logger.error("Se ha detectado un error solicitando el authorization token. Arakiri.")
auth_type: "apikey", raise resultado[:error]
zapikey: "1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60"}) end
# ?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60") puts "-------RESULTADO DE GET AUTHORIZATION TOKEN----"
when "getJSON" pp resultado
execute_function("https://www.zohoapis.com/crm/v2/functions/getjson/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60") puts "..........."
when "getJSONParams" @token_type = resultado[:token_type]
execute_function("https://www.zohoapis.com/crm/v2/functions/getjsonparams/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60",params) @api_domain = resultado[:api_domain]
when "call" @access_token = resultado[:access_token]
#just standard function @expires_in = (Time.new + resultado[:expires_in]).to_datetime
#https://crm.zoho.com/crm/v2/functions/{api_name_of_function}/actions/execute?auth_type=apikey&zapikey={zapikey} # El code lo tengo que invalidar porque ya no es valido
execute_function("https://crm.zoho.com/crm/v2/functions/{api_name_of_function}/actions/execute?auth_type=apikey&zapikey=1003.7fb3bae78b241ff68541181c3b699cf1.983d91325ef11808acdc31d225fdca60") @code = nil
when "read_api" persist_token
execute_function("https://www.zohoapis.com/crm/v2/Modules/") return true
when "adamo_address" end
result=Array.new
(0..4).each do |page| def refresh_oauth_token
puts "Zoho-oauthtoken #{token}" #params=auth_params("refresh_token")
url="https://www.zohoapis.com/crm/v2/Adamo_Addresses?page=#{page}&sort_by=Adamo_ID" @logger.info("Refrescando el token....")
#temp= HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").get(url) url="https://accounts.zoho.com/oauth/v2/token?refresh_token=#{@refresh_token}&client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token"
temp=HTTParty.get(url,format: :json,:headers => {"Authorization" => "Zoho-oauthtoken #{token}"}) @logger.info("URL REFRESCO: #{url}")
puts "......." # Pruebo sin pasar el secret
pp temp.body #url="https://accounts.zoho.com/oauth/v2/token?refresh_token=#{@refresh_token}&client_id=#{@client_id}&grant_type=refresh_token"
puts "......" res=post(url)
result << temp resultado = JSON.parse(res,:symbolize_names => true)
if resultado.has_key?(:error)
pp resultado
@logger.error("Se ha detectado un error al refrescar el token.")
raise resultado[:error]
end
puts "-----------"
pp resultado
puts "..........."
@access_token = resultado[:access_token]
@token_type = resultado[:token_type]
@api_domain = resultado[:api_domain]
@expires_in = (Time.new + resultado[:expires_in]).to_datetime
return true
end
def update_life_token!(force=false)
#Recogemos el token para toda la vida
token_url="https://accounts.zoho.com/apiauthtoken/xml/create?SCOPE=#{@scope}&EMAIL_ID=#{@user}&PASSWORD=#{@pass}"
#A no ser que forcemos, devolvera true sin actualizar si el tokem es aun valido
unless force
if valid_token?
return true
end
end
response=@http.get(token_url).to_s
auth=/AUTHTOKEN=(?<token>\w{32})/.match(response)
result=/RESULT=(?<result>\w*)/.match(response)
if true?(result[:result])
@life_token = auth[:token]
else
return false
end end
return result
when "get_settings"
url= "https://www.zohoapis.com/crm/v2/settings/modules"
params={:scope => @scope}
return get_params(url,params)
else
puts "Unknown function"
end end
return normalize_output(salida)
end
def execute_oauth(function)
url="https://www.zohoapis.com/crm/v2/functions/holamundo/actions/execute?auth_type=oauth"
end
def valid_json?(string) def auth_params(grant_type=@grant_type)
!!JSON.parse(string) #osparams necesarios para una autenticaciton
rescue JSON::ParserError if grant_type == "refresh_token"
false #Ojo, el @refresh_token es efimero ya que solo se tiene en cuenta
end # en el momento que se ejecuta get_refresh_token dentro de refresh_token
auth_params = {
private refresh_token: @refresh_token,
client_id: @client_id,
def execute_function(url,params=nil) client_secret: @client_secret,
# Ejecutamos una funcion GET con los parametors dados grant_type: grant_type
}
# payload = { else
# limit: 20, auth_params = {
# authtoken: @life_token, access_token: token,
# scope: "creatorapi", client_id: @client_id,
# } client_secret: @client_secret,
grant_type: grant_type
execute_url = url }
payload = params end
get_params(execute_url, params)
end
def get_refresh_token
@logger.info("#{__method__} con @refresh_token = #{@refresh_token} y grant_token (@code) = #{@code}")
#Proceso OAUTH para recibir un nuevo refresh_token para poder refrescar el token
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}" end
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token&code=#{@code}&redirect_uri=http://localhost:8000/auth/callback"
url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}&redirect_uri=#{@redirect_uri}"
res=post(url)
resultado = JSON.parse(res,:symbolize_names => true)
if resultado.has_key?(:error)
#pp resultado
@logger.error("Se ha detectado un error solicitando el refresh token. Arakiri.")
raise resultado[:error]
end
puts "-------RESULTADO DE GET REFRESH TOKEN----"
pp resultado
puts "..........."
@refresh_token = resultado[:refresh_token]
@token_type = resultado[:token_type]
@api_domain = resultado[:api_domain]
@access_token = resultado[:access_token]
@expires_in = (Time.new + resultado[:expires_in]).to_datetime
persist_token
return true
end
def get_authorization_token
@logger.info("#{__method__} con @refresh_token = #{@refresh_token} y grant_token (@code) = #{@code}")
#Proceso OAUTH para recibir un nuevo refresh_token para poder refrescar el token
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}" def valid_token?
#url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token&code=#{@code}&redirect_uri=http://localhost:8000/auth/callback" #Alguna consulta que nos verifique el que token es valido.
url="https://accounts.zoho.com/oauth/v2/token?client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=authorization_code&code=#{@code}&redirect_uri=#{@redirect_uri}" #Dependiendo del tipo de token tenemos distintas opciones
res=post(url) case check_mode
resultado = JSON.parse(res,:symbolize_names => true) when "oauth"
if resultado.has_key?(:error) valid_oauth_token?
#pp resultado when "apikey"
@logger.error("Se ha detectado un error solicitando el authorization token. Arakiri.") return @zapikey =! nil
raise resultado[:error] when "auth-token"
end return @life_token =! nil
puts "-------RESULTADO DE GET AUTHORIZATION TOKEN----" else
pp resultado raise "Error checking validity of token due an unexpected mode"
puts "..........."
@token_type = resultado[:token_type]
@api_domain = resultado[:api_domain]
@access_token = resultado[:access_token]
@expires_in = (Time.new + resultado[:expires_in]).to_datetime
# El code lo tengo que invalidar porque ya no es valido
@code = nil
persist_token
return true
end
def refresh_oauth_token
#params=auth_params("refresh_token")
@logger.info("Refrescando el token....")
url="https://accounts.zoho.com/oauth/v2/token?refresh_token=#{@refresh_token}&client_id=#{@client_id}&client_secret=#{@client_secret}&grant_type=refresh_token"
@logger.info("URL REFRESCO: #{url}")
# Pruebo sin pasar el secret
#url="https://accounts.zoho.com/oauth/v2/token?refresh_token=#{@refresh_token}&client_id=#{@client_id}&grant_type=refresh_token"
res=post(url)
resultado = JSON.parse(res,:symbolize_names => true)
if resultado.has_key?(:error)
pp resultado
@logger.error("Se ha detectado un error al refrescar el token.")
raise resultado[:error]
end
puts "-----------"
pp resultado
puts "..........."
@access_token = resultado[:access_token]
@token_type = resultado[:token_type]
@api_domain = resultado[:api_domain]
@expires_in = (Time.new + resultado[:expires_in]).to_datetime
return true
end
def update_life_token!(force=false)
#Recogemos el token para toda la vida
token_url="https://accounts.zoho.com/apiauthtoken/xml/create?SCOPE=#{@scope}&EMAIL_ID=#{@user}&PASSWORD=#{@pass}"
#A no ser que forcemos, devolvera true sin actualizar si el tokem es aun valido
unless force
if valid_token?
return true
end end
end end
response=@http.get(token_url).to_s
auth=/AUTHTOKEN=(?<token>\w{32})/.match(response) def valid_oauth_token?
result=/RESULT=(?<result>\w*)/.match(response) @logger.info("Checking if the token is still valid...")
show_current_options
#options = nil
#if token.nil?
# puts "No hay token"
# begin
# options=options_from_json_file({:json_file=>'token.json',:auth_type=>'oauth'})
# rescue Exception => e
# @logger.info("No es posible tratar el fichero de token")
# return false
# end
# @logger.info("VAmos a inilizalizar las opciones")
# pp options
# initialize_options(options) unless options.nil?
if true?(result[:result]) #Aqui tenemos que ver si aun es valido
@life_token = auth[:token] expires = @expires_in
else expires = @expiry_time if expires.nil?
unless expires.nil?
expires = DateTime.strptime(expires.to_s,'%Q') if expires.kind_of?String
@logger.info("Comprobando si el token ha expirado")
puts DateTime.now < expires
puts "............................"
return DateTime.now < expires
else
@logger.info("Valid oauth token aun no esta implementado")
return true
end
return false return false
end end
end
def auth_params(grant_type=@grant_type) def authorization_request
#osparams necesarios para una autenticaciton raise "Only available for OAuth" unless check_mode == "oauth"
if grant_type == "refresh_token" #"https://accounts.zoho.com/oauth/v2/auth?scope=ZohoCRM.users.ALL&client_id={client_id}&response_type=code&access_type={"offline"or"online"}&redirect_uri={redirect_uri}"
#Ojo, el @refresh_token es efimero ya que solo se tiene en cuenta
# en el momento que se ejecuta get_refresh_token dentro de refresh_token
auth_params = {
refresh_token: @refresh_token,
client_id: @client_id,
client_secret: @client_secret,
grant_type: grant_type
}
else
auth_params = {
access_token: token,
client_id: @client_id,
client_secret: @client_secret,
grant_type: grant_type
}
end end
end
def valid_token? def get(url)
#Alguna consulta que nos verifique el que token es valido. HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").accept(:json).get(url)
#Dependiendo del tipo de token tenemos distintas opciones
case check_mode
when "oauth"
valid_oauth_token?
when "apikey"
return @zapikey =! nil
when "auth-token"
return @life_token =! nil
else
raise "Error checking validity of token due an unexpected mode"
end end
end
def get_params(url,payload)
def valid_oauth_token? if check_mode == "oauth"
@logger.info("Checking if the token is still valid...") @logger.info("Haciendo el get params de OAuth")
show_current_options HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").accept(:json).get(url, :params => payload)
#options = nil else
#if token.nil? @logger.info("Haciendo el get params")
# puts "No hay token" puts "........................."
# begin pp @http
# options=options_from_json_file({:json_file=>'token.json',:auth_type=>'oauth'}) puts "........................."
# rescue Exception => e @http.get(url, :params => payload).to_s
# @logger.info("No es posible tratar el fichero de token") end
# return false end
# end
# @logger.info("VAmos a inilizalizar las opciones") def true?(obj)
# pp options obj.to_s.downcase == "true"
# initialize_options(options) unless options.nil? end
def post_payload(callback_url, payload)
#Aqui tenemos que ver si aun es valido puts "Posting with payload"
expires = @expires_in #pp payload
expires = @expiry_time if expires.nil? @http.post(callback_url, json: payload)
unless expires.nil? rescue HTTP::Error
expires = DateTime.strptime(expires.to_s,'%Q') if expires.kind_of?String # handle exception
@logger.info("Comprobando si el token ha expirado") end
puts DateTime.now < expires
puts "............................" def post(url)
return DateTime.now < expires puts "Posting"
else #pp payload
@logger.info("Valid oauth token aun no esta implementado") @http.post(url)
rescue HTTP::Error
# handle exception
end
def normalize_output(output)
raise "#{__method__} Invalid string. I can't normalize this crap!" unless valid_json?(output)
@logger.info "Normalizing..."
return Zoholib::Zoho::Response.new(output)
end
def sanitize(string)
util=ERB
return JSON.parse(util.json_escape)
end
# INIT CONTEXT
def initialize_options(options)
# Utilizamos options para configurar las distintas maneras de autenticarse
# Si las options tienen un json file extraeremos todas las opciones de ahi
options=options_from_json_file(options) if options.has_key?(:json_file)
@logger.info("Opciones en blanco") if options.empty?
raise "Invalid auth type" unless validate_auth_type(options)
raise "Invalid options" unless validate_options(options)
case check_mode
when "apikey"
@user=nil
@pass=nil
@scope=nil
@client_id=nil
@client_secret=nil
@code=nil
@grant_type=nil
@access_token=nil
@refresh_token=nil
@api_domain=nil
@toke_type=nil
@expires_in=nil
@zapikey=options[:zapikey]
@redirect_uri=nil
when "oauth"
@user=nil
@pass=nil
@scope=options[:scope]
@client_id=options[:client_id]
@client_secret=options[:client_secret]
@code=options[:code]
@grant_type=options[:grant_type]
@access_token=options[:access_token]
@refresh_token=options[:refresh_token]
@api_domain=nil
@toke_type=nil
@expires_in=options[:expiry_time]
@zapikey=nil
@redirect_uri=options[:redirect_uri]
when "auth-token"
@user=options[:user]
@pass=options[:pass]
@scope=options[:scope]
@client_id=nil
@client_secret=nil
@code=nil
@grant_type=nil
@access_token=nil
@refresh_token=nil
@api_domain=nil
@toke_type=nil
@expires_in=nil
@zapikey=nil
@redirect_uri=nil
else
raise "Unable to inilizalie!"
end
@scope=@scope.join(",") if @scope.kind_of?Array
return true
end
def options_from_json_file(options)
@logger.info("Parsing options from file...")
raise "Unable to find option json_file!" unless options.has_key?(:json_file)
begin
content = File.read(options[:json_file])
new_options=JSON.parse(content, :symbolize_names => true)
options.delete(:json_file)
new_options[:expires_in] = DateTime.strptime(new_options[:expiry_time].to_s,'%Q')
options = options.merge(new_options)
rescue Exception => e
puts e.backtrace
raise "Unable to read the json_file: #{e.message}"
end
#pp options
return options
end
def load_previous_token(previous_token="token.json")
@logger.info("Loading_previous_token...")
begin
content = File.read(previous_token)
new_options=JSON.parse(content, :symbolize_names => true)
@logger.info("LOADED FROM FILE:#{new_options} ")
#new_options[:expires_in] = DateTime.strptime(new_options[:expiry_time].to_s,'%Q')
initialize_options(new_options)
rescue Exception => e
puts e.backtrace
raise "Unable to load previous token: #{e.message}"
end
#pp options
return true return true
end end
return false
end def check_mode
#Check if im running in oauthv2 or auth-token
def authorization_request return @auth_type
raise "Only available for OAuth" unless check_mode == "oauth"
#"https://accounts.zoho.com/oauth/v2/auth?scope=ZohoCRM.users.ALL&client_id={client_id}&response_type=code&access_type={"offline"or"online"}&redirect_uri={redirect_uri}"
end
def get(url)
HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").accept(:json).get(url)
end
def get_params(url,payload)
if check_mode == "oauth"
@logger.info("Haciendo el get params de OAuth")
HTTP.use(logging: {logger: @logger}).headers("Authorization" => "Zoho-oauthtoken #{token}").accept(:json).get(url, :params => payload)
else
@logger.info("Haciendo el get params")
puts "........................."
pp @http
puts "........................."
@http.get(url, :params => payload).to_s
end end
end
def validate_auth_type(options)
def true?(obj) #Comprobamos que forma parte de uno de los metodos de autenticacion soporteados
obj.to_s.downcase == "true" unless ["oauth","apikey","auth-token"].member?(options[:auth_type])
end @logger.warn("Initializing with detault auth_type oauth")
@auth_type="oauth"
def post_payload(callback_url, payload) else
puts "Posting with payload" @auth_type = options[:auth_type]
#pp payload end
@http.post(callback_url, json: payload) return true
rescue HTTP::Error end
# handle exception
end
def required_options(auth_type=@auth_type)
def post(url) #Dependiendo del tipo de autenticacion, indica cuales son las optciones requeridas
puts "Posting" case auth_type
#pp payload
@http.post(url)
rescue HTTP::Error
# handle exception
end
def normalize_output(output)
raise "#{__method__} Invalid string. I can't normalize this crap!" unless valid_json?(output)
@logger.info "Normalizing..."
return Zoholib::Zoho::Response.new(output)
end
def sanitize(string)
util=ERB
return JSON.parse(util.json_escape)
end
# INIT CONTEXT
def initialize_options(options)
# Utilizamos options para configurar las distintas maneras de autenticarse
# Si las options tienen un json file extraeremos todas las opciones de ahi
options=options_from_json_file(options) if options.has_key?(:json_file)
@logger.info("Opciones en blanco") if options.empty?
raise "Invalid auth type" unless validate_auth_type(options)
raise "Invalid options" unless validate_options(options)
case check_mode
when "apikey"
@user=nil
@pass=nil
@scope=nil
@client_id=nil
@client_secret=nil
@code=nil
@grant_type=nil
@access_token=nil
@refresh_token=nil
@api_domain=nil
@toke_type=nil
@expires_in=nil
@zapikey=options[:zapikey]
@redirect_uri=nil
when "oauth" when "oauth"
@user=nil return [:client_id,:client_secret,:scope]
@pass=nil #return [:client_id,:client_secret,:code,:grant_type,:scope]
@scope=options[:scope] when "apikey"
@client_id=options[:client_id] return [:zapikey]
@client_secret=options[:client_secret]
@code=options[:code]
@grant_type=options[:grant_type]
@access_token=options[:access_token]
@refresh_token=options[:refresh_token]
@api_domain=nil
@toke_type=nil
@expires_in=options[:expiry_time]
@zapikey=nil
@redirect_uri=options[:redirect_uri]
when "auth-token" when "auth-token"
@user=options[:user] return [:user,:pass,:scope]
@pass=options[:pass]
@scope=options[:scope]
@client_id=nil
@client_secret=nil
@code=nil
@grant_type=nil
@access_token=nil
@refresh_token=nil
@api_domain=nil
@toke_type=nil
@expires_in=nil
@zapikey=nil
@redirect_uri=nil
else else
raise "Unable to inilizalie!" raise "#{__method__} Unknown auth_type #{auth_type}"
end
end
def validate_options(options)
# Comprueba que segun el metodo de autenticacion dado, nos han pasado todas la opciones necesarias
required_options.each do |key|
raise "#{__method__} Option #{key.to_s} not found!" unless options.has_key?(key)
raise "#{__method__} Option #{key.to_s} not found!" if options[key].nil?
end end
@scope=@scope.join(",") if @scope.kind_of?Array
return true return true
end
def options_from_json_file(options)
@logger.info("Parsing options from file...")
raise "Unable to find option json_file!" unless options.has_key?(:json_file)
begin
content = File.read(options[:json_file])
new_options=JSON.parse(content, :symbolize_names => true)
options.delete(:json_file)
new_options[:expires_in] = DateTime.strptime(new_options[:expiry_time].to_s,'%Q')
options = options.merge(new_options)
rescue Exception => e
puts e.backtrace
raise "Unable to read the json_file: #{e.message}"
end
#pp options
return options
end
def load_previous_token(previous_token="token.json")
@logger.info("Loading_previous_token...")
begin
content = File.read(previous_token)
new_options=JSON.parse(content, :symbolize_names => true)
@logger.info("LOADED FROM FILE:#{new_options} ")
#new_options[:expires_in] = DateTime.strptime(new_options[:expiry_time].to_s,'%Q')
initialize_options(new_options)
rescue Exception => e
puts e.backtrace
raise "Unable to load previous token: #{e.message}"
end
#pp options
return true
end
def check_mode
#Check if im running in oauthv2 or auth-token
return @auth_type
end
def validate_auth_type(options)
#Comprobamos que forma parte de uno de los metodos de autenticacion soporteados
unless ["oauth","apikey","auth-token"].member?(options[:auth_type])
@logger.warn("Initializing with detault auth_type oauth")
@auth_type="oauth"
else
@auth_type = options[:auth_type]
end
return true
end
def required_options(auth_type=@auth_type)
#Dependiendo del tipo de autenticacion, indica cuales son las optciones requeridas
case auth_type
when "oauth"
return [:client_id,:client_secret,:scope]
#return [:client_id,:client_secret,:code,:grant_type,:scope]
when "apikey"
return [:zapikey]
when "auth-token"
return [:user,:pass,:scope]
else
raise "#{__method__} Unknown auth_type #{auth_type}"
end end
end
def validate_scope
def validate_options(options) # existen distintos tipos de scopes dependiendo del metodo
# Comprueba que segun el metodo de autenticacion dado, nos han pasado todas la opciones necesarias # auth-token
required_options.each do |key| # scope="ZohoCreator/creatorapi"
raise "#{__method__} Option #{key.to_s} not found!" unless options.has_key?(key) # oauth
raise "#{__method__} Option #{key.to_s} not found!" if options[key].nil? # scope="ZohoCRM.modules.ALL,ZohoCRM.settings.ALL"
# apikey
# scope=nil
return true
end
def persist_token
expiry_time = @expires_in.strftime("%Q") if @expires_in.kind_of?DateTime
token_information = {
:client_id =>@client_id,
:client_secret => @client_secret,
:scope => @scope,
:access_token => token,
:code => @code,
:expiry_time => expiry_time,
:grant_type => @grant_type,
:redirect_uri => @redirect_uri,
:refresh_token => @refresh_token,
:auth_type => 'oauth'
}
f=File.new("token.json","w+")
f.print(token_information.to_json)
f.close
end end
return true
end
def validate_scope
# existen distintos tipos de scopes dependiendo del metodo
# auth-token
# scope="ZohoCreator/creatorapi"
# oauth
# scope="ZohoCRM.modules.ALL,ZohoCRM.settings.ALL"
# apikey
# scope=nil
return true
end
def persist_token def show_current_options
expiry_time = @expires_in.strftime("%Q") if @expires_in.kind_of?DateTime @logger.info("auth_type : #{@auth_type}")
token_information = { @logger.info("user : #{@user}")
:client_id =>@client_id, @logger.info("pass : #{@pass}")
:client_secret => @client_secret, @logger.info("scope : #{@scope}")
:scope => @scope, @logger.info("life_token : #{@life_token}")
:access_token => token, @logger.info("client_id : #{@client_id}")
:code => @code, @logger.info("client_secret : #{@client_secret}")
:expiry_time => expiry_time, @logger.info("code : #{@code}")
:grant_type => @grant_type, @logger.info("grant_type : #{@grant_type}")
:redirect_uri => @redirect_uri, @logger.info("access_token : #{@access_token}")
:refresh_token => @refresh_token, @logger.info("refresh_token : #{@refresh_token}")
:auth_type => 'oauth' @logger.info("api_domain : #{@api_domain}")
} @logger.info("token_type : #{@token_type}")
f=File.new("token.json","w+") @logger.info("expires_in : #{@expires_in}")
f.print(token_information.to_json) @logger.info("expiry_time : #{@expiry_time}")
f.close @logger.info("zapikey : #{@zapikey}")
end @logger.info("redirect_uri : #{@redirect_uri}")
end
def show_current_options
@logger.info("auth_type : #{@auth_type}")
@logger.info("user : #{@user}")
@logger.info("pass : #{@pass}")
@logger.info("scope : #{@scope}")
@logger.info("life_token : #{@life_token}")
@logger.info("client_id : #{@client_id}")
@logger.info("client_secret : #{@client_secret}")
@logger.info("code : #{@code}")
@logger.info("grant_type : #{@grant_type}")
@logger.info("access_token : #{@access_token}")
@logger.info("refresh_token : #{@refresh_token}")
@logger.info("api_domain : #{@api_domain}")
@logger.info("token_type : #{@token_type}")
@logger.info("expires_in : #{@expires_in}")
@logger.info("expiry_time : #{@expiry_time}")
@logger.info("zapikey : #{@zapikey}")
@logger.info("redirect_uri : #{@redirect_uri}")
end end
end end
end end
require 'httparty' require 'httparty'
require 'json' require 'json'
module Wedoops
module Zoholib module Zoholib
class ZohoRequest class ZohoRequest
include HTTParty include HTTParty
#debug_output $stdout #debug_output $stdout
base_uri "https://accounts.zoho.com/oauth/v2/"
#https://accounts.zoho.com/oauth/v2/auth?
#https://accounts.zoho.com/oauth/v2/token?
headers 'Content-Type' => 'application/json'
attr_reader :subdomain, :uri
base_uri "https://accounts.zoho.com/oauth/v2/"
#https://accounts.zoho.com/oauth/v2/auth?
#https://accounts.zoho.com/oauth/v2/token?
headers 'Content-Type' => 'application/json'
attr_reader :subdomain, :uri
end
end end
end end
\ No newline at end of file
...@@ -5,7 +5,7 @@ require 'zoholib' ...@@ -5,7 +5,7 @@ require 'zoholib'
RSpec.configure do |conf| RSpec.configure do |conf|
conf.before(:all) do conf.before(:all) do
Zoholib.configure do |config| Wedoops::Zoholib.configure do |config|
puts "Trying to config" puts "Trying to config"
config.client_id = "client_id" config.client_id = "client_id"
config.client_secret = "client_secret" config.client_secret = "client_secret"
......
require 'spec_helper' require 'spec_helper'
require 'stringio' require 'stringio'
RSpec.describe Zoholib do RSpec.describe Wedoops::Zoholib do
it 'has a version number' do it 'has a version number' do
expect(Zoholib::VERSION).not_to be nil expect(Wedoops::Zoholib::VERSION).not_to be nil
end end
it 'does something useful' do it 'does something useful' do
...@@ -12,23 +12,23 @@ RSpec.describe Zoholib do ...@@ -12,23 +12,23 @@ RSpec.describe Zoholib do
describe 'Configuration' do describe 'Configuration' do
it 'The configuration shuld be a Zoholib::Configuration' do it 'The configuration shuld be a Zoholib::Configuration' do
expect(Zoholib.configuration).to be_a_kind_of(Zoholib::Configuration) expect(Wedoops::Zoholib.configuration).to be_a_kind_of(Wedoops::Zoholib::Configuration)
end end
it 'The client_id is a string' do it 'The client_id is a string' do
expect(Zoholib.configuration.client_id).to be_an(String) expect(Wedoops::Zoholib.configuration.client_id).to be_an(String)
end end
it 'The client_secret is a string' do it 'The client_secret is a string' do
expect(Zoholib.configuration.client_secret).to be_an(String) expect(Wedoops::Zoholib.configuration.client_secret).to be_an(String)
end end
it 'The scopes is a string' do it 'The scopes is a string' do
expect(Zoholib.configuration.scope).to be_an(String) expect(Wedoops::Zoholib.configuration.scope).to be_an(String)
end end
it 'The refresh_token is a string' do it 'The refresh_token is a string' do
expect(Zoholib.configuration.refresh_token).to be_an(String) expect(Wedoops::Zoholib.configuration.refresh_token).to be_an(String)
end end
end end
end end
\ No newline at end of file
...@@ -6,7 +6,7 @@ require 'zoholib/version' ...@@ -6,7 +6,7 @@ require 'zoholib/version'
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = 'zoholib' spec.name = 'zoholib'
spec.version = Zoholib::VERSION spec.version = Wedoops::Zoholib::VERSION
spec.date = '2020-04-25' spec.date = '2020-04-25'
spec.authors = ['Wedoops.io'] spec.authors = ['Wedoops.io']
spec.email = 'wedoops@wedoops.io' spec.email = 'wedoops@wedoops.io'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment