drip-ruby 3.4.2 → 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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +35 -0
  3. data/.rubocop.yml +27 -6
  4. data/.rubocop_todo.yml +1 -97
  5. data/CHANGELOG.md +41 -1
  6. data/Gemfile +9 -8
  7. data/README.md +1 -2
  8. data/drip-ruby.gemspec +4 -4
  9. data/flake.lock +61 -0
  10. data/flake.nix +32 -0
  11. data/lib/drip/client/accounts.rb +3 -1
  12. data/lib/drip/client/broadcasts.rb +3 -1
  13. data/lib/drip/client/campaign_subscriptions.rb +3 -1
  14. data/lib/drip/client/campaigns.rb +6 -4
  15. data/lib/drip/client/configuration.rb +9 -1
  16. data/lib/drip/client/conversions.rb +3 -1
  17. data/lib/drip/client/forms.rb +3 -1
  18. data/lib/drip/client/http_client.rb +30 -11
  19. data/lib/drip/client/orders.rb +1 -1
  20. data/lib/drip/client/shopper_activity.rb +26 -2
  21. data/lib/drip/client/subscribers.rb +5 -4
  22. data/lib/drip/client/webhooks.rb +4 -2
  23. data/lib/drip/client/workflow_triggers.rb +5 -3
  24. data/lib/drip/client/workflows.rb +5 -5
  25. data/lib/drip/client.rb +3 -3
  26. data/lib/drip/collection.rb +2 -2
  27. data/lib/drip/resource.rb +6 -6
  28. data/lib/drip/resources/tag.rb +0 -5
  29. data/lib/drip/response.rb +21 -18
  30. data/lib/drip/version.rb +1 -1
  31. data/test/drip/client/accounts_test.rb +18 -2
  32. data/test/drip/client/broadcasts_test.rb +2 -2
  33. data/test/drip/client/campaign_subscriptions_test.rb +1 -1
  34. data/test/drip/client/campaigns_test.rb +5 -5
  35. data/test/drip/client/configuration_test.rb +14 -1
  36. data/test/drip/client/conversions_test.rb +2 -2
  37. data/test/drip/client/custom_fields_test.rb +1 -1
  38. data/test/drip/client/events_test.rb +1 -1
  39. data/test/drip/client/forms_test.rb +2 -2
  40. data/test/drip/client/http_client_test.rb +32 -2
  41. data/test/drip/client/orders_test.rb +1 -1
  42. data/test/drip/client/shopper_activity_test.rb +35 -1
  43. data/test/drip/client/subscribers_test.rb +39 -2
  44. data/test/drip/client/tags_test.rb +1 -1
  45. data/test/drip/client/users_test.rb +1 -1
  46. data/test/drip/client/webhooks_test.rb +1 -1
  47. data/test/drip/client/workflow_triggers_test.rb +2 -2
  48. data/test/drip/client/workflows_test.rb +18 -2
  49. data/test/drip/client_test.rb +8 -6
  50. data/test/drip/collection_test.rb +1 -1
  51. data/test/drip/collections/account_test.rb +1 -1
  52. data/test/drip/collections/broadcasts_test.rb +1 -1
  53. data/test/drip/collections/campaign_subscriptions_test.rb +1 -1
  54. data/test/drip/collections/campaigns_test.rb +1 -1
  55. data/test/drip/collections/errors_test.rb +1 -1
  56. data/test/drip/collections/orders_test.rb +1 -1
  57. data/test/drip/collections/purchases_test.rb +1 -1
  58. data/test/drip/collections/tags_test.rb +1 -1
  59. data/test/drip/collections/webhooks_test.rb +1 -1
  60. data/test/drip/collections/workflow_triggers_test.rb +1 -1
  61. data/test/drip/collections/workflows_test.rb +1 -1
  62. data/test/drip/collections_test.rb +1 -1
  63. data/test/drip/request_test.rb +1 -1
  64. data/test/drip/resource_test.rb +1 -1
  65. data/test/drip/resources/account_test.rb +1 -1
  66. data/test/drip/resources/order_test.rb +1 -1
  67. data/test/drip/resources/subscriber_test.rb +1 -1
  68. data/test/drip/resources/tag_test.rb +1 -1
  69. data/test/drip/resources_test.rb +1 -1
  70. data/test/drip/response_test.rb +1 -1
  71. data/test/test_helper.rb +2 -2
  72. metadata +10 -53
  73. data/.travis.yml +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a315464f308426c87063f971108b2861cc7f6beacf9320fdf16af17bed73fc16
