setsuzoku 0.10.12 → 0.11.8
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 +4 -4
- data/Gemfile.lock +5 -5
- data/lib/setsuzoku/api_response.rb +1 -1
- data/lib/setsuzoku/api_strategy.rb +2 -2
- data/lib/setsuzoku/credential.rb +6 -0
- data/lib/setsuzoku/rspec/dynamic_spec_helper.rb +10 -7
- data/lib/setsuzoku/service/web_service/api_strategies/rest_strategy.rb +14 -9
- data/lib/setsuzoku/service/web_service/api_strategy.rb +3 -1
- data/lib/setsuzoku/service/web_service/auth_strategies/o_auth_strategy.rb +21 -29
- data/lib/setsuzoku/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ce2db23193b6cfc30d0286a655c29686d0c4a65b9f11d102fb4626354730c00
|
4
|
+
data.tar.gz: 2ed86eb0454c3c2576bca8ab2e7b5103d0ebd3cb59eaa055cbcaf59fe20c4a5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c119e54f7b79cfcde12566681a236af85c0d8b06a06b3fe58087d52663477475f54b28077134b4074293d073a0ff058a9e8d88ba1faccde2db904012d8e8c85f
|
7
|
+
data.tar.gz: 4d1e2288730612ef2aa9845f642d1473d2b518e7d29561e27fffe68ac11fbba2c61e9b4052a0666ba03492b451236f0274593b687a3fd11ee7ce160f2714868f
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
setsuzoku (0.
|
4
|
+
setsuzoku (0.11.8)
|
5
5
|
activesupport (~> 5.0)
|
6
6
|
faraday (~> 0.11)
|
7
7
|
httparty (~> 0.16.4)
|
@@ -18,7 +18,7 @@ GEM
|
|
18
18
|
tzinfo (~> 1.1)
|
19
19
|
addressable (2.7.0)
|
20
20
|
public_suffix (>= 2.0.2, < 5.0)
|
21
|
-
concurrent-ruby (1.1.
|
21
|
+
concurrent-ruby (1.1.7)
|
22
22
|
crack (0.4.3)
|
23
23
|
safe_yaml (~> 1.0.0)
|
24
24
|
diff-lcs (1.4.2)
|
@@ -28,7 +28,7 @@ GEM
|
|
28
28
|
httparty (0.16.4)
|
29
29
|
mime-types (~> 3.0)
|
30
30
|
multi_xml (>= 0.5.2)
|
31
|
-
i18n (1.8.
|
31
|
+
i18n (1.8.5)
|
32
32
|
concurrent-ruby (~> 1.0)
|
33
33
|
mime-types (3.3.1)
|
34
34
|
mime-types-data (~> 3.2015)
|
@@ -37,7 +37,7 @@ GEM
|
|
37
37
|
minitest (5.14.1)
|
38
38
|
multi_xml (0.6.0)
|
39
39
|
multipart-post (2.1.1)
|
40
|
-
nokogiri (1.10.
|
40
|
+
nokogiri (1.10.10)
|
41
41
|
mini_portile2 (~> 2.4.0)
|
42
42
|
public_suffix (4.0.5)
|
43
43
|
rake (10.5.0)
|
@@ -57,7 +57,7 @@ GEM
|
|
57
57
|
safe_yaml (1.0.5)
|
58
58
|
sorbet (0.5.5675)
|
59
59
|
sorbet-static (= 0.5.5675)
|
60
|
-
sorbet-runtime (0.5.
|
60
|
+
sorbet-runtime (0.5.5878)
|
61
61
|
sorbet-static (0.5.5675-universal-darwin-14)
|
62
62
|
thread_safe (0.3.6)
|
63
63
|
tzinfo (1.2.7)
|
@@ -4,7 +4,7 @@
|
|
4
4
|
module Setsuzoku
|
5
5
|
# The generic API response object that all API responses should return.
|
6
6
|
class ApiResponse < T::Struct
|
7
|
-
prop :data, T.nilable(T
|
7
|
+
prop :data, T.nilable(T.untyped), default: {}
|
8
8
|
prop :success, T::Boolean, default: false
|
9
9
|
prop :error, T.nilable(String), default: nil
|
10
10
|
end
|
@@ -80,7 +80,7 @@ module Setsuzoku
|
|
80
80
|
self.external_api_handler.call_external_api_wrapper(plugin: self.plugin, request: request, action_details: action_details) do
|
81
81
|
begin
|
82
82
|
# raise if the token is invalid and needs refreshed, but don't raise if we are trying to get a refresh token
|
83
|
-
raise Setsuzoku::Exception::InvalidAuthCredentials.new unless (
|
83
|
+
raise Setsuzoku::Exception::InvalidAuthCredentials.new unless (strategy == :auth || self.auth_strategy.auth_credential_valid?)
|
84
84
|
raw_response = self.perform_external_call(request: request, action_details: action_details, **options)
|
85
85
|
formatted_response = self.parse_response(response: raw_response, response_type: action_details[:actions][request.action][:response_type])
|
86
86
|
success = true
|
@@ -118,7 +118,7 @@ module Setsuzoku
|
|
118
118
|
# @param options [Hash] the parsing options. Generally the response_type. e.g. :xml, :json
|
119
119
|
#
|
120
120
|
# @return [Hash] the parsed hash of the response object.
|
121
|
-
sig { abstract.params(response: T.untyped, options: T.untyped).returns(T
|
121
|
+
sig { abstract.params(response: T.untyped, options: T.untyped).returns(T.untyped) }
|
122
122
|
def parse_response(response:, **options); end
|
123
123
|
end
|
124
124
|
end
|
data/lib/setsuzoku/credential.rb
CHANGED
@@ -14,6 +14,12 @@ module Setsuzoku
|
|
14
14
|
sig { abstract.returns(Struct) }
|
15
15
|
def self.stub_credential; end
|
16
16
|
|
17
|
+
# The status of the credential.
|
18
|
+
#
|
19
|
+
# @return [Hash] the status of the credential.
|
20
|
+
sig { abstract.returns(String) }
|
21
|
+
def status; end
|
22
|
+
|
17
23
|
# A settings object for the credential.
|
18
24
|
#
|
19
25
|
# @return [Hash] the settings for the credential.
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'active_support/core_ext/class/subclasses'
|
4
4
|
require 'active_support/inflector/methods'
|
5
|
+
require 'faraday'
|
6
|
+
|
5
7
|
module Setsuzoku
|
6
8
|
module DynamicSpecHelper
|
7
9
|
|
@@ -150,20 +152,21 @@ module Setsuzoku
|
|
150
152
|
stub.each do |action_name, props|
|
151
153
|
props.each do |propz|
|
152
154
|
plugin.api_strategy.current_action = action_name
|
153
|
-
default_headers = plugin.api_strategy.request_options(propz[:request_format])[:headers] || { '
|
155
|
+
default_headers = plugin.api_strategy.request_options(propz[:request_format])[:headers] || { 'Content-Type' => "application/#{propz[:request_format]}" }
|
154
156
|
if plugin.auth_strategy.is_a?(Setsuzoku::Service::WebService::AuthStrategies::BasicAuthStrategy)
|
155
157
|
basic_auth = plugin.api_strategy.request_options(propz[:request_format])[:basic_auth]
|
156
158
|
auth_header = { 'Authorization' => "Basic #{Base64.encode64("#{basic_auth[:username]}:#{basic_auth[:password]}").gsub("\n", '')}" }
|
157
|
-
|
159
|
+
elsif plugin.auth_strategy.is_a?(Setsuzoku::Service::WebService::AuthStrategies::OAuthStrategy)
|
160
|
+
auth_header = { 'Authorization' => "Bearer #{plugin.api_strategy.request_options(propz[:request_format])[:token]}" }
|
158
161
|
end
|
162
|
+
default_headers.merge!(auth_header) if auth_header
|
159
163
|
headers = propz[:headers] ? [propz[:headers]] : [default_headers]
|
160
164
|
stub_directory ||= "#{plugin.class.plugin_namespace}/#{provider}"
|
165
|
+
|
161
166
|
headers.each do |header|
|
162
|
-
header =
|
163
|
-
|
164
|
-
|
165
|
-
'User-Agent'=>'Ruby'
|
166
|
-
}.merge(header.deep_stringify_keys)
|
167
|
+
header = Faraday.new.headers
|
168
|
+
.merge({'Accept'=>'*/*','Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'})
|
169
|
+
.merge(header.deep_stringify_keys)
|
167
170
|
|
168
171
|
if propz[:stub_data]
|
169
172
|
# we have specified specific stub data for this action
|
@@ -33,7 +33,7 @@ module Setsuzoku
|
|
33
33
|
# media_type - 'json'
|
34
34
|
#
|
35
35
|
# @return [Hash] the parsed response object.
|
36
|
-
sig { override.params(request:
|
36
|
+
sig { override.params(request: RestAPIRequest, action_details: T::Hash[T.untyped, T.untyped], options: T.untyped).returns(Faraday::Response) }
|
37
37
|
def perform_external_call(request:, action_details:, **options)
|
38
38
|
request_properties = self.get_request_properties(action_name: request.action, action_details: action_details, req_params: request.body)
|
39
39
|
request_options = self.request_options(request_properties[:request_format], action_details[:actions][request.action])
|
@@ -43,11 +43,14 @@ module Setsuzoku
|
|
43
43
|
@faraday = Faraday.new(url: request_properties[:formatted_full_url], request: { params_encoder: Faraday::FlatParamsEncoder }) do |faraday|
|
44
44
|
faraday.request(:multipart) if options[:attachments].present?
|
45
45
|
faraday.request(:url_encoded)
|
46
|
-
# faraday.
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
#TODO: change these to faraday = self.auth_strategy.set_authorization!(request: faraday)
|
47
|
+
unless request.without_headers
|
48
|
+
if request_options[:token]
|
49
|
+
faraday.authorization(:Bearer, request_options[:token])
|
50
|
+
elsif request_options[:basic_auth]
|
51
|
+
faraday.request(:basic_auth, request_options[:basic_auth][:username], request_options[:basic_auth][:password])
|
52
|
+
end
|
53
|
+
end
|
51
54
|
faraday.adapter Faraday.default_adapter
|
52
55
|
end
|
53
56
|
|
@@ -60,7 +63,11 @@ module Setsuzoku
|
|
60
63
|
req.body = payload
|
61
64
|
end
|
62
65
|
else
|
63
|
-
|
66
|
+
if request.without_headers
|
67
|
+
@faraday.headers = {}
|
68
|
+
elsif request_options[:headers]
|
69
|
+
@faraday.headers = (@faraday.headers || {}).merge(request_options[:headers])
|
70
|
+
end
|
64
71
|
resp = @faraday.send(request_properties[:request_method], request_properties[:formatted_full_url], full_request)
|
65
72
|
end
|
66
73
|
resp
|
@@ -81,7 +88,6 @@ module Setsuzoku
|
|
81
88
|
request_method = request_method.downcase.to_sym
|
82
89
|
request_format = action[:request_type]
|
83
90
|
response_format = action[:response_type]
|
84
|
-
token = action[:token]
|
85
91
|
stub_data = action[:stub_data] if for_stub
|
86
92
|
full_url = url + endpoint
|
87
93
|
formatted_full_url, req_params = self.replace_dynamic_vars(full_url: full_url, req_params: req_params)
|
@@ -93,7 +99,6 @@ module Setsuzoku
|
|
93
99
|
formatted_full_url: formatted_full_url,
|
94
100
|
req_params: req_params,
|
95
101
|
stub_data: stub_data,
|
96
|
-
token: token
|
97
102
|
}
|
98
103
|
end
|
99
104
|
|
@@ -72,13 +72,15 @@ module Setsuzoku
|
|
72
72
|
# @param options [Hash] the parsing options. Generally the response_type. e.g. :xml, :json
|
73
73
|
#
|
74
74
|
# @return [Hash] the parsed hash of the response object.
|
75
|
-
sig { override.params(response: Faraday::Response, options: T.untyped).returns(T
|
75
|
+
sig { override.params(response: Faraday::Response, options: T.untyped).returns(T.untyped) }
|
76
76
|
def parse_response(response:, **options)
|
77
77
|
case options[:response_type]
|
78
78
|
when :json
|
79
79
|
JSON.parse(response.body).deep_symbolize_keys
|
80
80
|
when :xml
|
81
81
|
convert_xml_to_hash(response.body)
|
82
|
+
when :html
|
83
|
+
response.body
|
82
84
|
else
|
83
85
|
JSON.parse(response.body).deep_symbolize_keys
|
84
86
|
end
|
@@ -31,9 +31,7 @@ module Setsuzoku
|
|
31
31
|
sig { override.returns(T::Hash[Symbol, T.untyped]) }
|
32
32
|
def auth_headers
|
33
33
|
{
|
34
|
-
|
35
|
-
'Authorization': "Bearer #{self.credential.token}"
|
36
|
-
}
|
34
|
+
token: self.credential.token
|
37
35
|
}
|
38
36
|
end
|
39
37
|
|
@@ -73,7 +71,7 @@ module Setsuzoku
|
|
73
71
|
# @return [Boolean] true if the token is invalid.
|
74
72
|
sig { returns(T::Boolean) }
|
75
73
|
def token_is_invalid?
|
76
|
-
active = self.credential.
|
74
|
+
active = self.credential.status != 'disabled'
|
77
75
|
active && !self.credential.expires_on.blank? &&
|
78
76
|
!self.credential.refresh_token.blank? &&
|
79
77
|
(self.credential.expires_on < refresh_before_expiration_time)
|
@@ -112,38 +110,32 @@ module Setsuzoku
|
|
112
110
|
sig { params(body: T::Hash[Symbol, String], action: Symbol).void }
|
113
111
|
def get_token!(body, action)
|
114
112
|
success = false
|
115
|
-
request = self.api_strategy.request_class.new(action: action, body: body)
|
113
|
+
request = self.api_strategy.request_class.new(action: action, body: body, without_headers: true)
|
116
114
|
|
117
115
|
resp = self.api_strategy.call_external_api(request: request, strategy: :auth)
|
118
116
|
|
117
|
+
attrs = {}
|
119
118
|
if resp.data && resp.data[:access_token]
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
end
|
128
|
-
|
129
|
-
self.plugin.set_credential_fields!(resp) if self.plugin.respond_to?(:set_credential_fields!)
|
130
|
-
|
131
|
-
#TODO: figure out a better way to do this when we add other integrations...
|
132
|
-
#
|
133
|
-
# if self.is_a?(FacebookIntegration)
|
134
|
-
# resp = self.exchange_for_long_lived_token
|
135
|
-
# if resp && resp.data['access_token']
|
136
|
-
# self.token = resp.data['access_token']
|
137
|
-
# self.refresh_token = resp.data['access_token']
|
138
|
-
# self.expires_on = 59.days.from_now
|
139
|
-
# end
|
140
|
-
# end
|
119
|
+
attrs[:status] = 'active'
|
120
|
+
attrs[:token] = resp.data[:access_token]
|
121
|
+
attrs[:refresh_token] = resp.data[:refresh_token] if resp.data.key?(:refresh_token)
|
122
|
+
attrs[:expires_on] = resp.data[:expires_in].to_i.seconds.from_now if resp.data[:expires_in]
|
123
|
+
|
124
|
+
plugin_attrs = self.plugin.credential_fields_to_update(resp) if self.plugin.respond_to?(:credential_fields_to_update)
|
125
|
+
attrs.merge!(plugin_attrs)
|
141
126
|
else
|
142
|
-
|
127
|
+
attrs[:status] = 'error'
|
143
128
|
end
|
144
129
|
|
145
|
-
|
146
|
-
|
130
|
+
# Only save Setsuzoku known fields, and any additional attributes the plugin specifies
|
131
|
+
# in credential_fields_to_update.
|
132
|
+
if self.credential.respond_to?(:"update_columns")
|
133
|
+
# we issue an update_columns instead of a save/update_attributes
|
134
|
+
# so as to only mutate these attributes
|
135
|
+
# and not any other fields that may have been set for the credential
|
136
|
+
save = self.credential.update_columns(attrs)
|
137
|
+
self.credential.touch if save && self.credential.respond_to?(:"touch")
|
138
|
+
save && resp.success
|
147
139
|
else
|
148
140
|
resp.success
|
149
141
|
end
|
data/lib/setsuzoku/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: setsuzoku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Stadtler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|