hubspot-api-client 7.2.0 → 7.3.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/hubspot/version.rb +1 -1
  4. data/sample-apps/timeline-events-app/.env.template +5 -0
  5. data/sample-apps/timeline-events-app/.gitignore +35 -0
  6. data/sample-apps/timeline-events-app/.rspec +1 -0
  7. data/sample-apps/timeline-events-app/.ruby-version +1 -0
  8. data/sample-apps/timeline-events-app/Dockerfile +22 -0
  9. data/sample-apps/timeline-events-app/Gemfile +33 -0
  10. data/sample-apps/timeline-events-app/Gemfile.lock +271 -0
  11. data/sample-apps/timeline-events-app/README.md +0 -0
  12. data/sample-apps/timeline-events-app/Rakefile +6 -0
  13. data/sample-apps/timeline-events-app/app/assets/config/manifest.js +3 -0
  14. data/sample-apps/timeline-events-app/app/assets/images/.keep +0 -0
  15. data/sample-apps/timeline-events-app/app/assets/javascripts/application.js +15 -0
  16. data/sample-apps/timeline-events-app/app/assets/javascripts/cable.js +13 -0
  17. data/sample-apps/timeline-events-app/app/assets/javascripts/channels/.keep +0 -0
  18. data/sample-apps/timeline-events-app/app/assets/stylesheets/application.css +101 -0
  19. data/sample-apps/timeline-events-app/app/controllers/application_controller.rb +12 -0
  20. data/sample-apps/timeline-events-app/app/controllers/concerns/.keep +0 -0
  21. data/sample-apps/timeline-events-app/app/controllers/concerns/exception_handler.rb +12 -0
  22. data/sample-apps/timeline-events-app/app/controllers/oauth/authorization_controller.rb +19 -0
  23. data/sample-apps/timeline-events-app/app/controllers/timeline_events_controller.rb +37 -0
  24. data/sample-apps/timeline-events-app/app/helpers/application_helper.rb +2 -0
  25. data/sample-apps/timeline-events-app/app/lib/services/authorization/authorize_hubspot.rb +15 -0
  26. data/sample-apps/timeline-events-app/app/lib/services/authorization/get_authorization_uri.rb +33 -0
  27. data/sample-apps/timeline-events-app/app/lib/services/authorization/tokens/base.rb +19 -0
  28. data/sample-apps/timeline-events-app/app/lib/services/authorization/tokens/generate.rb +26 -0
  29. data/sample-apps/timeline-events-app/app/lib/services/authorization/tokens/refresh.rb +33 -0
  30. data/sample-apps/timeline-events-app/app/lib/services/hubspot/contacts/search.rb +37 -0
  31. data/sample-apps/timeline-events-app/app/lib/services/hubspot/timeline/create_event.rb +20 -0
  32. data/sample-apps/timeline-events-app/app/lib/services/hubspot/timeline/create_template.rb +39 -0
  33. data/sample-apps/timeline-events-app/app/models/application_record.rb +3 -0
  34. data/sample-apps/timeline-events-app/app/models/concerns/.keep +0 -0
  35. data/sample-apps/timeline-events-app/app/views/layouts/application.html.erb +23 -0
  36. data/sample-apps/timeline-events-app/app/views/oauth/authorization/login.html.erb +15 -0
  37. data/sample-apps/timeline-events-app/app/views/shared/_header.html.erb +12 -0
  38. data/sample-apps/timeline-events-app/app/views/timeline_events/index.html.erb +55 -0
  39. data/sample-apps/timeline-events-app/bin/bundle +3 -0
  40. data/sample-apps/timeline-events-app/bin/rails +9 -0
  41. data/sample-apps/timeline-events-app/bin/rake +9 -0
  42. data/sample-apps/timeline-events-app/bin/setup +36 -0
  43. data/sample-apps/timeline-events-app/bin/spring +17 -0
  44. data/sample-apps/timeline-events-app/bin/update +31 -0
  45. data/sample-apps/timeline-events-app/bin/yarn +11 -0
  46. data/sample-apps/timeline-events-app/config.ru +5 -0
  47. data/sample-apps/timeline-events-app/config/application.rb +19 -0
  48. data/sample-apps/timeline-events-app/config/boot.rb +3 -0
  49. data/sample-apps/timeline-events-app/config/database.yml +25 -0
  50. data/sample-apps/timeline-events-app/config/environment.rb +5 -0
  51. data/sample-apps/timeline-events-app/config/environments/development.rb +61 -0
  52. data/sample-apps/timeline-events-app/config/environments/production.rb +94 -0
  53. data/sample-apps/timeline-events-app/config/environments/test.rb +46 -0
  54. data/sample-apps/timeline-events-app/config/initializers/assets.rb +14 -0
  55. data/sample-apps/timeline-events-app/config/initializers/filter_parameter_logging.rb +4 -0
  56. data/sample-apps/timeline-events-app/config/initializers/hubspot-api-client.rb +3 -0
  57. data/sample-apps/timeline-events-app/config/initializers/mime_types.rb +1 -0
  58. data/sample-apps/timeline-events-app/config/initializers/wrap_parameters.rb +14 -0
  59. data/sample-apps/timeline-events-app/config/locales/en.yml +33 -0
  60. data/sample-apps/timeline-events-app/config/puma.rb +34 -0
  61. data/sample-apps/timeline-events-app/config/routes.rb +7 -0
  62. data/sample-apps/timeline-events-app/config/spring.rb +6 -0
  63. data/sample-apps/timeline-events-app/db/seeds.rb +7 -0
  64. data/sample-apps/timeline-events-app/docker-compose.yml +11 -0
  65. data/sample-apps/timeline-events-app/docker-entrypoint.sh +8 -0
  66. data/sample-apps/timeline-events-app/lib/assets/.keep +0 -0
  67. data/sample-apps/timeline-events-app/lib/tasks/.keep +0 -0
  68. data/sample-apps/timeline-events-app/log/.keep +0 -0
  69. data/sample-apps/timeline-events-app/package.json +5 -0
  70. data/sample-apps/timeline-events-app/public/404.html +67 -0
  71. data/sample-apps/timeline-events-app/public/422.html +67 -0
  72. data/sample-apps/timeline-events-app/public/500.html +66 -0
  73. data/sample-apps/timeline-events-app/public/apple-touch-icon-precomposed.png +0 -0
  74. data/sample-apps/timeline-events-app/public/apple-touch-icon.png +0 -0
  75. data/sample-apps/timeline-events-app/public/favicon.ico +0 -0
  76. data/sample-apps/timeline-events-app/public/robots.txt +1 -0
  77. data/sample-apps/timeline-events-app/spec/rails_helper.rb +42 -0
  78. data/sample-apps/timeline-events-app/spec/spec_helper.rb +11 -0
  79. data/sample-apps/timeline-events-app/tmp/.keep +0 -0
  80. metadata +148 -2
