shopify_app 21.2.0 → 21.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +7 -8
  3. data/.github/workflows/stale.yml +1 -0
  4. data/.spin/rails/prepare-application +8 -0
  5. data/CHANGELOG.md +15 -0
  6. data/Gemfile +1 -0
  7. data/Gemfile.lock +106 -91
  8. data/README.md +19 -15
  9. data/SECURITY.md +1 -1
  10. data/app/controllers/concerns/shopify_app/authenticated.rb +4 -9
  11. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +3 -2
  12. data/app/controllers/concerns/shopify_app/ensure_has_session.rb +19 -0
  13. data/app/controllers/concerns/shopify_app/ensure_installed.rb +62 -0
  14. data/app/controllers/concerns/shopify_app/require_known_shop.rb +3 -38
  15. data/app/controllers/shopify_app/authenticated_controller.rb +1 -1
  16. data/app/controllers/shopify_app/callback_controller.rb +64 -27
  17. data/app/controllers/shopify_app/extension_verification_controller.rb +4 -1
  18. data/app/controllers/shopify_app/sessions_controller.rb +11 -2
  19. data/config/locales/ja.yml +1 -1
  20. data/docs/Troubleshooting.md +38 -2
  21. data/docs/Upgrading.md +40 -32
  22. data/docs/shopify_app/controller-concerns.md +48 -0
  23. data/docs/shopify_app/logging.md +21 -0
  24. data/docs/shopify_app/webhooks.md +13 -0
  25. data/lib/generators/shopify_app/add_app_uninstalled_job/add_app_uninstalled_job_generator.rb +15 -0
  26. data/lib/generators/shopify_app/add_app_uninstalled_job/templates/app_uninstalled_job.rb.tt +22 -0
  27. data/lib/generators/shopify_app/add_gdpr_jobs/add_gdpr_jobs_generator.rb +23 -0
  28. data/lib/generators/shopify_app/add_gdpr_jobs/templates/customers_data_request_job.rb.tt +22 -0
  29. data/lib/generators/shopify_app/add_gdpr_jobs/templates/customers_redact_job.rb.tt +22 -0
  30. data/lib/generators/shopify_app/add_gdpr_jobs/templates/shop_redact_job.rb.tt +22 -0
  31. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +1 -0
  32. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +2 -1
  33. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt +2 -1
  34. data/lib/generators/shopify_app/authenticated_controller/templates/authenticated_controller.rb +1 -1
  35. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +1 -1
  36. data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +1 -1
  37. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +8 -2
  38. data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +1 -1
  39. data/lib/generators/shopify_app/shopify_app_generator.rb +2 -0
  40. data/lib/shopify_app/access_scopes/noop_strategy.rb +4 -0
  41. data/lib/shopify_app/access_scopes/user_strategy.rb +5 -0
  42. data/lib/shopify_app/configuration.rb +11 -0
  43. data/lib/shopify_app/controller_concerns/ensure_billing.rb +3 -0
  44. data/lib/shopify_app/controller_concerns/itp.rb +5 -0
  45. data/lib/shopify_app/controller_concerns/login_protection.rb +52 -13
  46. data/lib/shopify_app/controller_concerns/redirect_for_embedded.rb +4 -1
  47. data/lib/shopify_app/controller_concerns/webhook_verification.rb +4 -1
  48. data/lib/shopify_app/logger.rb +28 -0
  49. data/lib/shopify_app/managers/scripttags_manager.rb +1 -0
  50. data/lib/shopify_app/managers/webhooks_manager.rb +6 -0
  51. data/lib/shopify_app/session/jwt.rb +1 -1
  52. data/lib/shopify_app/session/session_repository.rb +15 -4
  53. data/lib/shopify_app/version.rb +1 -1
  54. data/lib/shopify_app.rb +2 -0
  55. data/shopify_app.gemspec +2 -1
  56. data/yarn.lock +5 -5
  57. metadata +30 -4
@@ -8,6 +8,7 @@ module ShopifyApp
8
8
  source_root File.expand_path("../templates", __FILE__)
9
9
 
10
10
  def generate_app_extension
11
+ ShopifyApp::Logger.deprecated("MarketingActivitiesController will be removed in an upcoming version", "22.0.0")
11
12
  template("marketing_activities_controller.rb", "app/controllers/marketing_activities_controller.rb")