4
- data.tar.gz: 70cd96e4f9ea7a463f73ae83990e8cfda6519563bbcaec9b4942d1862d7613b8
3
+ metadata.gz: 37b3a95212197fb3a6921842f1613d3ee1e4f2189322f11e102c3146ddea7d21
4
+ data.tar.gz: 11f956e7ad3323e9e5837d28ed6e2cfbbf0c359f7a91c257fdafdfd3255dcec5
5
5
  SHA512:
6
- metadata.gz: b9d9dba42336127f9cfc9269ab57ff0f7af9fac620fb735d0749cb40ecf76a96175e25bee9b2a55ef94fd4ba038d10ae0fa371c9b0b0d7ded6f09f4169bbcb93
7
- data.tar.gz: 1991082152cbf1bfc5748a37e6108418313871ea5272e8ad42b33a2be4081174b282601deedd027f8187df2e513071ea80636423f77168fffe2d2f42dba82af2
6
+ metadata.gz: 84bb04b31f437feda68912b961a8f98c643dafdc153a6a9284daf73b32e045e29670faf99d45d928a4df7c0af433a3ccda1af1e41b287372126a2d928ec02996
7
+ data.tar.gz: 6c99c173680a681847fba94e3697b93ffebc999b1d146eb936ee23eeb9f00511e8c150c5b1c7bd5e9154bc72205c32dcb484fc90a83c70e00fa92c4ad0766ffc
@@ -0,0 +1,35 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ ruby: ["3.1", "3.2", "3.3", "3.4"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ bundler-cache: true
21
+ - run: bundle exec rake test
22
+
23
+ # Runs the suite through the same flake.nix shell used for local development,
24
+ # so a broken dev environment fails CI instead of surfacing only when someone
25
+ # next runs `nix develop`. No Nix cache action is wired up here: this flake
26
+ # doesn't build anything from source, so every package is already served by
27
+ # the public cache.nixos.org substituter and there's nothing to gain from one.
28
+ nix:
29
+ runs-on: ubuntu-latest
30
+ steps:
31
+ - uses: actions/checkout@v4
32
+ - uses: DeterminateSystems/determinate-nix-action@v3
33
+ - run: nix develop --command bundle install
34
+ - run: nix develop --command bundle exec rake test
35
+ - run: nix develop --command bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -1,11 +1,15 @@
1
+ plugins:
2
+ - rubocop-performance
3
+
1
4
  inherit_from: .rubocop_todo.yml
2
5
 
3
6
  AllCops:
4
- TargetRubyVersion: '2.3'
7
+ TargetRubyVersion: '3.1'
8
+ NewCops: enable
5
9
  Exclude:
6
10
  - 'test/fixtures/**/*'
7
11
 
8
- Layout/AlignParameters:
12
+ Layout/ParameterAlignment:
9
13
  EnforcedStyle: with_fixed_indentation
10
14
 
11
15
  Layout/ClosingParenthesisIndentation:
@@ -14,15 +18,32 @@ Layout/ClosingParenthesisIndentation:
14
18
  Layout/DotPosition:
15
19
  EnforcedStyle: trailing
16
20
 
17
- Style/BracesAroundHashParameters:
18
- Enabled: false
19
-
20
21
  Layout/AccessModifierIndentation:
21
22
  EnforcedStyle: outdent
22
23
 
23
- Metrics/LineLength:
24
+ Layout/LineLength:
24
25
  Enabled: false
25
26
 
27
+ Style/StringLiterals:
28
+ Enabled: false
29
+
30
+ # This codebase intentionally uses the compact `class Drip::Client::Foo`
31
+ # style throughout instead of nested `module`/`class` blocks.
32
+ Style/ClassAndModuleChildren:
33
+ Enabled: false
34
+
35
+ # Methods are documented with "Public:"-style comments above each method
36
+ # rather than class/module-level documentation.
37
+ Style/Documentation:
38
+ Enabled: false
39
+
40
+ # Data-literal methods that just enumerate known classes aren't meaningfully
41
+ # simplified by splitting them up.
42
+ Metrics/MethodLength:
43
+ Exclude:
44
+ - 'lib/drip/resources.rb'
45
+ - 'lib/drip/collections.rb'
46
+
26
47
  Layout/MultilineOperationIndentation:
27
48
  EnforcedStyle: 'indented'
28
49
 
data/.rubocop_todo.yml CHANGED
@@ -1,103 +1,7 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-05-02 16:45:21 -0500 using RuboCop version 0.67.2.
3
+ # using RuboCop version 1.88.2.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
-
9
- # Offense count: 2
10
- # Cop supports --auto-correct.
11
- Layout/EmptyLineAfterGuardClause:
12
- Exclude:
13
- - 'lib/drip/client/subscribers.rb'
14
- - 'lib/drip/response.rb'
15
-
16
- # Offense count: 2
17
- # Cop supports --auto-correct.
18
- # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
19
- Lint/UnusedMethodArgument:
20
- Exclude:
21
- - 'lib/drip/client.rb'
22
- - 'lib/drip/collection.rb'
23
-
24
- # Offense count: 2
25
- Metrics/AbcSize:
26
- Max: 25
27
-
28
- # Offense count: 8
29
- # Configuration parameters: CountComments, ExcludedMethods.
30
- # ExcludedMethods: refine
31
- Metrics/BlockLength:
32
- Max: 46
33
-
34
- # Offense count: 4
35
- # Configuration parameters: CountComments, ExcludedMethods.
36
- Metrics/MethodLength:
37
- Max: 26
38
-
39
- # Offense count: 1
40
- Metrics/PerceivedComplexity:
41
- Max: 8
42
-
43
- # Offense count: 4
44
- # Cop supports --auto-correct.
45
- Performance/InefficientHashSearch:
46
- Exclude:
47
- - 'lib/drip/resource.rb'
48
- - 'lib/drip/response.rb'
49
-
50
- # Offense count: 24
51
- # Cop supports --auto-correct.
52
- # Configuration parameters: AutoCorrect, EnforcedStyle.
53
- # SupportedStyles: nested, compact
54
- Style/ClassAndModuleChildren:
55
- Enabled: false
56
-
57
- # Offense count: 44
58
- Style/Documentation:
59
- Enabled: false
60
-
61
- # Offense count: 1
62
- # Cop supports --auto-correct.
63
- Style/Encoding:
64
- Exclude:
65
- - 'drip-ruby.gemspec'
66
-
67
- # Offense count: 2
68
- # Cop supports --auto-correct.
69
- Style/ExpandPathArguments:
70
- Exclude:
71
- - 'drip-ruby.gemspec'
72
- - 'test/test_helper.rb'
73
-
74
- # Offense count: 1
75
- # Configuration parameters: MinBodyLength.
76
- Style/GuardClause:
77
- Exclude:
78
- - 'lib/drip/client.rb'
79
-
80
- # Offense count: 2
81
- # Cop supports --auto-correct.
82
- Style/IfUnlessModifier:
83
- Exclude:
84
- - 'lib/drip/client.rb'
85
-
86
- # Offense count: 2
87
- Style/MissingRespondToMissing:
88
- Exclude:
89
- - 'lib/drip/resource.rb'
90
- - 'lib/drip/response.rb'
91
-
92
- # Offense count: 12
93
- # Cop supports --auto-correct.
94
- # Configuration parameters: Strict.
95
- Style/NumericLiterals:
96
- MinDigits: 8
97
-
98
- # Offense count: 700
99
- # Cop supports --auto-correct.
100
- # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
101
- # SupportedStyles: single_quotes, double_quotes
102
- Style/StringLiterals:
103
- Enabled: false
data/CHANGELOG.md CHANGED
@@ -6,10 +6,50 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- [master]: https://github.com/DripEmail/drip-ruby/compare/v3.4.2...HEAD
9
+ [main]: https://github.com/DripEmail/drip-ruby/compare/v3.5.0...HEAD
10
10
 
11
11
  - Your contribution here!
12
12
 
13
+ ## [3.5.0] - 2026-07-10
14
+
15
+ [3.5.0]: https://github.com/DripEmail/drip-ruby/compare/v3.4.3...v3.5.0
16
+
17
+ ### Security
18
+ - `Drip::Client::HTTPClient` no longer forwards the `Authorization`/Basic-auth
19
+ credentials when an HTTP redirect points to a different host than the one
20
+ originally requested.
21
+ - Path segments and query values built from caller-supplied ids (`id`,
22
+ `campaign_id`, `workflow_id`, `subscriber_id`, etc.) are now consistently
23
+ URL-escaped, matching the existing behavior for emails and tags.
24
+
25
+ ### Fixed
26
+ - `Drip::Client::Orders#create_or_update_order` no longer merges the `email`
27
+ option under a symbol key alongside a possible string `"email"` key, which
28
+ produced a hash with a duplicate JSON key and a deprecation warning under
29
+ recent `json` gem versions.
30
+
31
+ ### Changed
32
+ - Raised `required_ruby_version` to `>= 3.1` and bumped development
33
+ dependencies (minitest, mocha, rake, rubocop, rubocop-performance,
34
+ shoulda-context, simplecov, webmock) to current versions.
35
+ - Replaced Travis CI with a GitHub Actions workflow that runs the test suite
36
+ across Ruby 3.1-3.4 (via `ruby/setup-ruby`) plus a job that runs the suite
37
+ and rubocop through the project's `flake.nix` shell (via
38
+ `DeterminateSystems/determinate-nix-action`), so the documented dev
39
+ environment is itself covered by CI.
40
+ - Upgraded rubocop from 0.67.2 to 1.x, resolved the accumulated
41
+ `.rubocop_todo.yml` offenses, and fixed the underlying code where
42
+ reasonable rather than just re-suppressing them.
43
+ - Added a `flake.nix` development shell (ruby, bundler, libyaml, pkg-config)
44
+ for a reproducible local dev environment.
45
+
46
+ ## [3.4.3] - 2023-02-15
47
+
48
+ [3.4.3]: https://github.com/DripEmail/drip-ruby/compare/v3.4.2...v3.4.3
49
+
50
+ ### Added
51
+ - `Drip::Client::ShopperActivity#create_checkout_activity_event` can create `checkout` activity events now
52
+
13
53
  ## [3.4.2] - 2021-04-25
