ruby-pardot 1.2.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rubocop.yml +9 -0
  4. data/Gemfile +3 -1
  5. data/Gemfile.lock +26 -19
  6. data/README.rdoc +23 -18
  7. data/Rakefile +2 -3
  8. data/lib/pardot/authentication.rb +23 -12
  9. data/lib/pardot/client.rb +18 -6
  10. data/lib/pardot/error.rb +6 -2
  11. data/lib/pardot/http.rb +51 -41
  12. data/lib/pardot/objects/custom_fields.rb +33 -0
  13. data/lib/pardot/objects/emails.rb +9 -14
  14. data/lib/pardot/objects/list_memberships.rb +8 -12
  15. data/lib/pardot/objects/lists.rb +20 -25
  16. data/lib/pardot/objects/opportunities.rb +21 -26
  17. data/lib/pardot/objects/prospect_accounts.rb +6 -7
  18. data/lib/pardot/objects/prospects.rb +69 -71
  19. data/lib/pardot/objects/users.rb +17 -21
  20. data/lib/pardot/objects/visitor_activities.rb +15 -19
  21. data/lib/pardot/objects/visitors.rb +17 -21
  22. data/lib/pardot/objects/visits.rb +15 -19
  23. data/lib/pardot/version.rb +1 -1
  24. data/lib/ruby-pardot.rb +1 -0
  25. data/ruby-pardot.gemspec +15 -13
  26. data/spec/pardot/authentication_spec.rb +84 -50
  27. data/spec/pardot/client_spec.rb +52 -17
  28. data/spec/pardot/error_spec.rb +6 -4
  29. data/spec/pardot/http_spec.rb +96 -104
  30. data/spec/pardot/objects/custom_fields_spec.rb +53 -0
  31. data/spec/pardot/objects/emails_spec.rb +34 -33
  32. data/spec/pardot/objects/lists_spec.rb +34 -37
  33. data/spec/pardot/objects/opportunities_spec.rb +59 -60
  34. data/spec/pardot/objects/prospect_accounts_spec.rb +72 -73
  35. data/spec/pardot/objects/prospects_spec.rb +58 -57
  36. data/spec/pardot/objects/users_spec.rb +58 -60
  37. data/spec/pardot/objects/visitor_activities_spec.rb +57 -60
  38. data/spec/pardot/objects/visitors_spec.rb +56 -60
  39. data/spec/pardot/objects/visits_spec.rb +56 -60
  40. data/spec/spec_helper.rb +2 -0
  41. data/spec/support/client_support.rb +40 -4
  42. data/spec/support/fakeweb.rb +14 -5
  43. metadata +17 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33f862629251e35bc4abea0f50af5fbd34e83d2b561529107dda17f5c5fe5bf8
4
- data.tar.gz: 773061f478695e10e26c2f17ea36ba1a81ee2a241797426e1581a02ac59f24d1
3
+ metadata.gz: f3bbcca81ecfa08ef3cfb444a8117ef8a708f3e6975336e0f48fd480972449a6
4
+ data.tar.gz: 1f4b717f3150591b35ae17d96a5da3382235988afbe06c646cb84dfd198a7461
5
5
  SHA512:
6
- metadata.gz: 439fc348827c87938b93035b7b1d6bcdb6a043e49897041b9b45029b9f95dd3b562db3a3cad345b58dde4b9bb0c21823d311f18c90d4f593562b8d7e695f7f29
7
- data.tar.gz: b63c4c6083d3c86d2204ea43638a3133bf619a746d5c355d29a47c4c2dd326a68e1a5a77322183655829be0d0959b335a67f816a5bd7ad30609ef23b7b4325e3
6
+ metadata.gz: e0da946b746fed6cd5091b6d6e55d978a6cee69f641aa7e01040013d3ca81538eeec91424b6e23ca7232975cc100716681eba97007dd60d68f35f9c2bb5e0c6f
7
+ data.tar.gz: 519af7a9e7870b7a8da0242c7c6fd2f011ac46251a24f1fcd5f82117191f596c565032927bbdd152b76a3137038679d02355b750389ecd6d74c600d136c7d17c
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ .vscode
5
+ bin
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Metrics/BlockLength:
5
+ Enabled: false
6
+ Metrics/MethodLength:
7
+ Enabled: false
8
+ Layout/LineLength:
9
+ Enabled: false
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
- source :gemcutter
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in ruby-pardot.gemspec
4
6
  gemspec
