workato-connector-sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|