sfmc-fuelsdk-ruby 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +29 -1
- data/lib/marketingcloudsdk/client.rb +69 -22
- data/lib/marketingcloudsdk/version.rb +1 -1
- data/spec/client_spec.rb +286 -88
- data/spec/public_or_web_integration_credentials.rb.template +12 -0
- metadata +13 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6d1e7835b46241d74415cfc71fcf04898d24c36b4d7e02ecc2c79c0b4b43851
|
4
|
+
data.tar.gz: 6e49a53e6a97bda143d6cae5fb335f50dc793ea0da967c4236f69874137e7f17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7f5558179e22d3acf72b562b6ea219f1ffea55946ccab4bd2108e2e471f35102131113c6e4e58ad69801281e24d02a5e174006193ba018d26a14df79c60ec2a
|
7
|
+
data.tar.gz: aef480e9c3218532d934d69b9204b71822e7d2ee6c4a2eece74211bf8442196caa241328b43229a6e241b6baabd7130ca7104ace67d9fdd14632f7367deeeca1
|
@@ -0,0 +1,39 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Describe the issue you found
|
4
|
+
title: "[BUG]"
|
5
|
+
labels: bug
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Describe the bug**
|
11
|
+
A clear and concise description of what the bug is.
|
12
|
+
|
13
|
+
**To Reproduce**
|
14
|
+
Steps to reproduce the behavior.
|
15
|
+
|
16
|
+
**Expected behavior**
|
17
|
+
A clear and concise description of what you expected to happen.
|
18
|
+
|
19
|
+
**Screenshots**
|
20
|
+
If applicable, add screenshots to help explain your problem.
|
21
|
+
|
22
|
+
**Code snippet**
|
23
|
+
A code snippet that demonstrates the issue or a link to a code repository the developers can easily pull down to recreate the issue locally.
|
24
|
+
|
25
|
+
Note: Because the developers need to copy and paste the code snippet, including a code snippet as a media file (e.g. gif) is not sufficient.
|
26
|
+
|
27
|
+
|
28
|
+
**Environment**
|
29
|
+
- SDK Version [e.g. 1.2.0]
|
30
|
+
- Ruby version
|
31
|
+
|
32
|
+
**The bug has the severity**
|
33
|
+
- [ ] Critical: The defect affects critical functionality or critical data. It does not have a workaround.
|
34
|
+
- [ ] Major: The defect affects major functionality or major data. It has a workaround but is not obvious and is difficult.
|
35
|
+
- [ ] Minor: The defect affects minor functionality or non-critical data. It has an easy workaround.
|
36
|
+
- [ ] Trivial: The defect does not affect functionality or data. It does not even need a workaround. It does not impact productivity or efficiency. It is merely an inconvenience.
|
37
|
+
|
38
|
+
**Additional context**
|
39
|
+
Add any other context about the problem here.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Suggest an idea for this project
|
4
|
+
title: "[Enhancement]"
|
5
|
+
labels: enhancement
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Is your feature request related to a problem? Please describe**
|
11
|
+
A clear and concise description of what the problem is.
|
12
|
+
|
13
|
+
**Describe the solution you'd like**
|
14
|
+
A clear and concise description of what you want to happen.
|
15
|
+
|
16
|
+
**Describe alternatives you've considered**
|
17
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
18
|
+
|
19
|
+
**Additional context**
|
20
|
+
Add any other context or screenshots about the feature request here.
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,6 +6,34 @@ ExactTarget Fuel SDK / SalesforceMarektingCloudSDK for Ruby
|
|
6
6
|
## Overview ##
|
7
7
|
The Fuel SDK for Ruby provides easy access to ExactTarget's Fuel API Family services, including a collection of REST APIs and a SOAP API. These APIs provide access to ExactTarget functionality via common collection types such as array/hash.
|
8
8
|
|
9
|
+
## New Features in Version 1.3.0 ##
|
10
|
+
- **Added Refresh Token support for OAuth2 authentication**
|
11
|
+
- **Added Web/Public App support for OAuth2 authentication**
|
12
|
+
|
13
|
+
More details on Access Tokens for Web/Public Apps can be found [here](https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/access-token-app.htm)
|
14
|
+
|
15
|
+
Example of instantiating the Client class:
|
16
|
+
|
17
|
+
```
|
18
|
+
myclient = MarketingCloudSDK::Client.new({
|
19
|
+
'client' => {
|
20
|
+
'id' => '<CLIENT_ID>',
|
21
|
+
'secret' => '<CLIENT_SECRET>',
|
22
|
+
'request_token_url' => '<AUTH TENANT SPECIFIC ENDPOINT>',
|
23
|
+
'soap_endpoint' => '<SOAP TENANT SPECIFIC ENDPOINT>',
|
24
|
+
'base_api_url' => '<REST TENANT SPECIFIC ENDPOINT>',
|
25
|
+
'use_oAuth2_authentication' => true,
|
26
|
+
'account_id' => <TARGET_ACCOUNT_ID>,
|
27
|
+
'scope' => '<PERMISSION_LIST>',
|
28
|
+
'application_type' => '<APPLICATION_TYPE>',
|
29
|
+
'redirect_URI' => '<REDIRECT_URI_FOR_PUBLIC/WEB_APP>',
|
30
|
+
'authorization_code' => '<AUTHORIZATION_CODE_FOR_PUBLIC/WEB_APP>'
|
31
|
+
}
|
32
|
+
})
|
33
|
+
```
|
34
|
+
|
35
|
+
* application_type can have one of the following values: `server`, `public`, `web`. The default value of application_type is `server`.
|
36
|
+
|
9
37
|
|
10
38
|
## New Features in Version 1.2.0 ##
|
11
39
|
- **OAuth2 authentication support** - [More Details](https://developer.salesforce.com/docs/atlas.en-us.mc-app-development.meta/mc-app-development/integration-considerations.htm)
|
@@ -65,7 +93,7 @@ gem build marketingcloudsdk.gemspec
|
|
65
93
|
Install the newly built gem
|
66
94
|
|
67
95
|
```ruby
|
68
|
-
gem install marketingcloudsdk-1.
|
96
|
+
gem install marketingcloudsdk-1.3.0.gem
|
69
97
|
```
|
70
98
|
|
71
99
|
If you have not registered your application or you need to lookup your Application Key or Application Signature values, please go to App Center at [Code@: ExactTarget's Developer Community](http://code.exacttarget.com/appcenter "Code@ App Center").
|
@@ -78,7 +78,7 @@ module MarketingCloudSDK
|
|
78
78
|
class Client
|
79
79
|
attr_accessor :debug, :access_token, :auth_token, :internal_token, :refresh_token,
|
80
80
|
:id, :secret, :signature, :base_api_url, :package_name, :package_folders, :parent_folders, :auth_token_expiration,
|
81
|
-
:request_token_url, :soap_endpoint, :use_oAuth2_authentication, :account_id, :scope
|
81
|
+
:request_token_url, :soap_endpoint, :use_oAuth2_authentication, :account_id, :scope, :application_type, :authorization_code, :redirect_URI
|
82
82
|
|
83
83
|
include MarketingCloudSDK::Soap
|
84
84
|
include MarketingCloudSDK::Rest
|
@@ -86,12 +86,13 @@ module MarketingCloudSDK
|
|
86
86
|
def jwt= encoded_jwt
|
87
87
|
raise 'Require app signature to decode JWT' unless self.signature
|
88
88
|
decoded_jwt = JWT.decode(encoded_jwt, self.signature, true)
|
89
|
+
decoded_jwt_first = decoded_jwt.first
|
89
90
|
|
90
|
-
self.auth_token =
|
91
|
-
self.internal_token =
|
92
|
-
self.refresh_token =
|
93
|
-
self.auth_token_expiration = Time.new +
|
94
|
-
self.package_name =
|
91
|
+
self.auth_token = decoded_jwt_first['request']['user']['oauthToken']
|
92
|
+
self.internal_token = decoded_jwt_first['request']['user']['internalOauthToken']
|
93
|
+
self.refresh_token = decoded_jwt_first['request']['user']['refreshToken']
|
94
|
+
self.auth_token_expiration = Time.new + decoded_jwt_first['request']['user']['expiresIn']
|
95
|
+
self.package_name = decoded_jwt_first['request']['application']['package']
|
95
96
|
end
|
96
97
|
|
97
98
|
def initialize(params={}, debug=false)
|
@@ -108,6 +109,9 @@ module MarketingCloudSDK
|
|
108
109
|
self.use_oAuth2_authentication = client_config["use_oAuth2_authentication"]
|
109
110
|
self.account_id = client_config["account_id"]
|
110
111
|
self.scope = client_config["scope"]
|
112
|
+
self.application_type = client_config["application_type"]
|
113
|
+
self.authorization_code = client_config["authorization_code"]
|
114
|
+
self.redirect_URI = client_config["redirect_URI"]
|
111
115
|
end
|
112
116
|
|
113
117
|
# Set a default value in case no 'client' params is sent
|
@@ -123,6 +127,26 @@ module MarketingCloudSDK
|
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
130
|
+
if application_type.to_s.strip.empty?
|
131
|
+
self.application_type = 'server'
|
132
|
+
end
|
133
|
+
|
134
|
+
if ['web', 'public'].include? application_type
|
135
|
+
if authorization_code.to_s.strip.empty? or redirect_URI.to_s.strip.empty?
|
136
|
+
raise 'authorization_code or redirect_URI is null: For Public/Web Apps, the authorization_code and redirect_URI must be passed when instantiating Client'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if application_type == 'public'
|
141
|
+
if id.to_s.strip.empty?
|
142
|
+
raise 'id is null: id must be passed when instantiating Client'
|
143
|
+
end
|
144
|
+
else
|
145
|
+
if id.to_s.strip.empty? or secret.to_s.strip.empty?
|
146
|
+
raise 'id and secret must pe passed when instantiating Client'
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
126
150
|
self.jwt = params['jwt'] if params['jwt']
|
127
151
|
self.refresh_token = params['refresh_token'] if params['refresh_token']
|
128
152
|
|
@@ -133,7 +157,6 @@ module MarketingCloudSDK
|
|
133
157
|
|
134
158
|
def refresh force=false
|
135
159
|
@refresh_mutex.synchronize do
|
136
|
-
raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)
|
137
160
|
|
138
161
|
if (self.use_oAuth2_authentication == true)
|
139
162
|
self.refreshWithOAuth2(force)
|
@@ -169,43 +192,67 @@ module MarketingCloudSDK
|
|
169
192
|
end
|
170
193
|
|
171
194
|
def refreshWithOAuth2 force=false
|
172
|
-
raise 'Require Client Id and Client Secret to refresh tokens' unless (id && secret)
|
173
195
|
#If we don't already have a token or the token expires within 5 min(300 seconds)
|
174
196
|
if (self.access_token.nil? || Time.new + 300 > self.auth_token_expiration || force) then
|
175
|
-
payload = Hash.new.tap do |h|
|
176
|
-
h['client_id']= id
|
177
|
-
h['client_secret'] = secret
|
178
|
-
h['grant_type'] = 'client_credentials'
|
179
|
-
|
180
|
-
if (not self.account_id.to_s.strip.empty?)then
|
181
|
-
h['account_id'] = account_id
|
182
|
-
end
|
183
197
|
|
184
|
-
|
185
|
-
h['scope'] = scope
|
186
|
-
end
|
187
|
-
end
|
198
|
+
payload = createPayload
|
188
199
|
|
189
200
|
options = Hash.new.tap do |h|
|
190
201
|
h['data'] = payload
|
191
202
|
h['content_type'] = 'application/json'
|
192
203
|
end
|
193
204
|
|
194
|
-
|
205
|
+
auth_endpoint = request_token_url + '/v2/token'
|
195
206
|
|
196
|
-
response = post(
|
207
|
+
response = post(auth_endpoint, options)
|
197
208
|
raise "Unable to refresh token: #{response['message']}" unless response.has_key?('access_token')
|
198
209
|
|
199
210
|
self.access_token = response['access_token']
|
200
211
|
self.auth_token_expiration = Time.new + response['expires_in']
|
201
212
|
self.soap_endpoint = response['soap_instance_url'] + 'service.asmx'
|
202
213
|
self.base_api_url = response['rest_instance_url']
|
214
|
+
|
215
|
+
if response.has_key?('refresh_token')
|
216
|
+
self.refresh_token = response['refresh_token']
|
217
|
+
end
|
218
|
+
|
203
219
|
return true
|
204
220
|
else
|
205
221
|
return false
|
206
222
|
end
|
207
223
|
end
|
208
224
|
|
225
|
+
def createPayload
|
226
|
+
payload = Hash.new.tap do |h|
|
227
|
+
h['client_id'] = id
|
228
|
+
|
229
|
+
if application_type != 'public'
|
230
|
+
h['client_secret'] = secret
|
231
|
+
end
|
232
|
+
|
233
|
+
if !refresh_token.to_s.strip.empty?
|
234
|
+
h['grant_type'] = 'refresh_token'
|
235
|
+
h['refresh_token'] = refresh_token
|
236
|
+
elsif ['web', 'public'].include? application_type
|
237
|
+
h['grant_type'] = 'authorization_code'
|
238
|
+
h['code'] = authorization_code
|
239
|
+
h['redirect_uri'] = redirect_URI
|
240
|
+
else
|
241
|
+
h['grant_type'] = 'client_credentials'
|
242
|
+
end
|
243
|
+
|
244
|
+
unless account_id.to_s.strip.empty?
|
245
|
+
h['account_id'] = account_id
|
246
|
+
end
|
247
|
+
|
248
|
+
unless scope.to_s.strip.empty?
|
249
|
+
h['scope'] = scope
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
payload
|
254
|
+
end
|
255
|
+
|
209
256
|
def refresh!
|
210
257
|
refresh true
|
211
258
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -1,94 +1,208 @@
|
|
1
1
|
require 'spec_helper.rb'
|
2
|
+
require 'public_or_web_integration_credentials'
|
3
|
+
|
4
|
+
def get_test_stub
|
5
|
+
{'client' => {
|
6
|
+
'use_oAuth2_authentication' => true,
|
7
|
+
'id' => 'id',
|
8
|
+
'secret' => 'secret',
|
9
|
+
'request_token_url' => 'request_token_url',
|
10
|
+
'account_id' => 'account_id',
|
11
|
+
'authorization_code' => 'authorization_code',
|
12
|
+
'redirect_URI' => 'redirect_URI'
|
13
|
+
}}
|
14
|
+
end
|
2
15
|
|
3
|
-
describe
|
16
|
+
describe(MarketingCloudSDK::Client) do
|
4
17
|
|
5
18
|
context 'initialized' do
|
6
19
|
|
20
|
+
before(:each) do
|
21
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
22
|
+
end
|
23
|
+
|
7
24
|
it 'with client parameters' do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
expect(client.
|
13
|
-
expect(client.
|
14
|
-
expect(client.
|
25
|
+
test_stub = get_test_stub
|
26
|
+
|
27
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
28
|
+
|
29
|
+
expect(client.use_oAuth2_authentication).to be test_stub['client']['use_oAuth2_authentication']
|
30
|
+
expect(client.id).to eq test_stub['client']['id']
|
31
|
+
expect(client.secret).to eq test_stub['client']['secret']
|
32
|
+
expect(client.account_id).to eq test_stub['client']['account_id']
|
33
|
+
expect(client.request_token_url).to eq test_stub['client']['request_token_url']
|
15
34
|
end
|
16
35
|
|
17
36
|
it 'with debug=true' do
|
18
|
-
client = MarketingCloudSDK::Client.new(
|
37
|
+
client = MarketingCloudSDK::Client.new(get_test_stub, true)
|
38
|
+
|
19
39
|
expect(client.debug).to be true
|
20
40
|
end
|
21
41
|
|
22
42
|
it 'with debug=false' do
|
23
|
-
client = MarketingCloudSDK::Client.new(
|
43
|
+
client = MarketingCloudSDK::Client.new(get_test_stub, false)
|
44
|
+
|
24
45
|
expect(client.debug).to be false
|
25
46
|
end
|
26
47
|
|
27
|
-
it '
|
28
|
-
client = MarketingCloudSDK::Client.new(
|
29
|
-
expect(client.request_token_url).to eq 'fake/url'
|
30
|
-
end
|
48
|
+
it 'with base_api_url set to default value if base_api_url is not set' do
|
49
|
+
client = MarketingCloudSDK::Client.new(get_test_stub)
|
31
50
|
|
32
|
-
it 'sets the base_api_url url to a default if it does not exist' do
|
33
|
-
client = MarketingCloudSDK::Client.new({}, false)
|
34
51
|
expect(client.base_api_url).to eq 'https://www.exacttargetapis.com'
|
35
52
|
end
|
36
53
|
|
37
|
-
it '
|
38
|
-
|
39
|
-
|
54
|
+
it 'with null/blank/empty request_token_url and use_oAuth2_authentication=true should raise exception' do
|
55
|
+
expected_exception = 'request_token_url (Auth TSE) is mandatory when using OAuth2 authentication'
|
56
|
+
|
57
|
+
test_stub = get_test_stub
|
58
|
+
|
59
|
+
[nil, ' ', ''].each do |exception_raiser|
|
60
|
+
test_stub['client']['request_token_url'] = exception_raiser
|
61
|
+
expect { MarketingCloudSDK::Client.new(test_stub) }.to raise_error(expected_exception)
|
62
|
+
end
|
40
63
|
end
|
41
64
|
|
42
|
-
it '
|
43
|
-
client = MarketingCloudSDK::Client.new
|
65
|
+
it 'with SoapClient' do
|
66
|
+
client = MarketingCloudSDK::Client.new(get_test_stub)
|
67
|
+
|
44
68
|
expect(client).to be_kind_of MarketingCloudSDK::Soap
|
45
69
|
end
|
46
70
|
|
47
|
-
it '
|
48
|
-
client = MarketingCloudSDK::Client.new
|
71
|
+
it 'with RestClient' do
|
72
|
+
client = MarketingCloudSDK::Client.new(get_test_stub)
|
73
|
+
|
74
|
+
expect(client).to be_kind_of MarketingCloudSDK::Rest
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'with wsdl set to default value if not set in params' do
|
78
|
+
client = MarketingCloudSDK::Client.new(get_test_stub)
|
79
|
+
|
49
80
|
expect(client.wsdl).to eq 'https://webservice.exacttarget.com/etframework.wsdl'
|
50
81
|
end
|
51
82
|
|
52
|
-
it '
|
53
|
-
client = MarketingCloudSDK::Client.new
|
54
|
-
|
83
|
+
it 'with application_type set to \'server\' if application_type is not set in params' do
|
84
|
+
client = MarketingCloudSDK::Client.new(get_test_stub)
|
85
|
+
|
86
|
+
expect(client.application_type).to eq 'server'
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'with web/public app and null/blank/empty authorization_code or redirect_URI should raise exception' do
|
90
|
+
expected_exception = 'authorization_code or redirect_URI is null: For Public/Web Apps, the authorization_code and redirect_URI must be passed when instantiating Client'
|
91
|
+
|
92
|
+
exception_raisers = Hash.new.tap do |h|
|
93
|
+
h[nil] = 'nil'
|
94
|
+
h[' '] = 'blank string'
|
95
|
+
h[''] = 'empty string'
|
96
|
+
end
|
97
|
+
|
98
|
+
test_stub = get_test_stub
|
99
|
+
|
100
|
+
['web', 'public'].each do |app_type|
|
101
|
+
[nil, ' ', ''].each do |exception_raiser|
|
102
|
+
['authorization_code', 'redirect_URI'].each do |under_test_prop|
|
103
|
+
|
104
|
+
it "#{app_type} app with #{exception_raisers[exception_raiser]} #{under_test_prop} raises an exception" do
|
105
|
+
|
106
|
+
test_stub['client']['application_type'] = app_type
|
107
|
+
test_stub['client'][under_test_prop] = exception_raiser
|
108
|
+
|
109
|
+
expect { MarketingCloudSDK::Client.new(test_stub) }.to raise_error(expected_exception)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'with public app and null/blank/empty id should raise exception' do
|
117
|
+
expected_exception = 'id is null: id must be passed when instantiating Client'
|
118
|
+
|
119
|
+
test_stub = get_test_stub
|
120
|
+
test_stub['client']['application_type'] = 'public'
|
121
|
+
test_stub['client']['authorization_code'] = 'authorization_code'
|
122
|
+
test_stub['client']['redirect_URI'] = 'redirect_URI'
|
123
|
+
|
124
|
+
[nil, ' ', ''].each do |exception_raiser|
|
125
|
+
test_stub['client']['id'] = exception_raiser
|
126
|
+
|
127
|
+
expect { MarketingCloudSDK::Client.new(test_stub) }.to raise_error(expected_exception)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'with web/server app and null/blank/empty id or secret should raise exception' do
|
132
|
+
expected_exception = 'id and secret must pe passed when instantiating Client'
|
133
|
+
|
134
|
+
exception_raisers = Hash.new.tap do |h|
|
135
|
+
h[nil] = 'nil'
|
136
|
+
h[' '] = 'blank string'
|
137
|
+
h[''] = 'empty string'
|
138
|
+
end
|
139
|
+
|
140
|
+
test_stub = get_test_stub
|
141
|
+
test_stub['client']['authorization_code'] = 'authorization_code'
|
142
|
+
test_stub['client']['redirect_URI'] = 'redirect_URI'
|
143
|
+
|
144
|
+
['web', 'server'].each do |app_type|
|
145
|
+
[nil, ' ', ''].each do |exception_raiser|
|
146
|
+
['id', 'secret'].each do |under_test_prop|
|
147
|
+
|
148
|
+
it "#{app_type} app with #{exception_raisers[exception_raiser]} #{under_test_prop} raises an exception" do
|
149
|
+
|
150
|
+
test_stub['client']['application_type'] = app_type
|
151
|
+
test_stub['client'][under_test_prop] = exception_raiser
|
152
|
+
|
153
|
+
expect { MarketingCloudSDK::Client.new(test_stub) }.to raise_error(expected_exception)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
55
158
|
end
|
56
159
|
|
57
160
|
describe 'with a wsdl' do
|
58
161
|
|
59
|
-
|
162
|
+
test_stub = get_test_stub
|
163
|
+
|
164
|
+
let(:client) { MarketingCloudSDK::Client.new test_stub }
|
60
165
|
|
61
166
|
it'creates a SoapClient' do
|
62
167
|
expect(client).to be_kind_of MarketingCloudSDK::Soap
|
63
168
|
end
|
64
169
|
|
65
170
|
it'#wsdl returns default wsdl' do
|
66
|
-
expect(client.wsdl).to eq '
|
171
|
+
expect(client.wsdl).to eq 'https://webservice.exacttarget.com/etframework.wsdl'
|
67
172
|
end
|
68
173
|
end
|
69
174
|
end
|
70
175
|
|
71
176
|
context 'instance can set' do
|
72
177
|
|
73
|
-
|
178
|
+
before(:each) do
|
179
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
180
|
+
end
|
181
|
+
|
182
|
+
let(:client) { MarketingCloudSDK::Client.new (get_test_stub)}
|
74
183
|
|
75
184
|
it 'client id' do
|
76
|
-
client.id =
|
77
|
-
|
185
|
+
client.id = 'some_id'
|
186
|
+
|
187
|
+
expect(client.id).to eq 'some_id'
|
78
188
|
end
|
79
189
|
|
80
190
|
it 'client secret' do
|
81
|
-
client.secret = '
|
82
|
-
|
191
|
+
client.secret = 'some_secret'
|
192
|
+
|
193
|
+
expect(client.secret).to eq 'some_secret'
|
83
194
|
end
|
84
195
|
|
85
196
|
it 'refresh token' do
|
86
|
-
client.refresh_token = '
|
87
|
-
|
197
|
+
client.refresh_token = 'some_refresh_token'
|
198
|
+
|
199
|
+
expect(client.refresh_token).to eq 'some_refresh_token'
|
88
200
|
end
|
89
201
|
|
90
202
|
it 'debug' do
|
203
|
+
client.debug = false
|
91
204
|
expect(client.debug).to be false
|
205
|
+
|
92
206
|
client.debug = true
|
93
207
|
expect(client.debug).to be true
|
94
208
|
end
|
@@ -97,23 +211,23 @@ describe MarketingCloudSDK::Client do
|
|
97
211
|
describe '#jwt=' do
|
98
212
|
|
99
213
|
let(:payload) {
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
214
|
+
{
|
215
|
+
'request' => {
|
216
|
+
'user'=> {
|
217
|
+
'oauthToken' => 'oAuthToken',
|
218
|
+
'expiresIn' => 3600,
|
219
|
+
'internalOauthToken' => 'internalOauthToken',
|
220
|
+
'refreshToken' => 'refreshToken'
|
221
|
+
},
|
222
|
+
'application'=> {
|
223
|
+
'package' => 'JustTesting'
|
224
|
+
}
|
225
|
+
}
|
111
226
|
}
|
112
|
-
}
|
113
227
|
}
|
114
228
|
|
115
229
|
let(:sig){
|
116
|
-
sig = '
|
230
|
+
sig = 'signature'
|
117
231
|
}
|
118
232
|
|
119
233
|
let(:encoded) {
|
@@ -121,13 +235,20 @@ describe MarketingCloudSDK::Client do
|
|
121
235
|
}
|
122
236
|
|
123
237
|
it 'raises an exception when signature is missing' do
|
124
|
-
|
238
|
+
test_stub = get_test_stub
|
239
|
+
test_stub['jwt'] = encoded
|
240
|
+
|
241
|
+
expect { MarketingCloudSDK::Client.new test_stub }.to raise_exception 'Require app signature to decode JWT'
|
125
242
|
end
|
126
243
|
|
127
244
|
describe 'decodes JWT' do
|
128
245
|
|
246
|
+
before(:each) do
|
247
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
248
|
+
end
|
249
|
+
|
129
250
|
let(:sig){
|
130
|
-
sig = '
|
251
|
+
sig = 'signature'
|
131
252
|
}
|
132
253
|
|
133
254
|
let(:encoded) {
|
@@ -135,84 +256,161 @@ describe MarketingCloudSDK::Client do
|
|
135
256
|
}
|
136
257
|
|
137
258
|
let(:client) {
|
138
|
-
|
259
|
+
test_stub = get_test_stub
|
260
|
+
test_stub['client']['signature'] = sig
|
261
|
+
test_stub['jwt'] = encoded
|
262
|
+
|
263
|
+
MarketingCloudSDK::Client.new test_stub
|
139
264
|
}
|
140
265
|
|
141
266
|
it 'making auth token available to client' do
|
142
|
-
client.
|
143
|
-
expect(client.auth_token).to eq 123456789
|
267
|
+
expect(client.auth_token).to eq payload['request']['user']['oauthToken']
|
144
268
|
end
|
145
269
|
|
146
270
|
it 'making internal token available to client' do
|
147
|
-
client.
|
148
|
-
expect(client.internal_token).to eq 987654321
|
271
|
+
expect(client.internal_token).to eq payload['request']['user']['internalOauthToken']
|
149
272
|
end
|
150
273
|
|
151
274
|
it 'making refresh token available to client' do
|
152
|
-
client.
|
153
|
-
expect(client.refresh_token).to eq 101010101010
|
275
|
+
expect(client.refresh_token).to eq payload['request']['user']['refreshToken']
|
154
276
|
end
|
155
277
|
end
|
156
278
|
end
|
157
279
|
|
158
280
|
describe '#refresh_token' do
|
159
|
-
|
281
|
+
|
282
|
+
before(:each) do
|
283
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
284
|
+
end
|
285
|
+
|
286
|
+
let(:client) { MarketingCloudSDK::Client.new get_test_stub }
|
160
287
|
|
161
288
|
it 'defaults to nil' do
|
162
289
|
expect(client.refresh_token).to be_nil
|
163
290
|
end
|
164
291
|
|
165
292
|
it 'can be accessed' do
|
166
|
-
client.refresh_token = '
|
167
|
-
expect(client.refresh_token).to eq '
|
293
|
+
client.refresh_token = 'refresh_token'
|
294
|
+
expect(client.refresh_token).to eq 'refresh_token'
|
168
295
|
end
|
169
296
|
end
|
170
297
|
|
171
|
-
|
298
|
+
context 'authentication payload' do
|
299
|
+
|
300
|
+
before(:each) do
|
301
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
302
|
+
end
|
172
303
|
|
173
|
-
|
304
|
+
it 'should have public app attributes' do
|
305
|
+
test_stub = get_test_stub
|
306
|
+
test_stub['client']['application_type'] = 'public'
|
174
307
|
|
175
|
-
|
308
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
176
309
|
|
177
|
-
|
178
|
-
expect { client.refresh }.to raise_exception 'Require Client Id and Client Secret to refresh tokens'
|
179
|
-
end
|
310
|
+
payload = client.createPayload
|
180
311
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
312
|
+
expect(client.id).to eq payload['client_id']
|
313
|
+
expect(client.redirect_URI).to eq payload['redirect_uri']
|
314
|
+
expect(client.authorization_code).to eq payload['code']
|
315
|
+
expect('authorization_code').to eq payload['grant_type']
|
316
|
+
end
|
185
317
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
318
|
+
it 'should not have client secret for public app' do
|
319
|
+
test_stub = get_test_stub
|
320
|
+
test_stub['client']['application_type'] = 'public'
|
321
|
+
|
322
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
323
|
+
|
324
|
+
payload = client.createPayload
|
325
|
+
|
326
|
+
expect(payload.key?('client_secret')).to be false
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'should have web app attributes' do
|
330
|
+
test_stub = get_test_stub
|
331
|
+
test_stub['client']['application_type'] = 'web'
|
332
|
+
|
333
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
334
|
+
|
335
|
+
payload = client.createPayload
|
336
|
+
|
337
|
+
expect('authorization_code').to eq payload['grant_type']
|
338
|
+
expect(client.id).to eq payload['client_id']
|
339
|
+
expect(client.secret).to eq payload['client_secret']
|
340
|
+
expect(client.redirect_URI).to eq payload['redirect_uri']
|
341
|
+
expect(client.authorization_code).to eq payload['code']
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'should have server attributes' do
|
345
|
+
test_stub = get_test_stub
|
346
|
+
test_stub['client']['application_type'] = 'server'
|
347
|
+
|
348
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
349
|
+
|
350
|
+
payload = client.createPayload
|
351
|
+
|
352
|
+
expect('client_credentials').to eq payload['grant_type']
|
353
|
+
expect(client.id).to eq payload['client_id']
|
354
|
+
expect(client.secret).to eq payload['client_secret']
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'should not have code and redirect_uri for server app' do
|
358
|
+
test_stub = get_test_stub
|
359
|
+
test_stub['client']['application_type'] = 'server'
|
360
|
+
|
361
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
362
|
+
|
363
|
+
payload = client.createPayload
|
364
|
+
|
365
|
+
expect(payload.key?('code')).to be false
|
366
|
+
expect(payload.key?('redirect_uri')).to be false
|
367
|
+
end
|
368
|
+
|
369
|
+
it 'should have refresh_token attribute when refresh_token is not null/blank/empty on client' do
|
370
|
+
test_stub = get_test_stub
|
371
|
+
test_stub['refresh_token'] = 'refresh_token'
|
372
|
+
test_stub['client']['application_type'] = 'public'
|
373
|
+
|
374
|
+
client = MarketingCloudSDK::Client.new(test_stub)
|
375
|
+
|
376
|
+
payload = client.createPayload
|
377
|
+
|
378
|
+
expect('refresh_token').to eq payload['grant_type']
|
379
|
+
expect(client.refresh_token).to eq payload['refresh_token']
|
190
380
|
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context 'for public and web integrations, access_token and refresh_token' do
|
384
|
+
# Test expects a Public/Web App integration config in spec/public_or_web_integration_credentials.rb
|
385
|
+
it 'should differ if refresh token is enforced' do
|
191
386
|
|
192
|
-
|
193
|
-
# let(:client) { MarketingCloudSDK::Client.new 'client' => { 'id' => 123, 'secret' => 'sssh'} }
|
194
|
-
# it 'accessType=offline' do
|
195
|
-
# client.stub(:post)
|
196
|
-
# .with({'clientId' => 123, 'secret' => 'ssh', 'accessType' => 'offline'})
|
197
|
-
# .and_return()
|
198
|
-
#end
|
387
|
+
client = MarketingCloudSDK::Client.new(auth)
|
199
388
|
|
200
|
-
|
201
|
-
|
389
|
+
auth_token1 = client.access_token
|
390
|
+
refresh_token1 = client.refresh_token
|
202
391
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
392
|
+
client.refreshWithOAuth2(true)
|
393
|
+
|
394
|
+
auth_token2 = client.access_token
|
395
|
+
refresh_token2 = client.refresh_token
|
396
|
+
|
397
|
+
expect(auth_token1).not_to eq(auth_token2)
|
398
|
+
expect(refresh_token1).not_to eq(refresh_token2)
|
399
|
+
end
|
207
400
|
end
|
208
401
|
|
209
402
|
describe 'includes HTTPRequest' do
|
210
403
|
|
211
|
-
|
404
|
+
before(:each) do
|
405
|
+
allow_any_instance_of(MarketingCloudSDK::Client).to receive(:refresh).and_return(true)
|
406
|
+
end
|
407
|
+
|
408
|
+
subject { MarketingCloudSDK::Client.new get_test_stub}
|
212
409
|
|
213
410
|
it { should respond_to(:get) }
|
214
411
|
it { should respond_to(:post) }
|
215
412
|
it { should respond_to(:patch) }
|
216
413
|
it { should respond_to(:delete) }
|
414
|
+
|
217
415
|
end
|
218
416
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
def auth
|
2
|
+
{
|
3
|
+
'client' => {
|
4
|
+
'id' => '<CLIENT_ID>',
|
5
|
+
'request_token_url' => '<AUTH TENANT SPECIFIC ENDPOINT>',
|
6
|
+
'use_oAuth2_authentication' => true,
|
7
|
+
'application_type' => '<APPLICATION_TYPE>',
|
8
|
+
'redirect_URI' => '<REDIRECT_URI_FOR_PUBLIC/WEB_APP>',
|
9
|
+
'authorization_code' => '<AUTHORIZATION_CODE_FOR_PUBLIC/WEB_APP>'
|
10
|
+
}
|
11
|
+
}
|
12
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfmc-fuelsdk-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Salesforce
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,22 +118,22 @@ dependencies:
|
|
118
118
|
name: jwt
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- - "~>"
|
122
|
-
- !ruby/object:Gem::Version
|
123
|
-
version: '1.0'
|
124
121
|
- - ">="
|
125
122
|
- !ruby/object:Gem::Version
|
126
123
|
version: 1.0.0
|
124
|
+
- - "~>"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '1.0'
|
127
127
|
type: :runtime
|
128
128
|
prerelease: false
|
129
129
|
version_requirements: !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
|
-
- - "~>"
|
132
|
-
- !ruby/object:Gem::Version
|
133
|
-
version: '1.0'
|
134
131
|
- - ">="
|
135
132
|
- !ruby/object:Gem::Version
|
136
133
|
version: 1.0.0
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '1.0'
|
137
137
|
description: API wrapper for SOAP and REST API with Salesforce Marketing Cloud (ExactTarget)
|
138
138
|
email:
|
139
139
|
- mcsdkadmin@salesforce.com
|
@@ -141,6 +141,8 @@ executables: []
|
|
141
141
|
extensions: []
|
142
142
|
extra_rdoc_files: []
|
143
143
|
files:
|
144
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
145
|
+
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
144
146
|
- ".gitignore"
|
145
147
|
- Gemfile
|
146
148
|
- Gemfile.lock
|
@@ -193,6 +195,7 @@ files:
|
|
193
195
|
- spec/http_request_spec.rb
|
194
196
|
- spec/objects_helper_spec.rb
|
195
197
|
- spec/objects_spec.rb
|
198
|
+
- spec/public_or_web_integration_credentials.rb.template
|
196
199
|
- spec/rest_spec.rb
|
197
200
|
- spec/soap_spec.rb
|
198
201
|
- spec/spec_helper.rb
|
@@ -217,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
217
220
|
version: '0'
|
218
221
|
requirements: []
|
219
222
|
rubyforge_project:
|
220
|
-
rubygems_version: 2.7.
|
223
|
+
rubygems_version: 2.7.8
|
221
224
|
signing_key:
|
222
225
|
specification_version: 4
|
223
226
|
summary: Fuel Client Library for Ruby
|
@@ -256,6 +259,7 @@ test_files:
|
|
256
259
|
- spec/http_request_spec.rb
|
257
260
|
- spec/objects_helper_spec.rb
|
258
261
|
- spec/objects_spec.rb
|
262
|
+
- spec/public_or_web_integration_credentials.rb.template
|
259
263
|
- spec/rest_spec.rb
|
260
264
|
- spec/soap_spec.rb
|
261
265
|
- spec/spec_helper.rb
|