@@ -0,0 +1,101 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
6
+ * vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
16
+
17
+ .wrapper .container {
18
+ padding-bottom: 2rem;
19
+ padding-top: 2rem;
20
+ }
21
+
22
+ .navigation {
23
+ background: #f4f5f6;
24
+ border-bottom: .1rem solid #d1d1d1;
25
+ display: block;
26
+ height: 5.2rem;
27
+ left: 0;
28
+ max-width: 100%;
29
+ width: 100%;
30
+ }
31
+
32
+ .navigation .container {
33
+ padding-bottom: 0;
34
+ padding-top: 0
35
+ }
36
+
37
+ .navigation .navigation-list {
38
+ list-style: none;
39
+ margin-bottom: 0;
40
+ }
41
+
42
+ .navigation .navigation-item {
43
+ float: left;
44
+ margin-bottom: 0;
45
+ margin-left: 2.5rem;
46
+ position: relative
47
+ }
48
+
49
+ .navigation .navigation-title, .navigation .title {
50
+ color: #606c76;
51
+ position: relative
52
+ }
53
+
54
+ .navigation .navigation-link, .navigation .navigation-title, .navigation .title {
55
+ display: inline;
56
+ font-size: 1.6rem;
57
+ line-height: 5.2rem;
58
+ padding: 0;
59
+ text-decoration: none
60
+ }
61
+
62
+ .navigation .navigation-link.active {
63
+ color: #606c76
64
+ }
65
+
66
+ pre {
67
+ line-height: 0.7;
68
+ }
69
+
70
+ pre p {
71
+ margin: 0;
72
+ margin-left: 5px;
73
+ }
74
+
75
+ .row {
76
+ display: flex;
77
+ }
78
+
79
+ .column {
80
+ flex: 50%;
81
+ }
82
+
83
+ .alert {
84
+ padding: 20px;
85
+ background-color: #f7786f;
86
+ color: white;
87
+ margin-bottom: 15px;
88
+ }
89
+
90
+ .contacts-iframe {
91
+ height: 700px;
92
+ width: 100%;
93
+ position:relative;
94
+ }
95
+
96
+ .contacts-iframe iframe {
97
+ border: none;
98
+ position:absolute;
99
+ width:1080px;
100
+ height:900px;
101
+ }
@@ -0,0 +1,12 @@
1
+ class ApplicationController < ActionController::Base
2
+ include ExceptionHandler
3
+
4
+ before_action :check_env_variables
5
+
6
+ private
7
+
8
+ def check_env_variables
9
+ missing_vars = %w[HUBSPOT_CLIENT_ID HUBSPOT_CLIENT_SECRET].select { |var| ENV[var].blank? }
10
+ raise(ExceptionHandler::HubspotError.new, "Please specify #{missing_vars.join(', ')} in .env") if missing_vars.present?
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module ExceptionHandler
2
+ extend ActiveSupport::Concern
3
+
4
+ class HubspotError < StandardError; end
5
+
6
+ included do
7
+ rescue_from HubspotError do |error|
8
+ @error = error
9
+ render template: 'timeline_events/index'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ module Oauth
2
+ class AuthorizationController < ApplicationController
3
+ def authorize
4
+ url = Services::Authorization::GetAuthorizationUri.new(request: request).call
5
+ redirect_to url
6
+ end
7
+
8
+ def callback
9
+ session[:tokens] = Services::Authorization::Tokens::Generate.new(
10
+ code: params[:code],
11
+ request: request
12
+ ).call
13
+ Services::Authorization::AuthorizeHubspot.new(tokens: session[:tokens]).call
14
+ redirect_to root_path
15
+ end
16
+
17
+ def login;end
18
+ end
19
+ end
@@ -0,0 +1,37 @@
1
+ class TimelineEventsController < ApplicationController
2
+ before_action :authorize
3
+
4
+ def index
5
+ return unless params[:contact_id]
6
+
7
+ @contacts_url = 'https://app.hubspot.com/contacts/' + ENV['HUBSPOT_ACCOUNT_ID'] +
8
+ '/contact/' + params[:contact_id]
9
+ end
10
+
11
+ def create
12
+ if email_valid?
13
+ template = Services::Hubspot::Timeline::CreateTemplate.new(template_params).call
14
+ event = Services::Hubspot::Timeline::CreateEvent.new(template_params[:email], template.id).call
15
+ redirect_to root_path(contact_id: event.object_id)
16
+ else
17
+ redirect_to root_path, flash: { error: "Error: we can't find this email in your contacts list." }
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def email_valid?
24
+ Services::Hubspot::Contacts::Search.new(email: template_params[:email]).call.present?
25
+ end
26
+
27
+ def template_params
28
+ params.require(:event_template).permit(:email, :target_record_type, :header_template, :detail_template)
29
+ end
30
+
31
+ def authorize
32
+ redirect_to login_path and return if session['tokens'].blank?
33
+
34
+ session['tokens'] = Services::Authorization::Tokens::Refresh.new(tokens: session['tokens'], request: request).call
35
+ Services::Authorization::AuthorizeHubspot.new(tokens: session['tokens']).call
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,15 @@
1
+ module Services
2
+ module Authorization
3
+ class AuthorizeHubspot
4
+ def initialize(tokens:)
5
+ @tokens = tokens
6
+ end
7
+
8
+ def call
9
+ ::Hubspot.configure do |config|
10
+ config.access_token = @tokens[:access_token]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ module Services
2
+ module Authorization
3
+ class GetAuthorizationUri
4
+ CALLBACK_PATH = '/oauth/callback'.freeze
5
+
6
+ def initialize(request:)
7
+ @request = request
8
+ end
9
+
10
+ def call
11
+ check_presence_of_credentials
12
+
13
+ ::Hubspot::OAuthHelper.authorize_url(
14
+ client_id: ENV['HUBSPOT_CLIENT_ID'],
15
+ redirect_uri: redirect_uri,
16
+ scope: %w[contacts]
17
+ )
18
+ end
19
+
20
+ private
21
+
22
+ def redirect_uri
23
+ @request.protocol + @request.host_with_port + CALLBACK_PATH
24
+ end
25
+
26
+ def check_presence_of_credentials
27
+ return if ENV['HUBSPOT_CLIENT_ID'].present?
28
+
29
+ raise(ExceptionHandler::HubspotError.new, 'Please specify HUBSPOT_CLIENT_ID in .env')
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module Services
2
+ module Authorization
3
+ module Tokens
4
+ class Base
5
+ CALLBACK_PATH = '/oauth/callback'.freeze
6
+
7
+ def expires_at(expires_in)
8
+ Time.current + (expires_in * 0.95).round
9
+ end
10
+
11
+ private
12
+
13
+ def redirect_uri
14
+ @request.protocol + @request.host_with_port + CALLBACK_PATH
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ module Services
2
+ module Authorization
3
+ module Tokens
4
+ class Generate < Tokens::Base
5
+ def initialize(code:, request:)
6
+ @code = code
7
+ @request = request
8
+ end
9
+
10
+ def call
11
+ default_api = ::Hubspot::OAuth::DefaultApi.new
12
+ tokens = default_api.create_token(
13
+ grant_type: :authorization_code,
14
+ code: @code,
15
+ redirect_uri: redirect_uri,
16
+ client_id: ENV['HUBSPOT_CLIENT_ID'],
17
+ client_secret: ENV['HUBSPOT_CLIENT_SECRET'],
18
+ return_type: 'Object'
19
+ )
20
+ tokens[:expires_at] = expires_at(tokens[:expires_in])
21
+ tokens
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,33 @@
1
+ module Services
2
+ module Authorization
3
+ module Tokens
4
+ class Refresh < Tokens::Base
5
+ def initialize(tokens:, request:)
6
+ @tokens = tokens
7
+ @request = request
8
+ end
9
+
10
+ def call
11
+ @tokens = refresh_tokens if Time.current > @tokens[:expires_at]
12
+ @tokens
13
+ end
14
+
15
+ private
16
+
17
+ def refresh_tokens
18
+ default_api = ::Hubspot::OAuth::DefaultApi.new
19
+ tokens = default_api.create_token(
20
+ grant_type: :refresh_token,
21
+ refresh_token: @tokens[:refresh_token],
22
+ redirect_uri: redirect_uri,
23
+ client_id: ENV['HUBSPOT_CLIENT_ID'],
24
+ client_secret: ENV['HUBSPOT_CLIENT_SECRET'],
25
+ return_type: 'Object'
26
+ )
27
+ tokens[:expires_at] = expires_at(tokens[:expires_in])
28
+ tokens
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ module Services
2
+ module Hubspot
3
+ module Contacts
4
+ class Search
5
+ def initialize(email:)
6
+ @email = email
7
+ end
8
+
9
+ def call
10
+ search_api = ::Hubspot::Crm::Contacts::SearchApi.new
11
+ results = search_api.do_search(search_request, auth_names: 'oauth2').results
12
+ results = add_fullnames(results)
13
+ results
14
+ end
15
+
16
+ private
17
+
18
+ def search_request
19
+ filter = ::Hubspot::Crm::Contacts::Filter.new(
20
+ property_name: 'email',
21
+ operator: 'EQ',
22
+ value: @email
23
+ )
24
+ filter_group = ::Hubspot::Crm::Contacts::FilterGroup.new(filters: [filter])
25
+ ::Hubspot::Crm::Contacts::PublicObjectSearchRequest.new(filter_groups: [filter_group])
26
+ end
27
+
28
+ def add_fullnames(contacts)
29
+ contacts.each do |contact|
30
+ fullname = [contact.properties['firstname'], contact.properties['lastname']].reject(&:empty?).join(' ')
31
+ contact.properties['fullname'] = fullname
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ module Services
2
+ module Hubspot
3
+ module Timeline
4
+ class CreateEvent
5
+ def initialize(email, template_id)
6
+ @email = email
7
+ @template_id = template_id
8
+ end
9
+
10
+ def call
11
+ timeline_event = ::Hubspot::Crm::Timeline::TimelineEvent.new(
12
+ email: @email,
13
+ event_template_id: @template_id
14
+ )
15
+ ::Hubspot::Crm::Timeline::EventsApi.new.create(timeline_event: timeline_event)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,39 @@
1
+ module Services
2
+ module Hubspot
3
+ module Timeline
4
+ class CreateTemplate
5
+ def initialize(template_params)
6
+ @template_params = template_params
7
+ end
8
+
9
+ def call
10
+ api_client = api_client_with_hapikey
11
+ create_api = ::Hubspot::Crm::Timeline::TemplatesApi.new(api_client)
12
+ create_api.create(
13
+ ENV['HUBSPOT_APPLICATION_ID'],
14
+ timeline_event_template_create_request: template_create_request,
15
+ auth_names: 'hapikey'
16
+ )
17
+ end
18
+
19
+ private
20
+
21
+ def template_create_request
22
+ ::Hubspot::Crm::Timeline::TimelineEventTemplateCreateRequest.new(
23
+ object_type: @template_params[:target_record_type],
24
+ name: 'Test event template name',
25
+ header_template: @template_params[:header_template],
26
+ detail_template: @template_params[:detail_template]
27
+ )
28
+ end
29
+
30
+ def api_client_with_hapikey
31
+ config = ::Hubspot::Crm::Timeline::Configuration.new do |config|
32
+ config.api_key = { 'hapikey' => ENV['HUBSPOT_DEVELOPER_API_KEY'] }
33
+ end
34
+ ::Hubspot::Crm::Timeline::ApiClient.new(config)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ class ApplicationRecord < ActiveRecord::Base
2
+ self.abstract_class = true
3
+ end
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>HubSpot Ruby sample timeline events app</title>
6
+ <%= csrf_meta_tags %>
7
+ <%= csp_meta_tag %>
8
+
9
+ <link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,300italic,700,700italic">
10
+ <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
11
+ <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.css">
12
+
13
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
14
+ <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
15
+ </head>
16
+
17
+ <body>
18
+ <%= render partial: "shared/header"%>
19
+ <div class="wrapper">
20
+ <%= yield %>
21
+ </div>
22
+ </body>
23
+ </html>