data/Gemfile.lock CHANGED
@@ -1,40 +1,47 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-pardot (1.2.0)
4
+ ruby-pardot (1.4.0)
5
5
  crack (= 0.4.3)
6
- httparty (= 0.13.1)
6
+ httparty (= 0.18.1)
7
7
 
8
8
  GEM
9
- remote: http://rubygems.org/
9
+ remote: https://rubygems.org/
10
10
  specs:
11
11
  crack (0.4.3)
12
12
  safe_yaml (~> 1.0.0)
13
- diff-lcs (1.1.2)
13
+ diff-lcs (1.4.4)
14
14
  fakeweb (1.3.0)
15
- httparty (0.13.1)
16
- json (~> 1.8)
15
+ httparty (0.18.1)
16
+ mime-types (~> 3.0)
17
17
  multi_xml (>= 0.5.2)
18
- json (1.8.6)
18
+ mime-types (3.3.1)
19
+ mime-types-data (~> 3.2015)
20
+ mime-types-data (3.2020.1104)
19
21
  multi_xml (0.6.0)
20
- rspec (2.5.0)
21
- rspec-core (~> 2.5.0)
22
- rspec-expectations (~> 2.5.0)
23
- rspec-mocks (~> 2.5.0)
24
- rspec-core (2.5.1)
25
- rspec-expectations (2.5.0)
26
- diff-lcs (~> 1.1.2)
27
- rspec-mocks (2.5.0)
28
- safe_yaml (1.0.4)
22
+ rspec (3.5.0)
23
+ rspec-core (~> 3.5.0)
24
+ rspec-expectations (~> 3.5.0)
25
+ rspec-mocks (~> 3.5.0)
26
+ rspec-core (3.5.4)
27
+ rspec-support (~> 3.5.0)
28
+ rspec-expectations (3.5.0)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.5.0)
31
+ rspec-mocks (3.5.0)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.5.0)
34
+ rspec-support (3.5.0)
35
+ safe_yaml (1.0.5)
29
36
 
30
37
  PLATFORMS
31
38
  ruby
32
39
 
33
40
  DEPENDENCIES
34
41
  bundler (>= 1.10)
35
- fakeweb
36
- rspec
42
+ fakeweb (= 1.3.0)
43
+ rspec (= 3.5.0)
37
44
  ruby-pardot!
38
45
 
39
46
  BUNDLED WITH
40
- 2.0.1
47
+ 2.2.7
data/README.rdoc CHANGED
@@ -8,18 +8,23 @@ Add the following to your Gemfile
8
8
 
9
9
  === Authentication
10
10
 
