setsuzoku 0.10.12 → 0.11.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|