workato-connector-sdk 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +20 -0
- data/README.md +1093 -0
- data/exe/workato +5 -0
- data/lib/workato/cli/edit_command.rb +71 -0
- data/lib/workato/cli/exec_command.rb +191 -0
- data/lib/workato/cli/generate_command.rb +105 -0
- data/lib/workato/cli/generators/connector_generator.rb +94 -0
- data/lib/workato/cli/generators/master_key_generator.rb +56 -0
- data/lib/workato/cli/main.rb +142 -0
- data/lib/workato/cli/push_command.rb +208 -0
- data/lib/workato/connector/sdk/account_properties.rb +60 -0
- data/lib/workato/connector/sdk/action.rb +88 -0
- data/lib/workato/connector/sdk/block_invocation_refinements.rb +30 -0
- data/lib/workato/connector/sdk/connector.rb +230 -0
- data/lib/workato/connector/sdk/dsl/account_property.rb +15 -0
- data/lib/workato/connector/sdk/dsl/call.rb +17 -0
- data/lib/workato/connector/sdk/dsl/error.rb +15 -0
- data/lib/workato/connector/sdk/dsl/http.rb +60 -0
- data/lib/workato/connector/sdk/dsl/lookup_table.rb +15 -0
- data/lib/workato/connector/sdk/dsl/time.rb +21 -0
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +105 -0
- data/lib/workato/connector/sdk/dsl/workato_schema.rb +15 -0
- data/lib/workato/connector/sdk/dsl.rb +46 -0
- data/lib/workato/connector/sdk/errors.rb +30 -0
- data/lib/workato/connector/sdk/lookup_tables.rb +62 -0
- data/lib/workato/connector/sdk/object_definitions.rb +74 -0
- data/lib/workato/connector/sdk/operation.rb +217 -0
- data/lib/workato/connector/sdk/request.rb +399 -0
- data/lib/workato/connector/sdk/settings.rb +130 -0
- data/lib/workato/connector/sdk/summarize.rb +61 -0
- data/lib/workato/connector/sdk/trigger.rb +96 -0
- data/lib/workato/connector/sdk/version.rb +9 -0
- data/lib/workato/connector/sdk/workato_schemas.rb +37 -0
- data/lib/workato/connector/sdk/xml.rb +35 -0
- data/lib/workato/connector/sdk.rb +58 -0
- data/lib/workato/extension/array.rb +124 -0
- data/lib/workato/extension/case_sensitive_headers.rb +51 -0
- data/lib/workato/extension/currency.rb +15 -0
- data/lib/workato/extension/date.rb +14 -0
- data/lib/workato/extension/enumerable.rb +55 -0
- data/lib/workato/extension/extra_chain_cert.rb +40 -0
- data/lib/workato/extension/hash.rb +13 -0
- data/lib/workato/extension/integer.rb +17 -0
- data/lib/workato/extension/nil_class.rb +17 -0
- data/lib/workato/extension/object.rb +38 -0
- data/lib/workato/extension/phone.rb +14 -0
- data/lib/workato/extension/string.rb +268 -0
- data/lib/workato/extension/symbol.rb +13 -0
- data/lib/workato/extension/time.rb +13 -0
- data/lib/workato/testing/vcr_encrypted_cassette_serializer.rb +38 -0
- data/lib/workato/testing/vcr_multipart_body_matcher.rb +32 -0
- data/lib/workato-connector-sdk.rb +3 -0
- data/templates/.rspec.erb +3 -0
- data/templates/Gemfile.erb +10 -0
- data/templates/connector.rb.erb +37 -0
- data/templates/spec/action_spec.rb.erb +36 -0
- data/templates/spec/connector_spec.rb.erb +18 -0
- data/templates/spec/method_spec.rb.erb +13 -0
- data/templates/spec/object_definition_spec.rb.erb +18 -0
- data/templates/spec/pick_list_spec.rb.erb +13 -0
- data/templates/spec/spec_helper.rb.erb +38 -0
- data/templates/spec/trigger_spec.rb.erb +61 -0
- metadata +372 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Workato
|
4
|
+
module Connector
|
5
|
+
module Sdk
|
6
|
+
module Dsl
|
7
|
+
module Time
|
8
|
+
def now
|
9
|
+
::Time.zone.now
|
10
|
+
end
|
11
|
+
|
12
|
+
def today
|
13
|
+
::Time.zone.today
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
::Time.zone = Workato::Connector::Sdk::DEFAULT_TIME_ZONE
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jwt'
|
4
|
+
|
5
|
+
module Workato
|
6
|
+
module Connector
|
7
|
+
module Sdk
|
8
|
+
module Dsl
|
9
|
+
module WorkatoCodeLib
|
10
|
+
JWT_ALGORITHMS = %w[RS256 RS384 RS512].freeze
|
11
|
+
JWT_RSA_KEY_MIN_LENGTH = 2048
|
12
|
+
|
13
|
+
def workato
|
14
|
+
WorkatoCodeLib
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse_json(source)
|
18
|
+
WorkatoCodeLib.parse_json(source)
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def jwt_encode_rs256(payload, key, header_fields = {})
|
23
|
+
jwt_encode(payload, key, 'RS256', header_fields)
|
24
|
+
end
|
25
|
+
|
26
|
+
def jwt_encode(payload, key, algorithm, header_fields = {})
|
27
|
+
algorithm = algorithm.to_s.upcase
|
28
|
+
unless JWT_ALGORITHMS.include?(algorithm)
|
29
|
+
raise "Unsupported signing method. Supports only #{JWT_ALGORITHMS.join(', ')}. Got: '#{algorithm}'"
|
30
|
+
end
|
31
|
+
|
32
|
+
rsa_private = OpenSSL::PKey::RSA.new(key)
|
33
|
+
if rsa_private.n.num_bits < JWT_RSA_KEY_MIN_LENGTH
|
34
|
+
raise "A RSA key of size #{JWT_RSA_KEY_MIN_LENGTH} bits or larger MUST be used with JWT."
|
35
|
+
end
|
36
|
+
|
37
|
+
header_fields = header_fields.present? ? header_fields.with_indifferent_access.except(:typ, :alg) : {}
|
38
|
+
::JWT.encode(payload, rsa_private, algorithm, header_fields)
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_yaml(yaml)
|
42
|
+
::Psych.safe_load(yaml)
|
43
|
+
rescue ::Psych::DisallowedClass => e
|
44
|
+
raise e.message
|
45
|
+
end
|
46
|
+
|
47
|
+
def render_yaml(obj)
|
48
|
+
::Psych.dump(obj)
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_json(source)
|
52
|
+
JSON.parse(source)
|
53
|
+
end
|
54
|
+
|
55
|
+
def uuid
|
56
|
+
SecureRandom.uuid
|
57
|
+
end
|
58
|
+
|
59
|
+
RANDOM_SIZE = 32
|
60
|
+
|
61
|
+
def random_bytes(len)
|
62
|
+
unless (len.is_a? ::Integer) && (len <= RANDOM_SIZE)
|
63
|
+
raise "The requested length or random bytes sequence should be <= #{RANDOM_SIZE}"
|
64
|
+
end
|
65
|
+
|
66
|
+
String::Binary.new(::OpenSSL::Random.random_bytes(len))
|
67
|
+
end
|
68
|
+
|
69
|
+
ALLOWED_KEY_SIZES = [128, 192, 256].freeze
|
70
|
+
|
71
|
+
def aes_cbc_encrypt(string, key, init_vector = nil)
|
72
|
+
key_size = key.bytesize * 8
|
73
|
+
unless ALLOWED_KEY_SIZES.include?(key_size)
|
74
|
+
raise 'Incorrect key size for AES'
|
75
|
+
end
|
76
|
+
|
77
|
+
cipher = ::OpenSSL::Cipher.new("AES-#{key_size}-CBC")
|
78
|
+
cipher.encrypt
|
79
|
+
cipher.key = key
|
80
|
+
cipher.iv = init_vector if init_vector.present?
|
81
|
+
String::Binary.new(cipher.update(string) + cipher.final)
|
82
|
+
end
|
83
|
+
|
84
|
+
def aes_cbc_decrypt(string, key, init_vector = nil)
|
85
|
+
key_size = key.bytesize * 8
|
86
|
+
unless ALLOWED_KEY_SIZES.include?(key_size)
|
87
|
+
raise 'Incorrect key size for AES'
|
88
|
+
end
|
89
|
+
|
90
|
+
cipher = ::OpenSSL::Cipher.new("AES-#{key_size}-CBC")
|
91
|
+
cipher.decrypt
|
92
|
+
cipher.key = key
|
93
|
+
cipher.iv = init_vector if init_vector.present?
|
94
|
+
String::Binary.new(cipher.update(string) + cipher.final)
|
95
|
+
end
|
96
|
+
|
97
|
+
def pbkdf2_hmac_sha1(string, salt, iterations = 1000, key_len = 16)
|
98
|
+
String::Binary.new(::OpenSSL::PKCS5.pbkdf2_hmac_sha1(string, salt, iterations, key_len))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './block_invocation_refinements'
|
4
|
+
|
5
|
+
require_relative './dsl/http'
|
6
|
+
require_relative './dsl/call'
|
7
|
+
require_relative './dsl/error'
|
8
|
+
require_relative './dsl/account_property'
|
9
|
+
require_relative './dsl/lookup_table'
|
10
|
+
require_relative './dsl/workato_code_lib'
|
11
|
+
require_relative './dsl/workato_schema'
|
12
|
+
require_relative './dsl/time'
|
13
|
+
|
14
|
+
module Workato
|
15
|
+
module Connector
|
16
|
+
module Sdk
|
17
|
+
module Dsl
|
18
|
+
module Global
|
19
|
+
include Time
|
20
|
+
include AccountProperty
|
21
|
+
include LookupTable
|
22
|
+
include WorkatoCodeLib
|
23
|
+
include WorkatoSchema
|
24
|
+
|
25
|
+
def sleep(seconds)
|
26
|
+
::Kernel.sleep(seconds.presence || 0)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class WithDsl
|
31
|
+
include Global
|
32
|
+
|
33
|
+
using BlockInvocationRefinements
|
34
|
+
|
35
|
+
def execute(*args, &block)
|
36
|
+
instance_exec(*args, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.execute(*args, &block)
|
40
|
+
WithDsl.new.execute(*args, &block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Workato
|
4
|
+
module Connector
|
5
|
+
module Sdk
|
6
|
+
InvalidDefinitionError = Class.new(StandardError)
|
7
|
+
|
8
|
+
CustomRequestError = Class.new(StandardError)
|
9
|
+
|
10
|
+
class RequestError < StandardError
|
11
|
+
attr_reader :method,
|
12
|
+
:code,
|
13
|
+
:response
|
14
|
+
|
15
|
+
def initialize(message:, method:, code:, response:)
|
16
|
+
super(message)
|
17
|
+
@method = method
|
18
|
+
@code = code
|
19
|
+
@response = response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class NotImplementedError < RuntimeError
|
24
|
+
def initialize(msg = 'This part of Connector SDK is not implemented in workato-connector-sdk yet')
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
module Workato
|
7
|
+
module Connector
|
8
|
+
module Sdk
|
9
|
+
class LookupTables
|
10
|
+
include Singleton
|
11
|
+
|
12
|
+
def self.from_yaml(path = DEFAULT_LOOKUP_TABLES_PATH)
|
13
|
+
instance.load_data(YAML.load_file(path))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_csv(table_id, table_name, path)
|
17
|
+
rows = CSV.foreach(path, headers: true, return_headers: false).map(&:to_h)
|
18
|
+
instance.load_data(table_name => { id: table_id, rows: rows })
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
delegate :load_data,
|
23
|
+
:lookup,
|
24
|
+
to: :instance
|
25
|
+
end
|
26
|
+
|
27
|
+
def lookup(table_name_or_id, *args)
|
28
|
+
table = find_table(table_name_or_id)
|
29
|
+
return {} unless table
|
30
|
+
|
31
|
+
condition = args.extract_options!
|
32
|
+
row = table.lazy.where(condition).first
|
33
|
+
return {} unless row
|
34
|
+
|
35
|
+
row.to_hash.with_indifferent_access
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_data(data = {})
|
39
|
+
@table_by_id ||= {}
|
40
|
+
@table_by_name ||= {}
|
41
|
+
data.each do |name, table|
|
42
|
+
table = table.with_indifferent_access
|
43
|
+
rows = table['rows'].freeze
|
44
|
+
@table_by_id[table['id'].to_i] = rows
|
45
|
+
@table_by_name[name] = rows
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def find_table(table_name_or_id)
|
52
|
+
unless @table_by_id
|
53
|
+
raise 'Lookup Tables are not initialized. ' \
|
54
|
+
'Init data by calling LookupTable.from_file or LookupTable.load_data'
|
55
|
+
end
|
56
|
+
|
57
|
+
(table_name_or_id.is_int? && @table_by_id[table_name_or_id.to_i]) || @table_by_name[table_name_or_id]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './block_invocation_refinements'
|
4
|
+
|
5
|
+
module Workato
|
6
|
+
module Connector
|
7
|
+
module Sdk
|
8
|
+
class ObjectDefinitions
|
9
|
+
using BlockInvocationRefinements
|
10
|
+
|
11
|
+
def initialize(object_definitions:, connection:, methods:, settings:)
|
12
|
+
@object_definitions_source = object_definitions
|
13
|
+
@methods = methods
|
14
|
+
@connection = connection
|
15
|
+
@settings = settings
|
16
|
+
define_object_definition_methods(object_definitions)
|
17
|
+
end
|
18
|
+
|
19
|
+
def lazy(settings = nil, config_fields = {})
|
20
|
+
object_definitions_lazy_hash = DupHashWithIndifferentAccess.new do |h, name|
|
21
|
+
fields_proc = @object_definitions_source[name][:fields]
|
22
|
+
h[name] = Action.new(
|
23
|
+
action: {
|
24
|
+
execute: lambda do |connection, input|
|
25
|
+
instance_exec(connection, input, object_definitions_lazy_hash, &fields_proc)
|
26
|
+
end
|
27
|
+
},
|
28
|
+
methods: @methods,
|
29
|
+
connection: @connection,
|
30
|
+
settings: @settings
|
31
|
+
).execute(settings, config_fields)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :methods,
|
38
|
+
:connection,
|
39
|
+
:objects,
|
40
|
+
:settings
|
41
|
+
|
42
|
+
def define_object_definition_methods(object_definitions)
|
43
|
+
object_definitions.each do |(object, _definition)|
|
44
|
+
define_singleton_method(object) do
|
45
|
+
@object_definitions ||= {}
|
46
|
+
@object_definitions[object] ||= ObjectDefinition.new(name: object, object_definitions: self)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class ObjectDefinition
|
52
|
+
def initialize(name:, object_definitions:)
|
53
|
+
@object_definitions = object_definitions
|
54
|
+
@name = name
|
55
|
+
end
|
56
|
+
|
57
|
+
def fields(settings = nil, config_fields = {})
|
58
|
+
object_definitions_lazy_hash = @object_definitions.lazy(settings, config_fields)
|
59
|
+
object_definitions_lazy_hash[@name]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class DupHashWithIndifferentAccess < HashWithIndifferentAccess
|
64
|
+
def [](name)
|
65
|
+
super.deep_dup
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private_constant 'ObjectDefinition'
|
70
|
+
private_constant 'DupHashWithIndifferentAccess'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './dsl'
|
4
|
+
require_relative './block_invocation_refinements'
|
5
|
+
|
6
|
+
module Workato
|
7
|
+
module Connector
|
8
|
+
module Sdk
|
9
|
+
class Operation
|
10
|
+
include Dsl::Global
|
11
|
+
include Dsl::HTTP
|
12
|
+
include Dsl::Call
|
13
|
+
include Dsl::Error
|
14
|
+
|
15
|
+
using BlockInvocationRefinements
|
16
|
+
|
17
|
+
cattr_accessor :on_settings_updated
|
18
|
+
|
19
|
+
def initialize(operation:, connection: {}, methods: {}, settings: {}, object_definitions: nil)
|
20
|
+
@settings = settings.with_indifferent_access
|
21
|
+
@operation = operation.with_indifferent_access
|
22
|
+
@connection = connection.with_indifferent_access
|
23
|
+
@_methods = methods.with_indifferent_access
|
24
|
+
@object_definitions = object_definitions
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [], &block)
|
28
|
+
@settings = settings.with_indifferent_access if settings # is being used in request for refresh tokens
|
29
|
+
request_or_result = instance_exec(
|
30
|
+
@settings.with_indifferent_access, # a copy of settings hash is being used in executable blocks
|
31
|
+
input.with_indifferent_access,
|
32
|
+
Array.wrap(extended_input_schema).map(&:with_indifferent_access),
|
33
|
+
Array.wrap(extended_output_schema).map(&:with_indifferent_access),
|
34
|
+
&block
|
35
|
+
)
|
36
|
+
resolve_request(request_or_result)
|
37
|
+
end
|
38
|
+
|
39
|
+
def extended_schema(settings = nil, config_fields = {})
|
40
|
+
object_definitions_hash = object_definitions.lazy(settings, config_fields)
|
41
|
+
{
|
42
|
+
input: schema_fields(object_definitions_hash, settings, config_fields, &operation[:input_fields]),
|
43
|
+
output: schema_fields(object_definitions_hash, settings, config_fields, &operation[:output_fields])
|
44
|
+
}.with_indifferent_access
|
45
|
+
end
|
46
|
+
|
47
|
+
def input_fields(settings = nil, config_fields = {})
|
48
|
+
object_definitions_hash = object_definitions.lazy(settings, config_fields)
|
49
|
+
schema_fields(object_definitions_hash, settings, config_fields, &operation[:input_fields])
|
50
|
+
end
|
51
|
+
|
52
|
+
def output_fields(settings = nil, config_fields = {})
|
53
|
+
object_definitions_hash = object_definitions.lazy(settings, config_fields)
|
54
|
+
schema_fields(object_definitions_hash, settings, config_fields, &operation[:output_fields])
|
55
|
+
end
|
56
|
+
|
57
|
+
def summarize_input(input = {})
|
58
|
+
summarize(input, operation[:summarize_input])
|
59
|
+
end
|
60
|
+
|
61
|
+
def summarize_output(output = {})
|
62
|
+
summarize(output, operation[:summarize_output])
|
63
|
+
end
|
64
|
+
|
65
|
+
def sample_output(settings = nil, input = {})
|
66
|
+
execute(settings, input, &operation[:sample_output])
|
67
|
+
end
|
68
|
+
|
69
|
+
def refresh_authorization!(http_code, http_body, exception, settings = {})
|
70
|
+
return unless refresh_auth?(http_code, http_body, exception)
|
71
|
+
|
72
|
+
new_settings = if /oauth2/i =~ connection[:authorization][:type]
|
73
|
+
refresh_oauth2_token(settings)
|
74
|
+
elsif connection[:authorization][:acquire]
|
75
|
+
acquire_token(settings)
|
76
|
+
end
|
77
|
+
return unless new_settings
|
78
|
+
|
79
|
+
settings.merge!(new_settings)
|
80
|
+
|
81
|
+
on_settings_updated&.call(http_body, http_code, exception, settings)
|
82
|
+
|
83
|
+
settings
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def summarize(data, paths)
|
89
|
+
return data unless paths.present?
|
90
|
+
|
91
|
+
Summarize.new(data: data, paths: paths).call
|
92
|
+
end
|
93
|
+
|
94
|
+
def schema_fields(object_definitions_hash, settings, config_fields, &schema_proc)
|
95
|
+
return {} unless schema_proc
|
96
|
+
|
97
|
+
execute(settings, config_fields) do |connection, input|
|
98
|
+
instance_exec(
|
99
|
+
object_definitions_hash,
|
100
|
+
connection,
|
101
|
+
input,
|
102
|
+
&schema_proc
|
103
|
+
)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def resolve_request(request_or_result)
|
108
|
+
case request_or_result
|
109
|
+
when Request
|
110
|
+
resolve_request(request_or_result.execute!)
|
111
|
+
when ::Array
|
112
|
+
request_or_result.each_with_index.inject(request_or_result) do |acc, (item, index)|
|
113
|
+
response_item = resolve_request(item)
|
114
|
+
if response_item.equal?(item)
|
115
|
+
acc
|
116
|
+
else
|
117
|
+
(acc == request_or_result ? acc.dup : acc).tap { |a| a[index] = response_item }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
when ::Hash
|
121
|
+
request_or_result.inject(request_or_result.with_indifferent_access) do |acc, (key, value)|
|
122
|
+
response_value = resolve_request(value)
|
123
|
+
if response_value.equal?(value)
|
124
|
+
acc
|
125
|
+
else
|
126
|
+
(acc == request_or_result ? acc.dup : acc).tap { |h| h[key] = response_value }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
else
|
130
|
+
request_or_result
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def refresh_auth?(http_code, http_body, exception)
|
135
|
+
refresh_on = Array.wrap(connection[:authorization][:refresh_on]).compact
|
136
|
+
refresh_on.blank? || refresh_on.any? do |pattern|
|
137
|
+
pattern.is_a?(::Integer) && pattern == http_code ||
|
138
|
+
pattern === exception&.to_s ||
|
139
|
+
pattern === http_body
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def acquire_token(settings)
|
144
|
+
acquire = connection[:authorization][:acquire]
|
145
|
+
raise InvalidDefinitionError, "'acquire' block is required for authorization" unless acquire
|
146
|
+
|
147
|
+
Action.new(
|
148
|
+
action: {
|
149
|
+
execute: ->(connection) { instance_exec(connection, &acquire) }
|
150
|
+
},
|
151
|
+
connection: connection.merge(
|
152
|
+
authorization: connection[:authorization].merge(
|
153
|
+
apply: nil
|
154
|
+
)
|
155
|
+
),
|
156
|
+
methods: @_methods
|
157
|
+
).execute(settings)
|
158
|
+
end
|
159
|
+
|
160
|
+
def refresh_oauth2_token_using_refresh(settings)
|
161
|
+
refresh = connection[:authorization][:refresh]
|
162
|
+
new_tokens, new_settings = Action.new(
|
163
|
+
action: {
|
164
|
+
execute: lambda do |connection|
|
165
|
+
instance_exec(connection, connection[:refresh_token], &refresh)
|
166
|
+
end
|
167
|
+
},
|
168
|
+
methods: @_methods
|
169
|
+
).execute(settings)
|
170
|
+
|
171
|
+
new_tokens.with_indifferent_access.merge(new_settings || {})
|
172
|
+
end
|
173
|
+
|
174
|
+
def refresh_oauth2_token_using_token_url(settings)
|
175
|
+
if settings[:refresh_token].blank?
|
176
|
+
raise NotImplementedError, 'workato-connector-sdk does not support OAuth2 authorization process. '\
|
177
|
+
'Use Workato Debugger UI to acquire access_token and refresh_token'
|
178
|
+
end
|
179
|
+
|
180
|
+
response = RestClient::Request.execute(
|
181
|
+
url: connection[:authorization][:token_url].call(settings),
|
182
|
+
method: :post,
|
183
|
+
payload: {
|
184
|
+
client_id: connection[:authorization][:client_id].call(settings),
|
185
|
+
client_secret: connection[:authorization][:client_secret].call(settings),
|
186
|
+
grant_type: :refresh_token,
|
187
|
+
refresh_token: settings[:refresh_token]
|
188
|
+
},
|
189
|
+
headers: {
|
190
|
+
accept: :json
|
191
|
+
}
|
192
|
+
)
|
193
|
+
tokens = JSON.parse(response.body)
|
194
|
+
{
|
195
|
+
access_token: tokens['access_token'],
|
196
|
+
refresh_token: tokens['refresh_token'].presence || settings[:refresh_token]
|
197
|
+
}.with_indifferent_access
|
198
|
+
end
|
199
|
+
|
200
|
+
def refresh_oauth2_token(settings)
|
201
|
+
if connection[:authorization][:refresh]
|
202
|
+
refresh_oauth2_token_using_refresh(settings)
|
203
|
+
elsif connection[:authorization][:token_url]
|
204
|
+
refresh_oauth2_token_using_token_url(settings)
|
205
|
+
else
|
206
|
+
raise InvalidDefinitionError, "'refresh' block or 'token_url' is required for refreshing the token"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
attr_reader :operation,
|
211
|
+
:connection,
|
212
|
+
:settings,
|
213
|
+
:object_definitions
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|