gibbon 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +3 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +13 -1
- data/LICENSE.txt +1 -1
- data/README.markdown +12 -31
- data/gibbon.gemspec +3 -3
- data/lib/gibbon/api_request.rb +7 -1
- data/lib/gibbon/gibbon_helpers.rb +6 -2
- data/lib/gibbon/request.rb +4 -0
- data/lib/gibbon/version.rb +1 -1
- data/lib/gibbon.rb +0 -1
- data/spec/gibbon/gibbon_spec.rb +10 -1
- metadata +8 -10
- data/lib/gibbon/export.rb +0 -93
- data/spec/gibbon/export_spec.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61103c56f7d3ff60ca48fab8a2ca7c71949c1c01c784abd7ddb062dbd74d4560
|
4
|
+
data.tar.gz: 93f18505844eb71b72d189622547c61c0bda3c416bdb2a2caa4ec0358899e52b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e4203bc006c80cc20c5fff0217673543faa842a28b57eb3620a373a63409c0e1b5f503335d44ff05d8ba8d124db1f5b984dcf5f98632aaa8ee077d525d0a413
|
7
|
+
data.tar.gz: ecc7c39379e218a5a10d92c4597fdb9e5f28c90c8297ef5a19d04189044a0b86a0f84120151369ecca4c989c3d88bb359fcc651de9527497cba368b608225d9d
|
data/.github/FUNDING.yml
ADDED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
|
-
## [
|
1
|
+
## [3.5.0, unreleased] - 2022-06-05
|
2
|
+
- Remove support for retired Export API
|
2
3
|
|
4
|
+
## [3.4.4] - 2022-02-24
|
5
|
+
- Remove non-alpha characters when parsing datacenter from API keys to prevent potential attackers from injecting a domain via the API key. This would only be possible if one were using user-provided API keys (e.g. from a form, etc.).
|
6
|
+
|
7
|
+
## [3.4.3] - 2022-01-19
|
8
|
+
- Support for Faraday 2.0, which requires new syntax for basic auth
|
9
|
+
|
10
|
+
## [3.4.2] - 2021-09-21
|
11
|
+
- Fixing the deprecation warning in version 3.4.2 requires moving to a minimum version of Faraday 1.0.0 (more than 2 years old).
|
12
|
+
|
13
|
+
## [3.4.1] - 2021-09-12
|
14
|
+
- Fix deprecation warning for upcoming versions of Faraday (2.x.x)
|
3
15
|
|
4
16
|
## [3.4.0] - 2021-03-12
|
5
17
|
- Support for Faraday 1.x.x and higer
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gibbon is an API wrapper for MailChimp's [API](http://kb.mailchimp.com/api/).
|
4
4
|
|
5
|
-
[](https://travis-ci.com/amro/gibbon)
|
5
|
+
[](https://app.travis-ci.com/github/amro/gibbon)
|
6
6
|
|
7
7
|
## Important Notes
|
8
8
|
|
@@ -38,7 +38,7 @@ gibbon.open_timeout = 30
|
|
38
38
|
You can read about `timeout` and `open_timeout` in the [Net::HTTP](https://ruby-doc.org/stdlib-2.3.3/libdoc/net/http/rdoc/Net/HTTP.html) doc.
|
39
39
|
|
40
40
|
Now you can make requests using the resources defined in [MailChimp's docs](http://kb.mailchimp.com/api/resources). Resource IDs
|
41
|
-
are specified inline and a `CRUD` (`create`, `retrieve
|
41
|
+
are specified inline and a `CRUD` (`create`, `retrieve` (or `get`), `update`, `upsert`, or `delete`) verb initiates the request. `upsert` lets you update a record, if it exists, or insert it otherwise where supported by MailChimp's API.
|
42
42
|
|
43
43
|
***Note*** `upsert` requires Gibbon version 2.1.0 or newer!
|
44
44
|
|
@@ -48,6 +48,8 @@ You can specify `headers`, `params`, and `body` when calling a `CRUD` method. Fo
|
|
48
48
|
gibbon.lists.retrieve(headers: {"SomeHeader": "SomeHeaderValue"}, params: {"query_param": "query_param_value"})
|
49
49
|
```
|
50
50
|
|
51
|
+
***Note*** `get` can be substituted for `retrieve` as of Gibbon version 3.4.1 or newer!
|
52
|
+
|
51
53
|
Of course, `body` is only supported on `create`, `update`, and `upsert` calls. Those map to HTTP `POST`, `PATCH`, and `PUT` verbs respectively.
|
52
54
|
|
53
55
|
You can set `api_key`, `timeout`, `open_timeout`, `faraday_adapter`, `proxy`, `symbolize_keys`, `logger`, and `debug` globally:
|
@@ -178,6 +180,12 @@ Get a specific member's information (open/click rates etc.) from MailChimp:
|
|
178
180
|
gibbon.lists(list_id).members(lower_case_md5_hashed_email_address).retrieve
|
179
181
|
```
|
180
182
|
|
183
|
+
Permanently delete a specific member from a list:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
gibbon.lists(list_id).members(lower_case_md5_hashed_email_address).actions.delete_permanent.create
|
187
|
+
```
|
188
|
+
|
181
189
|
### Tags
|
182
190
|
|
183
191
|
[Tags](https://mailchimp.com/help/getting-started-tags/) are a flexible way to organize (slice and dice) your list: for example, you can send a campaign directly to one or more tags.
|
@@ -472,33 +480,6 @@ Gibbon 2.x+:
|
|
472
480
|
```ruby
|
473
481
|
gibbon.lists(list_id).members.create(body: {email_address: "foo@bar.com", status: "subscribed", merge_fields: {FNAME: "Bob", LNAME: "Smith"}})
|
474
482
|
```
|
475
|
-
## Export API 1.0
|
476
|
-
|
477
|
-
Gibbon 3.0.0+ supports MailChimp's [Export API 1.0](https://apidocs.mailchimp.com/export/1.0/). You can choose to handle the API response all at
|
478
|
-
once or line by line by passing a block. To access the Export API with Gibbon, you must first create an instance of `Gibbon::Export`:
|
479
|
-
|
480
|
-
```ruby
|
481
|
-
export = Gibbon::Export.new(api_key: "your_api_key")
|
482
|
-
```
|
483
|
-
|
484
|
-
Next, call the method corresponding to the API endpoint you'd like to query:
|
485
|
-
|
486
|
-
```ruby
|
487
|
-
export.list(id: list_id)
|
488
|
-
```
|
489
|
-
|
490
|
-
This fetches and returns all of the results at once. Pass a block if you'd like to handle the response as individual lines:
|
491
|
-
|
492
|
-
```ruby
|
493
|
-
export = Gibbon::Export.new(api_key: "your_api_key", timeout: 1200)
|
494
|
-
export.list(id: list_id) do |row|
|
495
|
-
puts row
|
496
|
-
end
|
497
|
-
```
|
498
|
-
|
499
|
-
This is useful when handling large sets of data. Setting the `timeout` here is optional, but a high value is recommended given the nature of the Export API. The default timeout is 600 seconds.
|
500
|
-
|
501
|
-
Gibbon supports all current Export API endpoints: `/list`, `/ecommOrders`, and `/campaignSubscriberActivity`. They're mapped onto Ruby methods with similar names: `list()`, `ecomm_orders()`, and `campaign_subscriber_activity()` respectively. Please see [MailChimp's API documentation](https://developer.mailchimp.com/documentation/mailchimp/guides/how-to-use-the-export-api/) for supported parameters.
|
502
483
|
|
503
484
|
## Thanks
|
504
485
|
|
@@ -506,5 +487,5 @@ Thanks to everyone who has [contributed](https://github.com/amro/gibbon/contribu
|
|
506
487
|
|
507
488
|
## Copyright
|
508
489
|
|
509
|
-
* Copyright (c) 2010-
|
510
|
-
* MailChimp (c) 2001-
|
490
|
+
* Copyright (c) 2010-2022 Amro Mousa. See LICENSE.txt for details.
|
491
|
+
* MailChimp (c) 2001-2022 The Rocket Science Group.
|
data/gibbon.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.email = ["amromousa@gmail.com"]
|
10
10
|
s.homepage = "http://github.com/amro/gibbon"
|
11
11
|
|
12
|
-
s.summary = %q{A wrapper for MailChimp API 3.0
|
13
|
-
s.description = %q{A wrapper for MailChimp API 3.0
|
12
|
+
s.summary = %q{A wrapper for MailChimp API 3.0}
|
13
|
+
s.description = %q{A wrapper for MailChimp API 3.0}
|
14
14
|
s.license = "MIT"
|
15
15
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
s.required_ruby_version = '>= 2.4.0'
|
21
21
|
|
22
|
-
s.add_dependency('faraday', '>=
|
22
|
+
s.add_dependency('faraday', '>= 1.0')
|
23
23
|
s.add_dependency('multi_json', '>= 1.11.0')
|
24
24
|
|
25
25
|
s.add_development_dependency 'rake'
|
data/lib/gibbon/api_request.rb
CHANGED
@@ -152,8 +152,14 @@ module Gibbon
|
|
152
152
|
if @request_builder.debug
|
153
153
|
faraday.response :logger, @request_builder.logger, bodies: true
|
154
154
|
end
|
155
|
+
|
156
|
+
if Faraday::VERSION.to_i >= 2
|
157
|
+
faraday.request :authorization, :basic, 'apikey', self.api_key
|
158
|
+
else
|
159
|
+
faraday.request :basic_auth, 'apikey', self.api_key
|
160
|
+
end
|
155
161
|
end
|
156
|
-
|
162
|
+
|
157
163
|
client
|
158
164
|
end
|
159
165
|
|
@@ -5,8 +5,12 @@ module Gibbon
|
|
5
5
|
data_center = ""
|
6
6
|
|
7
7
|
if api_key && api_key["-"]
|
8
|
-
#
|
9
|
-
|
8
|
+
# Remove all non-alphanumberic characters in case someone attempts to inject
|
9
|
+
# a different domain into the API key (e.g. when consuming user form-provided keys)
|
10
|
+
# This approach avoids assuming a 3 letter prefix (e.g. is MC were to create
|
11
|
+
# a us10 DC, this would continue to work), and will continue to hit MC's server
|
12
|
+
# rather than a would-be attacker's servers.
|
13
|
+
data_center = "#{api_key.split('-').last.gsub(/[^0-9a-z ]/i, '')}."
|
10
14
|
end
|
11
15
|
|
12
16
|
data_center
|
data/lib/gibbon/request.rb
CHANGED
data/lib/gibbon/version.rb
CHANGED
data/lib/gibbon.rb
CHANGED
data/spec/gibbon/gibbon_spec.rb
CHANGED
@@ -14,6 +14,7 @@ describe Gibbon do
|
|
14
14
|
@gibbon = Gibbon::Request.new
|
15
15
|
expect(@gibbon.api_key).to be_nil
|
16
16
|
end
|
17
|
+
|
17
18
|
it "sets an API key in the constructor" do
|
18
19
|
@gibbon = Gibbon::Request.new(api_key: @api_key)
|
19
20
|
expect(@gibbon.api_key).to eq(@api_key)
|
@@ -162,6 +163,14 @@ describe Gibbon do
|
|
162
163
|
@request = Gibbon::APIRequest.new(builder: @gibbon)
|
163
164
|
expect {@request.validate_api_key}.not_to raise_error
|
164
165
|
end
|
166
|
+
|
167
|
+
it "removes non-alpha characters from datacenter prefix" do
|
168
|
+
@api_key = "123-attacker.net/test/?"
|
169
|
+
@gibbon.api_key = @api_key
|
170
|
+
@gibbon.try
|
171
|
+
@request = Gibbon::APIRequest.new(builder: @gibbon)
|
172
|
+
expect(@request.api_url).to eq("https://attackernettest.api.mailchimp.com/3.0/try")
|
173
|
+
end
|
165
174
|
end
|
166
175
|
|
167
176
|
describe "class variables" do
|
@@ -213,7 +222,7 @@ describe Gibbon do
|
|
213
222
|
it "set debug on new instances" do
|
214
223
|
expect(Gibbon::Request.new.debug).to eq(Gibbon::Request.debug)
|
215
224
|
end
|
216
|
-
|
225
|
+
|
217
226
|
it "set faraday_adapter on new instances" do
|
218
227
|
expect(Gibbon::Request.new.faraday_adapter).to eq(Gibbon::Request.faraday_adapter)
|
219
228
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gibbon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Amro Mousa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: multi_json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.8'
|
83
|
-
description: A wrapper for MailChimp API 3.0
|
83
|
+
description: A wrapper for MailChimp API 3.0
|
84
84
|
email:
|
85
85
|
- amromousa@gmail.com
|
86
86
|
executables: []
|
@@ -88,6 +88,7 @@ extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
90
|
- ".document"
|
91
|
+
- ".github/FUNDING.yml"
|
91
92
|
- ".gitignore"
|
92
93
|
- ".travis.yml"
|
93
94
|
- CHANGELOG.md
|
@@ -99,7 +100,6 @@ files:
|
|
99
100
|
- gibbon.gemspec
|
100
101
|
- lib/gibbon.rb
|
101
102
|
- lib/gibbon/api_request.rb
|
102
|
-
- lib/gibbon/export.rb
|
103
103
|
- lib/gibbon/gibbon_error.rb
|
104
104
|
- lib/gibbon/gibbon_helpers.rb
|
105
105
|
- lib/gibbon/mailchimp_error.rb
|
@@ -107,7 +107,6 @@ files:
|
|
107
107
|
- lib/gibbon/response.rb
|
108
108
|
- lib/gibbon/version.rb
|
109
109
|
- spec/gibbon/api_request_spec.rb
|
110
|
-
- spec/gibbon/export_spec.rb
|
111
110
|
- spec/gibbon/gibbon_spec.rb
|
112
111
|
- spec/gibbon/mailchimp_error_spec.rb
|
113
112
|
- spec/gibbon/upsert_spec.rb
|
@@ -131,13 +130,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
130
|
- !ruby/object:Gem::Version
|
132
131
|
version: '0'
|
133
132
|
requirements: []
|
134
|
-
rubygems_version: 3.2.
|
133
|
+
rubygems_version: 3.2.27
|
135
134
|
signing_key:
|
136
135
|
specification_version: 4
|
137
|
-
summary: A wrapper for MailChimp API 3.0
|
136
|
+
summary: A wrapper for MailChimp API 3.0
|
138
137
|
test_files:
|
139
138
|
- spec/gibbon/api_request_spec.rb
|
140
|
-
- spec/gibbon/export_spec.rb
|
141
139
|
- spec/gibbon/gibbon_spec.rb
|
142
140
|
- spec/gibbon/mailchimp_error_spec.rb
|
143
141
|
- spec/gibbon/upsert_spec.rb
|
data/lib/gibbon/export.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
require 'net/https'
|
2
|
-
|
3
|
-
module Gibbon
|
4
|
-
class Export
|
5
|
-
include Helpers
|
6
|
-
|
7
|
-
attr_accessor :api_key, :timeout
|
8
|
-
|
9
|
-
def initialize(api_key: nil, timeout: nil)
|
10
|
-
@api_key = api_key || self.class.api_key || ENV['MAILCHIMP_API_KEY']
|
11
|
-
@timeout = timeout || self.class.timeout || 600
|
12
|
-
end
|
13
|
-
|
14
|
-
def list(params = {}, &block)
|
15
|
-
call("list", params, &block)
|
16
|
-
end
|
17
|
-
|
18
|
-
def ecomm_orders(params = {}, &block)
|
19
|
-
call("ecommOrders", params, &block)
|
20
|
-
end
|
21
|
-
|
22
|
-
def campaign_subscriber_activity(params = {}, &block)
|
23
|
-
call("campaignSubscriberActivity", params, &block)
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
def export_api_url
|
29
|
-
"https://#{get_data_center_from_api_key(@api_key)}api.mailchimp.com/export/1.0/"
|
30
|
-
end
|
31
|
-
|
32
|
-
def call(method, params = {}, &block)
|
33
|
-
rows = []
|
34
|
-
|
35
|
-
api_url = export_api_url + method + "/"
|
36
|
-
params = params.merge({ apikey: @api_key })
|
37
|
-
block = Proc.new { |row| rows << row } unless block_given?
|
38
|
-
|
39
|
-
ensure_api_key(params)
|
40
|
-
|
41
|
-
url = URI.parse(api_url)
|
42
|
-
req = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' => 'application/json'})
|
43
|
-
req.body = MultiJson.dump(params)
|
44
|
-
Net::HTTP.start(url.host, url.port, read_timeout: @timeout, use_ssl: true, ssl_version: :TLSv1_2) do |http|
|
45
|
-
# http://stackoverflow.com/questions/29598196/ruby-net-http-read-body-nethttpokread-body-called-twice-ioerror
|
46
|
-
http.request req do |response|
|
47
|
-
i = -1
|
48
|
-
last = ''
|
49
|
-
response.read_body do |chunk|
|
50
|
-
next if chunk.nil? or chunk.strip.empty?
|
51
|
-
infix = "\n" if last[-1, 1]==']'
|
52
|
-
lines, last = try_parse_line("#{last}#{infix}#{chunk}")
|
53
|
-
lines.each { |line| block.call(line, i += 1) }
|
54
|
-
end
|
55
|
-
block.call(parse_line(last), i += 1) unless last.nil? or last.empty?
|
56
|
-
end
|
57
|
-
end
|
58
|
-
rows unless block_given?
|
59
|
-
end
|
60
|
-
|
61
|
-
def try_parse_line(res)
|
62
|
-
lines = res.split("\n")
|
63
|
-
last = lines.pop || ''
|
64
|
-
lines.map! { |line| parse_line(line) }
|
65
|
-
[lines.compact, last]
|
66
|
-
rescue MultiJson::ParseError
|
67
|
-
[[], last]
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
def parse_line(line)
|
72
|
-
parsed_response = MultiJson.load(line)
|
73
|
-
rescue MultiJson::ParseError
|
74
|
-
return []
|
75
|
-
end
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
def ensure_api_key(params)
|
80
|
-
unless params[:apikey] && (get_data_center_from_api_key(params[:apikey]) != "")
|
81
|
-
raise Gibbon::GibbonError, "You must set an api_key prior to making a call"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
class << self
|
86
|
-
attr_accessor :api_key, :timeout
|
87
|
-
|
88
|
-
def method_missing(sym, *args, &block)
|
89
|
-
new(api_key: self.api_key, timeout: self.timeout).send(sym, *args, &block)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
data/spec/gibbon/export_spec.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'webmock/rspec'
|
3
|
-
|
4
|
-
describe Gibbon::Export do
|
5
|
-
before do
|
6
|
-
Gibbon::Export.send(:public, *Gibbon::Export.protected_instance_methods)
|
7
|
-
@export = Gibbon::Export.new
|
8
|
-
end
|
9
|
-
|
10
|
-
it "doesn't allow empty api key" do
|
11
|
-
expect {@export.list(id: "123456")}.to raise_error(Gibbon::GibbonError)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "doesn't allow api key without data center" do
|
15
|
-
@api_key = "123"
|
16
|
-
@export.api_key = @api_key
|
17
|
-
expect {@export.list(id: "123456")}.to raise_error(Gibbon::GibbonError)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "sets an API key from the 'MAILCHIMP_API_KEY' ENV variable" do
|
21
|
-
ENV['MAILCHIMP_API_KEY'] = 'TESTKEY-us1'
|
22
|
-
@export = Gibbon::Export.new
|
23
|
-
expect(@export.api_key).to eq('TESTKEY-us1')
|
24
|
-
ENV.delete('MAILCHIMP_API_KEY')
|
25
|
-
end
|
26
|
-
|
27
|
-
it "sets correct endpoint from api key" do
|
28
|
-
@api_key = "TESTKEY-us1"
|
29
|
-
@export.api_key = @api_key
|
30
|
-
expect(@export.export_api_url).to eq("https://us1.api.mailchimp.com/export/1.0/")
|
31
|
-
end
|
32
|
-
|
33
|
-
it "sets correct timeout" do
|
34
|
-
@api_key = "TESTKEY-us1"
|
35
|
-
@export.api_key = @api_key
|
36
|
-
@export.timeout = 9
|
37
|
-
expect(@export.timeout).to eq(9)
|
38
|
-
end
|
39
|
-
end
|