workato-connector-sdk 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +48 -22
- data/lib/workato/cli/exec_command.rb +6 -1
- data/lib/workato/cli/main.rb +45 -0
- data/lib/workato/cli/oauth2_command.rb +182 -0
- data/lib/workato/connector/sdk/action.rb +41 -4
- data/lib/workato/connector/sdk/connection.rb +144 -0
- data/lib/workato/connector/sdk/connector.rb +15 -7
- data/lib/workato/connector/sdk/object_definitions.rb +10 -10
- data/lib/workato/connector/sdk/operation.rb +17 -37
- data/lib/workato/connector/sdk/request.rb +11 -7
- data/lib/workato/connector/sdk/settings.rb +6 -3
- data/lib/workato/connector/sdk/version.rb +1 -1
- data/lib/workato/connector/sdk.rb +1 -0
- data/lib/workato/web/app.rb +23 -0
- data/templates/spec/action_spec.rb.erb +1 -1
- metadata +77 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1b501416ca8344b57fb05ebc9b48b3f1b19a4f4e
|
4
|
+
data.tar.gz: 47666c7e297ead213ca1228c38d3ed15dfbd699d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 266afec14bd2e2b5dcb4104df330d9cb8f96bac11a1d8d6e9199ca3bbd0576c35ff35475ef7b661610cdeef9292d36c4091cd744cac095a8d067a42dc2ccd7da
|
7
|
+
data.tar.gz: c1c1437158f46a43ab50102ce55d2846f76310d417fc130ca8d6aae1c0e34b7d962f26687929466cb94eb1859e5ab82d596c5eab736dd08e87ff0ae2dfdeeef7
|
data/README.md
CHANGED
@@ -39,6 +39,7 @@ Commands:
|
|
39
39
|
workato generate <SUBCOMMAND> # Generates code from template
|
40
40
|
workato help [COMMAND] # Describe available commands or one specific command
|
41
41
|
workato new <CONNECTOR_PATH> # Inits new connector folder
|
42
|
+
workato oauth2 # Implements OAuth Authorization Code flow
|
42
43
|
workato push # Upload and release connector's code
|
43
44
|
|
44
45
|
Options:
|
@@ -224,6 +225,7 @@ Commands:
|
|
224
225
|
workato generate <SUBCOMMAND> # Generates code from template
|
225
226
|
workato help [COMMAND] # Describe available commands or one specific command
|
226
227
|
workato new <CONNECTOR_PATH> # Inits new connector folder
|
228
|
+
workato oauth2 # Implements OAuth Authorization Code flow
|
227
229
|
workato push # Upload and release connector's code
|
228
230
|
|
229
231
|
Options:
|
@@ -259,7 +261,6 @@ Edit encrypted file, e.g. settings.yaml.enc
|
|
259
261
|
### 3.3 workato exec
|
260
262
|
```
|
261
263
|
workato help exec
|
262
|
-
|
263
264
|
Usage:
|
264
265
|
workato exec <PATH>
|
265
266
|
|
@@ -270,6 +271,7 @@ Options:
|
|
270
271
|
-k, [--key=KEY] # Path to file with encrypt/decrypt key. NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
271
272
|
-i, [--input=INPUT] # Path to file with input JSON
|
272
273
|
[--closure=CLOSURE] # Path to file with next poll closure JSON
|
274
|
+
[--continue=CONTINUE] # Path to file with next multistep action continue closure JSON
|
273
275
|
-a, [--args=ARGS] # Path to file with method arguments JSON
|
274
276
|
[--extended-input-schema=EXTENDED_INPUT_SCHEMA] # Path to file with extended input schema definition JSON
|
275
277
|
[--extended-output-schema=EXTENDED_OUTPUT_SCHEMA] # Path to file with extended output schema definition JSON
|
@@ -279,8 +281,11 @@ Options:
|
|
279
281
|
[--webhook-headers=WEBHOOK_HEADERS] # Path to file with webhook headers JSON
|
280
282
|
[--webhook-url=WEBHOOK_URL] # Webhook URL for automatic webhook subscription
|
281
283
|
-o, [--output=OUTPUT] # Write output to JSON file
|
282
|
-
[--
|
283
|
-
[--
|
284
|
+
[--oauth2-code=OAUTH2_CODE] # OAuth2 code exchange to tokens pair
|
285
|
+
[--redirect-url=REDIRECT_URL] # OAuth2 callback url
|
286
|
+
[--refresh-token=REFRESH_TOKEN] # OAuth2 refresh token
|
287
|
+
[--debug], [--no-debug]
|
288
|
+
[--verbose], [--no-verbose]
|
284
289
|
|
285
290
|
Description:
|
286
291
|
The 'workato exec' executes connector's lambda block at <PATH>. Lambda's parameters can be provided if needed, see options part.
|
@@ -358,7 +363,31 @@ Please select default HTTP mocking behavior suitable for your project?
|
|
358
363
|
|
359
364
|
- `simple` means your HTTP requests will be stored in plain text.
|
360
365
|
|
361
|
-
### 3.6 workato
|
366
|
+
### 3.6 workato oauth2
|
367
|
+
```
|
368
|
+
workato help oauth2
|
369
|
+
|
370
|
+
Usage:
|
371
|
+
workato oauth2
|
372
|
+
|
373
|
+
Options:
|
374
|
+
-c, [--connector=CONNECTOR] # Path to connector source code
|
375
|
+
-s, [--settings=SETTINGS] # Path to plain or encrypted file with connection configs, passwords, tokens, secrets etc
|
376
|
+
-n, [--connection=CONNECTION] # Connection name if settings file contains multiple settings
|
377
|
+
-k, [--key=KEY] # Path to file with encrypt/decrypt key. NOTE: key from WORKATO_CONNECTOR_MASTER_KEY has higher priority
|
378
|
+
[--port=PORT] # Listen requests on specific port
|
379
|
+
# Default: 45555
|
380
|
+
[--ip=IP] # Listen requests on specific interface
|
381
|
+
# Default: 127.0.0.1
|
382
|
+
[--https], [--no-https] # Start HTTPS server using self-signed certificate
|
383
|
+
[--verbose], [--no-verbose]
|
384
|
+
|
385
|
+
Implements OAuth Authorization Code flow
|
386
|
+
```
|
387
|
+
|
388
|
+
Use this to implement the OAuth2 Authorization code grant flow for applicable connectors. Applicable connectors are ones where the connection hash has `type: 'oauth2`. For more information, check out our guide on our [main docs site](https://docs.workato.com/developing-connectors/sdk/guides/authentication/oauth/auth-code.html#how-to-guide-oauth-2-0-authorization-code-variant).
|
389
|
+
|
390
|
+
### 3.7 workato push
|
362
391
|
```
|
363
392
|
workato help push
|
364
393
|
|
@@ -490,7 +519,7 @@ workato exec test #Output of the test: lambda function should be shown
|
|
490
519
|
> *Note*: You may also see a intermediary command from the Gem asking if you'd like to refresh your access tokens. This is done when HTTP requests are made which have a response that triggers the `refresh_on` block. Selecting yes would cause the Gem to update your settings file with the latest auth credentials.
|
491
520
|
|
492
521
|
### 4.3 Example: Testing your connection on CLI - OAuth 2 - auth code grant flows
|
493
|
-
For auth code grant flows, the Workato Gem
|
522
|
+
For auth code grant flows, the Workato Gem allows you to simulate the OAuth2 flow using the `workato oauth2` command.
|
494
523
|
|
495
524
|
```ruby
|
496
525
|
{
|
@@ -574,27 +603,24 @@ For auth code grant flows, the Workato Gem doesn't simulate the browser popup so
|
|
574
603
|
and a `settings.yaml.enc` or `settings.yaml` file with the following details
|
575
604
|
|
576
605
|
```yaml
|
577
|
-
|
578
|
-
|
579
|
-
refresh_token: "valid_refresh_token"
|
580
|
-
user_key: "valid_user_key"
|
581
|
-
client_id: "valid_client_id"
|
582
|
-
client_secret: "valid_client_secret"
|
583
|
-
Invalid Access Token:
|
584
|
-
access_token: "invalid_access_token"
|
585
|
-
refresh_token: "valid_refresh_token"
|
586
|
-
user_key: "valid_user_key"
|
587
|
-
client_id: "valid_client_id"
|
588
|
-
client_secret: "valid_client_secret"
|
606
|
+
client_id: valid_client_id
|
607
|
+
client_secret: valid_client_secret
|
589
608
|
```
|
590
609
|
|
591
|
-
You can now run the following commands to
|
610
|
+
You can now run the following commands to go through the OAuth2 Authorization code flow which includes a browser popup.
|
592
611
|
```bash
|
593
|
-
workato
|
594
|
-
workato exec test --connection='Invalid Access Token' --verbose #You should see a see a set of request where the test is tried, access token receives 401 and the sequence to refresh the gem using the refresh key is used! This allows you to test how your connector refreshes a connection.
|
612
|
+
workato oauth2
|
595
613
|
```
|
596
614
|
|
597
|
-
|
615
|
+
https://user-images.githubusercontent.com/25265275/137942408-812fa6ad-353f-4ea2-bf37-f804e2ff7b04.mov
|
616
|
+
|
617
|
+
|
618
|
+
> *Note*: `--verbose` can be used to detail everything, including the HTTP requests.
|
619
|
+
|
620
|
+
|
621
|
+
Now after you've successfully gone through the flow, you may be use the same `workato exec test` command to verify you're applying your token properly in your requests! Depending on when you received your token, you may also see a intermediary command from the Gem asking if you'd like to refresh your access tokens (if it has expired). This is done when HTTP requests are made which have a response that triggers the `refresh_on` block. Selecting "Yes" would cause the Gem to update your settings file with the latest auth credentials.
|
622
|
+
|
623
|
+
Take note, you may also use `workato exec` to execute lambdas in your `authorization` hash like `acquire` and `refresh`. **That said, we highlight recommend you use `workato exec test` and `workato oauth2` which handle the updating of your `settings.yaml` file automatically.**
|
598
624
|
|
599
625
|
### Example: Testing a sample action on CLI
|
600
626
|
Continuing from the previous example, let's take a look at a simple action and invoke the individual lambda functions.
|
@@ -633,7 +659,7 @@ Continuing from the previous example, let's take a look at a simple action and i
|
|
633
659
|
end,
|
634
660
|
|
635
661
|
|
636
|
-
execute: lambda do |connection, input, input_schema, output_schema|
|
662
|
+
execute: lambda do |connection, input, input_schema, output_schema, closure|
|
637
663
|
get("/api/v2/customers",input)
|
638
664
|
end,
|
639
665
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'thor'
|
4
|
-
require 'ruby-progressbar'
|
5
4
|
|
6
5
|
module Workato
|
7
6
|
module CLI
|
@@ -55,10 +54,14 @@ module Workato
|
|
55
54
|
extended_output_schema: from_json(options[:extended_output_schema]).presence || [],
|
56
55
|
config_fields: from_json(options[:config_fields]),
|
57
56
|
closure: from_json(options[:closure], parse_json_times: true).presence,
|
57
|
+
continue: from_json(options[:continue], parse_json_times: true),
|
58
58
|
payload: from_json(options[:webhook_payload]),
|
59
59
|
params: from_json(options[:webhook_params]),
|
60
60
|
headers: from_json(options[:webhook_headers]),
|
61
61
|
webhook_url: options[:webhook_url],
|
62
|
+
oauth2_code: options[:oauth2_code],
|
63
|
+
redirect_url: options[:redirect_url],
|
64
|
+
refresh_token: options[:refresh_token],
|
62
65
|
recipe_id: SecureRandom.uuid
|
63
66
|
}
|
64
67
|
end
|
@@ -149,6 +152,8 @@ module Workato
|
|
149
152
|
def with_progress
|
150
153
|
return yield unless verbose?
|
151
154
|
|
155
|
+
require 'ruby-progressbar'
|
156
|
+
|
152
157
|
say('')
|
153
158
|
|
154
159
|
old_stdout = $stdout
|
data/lib/workato/cli/main.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative './exec_command'
|
|
6
6
|
require_relative './edit_command'
|
7
7
|
require_relative './generate_command'
|
8
8
|
require_relative './push_command'
|
9
|
+
require_relative './oauth2_command'
|
9
10
|
require_relative './generators/connector_generator'
|
10
11
|
require_relative './generators/master_key_generator'
|
11
12
|
|
@@ -42,6 +43,7 @@ module Workato
|
|
42
43
|
"NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
|
43
44
|
method_option :input, type: :string, aliases: '-i', desc: 'Path to file with input JSON'
|
44
45
|
method_option :closure, type: :string, desc: 'Path to file with next poll closure JSON'
|
46
|
+
method_option :continue, type: :string, desc: 'Path to file with next multistep action continue closure JSON'
|
45
47
|
method_option :args, type: :string, aliases: '-a', desc: 'Path to file with method arguments JSON'
|
46
48
|
method_option :extended_input_schema, type: :string,
|
47
49
|
desc: 'Path to file with extended input schema definition JSON'
|
@@ -53,6 +55,9 @@ module Workato
|
|
53
55
|
method_option :webhook_headers, type: :string, desc: 'Path to file with webhook headers JSON'
|
54
56
|
method_option :webhook_url, type: :string, desc: 'Webhook URL for automatic webhook subscription'
|
55
57
|
method_option :output, type: :string, aliases: '-o', desc: 'Write output to JSON file'
|
58
|
+
method_option :oauth2_code, type: :string, desc: 'OAuth2 code exchange to tokens pair'
|
59
|
+
method_option :redirect_url, type: :string, desc: 'OAuth2 callback url'
|
60
|
+
method_option :refresh_token, type: :string, desc: 'OAuth2 refresh token'
|
56
61
|
|
57
62
|
method_option :debug, type: :boolean
|
58
63
|
|
@@ -139,6 +144,46 @@ module Workato
|
|
139
144
|
options: options
|
140
145
|
).call
|
141
146
|
end
|
147
|
+
|
148
|
+
desc 'oauth2', 'Implements OAuth Authorization Code flow'
|
149
|
+
|
150
|
+
method_option :connector,
|
151
|
+
type: :string,
|
152
|
+
aliases: '-c',
|
153
|
+
desc: 'Path to connector source code',
|
154
|
+
lazy_default: Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
|
155
|
+
method_option :settings,
|
156
|
+
type: :string,
|
157
|
+
aliases: '-s',
|
158
|
+
desc: 'Path to plain or encrypted file with connection configs, passwords, tokens, secrets etc',
|
159
|
+
lazy_default: Workato::Connector::Sdk::DEFAULT_ENCRYPTED_SETTINGS_PATH
|
160
|
+
method_option :connection,
|
161
|
+
type: :string,
|
162
|
+
aliases: '-n',
|
163
|
+
desc: 'Connection name if settings file contains multiple settings'
|
164
|
+
method_option :key,
|
165
|
+
type: :string,
|
166
|
+
aliases: '-k',
|
167
|
+
lazy_default: Workato::Connector::Sdk::DEFAULT_MASTER_KEY_PATH,
|
168
|
+
desc: 'Path to file with encrypt/decrypt key. '\
|
169
|
+
"NOTE: key from #{Workato::Connector::Sdk::DEFAULT_MASTER_KEY_ENV} has higher priority"
|
170
|
+
method_option :port,
|
171
|
+
type: :string,
|
172
|
+
desc: 'Listen requests on specific port',
|
173
|
+
default: Workato::CLI::OAuth2Command::DEFAULT_PORT
|
174
|
+
method_option :ip,
|
175
|
+
type: :string,
|
176
|
+
desc: 'Listen requests on specific interface',
|
177
|
+
default: Workato::CLI::OAuth2Command::DEFAULT_ADDRESS
|
178
|
+
method_option :https,
|
179
|
+
type: :boolean,
|
180
|
+
desc: 'Start HTTPS server using self-signed certificate'
|
181
|
+
|
182
|
+
def oauth2
|
183
|
+
OAuth2Command.new(
|
184
|
+
options: options
|
185
|
+
).call
|
186
|
+
end
|
142
187
|
end
|
143
188
|
end
|
144
189
|
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'workato/web/app'
|
4
|
+
|
5
|
+
module Workato
|
6
|
+
module CLI
|
7
|
+
class OAuth2Command
|
8
|
+
include Thor::Shell
|
9
|
+
|
10
|
+
AWAIT_CODE_TIMEOUT_INTERVAL = 180 # seconds
|
11
|
+
AWAIT_CODE_SLEEP_INTERVAL = 5 # seconds
|
12
|
+
|
13
|
+
DEFAULT_ADDRESS = '127.0.0.1'
|
14
|
+
DEFAULT_PORT = '45555'
|
15
|
+
|
16
|
+
def initialize(options: {})
|
17
|
+
@options = options
|
18
|
+
@port = options[:port] || DEFAULT_PORT
|
19
|
+
@https = options[:https].is_true?
|
20
|
+
@base_url = "#{https ? 'https' : 'http'}://localhost:#{port}"
|
21
|
+
@redirect_url = "#{base_url}#{Workato::Web::App::CALLBACK_PATH}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
require_gems
|
26
|
+
start_webrick
|
27
|
+
|
28
|
+
say 'Local server is running. Allow following redirect_url in your OAuth2 provider:'
|
29
|
+
say "\n"
|
30
|
+
say redirect_url
|
31
|
+
say ''
|
32
|
+
|
33
|
+
say_status :success, "Open #{authorize_url} in browser"
|
34
|
+
Launchy.open(authorize_url) do |exception|
|
35
|
+
raise(Error, "Attempted to open #{authorize_url} and failed because #{exception}")
|
36
|
+
end
|
37
|
+
|
38
|
+
code = await_code
|
39
|
+
say_status :success, "Receive OAuth2 code=#{code}"
|
40
|
+
|
41
|
+
tokens = acquire_token(code)
|
42
|
+
say_status :success, 'Receive OAuth2 tokens'
|
43
|
+
jj tokens if verbose?
|
44
|
+
|
45
|
+
settings_store.update(tokens)
|
46
|
+
say_status :success, 'Update settings file'
|
47
|
+
rescue Timeout::Error
|
48
|
+
say "Have not received callback from OAuth2 provider in #{AWAIT_CODE_TIMEOUT_INTERVAL} seconds. Aborting!"
|
49
|
+
rescue Errno::EADDRINUSE
|
50
|
+
say "Port #{port} already in use. Try to use different port with --port=#{rand(10_000..65_664)}"
|
51
|
+
rescue StandardError => e
|
52
|
+
say e.message
|
53
|
+
ensure
|
54
|
+
stop_webrick
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :https,
|
60
|
+
:base_url,
|
61
|
+
:redirect_url,
|
62
|
+
:port,
|
63
|
+
:options
|
64
|
+
|
65
|
+
def verbose?
|
66
|
+
!!options[:verbose]
|
67
|
+
end
|
68
|
+
|
69
|
+
def require_gems
|
70
|
+
require 'oauth2'
|
71
|
+
require 'launchy'
|
72
|
+
require 'rack'
|
73
|
+
end
|
74
|
+
|
75
|
+
def start_webrick
|
76
|
+
@thread = Thread.start do
|
77
|
+
Rack::Handler::WEBrick.run(
|
78
|
+
Workato::Web::App.new,
|
79
|
+
{
|
80
|
+
Port: port,
|
81
|
+
BindAddress: options[:ip] || DEFAULT_ADDRESS,
|
82
|
+
SSLEnable: https,
|
83
|
+
SSLVerifyClient: OpenSSL::SSL::VERIFY_NONE,
|
84
|
+
SSLCertName: [%w[CN localhost]]
|
85
|
+
}.tap do |server_options|
|
86
|
+
unless verbose?
|
87
|
+
server_options[:AccessLog] = []
|
88
|
+
server_options[:Logger] = WEBrick::Log.new($stderr, 0)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
)
|
92
|
+
end
|
93
|
+
@thread.abort_on_exception = true
|
94
|
+
end
|
95
|
+
|
96
|
+
def stop_webrick
|
97
|
+
Rack::Handler::WEBrick.shutdown
|
98
|
+
@thread.exit
|
99
|
+
end
|
100
|
+
|
101
|
+
def client
|
102
|
+
@client ||= OAuth2::Client.new(
|
103
|
+
connector.connection.authorization.client_id(settings),
|
104
|
+
connector.connection.authorization.client_secret(settings),
|
105
|
+
site: connector.connection.base_uri(settings),
|
106
|
+
token_url: connector.connection.authorization.token_url(settings),
|
107
|
+
redirect_uri: redirect_url
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
def authorize_url
|
112
|
+
return @authorize_url if defined?(@authorize_url)
|
113
|
+
|
114
|
+
@authorize_url =
|
115
|
+
if (authorization_url = connector.connection.authorization.authorization_url(settings))
|
116
|
+
params = {
|
117
|
+
client_id: connector.connection.authorization.client_id(settings),
|
118
|
+
redirect_uri: redirect_url
|
119
|
+
}
|
120
|
+
uri = URI(authorization_url)
|
121
|
+
uri.query = params.with_indifferent_access.merge(Rack::Utils.parse_nested_query(uri.query || '')).to_param
|
122
|
+
uri.to_s
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def settings_store
|
127
|
+
@settings_store ||= Workato::Connector::Sdk::Settings.new(
|
128
|
+
path: options[:settings],
|
129
|
+
name: options[:connection],
|
130
|
+
key_path: options[:key]
|
131
|
+
)
|
132
|
+
end
|
133
|
+
|
134
|
+
def settings
|
135
|
+
@settings ||= settings_store.read
|
136
|
+
end
|
137
|
+
|
138
|
+
def connector
|
139
|
+
@connector ||= Workato::Connector::Sdk::Connector.from_file(
|
140
|
+
options[:connector] || Workato::Connector::Sdk::DEFAULT_CONNECTOR_PATH
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
def await_code
|
145
|
+
code_uri = URI("#{base_url}#{Workato::Web::App::CODE_PATH}")
|
146
|
+
|
147
|
+
Timeout.timeout(AWAIT_CODE_TIMEOUT_INTERVAL) do
|
148
|
+
loop do
|
149
|
+
response = get(code_uri) rescue nil
|
150
|
+
break response if response.present?
|
151
|
+
|
152
|
+
sleep(AWAIT_CODE_SLEEP_INTERVAL)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def acquire_token(code)
|
158
|
+
if connector.source.dig(:connection, :authorization, :acquire)
|
159
|
+
tokens, _, extra_settings = connector.connection.authorization.acquire(settings, await_code, redirect_url)
|
160
|
+
tokens ||= {}
|
161
|
+
extra_settings ||= {}
|
162
|
+
extra_settings.merge(tokens)
|
163
|
+
else
|
164
|
+
client.auth_code.get_token(code).to_hash
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def get(uri)
|
169
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
170
|
+
if https
|
171
|
+
http.use_ssl = true
|
172
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
173
|
+
end
|
174
|
+
|
175
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
176
|
+
|
177
|
+
response = http.request(request)
|
178
|
+
response.body
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -14,6 +14,8 @@ module Workato
|
|
14
14
|
RETRY_DELAY = 5.seconds
|
15
15
|
MAX_RETRIES = 3
|
16
16
|
|
17
|
+
MAX_REINVOKES = 5
|
18
|
+
|
17
19
|
def initialize(action:, connection: {}, methods: {}, settings: {}, object_definitions: nil)
|
18
20
|
super(
|
19
21
|
operation: action,
|
@@ -26,10 +28,32 @@ module Workato
|
|
26
28
|
initialize_retry
|
27
29
|
end
|
28
30
|
|
29
|
-
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [],
|
31
|
+
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [], continue = {},
|
32
|
+
&block)
|
30
33
|
raise InvalidDefinitionError, "'execute' block is required for action" unless block || action[:execute]
|
31
34
|
|
32
|
-
|
35
|
+
loop do
|
36
|
+
if @reinvokes_remaining&.zero?
|
37
|
+
raise "Max number of reinvokes on SDK Gem reached. Current limit is #{reinvoke_limit}"
|
38
|
+
end
|
39
|
+
|
40
|
+
reinvoke_sleep if @reinvoke_after
|
41
|
+
|
42
|
+
@reinvoke_after = nil
|
43
|
+
|
44
|
+
result = super(
|
45
|
+
settings,
|
46
|
+
input,
|
47
|
+
extended_input_schema,
|
48
|
+
extended_output_schema,
|
49
|
+
continue,
|
50
|
+
&(block || action[:execute])
|
51
|
+
)
|
52
|
+
|
53
|
+
break result unless @reinvoke_after
|
54
|
+
|
55
|
+
continue = @reinvoke_after[:continue]
|
56
|
+
end
|
33
57
|
rescue RequestError => e
|
34
58
|
raise e unless retry?(e)
|
35
59
|
|
@@ -38,11 +62,16 @@ module Workato
|
|
38
62
|
end
|
39
63
|
|
40
64
|
def checkpoint!(continue:, temp_output: nil)
|
41
|
-
|
65
|
+
# no-op
|
42
66
|
end
|
43
67
|
|
44
68
|
def reinvoke_after(seconds:, continue:, temp_output: nil)
|
45
|
-
|
69
|
+
@reinvokes_remaining = (@reinvokes_remaining ? @reinvokes_remaining - 1 : reinvoke_limit)
|
70
|
+
@reinvoke_after = {
|
71
|
+
seconds: seconds,
|
72
|
+
continue: continue,
|
73
|
+
temp_output: temp_output
|
74
|
+
}
|
46
75
|
end
|
47
76
|
|
48
77
|
private
|
@@ -81,6 +110,14 @@ module Workato
|
|
81
110
|
@retry_methods.include?(exception.method.to_s.downcase)
|
82
111
|
end
|
83
112
|
|
113
|
+
def reinvoke_sleep
|
114
|
+
sleep((ENV['WAIT_REINVOKE_AFTER'].presence || @reinvoke_after[:seconds]).to_f)
|
115
|
+
end
|
116
|
+
|
117
|
+
def reinvoke_limit
|
118
|
+
@reinvoke_limit ||= (ENV['MAX_REINVOKES'].presence || MAX_REINVOKES).to_i
|
119
|
+
end
|
120
|
+
|
84
121
|
alias action operation
|
85
122
|
end
|
86
123
|
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './block_invocation_refinements'
|
4
|
+
|
5
|
+
module Workato
|
6
|
+
module Connector
|
7
|
+
module Sdk
|
8
|
+
class Connection
|
9
|
+
using BlockInvocationRefinements
|
10
|
+
|
11
|
+
attr_reader :source
|
12
|
+
|
13
|
+
def initialize(connection: {}, methods: {}, settings: {})
|
14
|
+
@methods_source = methods.with_indifferent_access
|
15
|
+
@source = connection.with_indifferent_access
|
16
|
+
@settings = settings
|
17
|
+
end
|
18
|
+
|
19
|
+
def authorization
|
20
|
+
@authorization ||= Authorization.new(
|
21
|
+
connection: source,
|
22
|
+
methods: methods_source,
|
23
|
+
settings: @settings
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_uri(settings = {})
|
28
|
+
source[:base_uri]&.call(settings.with_indifferent_access)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :methods_source
|
34
|
+
|
35
|
+
class Authorization
|
36
|
+
attr_reader :source
|
37
|
+
|
38
|
+
def initialize(connection: {}, methods: {}, settings: {})
|
39
|
+
@connection_source = connection.with_indifferent_access
|
40
|
+
@source = (connection[:authorization] || {}).with_indifferent_access
|
41
|
+
@methods_source = methods.with_indifferent_access
|
42
|
+
@settings = settings
|
43
|
+
end
|
44
|
+
|
45
|
+
def token_url?
|
46
|
+
source[:token_url].present?
|
47
|
+
end
|
48
|
+
|
49
|
+
def acquire?
|
50
|
+
source[:acquire].present?
|
51
|
+
end
|
52
|
+
|
53
|
+
def refresh?
|
54
|
+
source[:refresh].present?
|
55
|
+
end
|
56
|
+
|
57
|
+
def type
|
58
|
+
source[:type]
|
59
|
+
end
|
60
|
+
|
61
|
+
def refresh_on
|
62
|
+
Array.wrap(source[:refresh_on]).compact
|
63
|
+
end
|
64
|
+
|
65
|
+
def detect_on
|
66
|
+
Array.wrap(source[:detect_on]).compact
|
67
|
+
end
|
68
|
+
|
69
|
+
def client_id(settings = {})
|
70
|
+
client_id = source[:client_id]
|
71
|
+
|
72
|
+
if client_id.is_a?(Proc)
|
73
|
+
Dsl::WithDsl.execute(settings.with_indifferent_access, &client_id)
|
74
|
+
else
|
75
|
+
client_id
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def client_secret(settings = {})
|
80
|
+
client_secret_source = source[:client_secret]
|
81
|
+
|
82
|
+
if client_secret_source.is_a?(Proc)
|
83
|
+
Dsl::WithDsl.execute(settings.with_indifferent_access, &client_secret_source)
|
84
|
+
else
|
85
|
+
client_secret_source
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def authorization_url(settings = {})
|
90
|
+
source[:authorization_url]&.call(settings.with_indifferent_access)
|
91
|
+
end
|
92
|
+
|
93
|
+
def token_url(settings = {})
|
94
|
+
source[:token_url]&.call(settings.with_indifferent_access)
|
95
|
+
end
|
96
|
+
|
97
|
+
def acquire(settings = {}, oauth2_code = nil, redirect_url = nil)
|
98
|
+
acquire_proc = source[:acquire]
|
99
|
+
raise InvalidDefinitionError, "Expect 'acquire' block" unless acquire_proc
|
100
|
+
|
101
|
+
Workato::Connector::Sdk::Operation.new(
|
102
|
+
connection: Connection.new(
|
103
|
+
connection: connection_source.merge(
|
104
|
+
authorization: source.merge(
|
105
|
+
apply: nil
|
106
|
+
)
|
107
|
+
),
|
108
|
+
methods: methods_source,
|
109
|
+
settings: @settings
|
110
|
+
),
|
111
|
+
methods: methods_source,
|
112
|
+
settings: @settings
|
113
|
+
).execute(settings, { auth_code: oauth2_code, redirect_url: redirect_url }) do |connection, input|
|
114
|
+
instance_exec(connection, input[:auth_code], input[:redirect_url], &acquire_proc)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def refresh(settings = {}, refresh_token = nil)
|
119
|
+
refresh_proc = source[:refresh]
|
120
|
+
raise InvalidDefinitionError, "Expect 'refresh' block" unless refresh_proc
|
121
|
+
|
122
|
+
Workato::Connector::Sdk::Operation.new(
|
123
|
+
connection: Connection.new(
|
124
|
+
methods: methods_source,
|
125
|
+
settings: @settings
|
126
|
+
),
|
127
|
+
methods: methods_source,
|
128
|
+
settings: @settings
|
129
|
+
).execute(settings, { refresh_token: refresh_token }) do |connection, input|
|
130
|
+
instance_exec(connection, input[:refresh_token], &refresh_proc)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
attr_reader :connection_source,
|
137
|
+
:methods_source
|
138
|
+
end
|
139
|
+
|
140
|
+
private_constant :Authorization
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -24,9 +24,9 @@ module Workato
|
|
24
24
|
def actions
|
25
25
|
@actions ||= ActionsProxy.new(
|
26
26
|
actions: source[:actions].presence || {},
|
27
|
-
object_definitions: object_definitions,
|
28
27
|
methods: methods_source,
|
29
|
-
|
28
|
+
object_definitions: object_definitions,
|
29
|
+
connection: connection,
|
30
30
|
settings: settings
|
31
31
|
)
|
32
32
|
end
|
@@ -34,7 +34,7 @@ module Workato
|
|
34
34
|
def methods
|
35
35
|
@methods ||= MethodsProxy.new(
|
36
36
|
methods: methods_source,
|
37
|
-
connection:
|
37
|
+
connection: connection,
|
38
38
|
settings: settings
|
39
39
|
)
|
40
40
|
end
|
@@ -45,7 +45,7 @@ module Workato
|
|
45
45
|
execute: source[:test]
|
46
46
|
},
|
47
47
|
methods: methods_source,
|
48
|
-
connection:
|
48
|
+
connection: connection,
|
49
49
|
settings: send(:settings)
|
50
50
|
).execute(settings)
|
51
51
|
end
|
@@ -53,9 +53,9 @@ module Workato
|
|
53
53
|
def triggers
|
54
54
|
@triggers ||= TriggersProxy.new(
|
55
55
|
triggers: source[:triggers].presence || {},
|
56
|
-
object_definitions: object_definitions,
|
57
56
|
methods: methods_source,
|
58
|
-
connection:
|
57
|
+
connection: connection,
|
58
|
+
object_definitions: object_definitions,
|
59
59
|
settings: settings
|
60
60
|
)
|
61
61
|
end
|
@@ -64,7 +64,7 @@ module Workato
|
|
64
64
|
@object_definitions ||= ObjectDefinitions.new(
|
65
65
|
object_definitions: source[:object_definitions].presence || {},
|
66
66
|
methods: methods_source,
|
67
|
-
connection:
|
67
|
+
connection: connection,
|
68
68
|
settings: settings
|
69
69
|
)
|
70
70
|
end
|
@@ -72,6 +72,14 @@ module Workato
|
|
72
72
|
def pick_lists
|
73
73
|
@pick_lists ||= PickListsProxy.new(
|
74
74
|
pick_lists: source[:pick_lists].presence || {},
|
75
|
+
methods: methods_source,
|
76
|
+
connection: connection,
|
77
|
+
settings: settings
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def connection
|
82
|
+
@connection ||= Connection.new(
|
75
83
|
methods: methods_source,
|
76
84
|
connection: connection_source,
|
77
85
|
settings: settings
|
@@ -10,23 +10,23 @@ module Workato
|
|
10
10
|
|
11
11
|
def initialize(object_definitions:, connection:, methods:, settings:)
|
12
12
|
@object_definitions_source = object_definitions
|
13
|
-
@
|
13
|
+
@methods_source = methods
|
14
14
|
@connection = connection
|
15
15
|
@settings = settings
|
16
16
|
define_object_definition_methods(object_definitions)
|
17
17
|
end
|
18
18
|
|
19
19
|
def lazy(settings = nil, config_fields = {})
|
20
|
-
|
21
|
-
fields_proc =
|
22
|
-
|
20
|
+
DupHashWithIndifferentAccess.new do |object_definitions, name|
|
21
|
+
fields_proc = object_definitions_source[name][:fields]
|
22
|
+
object_definitions[name] = Action.new(
|
23
23
|
action: {
|
24
24
|
execute: lambda do |connection, input|
|
25
|
-
instance_exec(connection, input,
|
25
|
+
instance_exec(connection, input, object_definitions, &fields_proc)
|
26
26
|
end
|
27
27
|
},
|
28
|
-
methods:
|
29
|
-
connection:
|
28
|
+
methods: methods_source,
|
29
|
+
connection: connection,
|
30
30
|
settings: @settings
|
31
31
|
).execute(settings, config_fields)
|
32
32
|
end
|
@@ -34,10 +34,10 @@ module Workato
|
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
attr_reader :
|
37
|
+
attr_reader :methods_source,
|
38
38
|
:connection,
|
39
|
-
:
|
40
|
-
:
|
39
|
+
:settings,
|
40
|
+
:object_definitions_source
|
41
41
|
|
42
42
|
def define_object_definition_methods(object_definitions)
|
43
43
|
object_definitions.each do |(object, _definition)|
|
@@ -16,21 +16,23 @@ module Workato
|
|
16
16
|
|
17
17
|
cattr_accessor :on_settings_updated
|
18
18
|
|
19
|
-
def initialize(
|
19
|
+
def initialize(connection:, operation: {}, methods: {}, settings: {}, object_definitions: nil)
|
20
|
+
@connection = connection
|
20
21
|
@settings = settings.with_indifferent_access
|
21
22
|
@operation = operation.with_indifferent_access
|
22
|
-
@connection = connection.with_indifferent_access
|
23
23
|
@_methods = methods.with_indifferent_access
|
24
24
|
@object_definitions = object_definitions
|
25
25
|
end
|
26
26
|
|
27
|
-
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [],
|
27
|
+
def execute(settings = nil, input = {}, extended_input_schema = [], extended_output_schema = [], continue = {},
|
28
|
+
&block)
|
28
29
|
@settings = settings.with_indifferent_access if settings # is being used in request for refresh tokens
|
29
30
|
request_or_result = instance_exec(
|
30
31
|
@settings.with_indifferent_access, # a copy of settings hash is being used in executable blocks
|
31
32
|
input.with_indifferent_access,
|
32
33
|
Array.wrap(extended_input_schema).map(&:with_indifferent_access),
|
33
34
|
Array.wrap(extended_output_schema).map(&:with_indifferent_access),
|
35
|
+
continue.with_indifferent_access,
|
34
36
|
&block
|
35
37
|
)
|
36
38
|
resolve_request(request_or_result)
|
@@ -69,9 +71,9 @@ module Workato
|
|
69
71
|
def refresh_authorization!(http_code, http_body, exception, settings = {})
|
70
72
|
return unless refresh_auth?(http_code, http_body, exception)
|
71
73
|
|
72
|
-
new_settings = if /oauth2/i =~ connection
|
74
|
+
new_settings = if /oauth2/i =~ connection.authorization.type
|
73
75
|
refresh_oauth2_token(settings)
|
74
|
-
elsif connection
|
76
|
+
elsif connection.authorization.acquire?
|
75
77
|
acquire_token(settings)
|
76
78
|
end
|
77
79
|
return unless new_settings
|
@@ -132,7 +134,7 @@ module Workato
|
|
132
134
|
end
|
133
135
|
|
134
136
|
def refresh_auth?(http_code, http_body, exception)
|
135
|
-
refresh_on =
|
137
|
+
refresh_on = connection.authorization.refresh_on
|
136
138
|
refresh_on.blank? || refresh_on.any? do |pattern|
|
137
139
|
pattern.is_a?(::Integer) && pattern == http_code ||
|
138
140
|
pattern === exception&.to_s ||
|
@@ -141,48 +143,26 @@ module Workato
|
|
141
143
|
end
|
142
144
|
|
143
145
|
def acquire_token(settings)
|
144
|
-
|
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)
|
146
|
+
connection.authorization.acquire(settings)
|
158
147
|
end
|
159
148
|
|
160
149
|
def refresh_oauth2_token_using_refresh(settings)
|
161
|
-
|
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
|
-
|
150
|
+
new_tokens, new_settings = connection.authorization.refresh(settings, settings[:refresh_token])
|
171
151
|
new_tokens.with_indifferent_access.merge(new_settings || {})
|
172
152
|
end
|
173
153
|
|
174
154
|
def refresh_oauth2_token_using_token_url(settings)
|
175
155
|
if settings[:refresh_token].blank?
|
176
|
-
raise NotImplementedError, '
|
177
|
-
'Use
|
156
|
+
raise NotImplementedError, 'refresh_token is empty. ' \
|
157
|
+
'Use workato oauth2 command to acquire access_token and refresh_token'
|
178
158
|
end
|
179
159
|
|
180
160
|
response = RestClient::Request.execute(
|
181
|
-
url: connection
|
161
|
+
url: connection.authorization.token_url(settings),
|
182
162
|
method: :post,
|
183
163
|
payload: {
|
184
|
-
client_id: connection
|
185
|
-
client_secret: connection
|
164
|
+
client_id: connection.authorization.client_id(settings),
|
165
|
+
client_secret: connection.authorization.client_secret(settings),
|
186
166
|
grant_type: :refresh_token,
|
187
167
|
refresh_token: settings[:refresh_token]
|
188
168
|
},
|
@@ -198,9 +178,9 @@ module Workato
|
|
198
178
|
end
|
199
179
|
|
200
180
|
def refresh_oauth2_token(settings)
|
201
|
-
if connection
|
181
|
+
if connection.authorization.refresh?
|
202
182
|
refresh_oauth2_token_using_refresh(settings)
|
203
|
-
elsif connection
|
183
|
+
elsif connection.authorization.token_url?
|
204
184
|
refresh_oauth2_token_using_token_url(settings)
|
205
185
|
else
|
206
186
|
raise InvalidDefinitionError, "'refresh' block or 'token_url' is required for refreshing the token"
|
@@ -15,13 +15,13 @@ module Workato
|
|
15
15
|
class Request < SimpleDelegator
|
16
16
|
using BlockInvocationRefinements
|
17
17
|
|
18
|
-
def initialize(uri, method: 'GET',
|
18
|
+
def initialize(uri, method: 'GET', settings: {}, connection: nil, action: nil)
|
19
19
|
super(nil)
|
20
20
|
@uri = uri
|
21
|
-
@authorization = (connection[:authorization] || {}).with_indifferent_access
|
22
|
-
@settings = settings
|
23
|
-
@base_uri = connection[:base_uri]&.call(settings.with_indifferent_access)
|
24
21
|
@method = method
|
22
|
+
@settings = settings
|
23
|
+
@authorization = connection&.authorization
|
24
|
+
@base_uri = connection&.base_uri(settings)
|
25
25
|
@action = action
|
26
26
|
@headers = {}
|
27
27
|
@case_sensitive_headers = {}
|
@@ -321,7 +321,9 @@ module Workato
|
|
321
321
|
end
|
322
322
|
|
323
323
|
def detect_error!(response)
|
324
|
-
|
324
|
+
return unless @authorization
|
325
|
+
|
326
|
+
error_patterns = @authorization.detect_on
|
325
327
|
return unless error_patterns.any? { |pattern| pattern === response rescue false }
|
326
328
|
|
327
329
|
Kernel.raise(CustomRequestError, response.to_s)
|
@@ -357,13 +359,15 @@ module Workato
|
|
357
359
|
end
|
358
360
|
|
359
361
|
def authorized
|
360
|
-
|
362
|
+
return yield unless @authorization
|
363
|
+
|
364
|
+
apply = @authorization.source[:apply] || @authorization.source[:credentials]
|
361
365
|
return yield unless apply
|
362
366
|
|
363
367
|
first = true
|
364
368
|
begin
|
365
369
|
settings = @settings.with_indifferent_access
|
366
|
-
if /oauth2/i =~ @authorization
|
370
|
+
if /oauth2/i =~ @authorization.type
|
367
371
|
instance_exec(settings, settings[:access_token], @auth_type, &apply)
|
368
372
|
else
|
369
373
|
instance_exec(settings, @auth_type, &apply)
|
@@ -45,6 +45,8 @@ module Workato
|
|
45
45
|
begin
|
46
46
|
@encrypted = false
|
47
47
|
read_plain_file
|
48
|
+
rescue KeyError
|
49
|
+
raise
|
48
50
|
rescue StandardError
|
49
51
|
@encrypted = true
|
50
52
|
read_encrypted_file
|
@@ -76,7 +78,7 @@ module Workato
|
|
76
78
|
YAML.safe_load(f.read, [::Symbol]).to_hash.with_indifferent_access
|
77
79
|
end
|
78
80
|
|
79
|
-
name ? all_settings.fetch(name) : all_settings
|
81
|
+
(name ? all_settings.fetch(name) : all_settings) || {}
|
80
82
|
end
|
81
83
|
|
82
84
|
def update_plain_file(new_settings)
|
@@ -93,7 +95,7 @@ module Workato
|
|
93
95
|
def read_encrypted_file
|
94
96
|
all_settings = encrypted_configuration.config.with_indifferent_access
|
95
97
|
|
96
|
-
name ? all_settings.fetch(name) : all_settings
|
98
|
+
(name ? all_settings.fetch(name) : all_settings) || {}
|
97
99
|
end
|
98
100
|
|
99
101
|
def update_encrypted_file(new_settings)
|
@@ -106,7 +108,8 @@ module Workato
|
|
106
108
|
|
107
109
|
def merge_settings(all_settings, new_settings)
|
108
110
|
if name
|
109
|
-
all_settings[name]
|
111
|
+
all_settings[name] ||= {}
|
112
|
+
all_settings[name].merge!(new_settings)
|
110
113
|
else
|
111
114
|
all_settings.merge!(new_settings)
|
112
115
|
end
|
@@ -43,6 +43,7 @@ require_relative '../extension/time'
|
|
43
43
|
|
44
44
|
require_relative './sdk/account_properties'
|
45
45
|
require_relative './sdk/action'
|
46
|
+
require_relative './sdk/connection'
|
46
47
|
require_relative './sdk/connector'
|
47
48
|
require_relative './sdk/dsl'
|
48
49
|
require_relative './sdk/errors'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Workato
|
4
|
+
module Web
|
5
|
+
class App
|
6
|
+
CODE_PATH = '/code'
|
7
|
+
CALLBACK_PATH = '/oauth/callback'
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
req = Rack::Request.new(env)
|
11
|
+
case req.path_info
|
12
|
+
when /#{CODE_PATH}/
|
13
|
+
[200, { 'Content-Type' => 'text/plain' }, [@code.to_s]]
|
14
|
+
when /#{CALLBACK_PATH}/
|
15
|
+
@code = req.params['code']
|
16
|
+
[200, { 'Content-Type' => 'text/plain' }, ['We stored response code. Now you can close the browser window']]
|
17
|
+
else
|
18
|
+
[404, { 'Content-Type' => 'text/plain' }, ['404: Not Found']]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -11,7 +11,7 @@ RSpec.describe 'actions/<%= name %>', :vcr do
|
|
11
11
|
let(:action) { connector.actions.<%= name %> }
|
12
12
|
|
13
13
|
describe 'execute' do
|
14
|
-
subject(:output) { action.execute(settings, input, extended_input_schema, extended_output_schema) }
|
14
|
+
subject(:output) { action.execute(settings, input, extended_input_schema, extended_output_schema, continue) }
|
15
15
|
|
16
16
|
pending 'add some examples'
|
17
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workato-connector-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pavel Abolmasov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.4.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: em-http-request
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: gyoku
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - '='
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: 1.5.6
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: launchy
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2.0'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: loofah
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +150,34 @@ dependencies:
|
|
122
150
|
- - '='
|
123
151
|
- !ruby/object:Gem::Version
|
124
152
|
version: 1.10.10
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: oauth2
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '1.0'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '1.0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rack
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '2.0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '2.0'
|
125
181
|
- !ruby/object:Gem::Dependency
|
126
182
|
name: rest-client
|
127
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +234,20 @@ dependencies:
|
|
178
234
|
- - "~>"
|
179
235
|
- !ruby/object:Gem::Version
|
180
236
|
version: '1.0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: webrick
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - "~>"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '1.0'
|
244
|
+
type: :runtime
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - "~>"
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '1.0'
|
181
251
|
- !ruby/object:Gem::Dependency
|
182
252
|
name: bundler
|
183
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -294,11 +364,13 @@ files:
|
|
294
364
|
- lib/workato/cli/generators/connector_generator.rb
|
295
365
|
- lib/workato/cli/generators/master_key_generator.rb
|
296
366
|
- lib/workato/cli/main.rb
|
367
|
+
- lib/workato/cli/oauth2_command.rb
|
297
368
|
- lib/workato/cli/push_command.rb
|
298
369
|
- lib/workato/connector/sdk.rb
|
299
370
|
- lib/workato/connector/sdk/account_properties.rb
|
300
371
|
- lib/workato/connector/sdk/action.rb
|
301
372
|
- lib/workato/connector/sdk/block_invocation_refinements.rb
|
373
|
+
- lib/workato/connector/sdk/connection.rb
|
302
374
|
- lib/workato/connector/sdk/connector.rb
|
303
375
|
- lib/workato/connector/sdk/dsl.rb
|
304
376
|
- lib/workato/connector/sdk/dsl/account_property.rb
|
@@ -336,6 +408,7 @@ files:
|
|
336
408
|
- lib/workato/extension/time.rb
|
337
409
|
- lib/workato/testing/vcr_encrypted_cassette_serializer.rb
|
338
410
|
- lib/workato/testing/vcr_multipart_body_matcher.rb
|
411
|
+
- lib/workato/web/app.rb
|
339
412
|
- templates/.rspec.erb
|
340
413
|
- templates/Gemfile.erb
|
341
414
|
- templates/connector.rb.erb
|
@@ -369,7 +442,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
369
442
|
- !ruby/object:Gem::Version
|
370
443
|
version: '0'
|
371
444
|
requirements: []
|
372
|
-
|
445
|
+
rubyforge_project:
|
446
|
+
rubygems_version: 2.6.14.4
|
373
447
|
signing_key:
|
374
448
|
specification_version: 4
|
375
449
|
summary: Gem for running adapter's code outside Workato infrastructure
|