workato-connector-sdk 1.0.3 → 1.2.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 +5 -5
- data/README.md +1 -0
- data/lib/workato/cli/exec_command.rb +31 -8
- data/lib/workato/cli/multi_auth_selected_fallback.rb +33 -0
- data/lib/workato/cli/oauth2_command.rb +50 -12
- data/lib/workato/connector/sdk/connection.rb +84 -14
- data/lib/workato/connector/sdk/connector.rb +6 -4
- data/lib/workato/connector/sdk/dsl/aws.rb +5 -2
- data/lib/workato/connector/sdk/dsl/call.rb +5 -2
- data/lib/workato/connector/sdk/dsl/csv.rb +125 -0
- data/lib/workato/connector/sdk/dsl/execution_context.rb +44 -0
- data/lib/workato/connector/sdk/dsl/workato_code_lib.rb +8 -1
- data/lib/workato/connector/sdk/dsl.rb +1 -0
- data/lib/workato/connector/sdk/errors.rb +69 -1
- data/lib/workato/connector/sdk/lookup_tables.rb +3 -1
- data/lib/workato/connector/sdk/object_definitions.rb +16 -10
- data/lib/workato/connector/sdk/operation.rb +24 -8
- data/lib/workato/connector/sdk/request.rb +136 -58
- data/lib/workato/connector/sdk/schema.rb +5 -3
- data/lib/workato/connector/sdk/settings.rb +4 -2
- data/lib/workato/connector/sdk/trigger.rb +42 -19
- data/lib/workato/connector/sdk/version.rb +1 -1
- data/lib/workato/connector/sdk.rb +3 -2
- data/lib/workato/extension/case_sensitive_headers.rb +0 -25
- data/lib/workato/extension/content_encoding_decoder.rb +67 -0
- data/lib/workato/extension/currency.rb +1 -1
- data/lib/workato/extension/extra_chain_cert.rb +0 -14
- data/lib/workato/extension/hash_with_indifferent_access.rb +19 -0
- data/lib/workato/extension/phone.rb +1 -1
- data/lib/workato/extension/string.rb +6 -2
- data/lib/workato/utilities/encoding.rb +57 -0
- data/lib/workato/{connector/sdk → utilities}/xml.rb +4 -4
- metadata +48 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b49034b5762b2b44d0987d72eb74327e379284347b793714149d85d354a5bb57
|
4
|
+
data.tar.gz: 1be17d19381fe42689ef4a157a56eca0fb8c61a9c0e90e981e5a373305ed771f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bcc365d25ec713df12b75d9d6d5fb8a6a73266b94cf012829e4a2c98af955f1fcfa7b0d0f7e69861a4ee6cb54af24ed8952bbb590553e93a37fcf2933c69459
|
7
|
+
data.tar.gz: 1da6193b9a1b04e3d3e2c6fb34fcd0eeec7666908c61df5c7ec386381ba8f33207b50b8ffc1e9d581fecb599fc423f84f9f79867120322356aa4d645b9b7da5e
|
data/README.md
CHANGED
@@ -16,6 +16,7 @@ This guide below showcases how you can do the following things:
|
|
16
16
|
2. Choose between Ruby versions `2.4.10` `2.5.X` or `2.7.X`. Our preferred version is `2.7.X`.
|
17
17
|
3. Verify you're running a valid ruby version. Do this by running either `ruby -v` or the commands within your version manager. i.e., `rvm current` if you have installed RVM.
|
18
18
|
4. For Windows you need tzinfo-data gem installed as well. `gem install tzinfo-data`
|
19
|
+
5. SDK depends on `charlock_holmes` gem. Check [gem's documentation](https://github.com/brianmario/charlock_holmes#installing) if you have troubles when install this dependency. Additional [details for Windows](https://github.com/brianmario/charlock_holmes/issues/84#issuecomment-652877605)
|
19
20
|
|
20
21
|
```bash
|
21
22
|
ruby -v
|
@@ -2,11 +2,13 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'thor'
|
5
|
+
require_relative './multi_auth_selected_fallback'
|
5
6
|
|
6
7
|
module Workato
|
7
8
|
module CLI
|
8
9
|
class ExecCommand
|
9
10
|
include Thor::Shell
|
11
|
+
include MultiAuthSelectedFallback
|
10
12
|
|
11
13
|
DebugExceptionError = Class.new(StandardError)
|
12
14
|
|
@@ -63,7 +65,7 @@ module Workato
|
|
63
65
|
oauth2_code: options[:oauth2_code],
|
64
66
|
redirect_url: options[:redirect_url],
|
65
67
|
refresh_token: options[:refresh_token],
|
66
|
-
recipe_id:
|
68
|
+
recipe_id: Workato::Connector::Sdk::Operation.recipe_id!
|
67
69
|
}
|
68
70
|
end
|
69
71
|
|
@@ -84,13 +86,21 @@ module Workato
|
|
84
86
|
)
|
85
87
|
@settings = settings_store.read
|
86
88
|
|
89
|
+
Workato::Connector::Sdk::Connection.multi_auth_selected_fallback = lambda do |options|
|
90
|
+
next @selected_auth_type if @selected_auth_type
|
91
|
+
|
92
|
+
with_user_interaction do
|
93
|
+
@selected_auth_type = multi_auth_selected_fallback(options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
87
97
|
Workato::Connector::Sdk::Connection.on_settings_update = lambda do |message, &refresher|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
new_settings = refresher.call
|
98
|
+
new_settings = refresher.call
|
99
|
+
break unless new_settings
|
100
|
+
|
101
|
+
with_user_interaction do
|
93
102
|
loop do
|
103
|
+
say(message)
|
94
104
|
answer = ask('Updated settings file with new connection attributes? (Yes or No)').to_s.downcase
|
95
105
|
break new_settings if %w[n no].include?(answer)
|
96
106
|
next unless %w[y yes].include?(answer)
|
@@ -98,8 +108,6 @@ module Workato
|
|
98
108
|
settings_store.update(new_settings)
|
99
109
|
break new_settings
|
100
110
|
end
|
101
|
-
ensure
|
102
|
-
$stdout.resume if verbose?
|
103
111
|
end
|
104
112
|
end
|
105
113
|
|
@@ -128,6 +136,11 @@ module Workato
|
|
128
136
|
|
129
137
|
def execute_path
|
130
138
|
connector.invoke(path, params)
|
139
|
+
rescue Workato::Connector::Sdk::InvalidMultiAuthDefinition => e
|
140
|
+
raise "#{e.message}. Please ensure:\n"\
|
141
|
+
"- 'selected' block is defined and returns value from 'options' list\n" \
|
142
|
+
"- settings file contains value expected by 'selected' block\n\n"\
|
143
|
+
'See more: https://docs.workato.com/developing-connectors/sdk/guides/authentication/multi_auth.html'
|
131
144
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
132
145
|
raise DebugExceptionError, e if options[:debug]
|
133
146
|
|
@@ -178,6 +191,16 @@ module Workato
|
|
178
191
|
output
|
179
192
|
end
|
180
193
|
|
194
|
+
def with_user_interaction
|
195
|
+
$stdout.pause if verbose?
|
196
|
+
say('')
|
197
|
+
|
198
|
+
yield
|
199
|
+
ensure
|
200
|
+
say('')
|
201
|
+
$stdout.resume if verbose?
|
202
|
+
end
|
203
|
+
|
181
204
|
class ProgressLogger < SimpleDelegator
|
182
205
|
def initialize(progress)
|
183
206
|
super($stdout)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Workato
|
4
|
+
module CLI
|
5
|
+
module MultiAuthSelectedFallback
|
6
|
+
private
|
7
|
+
|
8
|
+
def multi_auth_selected_fallback(options)
|
9
|
+
say('Please select current auth type for multi-auth connector:')
|
10
|
+
options = options.keys
|
11
|
+
options.each_with_index do |option, idx|
|
12
|
+
say "[#{idx + 1}] #{option}"
|
13
|
+
end
|
14
|
+
say '[q] <exit>'
|
15
|
+
say('')
|
16
|
+
|
17
|
+
multi_auth_selected_fallback = loop do
|
18
|
+
answer = ask('Your choice:').to_s.downcase
|
19
|
+
break if answer == 'q'
|
20
|
+
next unless /\d+/ =~ answer && options[answer.to_i - 1]
|
21
|
+
|
22
|
+
break options[answer.to_i - 1]
|
23
|
+
end
|
24
|
+
return unless multi_auth_selected_fallback
|
25
|
+
|
26
|
+
say('')
|
27
|
+
say('Put selected auth type in your settings file to avoid this message in future')
|
28
|
+
|
29
|
+
multi_auth_selected_fallback
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -3,11 +3,13 @@
|
|
3
3
|
|
4
4
|
require 'securerandom'
|
5
5
|
require 'workato/web/app'
|
6
|
+
require_relative './multi_auth_selected_fallback'
|
6
7
|
|
7
8
|
module Workato
|
8
9
|
module CLI
|
9
10
|
class OAuth2Command
|
10
11
|
include Thor::Shell
|
12
|
+
include MultiAuthSelectedFallback
|
11
13
|
|
12
14
|
AWAIT_CODE_TIMEOUT_INTERVAL = 180 # seconds
|
13
15
|
AWAIT_CODE_SLEEP_INTERVAL = 5 # seconds
|
@@ -24,6 +26,7 @@ module Workato
|
|
24
26
|
end
|
25
27
|
|
26
28
|
def call
|
29
|
+
ensure_oauth2_type
|
27
30
|
require_gems
|
28
31
|
start_webrick
|
29
32
|
|
@@ -94,16 +97,31 @@ module Workato
|
|
94
97
|
end
|
95
98
|
|
96
99
|
def stop_webrick
|
100
|
+
return unless @thread
|
101
|
+
|
97
102
|
Rack::Handler::WEBrick.shutdown
|
98
103
|
@thread.exit
|
99
104
|
end
|
100
105
|
|
106
|
+
def ensure_oauth2_type
|
107
|
+
unless connector.connection.authorization.oauth2?
|
108
|
+
raise 'Authorization type is not OAuth2. '\
|
109
|
+
'For multi-auth connector ensure correct auth type was used. '\
|
110
|
+
"Expected: 'oauth2', got: '#{connector.connection.authorization.type}''"
|
111
|
+
end
|
112
|
+
rescue Workato::Connector::Sdk::InvalidMultiAuthDefinition => e
|
113
|
+
raise "#{e.message}. Please ensure:\n"\
|
114
|
+
"- 'selected' block is defined and returns value from 'options' list\n" \
|
115
|
+
"- settings file contains value expected by 'selected' block\n\n"\
|
116
|
+
'See more: https://docs.workato.com/developing-connectors/sdk/guides/authentication/multi_auth.html'
|
117
|
+
end
|
118
|
+
|
101
119
|
def client
|
102
120
|
@client ||= OAuth2::Client.new(
|
103
|
-
connector.connection.authorization.client_id
|
104
|
-
connector.connection.authorization.client_secret
|
105
|
-
site: connector.connection.base_uri
|
106
|
-
token_url: connector.connection.authorization.token_url
|
121
|
+
connector.connection.authorization.client_id,
|
122
|
+
connector.connection.authorization.client_secret,
|
123
|
+
site: connector.connection.base_uri,
|
124
|
+
token_url: connector.connection.authorization.token_url,
|
107
125
|
redirect_uri: redirect_url
|
108
126
|
)
|
109
127
|
end
|
@@ -112,14 +130,14 @@ module Workato
|
|
112
130
|
return @authorize_url if defined?(@authorize_url)
|
113
131
|
|
114
132
|
@authorize_url =
|
115
|
-
if (authorization_url = connector.connection.authorization.authorization_url
|
133
|
+
if (authorization_url = connector.connection.authorization.authorization_url)
|
116
134
|
params = {
|
117
135
|
state: SecureRandom.hex(8),
|
118
|
-
client_id: connector.connection.authorization.client_id
|
136
|
+
client_id: connector.connection.authorization.client_id,
|
119
137
|
redirect_uri: redirect_url
|
120
|
-
}
|
138
|
+
}.with_indifferent_access
|
121
139
|
uri = URI(authorization_url)
|
122
|
-
uri.query = params.
|
140
|
+
uri.query = params.merge(Rack::Utils.parse_nested_query(uri.query || '')).to_param
|
123
141
|
uri.to_s
|
124
142
|
end
|
125
143
|
end
|
@@ -133,12 +151,25 @@ module Workato
|
|
133
151
|
end
|
134
152
|
|
135
153
|
def settings
|
136
|
-
@settings
|
154
|
+
return @settings if defined?(@settings)
|
155
|
+
|
156
|
+
@settings = settings_store.read
|
157
|
+
|
158
|
+
Workato::Connector::Sdk::Connection.multi_auth_selected_fallback = lambda do |options|
|
159
|
+
next @selected_auth_type if @selected_auth_type
|
160
|
+
|
161
|
+
with_user_interaction do
|
162
|
+
@selected_auth_type = multi_auth_selected_fallback(options)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
@settings
|
137
167
|
end
|
138
168
|
|
139
169
|
def connector
|
140
170
|
@connector ||= Workato::Connector::Sdk::Connector.from_file(
|
141
|
-
options[:connector] || Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
|
171
|
+
options[:connector] || Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH,
|
172
|
+
settings
|
142
173
|
)
|
143
174
|
end
|
144
175
|
|
@@ -156,8 +187,8 @@ module Workato
|
|
156
187
|
end
|
157
188
|
|
158
189
|
def acquire_token(code)
|
159
|
-
if connector.
|
160
|
-
tokens, _, extra_settings = connector.connection.authorization.acquire(
|
190
|
+
if connector.connection.authorization.source[:acquire]
|
191
|
+
tokens, _, extra_settings = connector.connection.authorization.acquire(nil, code, redirect_url)
|
161
192
|
tokens ||= {}
|
162
193
|
extra_settings ||= {}
|
163
194
|
extra_settings.merge(tokens)
|
@@ -178,6 +209,13 @@ module Workato
|
|
178
209
|
response = http.request(request)
|
179
210
|
response.body
|
180
211
|
end
|
212
|
+
|
213
|
+
def with_user_interaction
|
214
|
+
say('')
|
215
|
+
yield
|
216
|
+
ensure
|
217
|
+
say('')
|
218
|
+
end
|
181
219
|
end
|
182
220
|
end
|
183
221
|
end
|
@@ -3,9 +3,33 @@
|
|
3
3
|
|
4
4
|
require_relative './block_invocation_refinements'
|
5
5
|
|
6
|
+
using Workato::Extension::HashWithIndifferentAccess
|
7
|
+
|
6
8
|
module Workato
|
7
9
|
module Connector
|
8
10
|
module Sdk
|
11
|
+
module SorbetTypes
|
12
|
+
AcquireOutput = T.type_alias do
|
13
|
+
T.any(
|
14
|
+
# oauth2
|
15
|
+
[
|
16
|
+
HashWithIndifferentAccess, # tokens
|
17
|
+
T.untyped, # resource_owner_id
|
18
|
+
T.nilable(HashWithIndifferentAccess) # settings
|
19
|
+
],
|
20
|
+
[
|
21
|
+
HashWithIndifferentAccess, # tokens
|
22
|
+
T.untyped # resource_owner_id
|
23
|
+
],
|
24
|
+
[
|
25
|
+
HashWithIndifferentAccess # tokens
|
26
|
+
],
|
27
|
+
# custom_auth
|
28
|
+
HashWithIndifferentAccess
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
9
33
|
class Connection
|
10
34
|
extend T::Sig
|
11
35
|
|
@@ -15,6 +39,7 @@ module Workato
|
|
15
39
|
attr_reader :source
|
16
40
|
|
17
41
|
cattr_accessor :on_settings_update
|
42
|
+
cattr_accessor :multi_auth_selected_fallback
|
18
43
|
|
19
44
|
sig do
|
20
45
|
params(
|
@@ -24,8 +49,8 @@ module Workato
|
|
24
49
|
).void
|
25
50
|
end
|
26
51
|
def initialize(connection: {}, methods: {}, settings: {})
|
27
|
-
@methods_source = T.let(methods
|
28
|
-
@source = T.let(connection
|
52
|
+
@methods_source = T.let(HashWithIndifferentAccess.wrap(methods), HashWithIndifferentAccess)
|
53
|
+
@source = T.let(HashWithIndifferentAccess.wrap(connection), HashWithIndifferentAccess)
|
29
54
|
@settings = T.let(settings, SorbetTypes::SettingsHash)
|
30
55
|
end
|
31
56
|
|
@@ -37,6 +62,7 @@ module Workato
|
|
37
62
|
sig { returns(HashWithIndifferentAccess) }
|
38
63
|
def settings
|
39
64
|
# we can't freeze or memoise because some developers modify it for storing something temporary in it.
|
65
|
+
# always return a new copy
|
40
66
|
@settings.with_indifferent_access
|
41
67
|
end
|
42
68
|
|
@@ -64,7 +90,10 @@ module Workato
|
|
64
90
|
|
65
91
|
sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.nilable(String)) }
|
66
92
|
def base_uri(settings = nil)
|
67
|
-
source[:base_uri]
|
93
|
+
return unless source[:base_uri]
|
94
|
+
|
95
|
+
merge_settings!(settings) if settings
|
96
|
+
Dsl::WithDsl.execute(self, self.settings, &source[:base_uri])
|
68
97
|
end
|
69
98
|
|
70
99
|
sig do
|
@@ -101,9 +130,6 @@ module Workato
|
|
101
130
|
class Authorization
|
102
131
|
extend T::Sig
|
103
132
|
|
104
|
-
sig { returns(HashWithIndifferentAccess) }
|
105
|
-
attr_reader :source
|
106
|
-
|
107
133
|
sig do
|
108
134
|
params(
|
109
135
|
connection: Connection,
|
@@ -123,6 +149,16 @@ module Workato
|
|
123
149
|
(source[:type].presence || 'none').to_s
|
124
150
|
end
|
125
151
|
|
152
|
+
sig { returns(T::Boolean) }
|
153
|
+
def oauth2?
|
154
|
+
!!(/oauth2/i =~ type)
|
155
|
+
end
|
156
|
+
|
157
|
+
sig { returns(T::Boolean) }
|
158
|
+
def multi?
|
159
|
+
@source[:type].to_s == 'multi'
|
160
|
+
end
|
161
|
+
|
126
162
|
sig { returns(T::Array[T.any(String, Symbol, Regexp, Integer)]) }
|
127
163
|
def refresh_on
|
128
164
|
Array.wrap(source[:refresh_on]).compact
|
@@ -135,10 +171,10 @@ module Workato
|
|
135
171
|
|
136
172
|
sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.nilable(String)) }
|
137
173
|
def client_id(settings = nil)
|
174
|
+
@connection.merge_settings!(settings) if settings
|
138
175
|
client_id = source[:client_id]
|
139
176
|
|
140
177
|
if client_id.is_a?(Proc)
|
141
|
-
@connection.merge_settings!(settings) if settings
|
142
178
|
Dsl::WithDsl.execute(@connection, @connection.settings, &client_id)
|
143
179
|
else
|
144
180
|
client_id
|
@@ -147,10 +183,10 @@ module Workato
|
|
147
183
|
|
148
184
|
sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.nilable(String)) }
|
149
185
|
def client_secret(settings = nil)
|
186
|
+
@connection.merge_settings!(settings) if settings
|
150
187
|
client_secret_source = source[:client_secret]
|
151
188
|
|
152
189
|
if client_secret_source.is_a?(Proc)
|
153
|
-
@connection.merge_settings!(settings) if settings
|
154
190
|
Dsl::WithDsl.execute(@connection, @connection.settings, &client_secret_source)
|
155
191
|
else
|
156
192
|
client_secret_source
|
@@ -159,12 +195,18 @@ module Workato
|
|
159
195
|
|
160
196
|
sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.nilable(String)) }
|
161
197
|
def authorization_url(settings = nil)
|
162
|
-
|
198
|
+
@connection.merge_settings!(settings) if settings
|
199
|
+
return unless source[:authorization_url]
|
200
|
+
|
201
|
+
Dsl::WithDsl.execute(@connection, @connection.settings, &source[:authorization_url])
|
163
202
|
end
|
164
203
|
|
165
204
|
sig { params(settings: T.nilable(SorbetTypes::SettingsHash)).returns(T.nilable(String)) }
|
166
205
|
def token_url(settings = nil)
|
167
|
-
|
206
|
+
@connection.merge_settings!(settings) if settings
|
207
|
+
return unless source[:token_url]
|
208
|
+
|
209
|
+
Dsl::WithDsl.execute(@connection, @connection.settings, &source[:token_url])
|
168
210
|
end
|
169
211
|
|
170
212
|
sig do
|
@@ -172,9 +214,10 @@ module Workato
|
|
172
214
|
settings: T.nilable(SorbetTypes::SettingsHash),
|
173
215
|
oauth2_code: T.nilable(String),
|
174
216
|
redirect_url: T.nilable(String)
|
175
|
-
).returns(
|
217
|
+
).returns(T.nilable(SorbetTypes::AcquireOutput))
|
176
218
|
end
|
177
219
|
def acquire(settings = nil, oauth2_code = nil, redirect_url = nil)
|
220
|
+
@connection.merge_settings!(settings) if settings
|
178
221
|
acquire_proc = source[:acquire]
|
179
222
|
raise InvalidDefinitionError, "Expect 'acquire' block" unless acquire_proc
|
180
223
|
|
@@ -202,6 +245,8 @@ module Workato
|
|
202
245
|
).returns(T::Boolean)
|
203
246
|
end
|
204
247
|
def refresh?(http_code, http_body, exception)
|
248
|
+
return false unless oauth2? || source[:acquire].present?
|
249
|
+
|
205
250
|
refresh_on = self.refresh_on
|
206
251
|
refresh_on.blank? || refresh_on.any? do |pattern|
|
207
252
|
pattern.is_a?(::Integer) && pattern == http_code ||
|
@@ -212,10 +257,10 @@ module Workato
|
|
212
257
|
|
213
258
|
sig { params(settings: HashWithIndifferentAccess).returns(T.nilable(HashWithIndifferentAccess)) }
|
214
259
|
def refresh!(settings)
|
215
|
-
if
|
260
|
+
if oauth2?
|
216
261
|
refresh_oauth2_token(settings)
|
217
262
|
elsif source[:acquire].present?
|
218
|
-
acquire(settings)
|
263
|
+
T.cast(acquire(settings), T.nilable(HashWithIndifferentAccess))
|
219
264
|
end
|
220
265
|
end
|
221
266
|
|
@@ -228,6 +273,7 @@ module Workato
|
|
228
273
|
)
|
229
274
|
end
|
230
275
|
def refresh(settings = nil, refresh_token = nil)
|
276
|
+
@connection.merge_settings!(settings) if settings
|
231
277
|
refresh_proc = source[:refresh]
|
232
278
|
raise InvalidDefinitionError, "Expect 'refresh' block" unless refresh_proc
|
233
279
|
|
@@ -242,6 +288,27 @@ module Workato
|
|
242
288
|
end
|
243
289
|
end
|
244
290
|
|
291
|
+
sig { returns(HashWithIndifferentAccess) }
|
292
|
+
def source
|
293
|
+
return @source unless multi?
|
294
|
+
|
295
|
+
unless @source[:selected]
|
296
|
+
raise InvalidMultiAuthDefinition, "Multi-auth connection must define 'selected' block"
|
297
|
+
end
|
298
|
+
|
299
|
+
if @source[:options].blank?
|
300
|
+
raise InvalidMultiAuthDefinition, "Multi-auth connection must define 'options' list"
|
301
|
+
end
|
302
|
+
|
303
|
+
selected_auth_key = @source[:selected].call(@connection.settings)
|
304
|
+
selected_auth_key ||= @connection.multi_auth_selected_fallback&.call(@source[:options])
|
305
|
+
selected_auth_value = @source.dig(:options, selected_auth_key)
|
306
|
+
|
307
|
+
raise UnresolvedMultiAuthOptionError, selected_auth_key unless selected_auth_value
|
308
|
+
|
309
|
+
selected_auth_value
|
310
|
+
end
|
311
|
+
|
245
312
|
private
|
246
313
|
|
247
314
|
sig { returns(HashWithIndifferentAccess) }
|
@@ -264,7 +331,10 @@ module Workato
|
|
264
331
|
sig { params(settings: HashWithIndifferentAccess).returns(HashWithIndifferentAccess) }
|
265
332
|
def refresh_oauth2_token_using_refresh(settings)
|
266
333
|
new_tokens, new_settings = refresh(settings, settings[:refresh_token])
|
267
|
-
new_tokens.
|
334
|
+
new_tokens = HashWithIndifferentAccess.wrap(new_tokens)
|
335
|
+
return new_tokens unless new_settings
|
336
|
+
|
337
|
+
new_tokens.merge(new_settings)
|
268
338
|
end
|
269
339
|
|
270
340
|
sig { params(settings: HashWithIndifferentAccess).returns(HashWithIndifferentAccess) }
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
using Workato::Extension::HashWithIndifferentAccess
|
5
|
+
|
4
6
|
module Workato
|
5
7
|
module Connector
|
6
8
|
module Sdk
|
@@ -21,10 +23,10 @@ module Workato
|
|
21
23
|
|
22
24
|
sig { params(definition: SorbetTypes::SourceHash, settings: SorbetTypes::SettingsHash).void }
|
23
25
|
def initialize(definition, settings = {})
|
24
|
-
@source = T.let(definition
|
25
|
-
@settings = T.let(settings
|
26
|
-
@connection_source = T.let(@source[:connection]
|
27
|
-
@methods_source = T.let(@source[:methods]
|
26
|
+
@source = T.let(HashWithIndifferentAccess.wrap(definition), HashWithIndifferentAccess)
|
27
|
+
@settings = T.let(HashWithIndifferentAccess.wrap(settings), HashWithIndifferentAccess)
|
28
|
+
@connection_source = T.let(HashWithIndifferentAccess.wrap(@source[:connection]), HashWithIndifferentAccess)
|
29
|
+
@methods_source = T.let(HashWithIndifferentAccess.wrap(@source[:methods]), HashWithIndifferentAccess)
|
28
30
|
end
|
29
31
|
|
30
32
|
sig { params(path: String, params: T::Hash[Symbol, T.untyped]).returns(T.untyped) }
|
@@ -2,6 +2,9 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'aws-sigv4'
|
5
|
+
require 'workato/utilities/xml'
|
6
|
+
|
7
|
+
using Workato::Extension::HashWithIndifferentAccess
|
5
8
|
|
6
9
|
module Workato
|
7
10
|
module Connector
|
@@ -55,7 +58,7 @@ module Workato
|
|
55
58
|
method: method,
|
56
59
|
path: path,
|
57
60
|
params: params,
|
58
|
-
headers: (headers
|
61
|
+
headers: HashWithIndifferentAccess.wrap(headers),
|
59
62
|
payload: payload
|
60
63
|
)
|
61
64
|
|
@@ -134,7 +137,7 @@ module Workato
|
|
134
137
|
headers: headers,
|
135
138
|
method: :get
|
136
139
|
)
|
137
|
-
response = Workato::
|
140
|
+
response = Workato::Utilities::Xml.parse_xml_to_hash(response.body)
|
138
141
|
|
139
142
|
temp_credentials = response.dig('AssumeRoleResponse', 0, 'AssumeRoleResult', 0, 'Credentials', 0)
|
140
143
|
{
|
@@ -7,9 +7,12 @@ module Workato
|
|
7
7
|
module Dsl
|
8
8
|
module Call
|
9
9
|
def call(method, *args)
|
10
|
-
|
10
|
+
method_proc = @_methods[method]
|
11
11
|
|
12
|
-
|
12
|
+
raise UndefinedMethodError, method unless method_proc
|
13
|
+
raise UnexpectedMethodDefinitionError.new(method, method_proc) unless method_proc.is_a?(Proc)
|
14
|
+
|
15
|
+
instance_exec(*args, &method_proc)
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'csv'
|
5
|
+
|
6
|
+
module Workato
|
7
|
+
module Connector
|
8
|
+
module Sdk
|
9
|
+
CsvError = Class.new(Sdk::RuntimeError)
|
10
|
+
|
11
|
+
CsvFormatError = Class.new(CsvError)
|
12
|
+
|
13
|
+
class CsvFileTooBigError < CsvError
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
sig { returns(Integer) }
|
17
|
+
attr_reader :size
|
18
|
+
|
19
|
+
sig { returns(Integer) }
|
20
|
+
attr_reader :max
|
21
|
+
|
22
|
+
sig { params(size: Integer, max: Integer).void }
|
23
|
+
def initialize(size, max)
|
24
|
+
super("CSV file is too big. Max allowed: #{max.to_s(:human_size)}, got: #{size.to_s(:human_size)}")
|
25
|
+
@size = T.let(size, Integer)
|
26
|
+
@max = T.let(max, Integer)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class CsvFileTooManyLinesError < CsvError
|
31
|
+
extend T::Sig
|
32
|
+
|
33
|
+
sig { returns(Integer) }
|
34
|
+
attr_reader :max
|
35
|
+
|
36
|
+
sig { params(max: Integer).void }
|
37
|
+
def initialize(max)
|
38
|
+
super("CSV file has too many lines. Max allowed: #{max}")
|
39
|
+
@max = T.let(max, Integer)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Dsl
|
44
|
+
module Csv
|
45
|
+
extend T::Sig
|
46
|
+
|
47
|
+
MAX_FILE_SIZE_FOR_PARSE = T.let(30.megabytes, Integer)
|
48
|
+
private_constant :MAX_FILE_SIZE_FOR_PARSE
|
49
|
+
|
50
|
+
MAX_LINES_FOR_PARSE = 65_000
|
51
|
+
private_constant :MAX_LINES_FOR_PARSE
|
52
|
+
|
53
|
+
class << self
|
54
|
+
extend T::Sig
|
55
|
+
|
56
|
+
sig do
|
57
|
+
params(
|
58
|
+
str: String,
|
59
|
+
headers: T.any(T::Boolean, T::Array[String], String),
|
60
|
+
col_sep: T.nilable(String),
|
61
|
+
row_sep: T.nilable(String),
|
62
|
+
quote_char: T.nilable(String),
|
63
|
+
skip_blanks: T.nilable(T::Boolean),
|
64
|
+
skip_first_line: T::Boolean
|
65
|
+
).returns(
|
66
|
+
T::Array[T::Hash[String, T.untyped]]
|
67
|
+
)
|
68
|
+
end
|
69
|
+
def parse(str, headers:, col_sep: nil, row_sep: nil, quote_char: nil, skip_blanks: nil,
|
70
|
+
skip_first_line: false)
|
71
|
+
if str.bytesize > MAX_FILE_SIZE_FOR_PARSE
|
72
|
+
raise CsvFileTooBigError.new(str.bytesize, MAX_FILE_SIZE_FOR_PARSE)
|
73
|
+
end
|
74
|
+
|
75
|
+
index = 0
|
76
|
+
options = { col_sep: col_sep, row_sep: row_sep, quote_char: quote_char, headers: headers,
|
77
|
+
skip_blanks: skip_blanks }.compact
|
78
|
+
Enumerator.new do |consumer|
|
79
|
+
CSV.parse(str, options) do |row|
|
80
|
+
if index.zero? && skip_first_line
|
81
|
+
index += 1
|
82
|
+
next
|
83
|
+
end
|
84
|
+
if index == MAX_LINES_FOR_PARSE
|
85
|
+
raise CsvFileTooManyLinesError, MAX_LINES_FOR_PARSE
|
86
|
+
end
|
87
|
+
|
88
|
+
index += 1
|
89
|
+
consumer.yield(T.cast(row, CSV::Row).to_hash)
|
90
|
+
end
|
91
|
+
end.to_a
|
92
|
+
rescue CSV::MalformedCSVError => e
|
93
|
+
raise CsvFormatError, e
|
94
|
+
rescue ArgumentError => e
|
95
|
+
raise Sdk::RuntimeError, e.message
|
96
|
+
end
|
97
|
+
|
98
|
+
sig do
|
99
|
+
params(
|
100
|
+
str: T.nilable(String),
|
101
|
+
headers: T.nilable(T::Array[String]),
|
102
|
+
col_sep: T.nilable(String),
|
103
|
+
row_sep: T.nilable(String),
|
104
|
+
quote_char: T.nilable(String),
|
105
|
+
force_quotes: T.nilable(T::Boolean),
|
106
|
+
blk: T.proc.params(csv: CSV).void
|
107
|
+
).returns(
|
108
|
+
String
|
109
|
+
)
|
110
|
+
end
|
111
|
+
def generate(str = nil, headers: nil, col_sep: nil, row_sep: nil, quote_char: nil, force_quotes: nil, &blk)
|
112
|
+
options = { col_sep: col_sep, row_sep: row_sep, quote_char: quote_char, headers: headers,
|
113
|
+
force_quotes: force_quotes }.compact
|
114
|
+
options[:write_headers] = options[:headers].present?
|
115
|
+
|
116
|
+
::CSV.generate(str || String.new, options, &blk)
|
117
|
+
rescue ArgumentError => e
|
118
|
+
raise Sdk::RuntimeError, e.message
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|