11
- The client will authenticate before performing other API calls, but you can manually authenticate as well
12
-
13
- client = Pardot::Client.new email, password, user_key
14
-
15
- # will raise a Pardot::ResponseError if login fails
16
- # will raise a Pardot::NetError if the http call fails
17
- client.authenticate
18
-
11
+ In order to use this client, an access token retrieved from Salesforce OAuth must be specified. See
12
+ the [authetication documentation on developer.pardot.com](https://developer.pardot.com/kb/authentication/) for more information.
13
+
14
+ require "ruby-pardot"
15
+
16
+ version = 3 # or 4
17
+ access_token = '<access_token>' # Retrieve an access token from Salesforce using OAuth
18
+ business_unit_id = '<business_unit_id>' # Specify the Business Unit ID of the account to access
19
+ client = Pardot::Client.new nil, nil, nil, version, access_token, business_unit_id
20
+
21
+ Usage of the username, password, and API key authentication is deprecated and will be removed in an upcoming release.
22
+
19
23
  === Object Types
20
24
 
21
25
  The available objects are:
22
26
 
27
+ * custom_fields
23
28
  * emails
24
29
  * lists
25
30
  * opportunities
@@ -30,15 +35,15 @@ The available objects are:
30
35
  * visits
31
36
 
32
37
  === Querying Objects
33
-
38
+
34
39
  http://developer.pardot.com/kb/api-version-3/querying-prospects
35
-
40
+
36
41
  Most objects accept limit, offset, sort_by, and sord_order parameters
37
42
 
38
43
  prospects = client.prospects.query(:assigned => false, :sort_by => "last_activity_at", :limit => 20)
39
-
44
+
40
45
  prospects["total_results"] # number of prospects found
41
-
46
+
42
47
  prospects["prospect"].each do |prospect|
43
48
  puts prospect["first_name"]
44
49
  end
@@ -50,11 +55,11 @@ See each individual object's API reference page for available methods
50
55
  http://developer.pardot.com/kb/api-version-3/using-prospects
51
56
 
52
57
  prospect = client.prospects.create("user@test.com", :first_name => "John", :last_name => "Doe")
53
-
58
+
54
59
  prospect.each do |key, value|
55
60
  puts "#{key} is #{value}"
56
61
  end
57
-
62
+
58
63
  === Emails
59
64
 
60
65
  See each individual call's [API reference page](http://developer.pardot.com/kb/api-version-3/introduction-table-of-contents).
@@ -63,15 +68,15 @@ See each individual call's [API reference page](http://developer.pardot.com/kb/a
63
68
  @pardot.emails.read_by_id(email_id)
64
69
  @pardot.emails.send_to_list(:email_template_id => template_id, 'list_ids[]' => list_id, :campaign_id => campaign_id)
65
70
  @pardot.emails.send_to_prospect(prospect_id, :campaign_id => campaign_id, :email_template_id => template_id)
66
-
71
+
67
72
  === Output formats
68
-
73
+
69
74
  client.format = "simple" # default
70
75
  client.format = "mobile"
71
76
  client.format = "full"
72
77
 
73
78
  === Error handling
74
-
79
+
75
80
  Pardot will respond with an error message when you provide invalid parameters
76
81
 
77
82
  begin
@@ -81,7 +86,7 @@ Pardot will respond with an error message when you provide invalid parameters
81
86
  end
82
87
 
83
88
  Performing API calls across the internet is inherently unsafe, so be sure to catch the exceptions
84
-
89
+
85
90
  begin
86
91
  visitor = client.visitors.query(:id_greater_than => 200)
87
92
  rescue Pardot::NetError => e
data/Rakefile CHANGED
@@ -1,11 +1,10 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
-
5
4
  require 'rspec/core'
6
5
  require 'rspec/core/rake_task'
7
6
 
8
- desc "Run all specs"
7
+ desc 'Run all specs'
9
8
  RSpec::Core::RakeTask.new(:spec) do |t|
10
- t.pattern = "./spec/**/*_spec.rb"
9
+ t.pattern = './spec/**/*_spec.rb'
11
10
  end
@@ -1,29 +1,40 @@
1
1
  module Pardot
2
2
  module Authentication
3
-
3
+ # @deprecated Use of username and password authentication is deprecated.
4
4
  def authenticate
5
- resp = post "login", nil, nil, nil, :email => @email, :password => @password, :user_key => @user_key
6
- update_version(resp["version"]) if resp && resp["version"]
7
- @api_key = resp && resp["api_key"]
5
+ if using_salesforce_access_token?
6
+ raise 'Authentication not available when using Salesforce access token. See https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/intro_oauth_and_connected_apps.htm for more information.'
7
+ end
8
+
9
+ warn '[DEPRECATION] Use of username and password authentication is deprecated in favor of Salesforce OAuth. See https://developer.pardot.com/kb/authentication/ for more information.'
10
+ resp = post 'login', nil, nil, nil, email: @email, password: @password, user_key: @user_key
11
+ update_version(resp['version']) if resp && resp['version']
12
+ @api_key = resp && resp['api_key']
8
13
  end
9
-
14
+
10
15
  def authenticated?
11
- @api_key != nil
16
+ !@api_key.nil? || !@salesforce_access_token.nil?
17
+ end
18
+
19
+ def using_salesforce_access_token?
20
+ @salesforce_access_token != nil
12
21
  end
13
-
22
+
14
23
  def reauthenticate
24
+ if using_salesforce_access_token?
25
+ raise 'Reauthentication not available when using Salesforce access token. See https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/oauth_refresh_token_flow.htm for more information.'
26
+ end
27
+
28
+ warn '[DEPRECATION] Use Salesforce OAuth to refresh the Salesforce access token. See https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/oauth_refresh_token_flow.htm for more information.'
15
29
  @api_key = nil
16
30
  authenticate
17
31
  end
18
32
 
19
33
  private
20
34
 
21
- def update_version version
22
- if version.is_a? Array
23
- version = version.last
24
- end
35
+ def update_version(version)
36
+ version = version.last if version.is_a? Array
25
37
  @version = version if version.to_i > 3
26
38
  end
27
-
28
39
  end
29
40
  end
data/lib/pardot/client.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  module Pardot
2
-
3
2
  class Client
4
-
5
3
  include HTTParty
6
4
  base_uri 'https://pi.pardot.com'
7
5
  format :xml
@@ -9,6 +7,7 @@ module Pardot
9
7
  include Authentication
10
8
  include Http
11
9
 
10
+ include Objects::CustomFields
12
11
  include Objects::Emails
13
12
  include Objects::Lists
14
13
  include Objects::ListMemberships
@@ -20,16 +19,29 @@ module Pardot
20
19
  include Objects::Visits
21
20
  include Objects::VisitorActivities
22
21
 
23
- attr_accessor :email, :password, :user_key, :api_key, :version, :format
22
+ attr_accessor :email, :password, :user_key, :api_key, :version, :salesforce_access_token, :business_unit_id, :format
23
+
24
+ # @deprecated Arguments email, password and user_key are deprecated. Use salesforce_access_token with Salesforce OAuth.
25
+ def initialize(email = nil, password = nil, user_key = nil, version = 3, salesforce_access_token = nil, business_unit_id = nil)
26
+ unless email.nil? || password.nil? || user_key.nil?
27
+ warn '[DEPRECATION] Use of username and password authentication is deprecated in favor of Salesforce OAuth. See https://developer.pardot.com/kb/authentication/ for more information.'
28
+ end
29
+
30
+ if !salesforce_access_token.nil? && business_unit_id.nil?
31
+ raise 'business_unit_id required when using Salesforce access_token'
32
+ end
33
+ if !business_unit_id.nil? && (!business_unit_id.start_with?('0Uv') || business_unit_id.length != 18)
34
+ raise "Invalid business_unit_id value. Expected ID to start with '0Uv' and be length of 18 characters."
35
+ end
24
36
 
25
- def initialize email, password, user_key, version = 3
26
37
  @email = email
27
38
  @password = password
28
39
  @user_key = user_key
29
40
  @version = version
41
+ @salesforce_access_token = salesforce_access_token
42
+ @business_unit_id = business_unit_id
30
43
 
31
- @format = "simple"
44
+ @format = 'simple'
32
45
  end
33
-
34
46
  end
35
47
  end
data/lib/pardot/error.rb CHANGED
@@ -1,19 +1,23 @@
1
1
  module Pardot
2
2
  class Error < StandardError; end
3
+
3
4
  class NetError < Error; end
5
+
4
6
  class ExpiredApiKeyError < Error; end
5
7
 
8
+ class AccessTokenExpiredError < Error; end
9
+
6
10
  class ResponseError < Error
7
11
  def initialize(res)
8
12
  @res = res
9
13
  end
10
14
 
11
15
  def to_s
12
- @res["__content__"]
16
+ @res['__content__']
13
17
  end
14
18
 
15
19
  def code
16
- @res["code"].to_i
20
+ @res['code'].to_i
17
21
  end
18
22
 
19
23
  def inspect
data/lib/pardot/http.rb CHANGED
@@ -1,70 +1,80 @@
1
1
  module Pardot
2
2
  module Http
3
-
4
- def get object, path, params = {}, num_retries = 0
3
+ def get(object, path, params = {}, num_retries = 0)
5
4
  smooth_params object, params
6
5
  full_path = fullpath object, path
7
- check_response self.class.get(full_path, :query => params)
8
-
6
+ headers = create_auth_header object
7
+ check_response self.class.get(full_path, query: params, headers: headers)
9
8
  rescue Pardot::ExpiredApiKeyError => e
10
9
  handle_expired_api_key :get, object, path, params, num_retries, e
11
-
12
10
  rescue SocketError, Interrupt, EOFError, SystemCallError, Timeout::Error, MultiXml::ParseError => e
13
- raise Pardot::NetError.new(e)
11
+ raise Pardot::NetError, e
14
12
  end
15
-
16
- def post object, path, params = {}, num_retries = 0, bodyParams = {}
13
+
14
+ def post(object, path, params = {}, num_retries = 0, bodyParams = {})
17
15
  smooth_params object, params
18
16
  full_path = fullpath object, path
19
- check_response self.class.post(full_path, :query => params, :body => bodyParams)
20
-
17
+ headers = create_auth_header object
18
+ check_response self.class.post(full_path, query: params, body: bodyParams, headers: headers)
21
19
  rescue Pardot::ExpiredApiKeyError => e
22
20
  handle_expired_api_key :post, object, path, params, num_retries, e
23
-
24
21
  rescue SocketError, Interrupt, EOFError, SystemCallError, Timeout::Error, MultiXml::ParseError => e
25
- raise Pardot::NetError.new(e)
22
+ raise Pardot::NetError, e
26
23
  end
27
-
24
+
28
25
  protected
29
-
30
- def handle_expired_api_key method, object, path, params, num_retries, e
26
+
27
+ # @deprecated With Salesforce OAuth, this method will never be invoked.
28
+ def handle_expired_api_key(method, object, path, params, num_retries, e)
31
29
  raise e unless num_retries == 0
32
-
30
+
33
31
  reauthenticate
34
-
32
+
35
33
  send(method, object, path, params, 1)
36
34
  end
37
-
38
- def smooth_params object, params
39
- return if object == "login"
40
-
35
+
36
+ def smooth_params(object, params)
37
+ return if object == 'login'
38
+
41
39
  authenticate unless authenticated?
42
- params.merge! :user_key => @user_key, :api_key => @api_key, :format => @format
40
+ params.merge! format: @format
43
41
  end
44
-
45
- def check_response http_response
46
- rsp = http_response["rsp"]
47
-
48
- error = rsp["err"] if rsp
49
- error ||= "Unknown Failure: #{rsp.inspect}" if rsp && rsp["stat"] == "fail"
42
+
43
+ def create_auth_header(object)
44
+ return if object == 'login'
45
+
46
+ if using_salesforce_access_token?
47
+ {
48
+ :Authorization => "Bearer #{@salesforce_access_token}",
49
+ 'Pardot-Business-Unit-Id' => @business_unit_id
50
+ }
51
+ else
52
+ { Authorization: "Pardot api_key=#{@api_key}, user_key=#{@user_key}" }
53
+ end
54
+ end
55
+
56
+ def check_response(http_response)
57
+ rsp = http_response['rsp']
58
+
59
+ error = rsp['err'] if rsp
60
+ error ||= "Unknown Failure: #{rsp.inspect}" if rsp && rsp['stat'] == 'fail'
50
61
  content = error['__content__'] if error.is_a?(Hash)
51
-
52
- if [error, content].include?("Invalid API key or user key") && @api_key
53
- raise ExpiredApiKeyError.new @api_key
62
+
63
+ if [error, content].grep(/access_token is invalid/).any? && using_salesforce_access_token?
64
+ raise AccessTokenExpiredError,
65
+ 'Access token is invalid. Use Salesforce OAuth to refresh the existing Salesforce access token or to retrieve a new token. See https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/oauth_refresh_token_flow.htm for more information.'
54
66
  end
55
-
56
- raise ResponseError.new error if error
57
-
67
+ raise ExpiredApiKeyError, @api_key if [error, content].include?('Invalid API key or user key') && @api_key
68
+
69
+ raise ResponseError, error if error
70
+
58
71
  rsp
59
72
  end
60
-
61
- def fullpath object, path
62
- full = File.join("/api", object, "version", @version.to_s)
63
- unless path.nil?
64
- full = File.join(full, path)
65
- end
73
+
74
+ def fullpath(object, path)
75
+ full = File.join('/api', object, 'version', @version.to_s)
76
+ full = File.join(full, path) unless path.nil?
66
77
  full
67
78
  end
68
-
69
79
  end
70
80
  end