14
54
 
15
55
  [3.4.2]: https://github.com/DripEmail/drip-ruby/compare/v3.4.1...v3.4.2
data/Gemfile CHANGED
@@ -5,12 +5,13 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in drip-ruby.gemspec
6
6
  gemspec
7
7
 
8
- gem "bundler", ">= 1.6", "< 3"
8
+ gem "base64"
9
+ gem "bundler", ">= 2.0", "< 5"
9
10
  gem "minitest", "~> 5.0"
10
- gem "mocha", "~> 1.1"
11
- gem "rake", "~> 12.0"
12
- gem "rubocop", "~> 0.67.2"
13
- gem "rubocop-performance", "~> 1.1.0"
14
- gem "shoulda-context", "~> 1.0"
15
- gem "simplecov", require: false
16
- gem "webmock", "~> 3.4"
11
+ gem "mocha", "~> 2.1"
12
+ gem "rake", "~> 13.0"
13
+ gem "rubocop", "~> 1.81"
14
+ gem "rubocop-performance", "~> 1.26"
15
+ gem "shoulda-context", "~> 1.2"
16
+ gem "simplecov", "~> 0.22", require: false
17
+ gem "webmock", "~> 3.24"
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  A Ruby toolkit for the [Drip](https://www.getdrip.com/) API.
4
4
 
5
- [![Build Status](https://travis-ci.org/DripEmail/drip-ruby.svg?branch=master)](https://travis-ci.org/DripEmail/drip-ruby)
6
- [![Code Climate](https://codeclimate.com/github/DripEmail/drip-ruby/badges/gpa.svg)](https://codeclimate.com/github/DripEmail/drip-ruby)
5
+ [![CI](https://github.com/DripEmail/drip-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/DripEmail/drip-ruby/actions/workflows/ci.yml)
7
6
  [![Gem Version](https://badge.fury.io/rb/drip-ruby.svg)](https://badge.fury.io/rb/drip-ruby)
8
7
 
9
8
 
data/drip-ruby.gemspec CHANGED
@@ -1,7 +1,6 @@
1
- # coding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
5
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
5
  require 'drip/version'
7
6
 
@@ -17,8 +16,9 @@ Gem::Specification.new do |spec|
17
16
 
18
17
  spec.files = `git ls-files -z`.split("\x0")
19
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
19
  spec.require_paths = ["lib"]
22
20
 
23
- spec.required_ruby_version = '>= 2.3'
21
+ spec.required_ruby_version = '>= 3.1'
22
+
23
+ spec.metadata['rubygems_mfa_required'] = 'true'
24
24
  end
data/flake.lock ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "nodes": {
3
+ "flake-utils": {
4
+ "inputs": {
5
+ "systems": "systems"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1731533236,
9
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+ "owner": "numtide",
11
+ "repo": "flake-utils",
12
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "numtide",
17
+ "repo": "flake-utils",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nixpkgs": {
22
+ "locked": {
23
+ "lastModified": 1783522502,
24
+ "narHash": "sha256-iffAls3iaNTyJC2faYcUXSI+Gp02cDjYl+MygxKl2GI=",
25
+ "owner": "NixOS",
26
+ "repo": "nixpkgs",
27
+ "rev": "0bb7ec54c8483066ec9d7720e780a5caa71f8612",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "NixOS",
32
+ "ref": "nixos-unstable",
33
+ "repo": "nixpkgs",
34
+ "type": "github"
35
+ }
36
+ },
37
+ "root": {
38
+ "inputs": {
39
+ "flake-utils": "flake-utils",
40
+ "nixpkgs": "nixpkgs"
41
+ }
42
+ },
43
+ "systems": {
44
+ "locked": {
45
+ "lastModified": 1681028828,
46
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+ "owner": "nix-systems",
48
+ "repo": "default",
49
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+ "type": "github"
51
+ },
52
+ "original": {
53
+ "owner": "nix-systems",
54
+ "repo": "default",
55
+ "type": "github"
56
+ }
57
+ }
58
+ },
59
+ "root": "root",
60
+ "version": 7
61
+ }
data/flake.nix ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ description = "Development environment for drip-ruby";
3
+
4
+ inputs = {
5
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6
+ flake-utils.url = "github:numtide/flake-utils";
7
+ };
8
+
9
+ outputs = { self, nixpkgs, flake-utils }:
10
+ flake-utils.lib.eachDefaultSystem (system:
11
+ let
12
+ pkgs = nixpkgs.legacyPackages.${system};
13
+ in
14
+ {
15
+ devShells.default = pkgs.mkShell {
16
+ packages = [
17
+ pkgs.ruby_3_3
18
+ pkgs.bundler
19
+ pkgs.libyaml
20
+ pkgs.pkg-config
21
+ ];
22
+
23
+ shellHook = ''
24
+ export GEM_HOME="$PWD/.bundle/gems"
25
+ export BUNDLE_PATH="$GEM_HOME"
26
+ export PATH="$GEM_HOME/bin:$PATH"
27
+ echo "drip-ruby dev shell ($(ruby -v))"
28
+ echo "Run 'bundle install' then 'bundle exec rake test' to get started."
29
+ '';
30
+ };
31
+ });
32
+ }
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module Accounts
@@ -18,7 +20,7 @@ module Drip
18
20
  # Returns a Drip::Response.
19
21
  # See https://www.getdrip.com/docs/rest-api#accounts
20
22
  def account(id)
21
- make_json_api_request :get, "v2/accounts/#{id}"
23
+ make_json_api_request :get, "v2/accounts/#{CGI.escape id.to_s}"
22
24
  end
23
25
  end
24
26
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module Broadcasts
@@ -24,7 +26,7 @@ module Drip
24
26
  # Returns a Drip::Response.
25
27
  # See https://www.getdrip.com/docs/rest-api#broadcasts
26
28
  def broadcast(id)
27
- make_json_api_request :get, "v2/#{account_id}/broadcasts/#{id}"
29
+ make_json_api_request :get, "v2/#{account_id}/broadcasts/#{CGI.escape id.to_s}"
28
30
  end
29
31
  end
30
32
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module CampaignSubscriptions
@@ -10,7 +12,7 @@ module Drip
10
12
  # Returns a Drip::Response.
11
13
  # See https://www.getdrip.com/docs.rest-api#campaign_subscriptions
12
14
  def campaign_subscriptions(subscriber_id)
13
- make_json_api_request :get, "v2/#{account_id}/subscribers/#{subscriber_id}/campaign_subscriptions"
15
+ make_json_api_request :get, "v2/#{account_id}/subscribers/#{CGI.escape subscriber_id.to_s}/campaign_subscriptions"
14
16
  end
15
17
  end
16
18
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module Campaigns
@@ -26,7 +28,7 @@ module Drip
26
28
  # Returns a Drip::Response.
27
29
  # See https://www.getdrip.com/docs/rest-api#campaigns
28
30
  def campaign(id)
29
- make_json_api_request :get, "v2/#{account_id}/campaigns/#{id}"
31
+ make_json_api_request :get, "v2/#{account_id}/campaigns/#{CGI.escape id.to_s}"
30
32
  end
31
33
 
32
34
  # Public: Activate a campaign.
@@ -36,7 +38,7 @@ module Drip
36
38
  # Returns a Drip::Response.
37
39
  # See https://www.getdrip.com/docs/rest-api#campaigns
38
40
  def activate_campaign(id)
39
- make_json_api_request :post, "v2/#{account_id}/campaigns/#{id}/activate"
41
+ make_json_api_request :post, "v2/#{account_id}/campaigns/#{CGI.escape id.to_s}/activate"
40
42
  end
41
43
 
42
44
  # Public: Pause a campaign.
@@ -46,7 +48,7 @@ module Drip
46
48
  # Returns a Drip::Response.
47
49
  # See https://www.getdrip.com/docs/rest-api#campaigns
48
50
  def pause_campaign(id)
49
- make_json_api_request :post, "v2/#{account_id}/campaigns/#{id}/pause"
51
+ make_json_api_request :post, "v2/#{account_id}/campaigns/#{CGI.escape id.to_s}/pause"
50
52
  end
51
53
 
52
54
  # Public: List everyone subscribed to a campaign.
@@ -70,7 +72,7 @@ module Drip
70
72
  # Returns a Drip::Response.
71
73
  # See https://www.getdrip.com/docs/rest-api#campaigns
72
74
  def campaign_subscribers(id, options = {})
73
- make_json_api_request :get, "v2/#{account_id}/campaigns/#{id}/subscribers", options
75
+ make_json_api_request :get, "v2/#{account_id}/campaigns/#{CGI.escape id.to_s}/subscribers", options
74
76
  end
75
77
  end
76
78
  end
@@ -6,7 +6,15 @@ module Drip
6
6
  DEFAULT_URL_PREFIX = "https://api.getdrip.com/"
7
7
  private_constant :DEFAULT_URL_PREFIX
8
8
 
9
- CONFIGURATION_FIELDS = %i[access_token api_key account_id url_prefix http_open_timeout http_timeout].freeze
9
+ CONFIGURATION_FIELDS = %i[
10
+ access_token
11
+ account_id
12
+ api_key
13
+ http_open_timeout
14
+ http_timeout
15
+ skip_analytics
16
+ url_prefix
17
+ ].freeze
10
18
 
11
19
  attr_accessor(*CONFIGURATION_FIELDS)
12
20
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module Conversions
@@ -22,7 +24,7 @@ module Drip
22
24
  # Returns a Drip::Response.
23
25
  # See https://www.getdrip.com/docs/rest-api#conversions
24
26
  def conversion(id)
25
- make_json_api_request :get, "v2/#{account_id}/goals/#{id}"
27
+ make_json_api_request :get, "v2/#{account_id}/goals/#{CGI.escape id.to_s}"
26
28
  end
27
29
  end
28
30
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module Drip
4
6
  class Client
5
7
  module Forms
@@ -18,7 +20,7 @@ module Drip
18
20
  # Returns a Drip::Response.
19
21
  # See https://www.getdrip.com/docs/rest-api#forms
20
22
  def form(id)
21
- make_json_api_request :get, "v2/#{account_id}/forms/#{id}"
23
+ make_json_api_request :get, "v2/#{account_id}/forms/#{CGI.escape id.to_s}"
22
24
  end
23
25
  end
24
26
  end
@@ -13,40 +13,59 @@ module Drip
13
13
  def make_request(drip_request, redirected_url: nil, step: 0)
14
14
  raise TooManyRedirectsError, 'too many HTTP redirects' if step >= REDIRECT_LIMIT
15
15
 
16
- uri = redirected_url || drip_request.url.tap do |orig_url|
16
+ uri = redirected_url || request_uri(drip_request)
17
+ response = perform_request(drip_request, uri)
18
+
19
+ return make_request(drip_request, redirected_url: URI(response["Location"]), step: step + 1) if response.is_a?(Net::HTTPRedirection)
20
+
21
+ response
22
+ end
23
+
24
+ private
25
+
26
+ def request_uri(drip_request)
27
+ drip_request.url.tap do |orig_url|
17
28
  next if drip_request.http_verb != :get
18
29
 
19
30
  orig_url.query = URI.encode_www_form(drip_request.options)
20
31
  end
32
+ end
21
33
 
22
- response = Net::HTTP.start(uri.host, uri.port, connection_options(uri.scheme)) do |http|
34
+ def perform_request(drip_request, uri)
35
+ Net::HTTP.start(uri.host, uri.port, connection_options(uri.scheme)) do |http|
23
36
  request = drip_request.verb_klass.new uri
24
37
  request.body = drip_request.body
25
38
 
26
- add_standard_headers(request)
39
+ add_standard_headers(request, authenticated: same_host?(uri, drip_request.url))
27
40
  request['Content-Type'] = drip_request.content_type
28
41
 
29
42
  http.request request
30
43
  end
31
-
32
- return make_request(drip_request, redirected_url: URI(response["Location"]), step: step + 1) if response.is_a?(Net::HTTPRedirection)
33
-
34
- response
35
44
  end
36
45
 
37
- private
46
+ # Only send credentials to the host the request was originally made to.
47
+ # A redirect to a different host must not be able to exfiltrate the API
48
+ # key/access token.
49
+ def same_host?(uri, original_url)
50
+ uri.host == original_url.host
51
+ end
38
52
 
39
- def add_standard_headers(request)
53
+ def add_standard_headers(request, authenticated:)
40
54
  request['User-Agent'] = "Drip Ruby v#{Drip::VERSION}"
41
55
  request['Accept'] = "*/*"
42
56
 
57
+ add_authentication(request) if authenticated
58
+
59
+ request['Skip-Analytics'] = true if @config.skip_analytics
60
+ request
61
+ end
62
+
63
+ def add_authentication(request)
43
64
  if @config.access_token
44
65
  request['Authorization'] = "Bearer #{@config.access_token}"
45
66
  else
46
67
  request.basic_auth @config.api_key, ""
47
68
  end
48
-
49
- request
50
69
  end
51
70
 
52
71
  def connection_options(uri_scheme)
@@ -12,7 +12,7 @@ module Drip
12
12
  # Returns a Drip::Response.
13
13
  # See https://developer.drip.com/#orders
14
14
  def create_or_update_order(email, options = {})
15
- data = options.merge(email: email)
15
+ data = options.merge("email" => email)
16
16
  make_json_api_request :post, "v2/#{account_id}/orders", private_generate_resource("orders", data)
17
17
  end
18
18