12
13
  generate_routes
13
14
  end
@@ -55,7 +55,8 @@ class MarketingActivitiesController < ShopifyApp::ExtensionVerificationControlle
55
55
  request_id = params[:request_id]
56
56
  message = params[:message]
57
57
 
58
- Rails.logger.info("[Marketing Activity App Error Feedback] Request id: #{request_id}, message: #{message}")
58
+ ShopifyApp::Logger.info("[Marketing Activity App Error Feedback]"\
59
+ "Request id: #{request_id}, message: #{message}")
59
60
 
60
61
  render(json: {}, status: :ok)
61
62
  end
@@ -12,7 +12,8 @@ class <%= @job_class_name %> < ActiveJob::Base
12
12
 
13
13
  if shop.nil?
14
14
  logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")
15
- return
15
+
16
+ raise ActiveRecord::RecordNotFound, "Shop Not Found"
16
17
  end
17
18
 
18
19
  shop.with_shopify_session do
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class AuthenticatedController < ApplicationController
4
- include ShopifyApp::Authenticated
4
+ include ShopifyApp::EnsureHasSession
5
5
  end
@@ -24,7 +24,7 @@
24
24
  });
25
25
 
26
26
  var fetchProducts = function() {
27
- var headers = new Headers({ "Authorization": "Bearer " + window.sessionToken });
27
+ var headers = new Headers({ "Content-Type": "text/javascript", "Authorization": "Bearer " + window.sessionToken });
28
28
  return fetch("/products", { headers })
29
29
  .then(response => response.json())
30
30
  .then(data => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  class HomeController < ApplicationController
4
4
  include ShopifyApp::EmbeddedApp
5
- include ShopifyApp::RequireKnownShop
5
+ include ShopifyApp::EnsureInstalled
6
6
  include ShopifyApp::ShopAccessScopesVerification
7
7
 
8
8
  def index
@@ -7,8 +7,14 @@ ShopifyApp.configure do |config|
7
7
  config.after_authenticate_job = false
8
8
  config.api_version = "<%= @api_version %>"
9
9
  config.shop_session_repository = 'Shop'
10
-
10
+ config.log_level = :info
11
11
  config.reauth_on_access_scope_changes = true
12
+ config.webhooks = [
13
+ { topic: "app/uninstalled", address: "webhooks/app_uninstalled"},
14
+ { topic: "customers/data_request", address: "webhooks/customers_data_request" },
15
+ { topic: "customer/redact", address: "webhooks/customers_redact"},
16
+ { topic: "shop/redact", address: "webhooks/shop_redact"}
17
+ ]
12
18
 
13
19
  config.api_key = ENV.fetch('SHOPIFY_API_KEY', '').presence
14
20
  config.secret = ENV.fetch('SHOPIFY_API_SECRET', '').presence
@@ -42,7 +48,7 @@ Rails.application.config.after_initialize do
42
48
  scope: ShopifyApp.configuration.scope,
43
49
  is_private: !ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', '').empty?,
44
50
  is_embedded: ShopifyApp.configuration.embedded_app,
45
- session_storage: ShopifyApp::SessionRepository,
51
+ log_level: :info,
46
52
  logger: Rails.logger,
47
53
  private_shop: ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', nil),
48
54
  user_agent_prefix: "ShopifyApp/#{ShopifyApp::VERSION}"
@@ -27,7 +27,7 @@ module Shopify
27
27
  private
28
28
 
29
29
  def log_error(message)
30
- Rails.logger.error(message)
30
+ ShopifyApp::Logger.error(message)
31
31
  end
32
32
 
33
33
  def no_access_token_error_message
@@ -9,6 +9,8 @@ module ShopifyApp
9
9
  end
10
10
 
11
11
  def run_all_generators
12
+ generate("shopify_app:add_app_uninstalled_job")
13
+ generate("shopify_app:add_gdpr_jobs")
12
14
  generate("shopify_app:install #{@opts.join(" ")}")
13
15
  generate("shopify_app:shop_model #{@opts.join(" ")}")
14
16
  generate("shopify_app:authenticated_controller")
@@ -7,6 +7,10 @@ module ShopifyApp
7
7
  def update_access_scopes?(*_args)
8
8
  false
9
9
  end
10
+
11
+ def covers_scopes?(*_args)
12
+ true
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -12,6 +12,11 @@ module ShopifyApp
12
12
  "#update_access_scopes? requires user_id or shopify_user_id parameter inputs")
13
13
  end
14
14
 
15
+ def covers_scopes?(current_shopify_session)
16
+ # NOTE: this not Ruby's `covers?` method, it is defined in ShopifyAPI::Auth::AuthScopes
17
+ current_shopify_session.scope.to_a.empty? || current_shopify_session.scope.covers?(ShopifyAPI::Context.scope)
18
+ end
19
+
15
20
  private
16
21
 
17
22
  def update_access_scopes_for_user_id?(user_id)
@@ -20,6 +20,7 @@ module ShopifyApp
20
20
  attr_accessor :api_version
21
21
 
22
22
  attr_accessor :reauth_on_access_scope_changes
23
+ attr_accessor :log_level
23
24
 
24
25
  # customise urls
25
26
  attr_accessor :root_url
@@ -82,7 +83,17 @@ module ShopifyApp
82
83
  ShopifyApp::AccessScopes::ShopStrategy
83
84
  end
84
85
 
86
+ def user_access_scopes_strategy=(class_name)
87
+ unless class_name.is_a?(String)
88
+ raise ConfigurationError, "Invalid user access scopes strategy - expected a string"
89
+ end
90
+
91
+ @user_access_scopes_strategy = class_name.safe_constantize
92
+ end
93
+
85
94
  def user_access_scopes_strategy
95
+ return @user_access_scopes_strategy if @user_access_scopes_strategy
96
+
86
97
  return ShopifyApp::AccessScopes::NoopStrategy unless reauth_on_access_scope_changes
87
98
 
88
99
  ShopifyApp::AccessScopes::UserStrategy
@@ -28,6 +28,7 @@ module ShopifyApp
28
28
  unless has_payment
29
29
  if request.xhr?
30
30
  add_top_level_redirection_headers(url: confirmation_url, ignore_response_code: true)
31
+ ShopifyApp::Logger.debug("Responding with 401 unauthorized")
31
32
  head(:unauthorized)
32
33
  else
33
34
  redirect_to(confirmation_url, allow_other_host: true)
@@ -55,6 +56,7 @@ module ShopifyApp
55
56
  end
56
57
 
57
58
  def has_subscription?(session)
59
+ ShopifyApp::Logger.debug("Checking if shop has subscription")
58
60
  response = run_query(session: session, query: RECURRING_PURCHASES_QUERY)
59
61
  subscriptions = response.body["data"]["currentAppInstallation"]["activeSubscriptions"]
60
62
 
@@ -70,6 +72,7 @@ module ShopifyApp
70
72
  end
71
73
 
72
74
  def has_one_time_payment?(session)
75
+ ShopifyApp::Logger.debug("Checking if has one time payment")
73
76
  purchases = nil
74
77
  end_cursor = nil
75
78
 
@@ -3,6 +3,11 @@
3
3
  module ShopifyApp
4
4
  # Cookie management helpers required for ITP implementation
5
5
  module Itp
6
+ extend ActiveSupport::Concern
7
+ included do
8
+ ShopifyApp::Logger.deprecated("Itp will be removed in an upcoming version", "22.0.0")
9
+ end
10
+
6
11
  private
7
12
 
8
13
  def set_test_cookie
@@ -5,11 +5,17 @@ require "browser_sniffer"
5
5
  module ShopifyApp
6
6
  module LoginProtection
7
7
  extend ActiveSupport::Concern
8
- include ShopifyApp::Itp
9
8
  include ShopifyApp::SanitizedParams
10
9
 
11
10
  included do
12
- after_action :set_test_cookie
11
+ if ancestors.include?(ShopifyApp::RequireKnownShop || ShopifyApp::EnsureInstalled)
12
+ message = <<~EOS
13
+ We detected the use of incompatible concerns (RequireKnownShop/EnsureInstalled and LoginProtection) in #{name},
14
+ which may lead to unpredictable behavior. In a future release of this library this will raise an error.
15
+ EOS
16
+ ShopifyApp::Logger.deprecated(message, "22.0.0")
17
+ end
18
+
13
19
  rescue_from ShopifyAPI::Errors::HttpResponseError, with: :handle_http_error
14
20
  end
15
21
 
@@ -18,20 +24,21 @@ module ShopifyApp
18
24
  def activate_shopify_session
19
25
  if current_shopify_session.blank?
20
26
  signal_access_token_required
27
+ ShopifyApp::Logger.debug("No session found, redirecting to login")
21
28
  return redirect_to_login
22
29
  end
23
30
 
24
- unless current_shopify_session.scope.to_a.empty? ||
25
- current_shopify_session.scope.covers?(ShopifyAPI::Context.scope)
26
-
31
+ unless ShopifyApp.configuration.user_access_scopes_strategy.covers_scopes?(current_shopify_session)
27
32
  clear_shopify_session
28
33
  return redirect_to_login
29
34
  end
30
35
 
31
36
  begin
37
+ ShopifyApp::Logger.debug("Activating Shopify session")
32
38
  ShopifyAPI::Context.activate_session(current_shopify_session)
33
39
  yield
34
40
  ensure
41
+ ShopifyApp::Logger.debug("Deactivating session")
35
42
  ShopifyAPI::Context.deactivate_session
36
43
  end
37
44
  end
@@ -39,14 +46,16 @@ module ShopifyApp
39
46
  def current_shopify_session
40
47
  @current_shopify_session ||= begin
41
48
  cookie_name = ShopifyAPI::Auth::Oauth::SessionCookie::SESSION_COOKIE_NAME
42
- ShopifyAPI::Utils::SessionUtils.load_current_session(
49
+ load_current_session(
43
50
  auth_header: request.headers["HTTP_AUTHORIZATION"],
44
51
  cookies: { cookie_name => cookies.encrypted[cookie_name] },
45
- is_online: user_session_expected?,
52
+ is_online: online_token_configured?,
46
53
  )
47
54
  rescue ShopifyAPI::Errors::CookieNotFoundError
55
+ ShopifyApp::Logger.warn("No cookies have been found - cookie name: #{cookie_name}")
48
56
  nil
49
57
  rescue ShopifyAPI::Errors::InvalidJwtTokenError
58
+ ShopifyApp::Logger.warn("Invalid JWT token for current Shopify session")
50
59
  nil
51
60
  end
52
61
  end
@@ -54,6 +63,7 @@ module ShopifyApp
54
63
  def login_again_if_different_user_or_shop
55
64
  return unless session_id_conflicts_with_params || session_shop_conflicts_with_params
56
65
 
66
+ ShopifyApp::Logger.debug("Clearing session and redirecting to login")
57
67
  clear_shopify_session
58
68
  redirect_to_login
59
69
  end
@@ -71,10 +81,13 @@ module ShopifyApp
71
81
 
72
82
  def add_top_level_redirection_headers(url: nil, ignore_response_code: false)
73
83
  if request.xhr? && (ignore_response_code || response.code.to_i == 401)
84
+ ShopifyApp::Logger.debug("Adding top level redirection headers")
74
85
  # Make sure the shop is set in the redirection URL
75
86
  unless params[:shop]
87
+ ShopifyApp::Logger.debug("Setting current shop session")
76
88
  params[:shop] = if current_shopify_session
77
89
  current_shopify_session.shop
90
+
78
91
  elsif (matches = request.headers["HTTP_AUTHORIZATION"]&.match(/^Bearer (.+)$/))
79
92
  jwt_payload = ShopifyAPI::Auth::JwtPayload.new(T.must(matches[1]))
80
93
  jwt_payload.shop
@@ -83,6 +96,7 @@ module ShopifyApp
83
96
 
84
97
  url ||= login_url_with_optional_shop
85
98
 
99
+ ShopifyApp::Logger.debug("Setting Reauthorize-Url to #{url}")
86
100
  response.set_header("X-Shopify-API-Request-Failure-Reauthorize", "1")
87
101
  response.set_header("X-Shopify-API-Request-Failure-Reauthorize-Url", url)
88
102
  end
@@ -103,8 +117,9 @@ module ShopifyApp
103
117
  end
104
118
 
105
119
  def redirect_to_login
106
- if request.xhr?
120
+ if requested_by_javascript?
107
121
  add_top_level_redirection_headers(ignore_response_code: true)
122
+ ShopifyApp::Logger.debug("Login redirect request is a XHR")
108
123
  head(:unauthorized)
109
124
  else
110
125
  if request.get?
@@ -117,12 +132,15 @@ module ShopifyApp
117
132
  query = query.merge(sanitized_params).to_query
118
133
  end
119
134
  session[:return_to] = query.blank? ? path.to_s : "#{path}?#{query}"
135
+ ShopifyApp::Logger.debug("Redirecting to #{login_url_with_optional_shop}")
120
136
  redirect_to(login_url_with_optional_shop)
121
137
  end
122
138
  end
123
139
 
124
140
  def close_session
125
141
  clear_shopify_session
142
+ ShopifyApp::Logger.debug("Closing session")
143
+ ShopifyApp::Logger.debug("Redirecting to #{login_url_with_optional_shop}")
126
144
  redirect_to(login_url_with_optional_shop)
127
145
  end
128
146
 
@@ -182,6 +200,8 @@ module ShopifyApp
182
200
 
183
201
  def fullpage_redirect_to(url)
184
202
  if ShopifyApp.configuration.embedded_app?
203
+ raise ::ShopifyApp::ShopifyDomainNotFound if current_shopify_domain.nil?
204
+
185
205
  render("shopify_app/shared/redirect", layout: false,
186
206
  locals: { url: url, current_shopify_domain: current_shopify_domain })
187
207
  else
@@ -191,13 +211,13 @@ module ShopifyApp
191
211
 
192
212
  def current_shopify_domain
193
213
  shopify_domain = sanitized_shop_name || current_shopify_session&.shop
194
-
195
- return shopify_domain if shopify_domain.present?
196
-
197
- raise ::ShopifyApp::ShopifyDomainNotFound
214
+ ShopifyApp::Logger.info("Installed store - #{shopify_domain} deduced from user session")
215
+ shopify_domain
198
216
  end
199
217
 
200
218
  def return_address
219
+ return base_return_address if current_shopify_domain.nil?
220
+
201
221
  return_address_with_params(shop: current_shopify_domain, host: host)
202
222
  rescue ::ShopifyApp::ShopifyDomainNotFound, ::ShopifyApp::ShopifyHostNotFound
203
223
  base_return_address
@@ -232,11 +252,30 @@ module ShopifyApp
232
252
  ShopifyApp::SessionRepository.retrieve_shop_session_by_shopify_domain(sanitize_shop_param(params))
233
253
  end
234
254
 
255
+ def online_token_configured?
256
+ !ShopifyApp.configuration.user_session_repository.blank? && ShopifyApp::SessionRepository.user_storage.present?
257
+ end
258
+
235
259
  def user_session_expected?
236
260
  return false if shop_session.nil?
237
261
  return false if ShopifyApp.configuration.shop_access_scopes_strategy.update_access_scopes?(shop_session.shop)
238
262
 
239
- !ShopifyApp.configuration.user_session_repository.blank? && ShopifyApp::SessionRepository.user_storage.present?
263
+ online_token_configured?
264
+ end
265
+
266
+ def load_current_session(auth_header: nil, cookies: nil, is_online: false)
267
+ return ShopifyAPI::Context.load_private_session if ShopifyAPI::Context.private?
268
+
269
+ session_id = ShopifyAPI::Utils::SessionUtils.current_session_id(auth_header, cookies, is_online)
270
+ return nil unless session_id
271
+
272
+ ShopifyApp::SessionRepository.load_session(session_id)
273
+ end
274
+
275
+ def requested_by_javascript?
276
+ request.xhr? ||
277
+ request.content_type == "text/javascript" ||
278
+ request.content_type == "application/javascript"
240
279
  end
241
280
  end
242
281
  end
@@ -16,7 +16,10 @@ module ShopifyApp
16
16
 
17
17
  def redirect_for_embedded
18
18
  # Don't actually redirect if we're already in the redirect route - we want the request to reach the FE
19
- redirect_to(redirect_uri_for_embedded) unless request.path == ShopifyApp.configuration.embedded_redirect_url
19
+ unless request.path == ShopifyApp.configuration.embedded_redirect_url
20
+ ShopifyApp::Logger.debug("Redirecting to #{redirect_uri_for_embedded}")
21
+ redirect_to(redirect_uri_for_embedded)
22
+ end
20
23
  end
21
24
 
22
25
  def redirect_uri_for_embedded
@@ -14,7 +14,10 @@ module ShopifyApp
14
14
 
15
15
  def verify_request
16
16
  data = request.raw_post
17
- return head(:unauthorized) unless hmac_valid?(data)
17
+ unless hmac_valid?(data)
18
+ ShopifyApp::Logger.debug("Webhook verification failed - HMAC invalid")
19
+ head(:unauthorized)
20
+ end
18
21
  end
19
22
 
20
23
  def shop_domain
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApp
4
+ class Logger < ShopifyAPI::Logger
5
+ class << self
6
+ def deprecated(message, version)
7
+ return unless enabled_for_log_level?(:warn)
8
+
9
+ raise ShopifyAPI::Errors::FeatureDeprecatedError unless valid_version(version)
10
+
11
+ ActiveSupport::Deprecation.warn("[#{version}] #{context(:warn)} #{message}")
12
+ end
13
+
14
+ private
15
+
16
+ def context(log_level)
17
+ current_shop = ShopifyAPI::Context.active_session&.shop || "Shop Not Found"
18
+ "[ ShopifyApp | #{log_level.to_s.upcase} | #{current_shop} ]"
19
+ end
20
+
21
+ def valid_version(version)
22
+ current_version = Gem::Version.create(ShopifyApp::VERSION)
23
+ deprecate_version = Gem::Version.create(version)
24
+ current_version < deprecate_version
25
+ end
26
+ end
27
+ end
28
+ end
@@ -24,6 +24,7 @@ module ShopifyApp
24
24
  attr_reader :required_scripttags, :shop_domain
25
25
 
26
26
  def initialize(scripttags, shop_domain)
27
+ ShopifyApp::Logger.deprecated("The ScripttagsManager will become deprecated in an upcoming version", "22.0.0")
27
28
  @required_scripttags = scripttags
28
29
  @shop_domain = shop_domain
29
30
  end
@@ -15,6 +15,8 @@ module ShopifyApp
15
15
  def create_webhooks(session:)
16
16
  return unless ShopifyApp.configuration.has_webhooks?
17
17
 
18
+ ShopifyApp::Logger.debug("Creating webhooks #{ShopifyApp.configuration.webhooks}")
19
+
18
20
  ShopifyAPI::Webhooks::Registry.register_all(session: session)
19
21
  end
20
22
 
@@ -23,12 +25,15 @@ module ShopifyApp
23
25
  return unless ShopifyApp.configuration.has_webhooks?
24
26
 
25
27
  add_registrations
28
+
29
+ ShopifyApp::Logger.debug("Recreating webhooks")
26
30
  ShopifyAPI::Webhooks::Registry.register_all(session: session)
27
31
  end
28
32
 
29
33
  def destroy_webhooks
30
34
  return unless ShopifyApp.configuration.has_webhooks?
31
35
 
36
+ ShopifyApp::Logger.debug("Destroying webhooks")
32
37
  ShopifyApp.configuration.webhooks.each do |attributes|
33
38
  ShopifyAPI::Webhooks::Registry.unregister(topic: attributes[:topic])
34
39
  end
@@ -37,6 +42,7 @@ module ShopifyApp
37
42
  def add_registrations
38
43
  return unless ShopifyApp.configuration.has_webhooks?
39
44
 
45
+ ShopifyApp::Logger.debug("Adding registrations to webhooks")
40
46
  ShopifyApp.configuration.webhooks.each do |attributes|
41
47
  webhook_path = path(attributes)
42
48
 
@@ -35,7 +35,7 @@ module ShopifyApp
35
35
  payload, _ = parse_token_data(ShopifyApp.configuration&.secret, ShopifyApp.configuration&.old_secret)
36
36
  @payload = validate_payload(payload)
37
37
  rescue *WARN_EXCEPTIONS => error
38
- Rails.logger.warn("[ShopifyApp::JWT] Failed to validate JWT: [#{error.class}] #{error}")
38
+ ShopifyApp::Logger.warn("Failed to validate JWT: [#{error.class}] #{error}")
39
39
  nil
40
40
  end
41
41
 
@@ -45,8 +45,11 @@ module ShopifyApp
45
45
  # ShopifyAPI::Auth::SessionStorage override
46
46
  def store_session(session)
47
47
  if session.online?
48
- user_storage.store(session, session.associated_user)
48
+ user = session.associated_user
49
+ ShopifyApp::Logger.debug("Storing online user session - session: #{session.id}")
50
+ user_storage.store(session, user)
49
51
  else
52
+ ShopifyApp::Logger.debug("Storing offline store session - session: #{session.id}")
50
53
  shop_storage.store(session)
51
54
  end
52
55
  end
@@ -55,9 +58,13 @@ module ShopifyApp
55
58
  def load_session(id)
56
59
  match = id.match(/^offline_(.*)/)
57
60
  if match
58
- retrieve_shop_session_by_shopify_domain(match[1])
61
+ domain = match[1]
62
+ ShopifyApp::Logger.debug("Loading session by domain - domain: #{domain}")
63
+ retrieve_shop_session_by_shopify_domain(domain)
59
64
  else
60
- retrieve_user_session_by_shopify_user_id(id.split("_").last)
65
+ user = id.split("_").last
66
+ ShopifyApp::Logger.debug("Loading session by user_id - user: #{user}")
67
+ retrieve_user_session_by_shopify_user_id(user)
61
68
  end
62
69
  end
63
70
 
@@ -66,9 +73,13 @@ module ShopifyApp
66
73
  match = id.match(/^offline_(.*)/)
67
74
 
68
75
  record = if match
76
+ domain = match[1]
77
+ ShopifyApp::Logger.debug("Destroying session by domain - domain: #{domain}")
69
78
  Shop.find_by(shopify_domain: match[1])
70
79
  else
71
- User.find_by(shopify_user_id: id.split("_").last)
80
+ shopify_user_id = id.split("_").last
81
+ ShopifyApp::Logger.debug("Destroying session by user - user_id: #{shopify_user_id}")
82
+ User.find_by(shopify_user_id: shopify_user_id)
72
83
  end
73
84
 
74
85
  record.destroy
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyApp
4
- VERSION = "21.2.0"
4
+ VERSION = "21.3.0"
5
5
  end
data/lib/shopify_app.rb CHANGED
@@ -37,6 +37,8 @@ module ShopifyApp
37
37
  # errors
38
38
  require "shopify_app/errors"
39
39
 
40
+ require "shopify_app/logger"
41
+
40
42
  # controller concerns
41
43
  require "shopify_app/controller_concerns/csrf_protection"
42
44
  require "shopify_app/controller_concerns/localization"
data/shopify_app.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_runtime_dependency("jwt", ">= 2.2.3")
20
20
  s.add_runtime_dependency("rails", "> 5.2.1")
21
21
  s.add_runtime_dependency("redirect_safely", "~> 1.0")
22
- s.add_runtime_dependency("shopify_api", "~> 12.2")
22
+ s.add_runtime_dependency("shopify_api", "~> 12.3")
23
23
  s.add_runtime_dependency("sprockets-rails", ">= 2.0.0")
24
24
 
25
25
  s.add_development_dependency("byebug")
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
30
30
  s.add_development_dependency("pry-stack_explorer")
31
31
  s.add_development_dependency("rake")
32
32
  s.add_development_dependency("rb-readline")
33
+ s.add_development_dependency("ruby-lsp")
33
34
  s.add_development_dependency("sqlite3", "~> 1.4")
34
35
  s.add_development_dependency("webmock")
35
36
 
data/yarn.lock CHANGED
@@ -3095,7 +3095,7 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
3095
3095
  isarray@2.0.1:
3096
3096
  version "2.0.1"
3097
3097
  resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
3098
- integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
3098
+ integrity sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==
3099
3099
 
3100
3100
  isarray@^2.0.5:
3101
3101
  version "2.0.5"
@@ -3601,7 +3601,7 @@ move-concurrently@^1.0.1:
3601
3601
  ms@2.0.0:
3602
3602
  version "2.0.0"
3603
3603
  resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
3604
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
3604
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
3605
3605
 
3606
3606
  ms@2.1.2:
3607
3607
  version "2.1.2"
@@ -4448,9 +4448,9 @@ socket.io-client@2.4.0:
4448
4448
  to-array "0.1.4"
4449
4449
 
4450
4450
  socket.io-parser@~3.3.0:
4451
- version "3.3.2"
4452
- resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6"
4453
- integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==
4451
+ version "3.3.3"
4452
+ resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.3.tgz#3a8b84823eba87f3f7624e64a8aaab6d6318a72f"
4453
+ integrity sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg==
4454
4454
  dependencies:
4455
4455
  component-emitter "~1.3.0"
4456
4456
  debug "~3.1.0"