shopify_app 21.0.0 → 22.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE/ENHANCEMENT.md +9 -0
  4. data/.github/ISSUE_TEMPLATE/bug-report.md +30 -47
  5. data/.github/ISSUE_TEMPLATE/feature-request.md +5 -29
  6. data/.github/workflows/build.yml +11 -12
  7. data/.github/workflows/release.yml +2 -2
  8. data/.github/workflows/remove-labels-on-activity.yml +1 -1
  9. data/.github/workflows/rubocop.yml +2 -3
  10. data/.nvmrc +1 -1
  11. data/.rubocop.yml +2 -1
  12. data/.ruby-version +1 -1
  13. data/.spin/rails/prepare-application +8 -0
  14. data/CHANGELOG.md +173 -7
  15. data/CODE_OF_CONDUCT.md +46 -0
  16. data/CONTRIBUTING.md +16 -6
  17. data/Gemfile +1 -0
  18. data/Gemfile.lock +160 -121
  19. data/README.md +67 -19
  20. data/SECURITY.md +1 -1
  21. data/app/assets/javascripts/shopify_app/redirect.js +3 -10
  22. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +9 -4
  23. data/app/controllers/concerns/shopify_app/ensure_has_session.rb +25 -0
  24. data/app/controllers/concerns/shopify_app/ensure_installed.rb +84 -0
  25. data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +5 -1
  26. data/app/controllers/shopify_app/authenticated_controller.rb +1 -1
  27. data/app/controllers/shopify_app/callback_controller.rb +101 -39
  28. data/app/controllers/shopify_app/extension_verification_controller.rb +4 -1
  29. data/app/controllers/shopify_app/sessions_controller.rb +37 -7
  30. data/app/controllers/shopify_app/webhooks_controller.rb +1 -1
  31. data/app/views/shopify_app/layouts/app_bridge.html.erb +17 -0
  32. data/app/views/shopify_app/sessions/patch_shopify_id_token.html.erb +0 -0
  33. data/app/views/shopify_app/shared/redirect.html.erb +10 -1
  34. data/config/locales/cs.yml +0 -18
  35. data/config/locales/da.yml +0 -15
  36. data/config/locales/de.yml +0 -17
  37. data/config/locales/en.yml +0 -11
  38. data/config/locales/es.yml +0 -17
  39. data/config/locales/fi.yml +0 -15
  40. data/config/locales/fr.yml +0 -18
  41. data/config/locales/it.yml +0 -16
  42. data/config/locales/ja.yml +0 -12
  43. data/config/locales/ko.yml +0 -14
  44. data/config/locales/nb.yml +0 -16
  45. data/config/locales/nl.yml +0 -16
  46. data/config/locales/pl.yml +0 -16
  47. data/config/locales/pt-BR.yml +0 -16
  48. data/config/locales/pt-PT.yml +0 -17
  49. data/config/locales/sv.yml +0 -16
  50. data/config/locales/th.yml +0 -15
  51. data/config/locales/tr.yml +0 -17
  52. data/config/locales/vi.yml +0 -17
  53. data/config/locales/zh-CN.yml +0 -11
  54. data/config/locales/zh-TW.yml +0 -11
  55. data/config/routes.rb +2 -1
  56. data/docs/Quickstart.md +14 -5
  57. data/docs/Troubleshooting.md +38 -25
  58. data/docs/Upgrading.md +103 -32
  59. data/docs/shopify_app/authentication.md +179 -58
  60. data/docs/shopify_app/controller-concerns.md +89 -0
  61. data/docs/shopify_app/engine.md +2 -11
  62. data/docs/shopify_app/generators.md +2 -2
  63. data/docs/shopify_app/logging.md +21 -0
  64. data/docs/shopify_app/sessions.md +358 -0
  65. data/docs/shopify_app/testing.md +32 -10
  66. data/docs/shopify_app/webhooks.md +97 -7
  67. data/karma.conf.js +6 -4
  68. data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +6 -3
  69. data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -1
  70. data/lib/generators/shopify_app/add_app_uninstalled_job/add_app_uninstalled_job_generator.rb +15 -0
  71. data/lib/generators/shopify_app/add_app_uninstalled_job/templates/app_uninstalled_job.rb.tt +22 -0
  72. data/lib/generators/shopify_app/add_declarative_webhook/add_declarative_webhook_generator.rb +53 -0
  73. data/lib/generators/shopify_app/add_declarative_webhook/templates/webhook_controller.rb.tt +13 -0
  74. data/lib/generators/shopify_app/add_declarative_webhook/templates/webhook_job.rb.tt +15 -0
  75. data/lib/generators/shopify_app/add_privacy_jobs/add_privacy_jobs_generator.rb +23 -0
  76. data/lib/generators/shopify_app/add_privacy_jobs/templates/customers_data_request_job.rb.tt +22 -0
  77. data/lib/generators/shopify_app/add_privacy_jobs/templates/customers_redact_job.rb.tt +22 -0
  78. data/lib/generators/shopify_app/add_privacy_jobs/templates/shop_redact_job.rb.tt +22 -0
  79. data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +8 -3
  80. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt +4 -2
  81. data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +1 -1
  82. data/lib/generators/shopify_app/authenticated_controller/templates/authenticated_controller.rb +1 -1
  83. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +1 -1
  84. data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +1 -1
  85. data/lib/generators/shopify_app/install/install_generator.rb +4 -4
  86. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +13 -3
  87. data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake +1 -1
  88. data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +1 -1
  89. data/lib/generators/shopify_app/routes/routes_generator.rb +1 -1
  90. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +1 -1
  91. data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +1 -1
  92. data/lib/generators/shopify_app/shopify_app_generator.rb +2 -0
  93. data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +1 -1
  94. data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_expires_at_column.erb +5 -0
  95. data/lib/generators/shopify_app/user_model/user_model_generator.rb +21 -1
  96. data/lib/shopify_app/access_scopes/noop_strategy.rb +4 -0
  97. data/lib/shopify_app/access_scopes/user_strategy.rb +9 -2
  98. data/lib/shopify_app/admin_api/with_token_refetch.rb +27 -0
  99. data/lib/shopify_app/auth/post_authenticate_tasks.rb +48 -0
  100. data/lib/shopify_app/auth/token_exchange.rb +73 -0
  101. data/lib/shopify_app/configuration.rb +82 -1
  102. data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +3 -3
  103. data/lib/shopify_app/controller_concerns/csrf_protection.rb +2 -1
  104. data/lib/shopify_app/controller_concerns/embedded_app.rb +42 -3
  105. data/lib/shopify_app/controller_concerns/ensure_billing.rb +28 -12
  106. data/lib/shopify_app/controller_concerns/frame_ancestors.rb +1 -1
  107. data/lib/shopify_app/controller_concerns/localization.rb +11 -8
  108. data/lib/shopify_app/controller_concerns/login_protection.rb +83 -38
  109. data/lib/shopify_app/controller_concerns/payload_verification.rb +1 -1
  110. data/lib/shopify_app/controller_concerns/redirect_for_embedded.rb +15 -3
  111. data/lib/shopify_app/controller_concerns/sanitized_params.rb +5 -0
  112. data/lib/shopify_app/controller_concerns/token_exchange.rb +111 -0
  113. data/lib/shopify_app/controller_concerns/webhook_verification.rb +4 -1
  114. data/lib/shopify_app/controller_concerns/with_shopify_id_token.rb +48 -0
  115. data/lib/shopify_app/engine.rb +7 -8
  116. data/lib/shopify_app/logger.rb +28 -0
  117. data/lib/shopify_app/managers/webhooks_manager.rb +20 -10
  118. data/lib/shopify_app/middleware/jwt_middleware.rb +13 -9
  119. data/lib/shopify_app/session/in_memory_user_session_store.rb +1 -1
  120. data/lib/shopify_app/session/jwt.rb +11 -2
  121. data/lib/shopify_app/session/session_repository.rb +66 -14
  122. data/lib/shopify_app/session/session_storage.rb +2 -2
  123. data/lib/shopify_app/session/shop_session_storage.rb +5 -1
  124. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +5 -1
  125. data/lib/shopify_app/session/user_session_storage.rb +6 -2
  126. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +27 -2
  127. data/lib/shopify_app/test_helpers/all.rb +1 -0
  128. data/lib/shopify_app/test_helpers/shopify_session_helper.rb +16 -0
  129. data/lib/shopify_app/utils.rb +82 -20
  130. data/lib/shopify_app/version.rb +1 -1
  131. data/lib/shopify_app.rb +12 -3
  132. data/package.json +5 -6
  133. data/service.yml +0 -2
  134. data/shopify_app.gemspec +6 -5
  135. data/translation.yml +1 -0
  136. data/yarn.lock +2139 -3910
  137. metadata +78 -58
  138. data/.github/workflows/stale.yml +0 -31
  139. data/app/assets/images/storage_access.svg +0 -1
  140. data/app/assets/javascripts/shopify_app/app_bridge_3.1.1.js +0 -10
  141. data/app/assets/javascripts/shopify_app/app_bridge_redirect.js +0 -22
  142. data/app/assets/javascripts/shopify_app/app_bridge_utils_3.1.1.js +0 -1
  143. data/app/assets/javascripts/shopify_app/enable_cookies.js +0 -3
  144. data/app/assets/javascripts/shopify_app/itp_helper.js +0 -40
  145. data/app/assets/javascripts/shopify_app/partition_cookies.js +0 -8
  146. data/app/assets/javascripts/shopify_app/post_redirect.js +0 -9
  147. data/app/assets/javascripts/shopify_app/request_storage_access.js +0 -3
  148. data/app/assets/javascripts/shopify_app/storage_access.js +0 -148
  149. data/app/assets/javascripts/shopify_app/storage_access_redirect.js +0 -17
  150. data/app/assets/javascripts/shopify_app/top_level.js +0 -2
  151. data/app/assets/javascripts/shopify_app/top_level_interaction.js +0 -11
  152. data/app/controllers/concerns/shopify_app/authenticated.rb +0 -19
  153. data/app/controllers/concerns/shopify_app/require_known_shop.rb +0 -48
  154. data/app/views/shopify_app/sessions/enable_cookies.html.erb +0 -70
  155. data/app/views/shopify_app/sessions/request_storage_access.html.erb +0 -68
  156. data/app/views/shopify_app/sessions/top_level_interaction.html.erb +0 -63
  157. data/app/views/shopify_app/shared/post_redirect_to_auth_shopify.html.erb +0 -13
  158. data/docs/shopify_app/script-tags.md +0 -28
  159. data/docs/shopify_app/session-repository.md +0 -88
  160. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +0 -41
  161. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +0 -62
  162. data/lib/shopify_app/controller_concerns/itp.rb +0 -45
  163. data/lib/shopify_app/jobs/scripttags_manager_job.rb +0 -16
  164. data/lib/shopify_app/managers/scripttags_manager.rb +0 -84
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class MarketingActivitiesController < ShopifyApp::ExtensionVerificationController
4
- def preload_form_data
5
- preload_data = {
6
- "form_data": {},
7
- }
8
- render(json: preload_data, status: :ok)
9
- end
10
-
11
- def update
12
- render(json: {}, status: :accepted)
13
- end
14
-
15
- def pause
16
- render(json: {}, status: :accepted)
17
- end
18
-
19
- def resume
20
- render(json: {}, status: :accepted)
21
- end
22
-
23
- def delete
24
- render(json: {}, status: :accepted)
25
- end
26
-
27
- def preview
28
- placeholder_img = "https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-image_small.png"
29
- preview_response = {
30
- "desktop": {
31
- "preview_url": placeholder_img,
32
- "content_type": "text/html",
33
- "width": 360,
34
- "height": 200,
35
- },
36
- "mobile": {
37
- "preview_url": placeholder_img,
38
- "content_type": "text/html",
39
- "width": 360,
40
- "height": 200,
41
- },
42
- }
43
- render(json: preview_response, status: :ok)
44
- end
45
-
46
- def create
47
- render(json: {}, status: :ok)
48
- end
49
-
50
- def republish
51
- render(json: {}, status: :accepted)
52
- end
53
-
54
- def errors
55
- request_id = params[:request_id]
56
- message = params[:message]
57
-
58
- Rails.logger.info("[Marketing Activity App Error Feedback] Request id: #{request_id}, message: #{message}")
59
-
60
- render(json: {}, status: :ok)
61
- end
62
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyApp
4
- # Cookie management helpers required for ITP implementation
5
- module Itp
6
- private
7
-
8
- def set_test_cookie
9
- return unless ShopifyApp.configuration.embedded_app?
10
- return unless user_agent_can_partition_cookies
11
-
12
- session["shopify.cookies_persist"] = true
13
- end
14
-
15
- def set_top_level_oauth_cookie
16
- session["shopify.top_level_oauth"] = true
17
- end
18
-
19
- def clear_top_level_oauth_cookie
20
- session.delete("shopify.top_level_oauth")
21
- end
22
-
23
- def user_agent_is_mobile
24
- user_agent = BrowserSniffer.new(request.user_agent).browser_info
25
-
26
- user_agent[:name].to_s.match(/Shopify\sMobile/)
27
- end
28
-
29
- def user_agent_is_pos
30
- user_agent = BrowserSniffer.new(request.user_agent).browser_info
31
-
32
- user_agent[:name].to_s.match(/Shopify\sPOS/)
33
- end
34
-
35
- def user_agent_can_partition_cookies
36
- user_agent = BrowserSniffer.new(request.user_agent).browser_info
37
-
38
- is_safari = user_agent[:name].to_s.match(/Safari/)
39
-
40
- return false unless is_safari
41
-
42
- user_agent[:version].to_s.match(/12\.0/)
43
- end
44
- end
45
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyApp
4
- class ScripttagsManagerJob < ActiveJob::Base
5
- queue_as do
6
- ShopifyApp.configuration.scripttags_manager_queue_name
7
- end
8
-
9
- def perform(shop_domain:, shop_token:, scripttags:)
10
- ShopifyAPI::Auth::Session.temp(shop: shop_domain, access_token: shop_token) do
11
- manager = ScripttagsManager.new(scripttags, shop_domain)
12
- manager.create_scripttags
13
- end
14
- end
15
- end
16
- end
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ShopifyApp
4
- class ScripttagsManager
5
- def self.queue(shop_domain, shop_token, scripttags)
6
- ShopifyApp::ScripttagsManagerJob.perform_later(
7
- shop_domain: shop_domain,
8
- shop_token: shop_token,
9
- # Procs cannot be serialized so we interpolate now, if necessary
10
- scripttags: build_src(scripttags, shop_domain)
11
- )
12
- end
13
-
14
- def self.build_src(scripttags, domain)
15
- scripttags.map do |tag|
16
- next tag unless tag[:src].respond_to?(:call)
17
-
18
- tag = tag.dup
19
- tag[:src] = tag[:src].call(domain)
20
- tag
21
- end
22
- end
23
-
24
- attr_reader :required_scripttags, :shop_domain
25
-
26
- def initialize(scripttags, shop_domain)
27
- @required_scripttags = scripttags
28
- @shop_domain = shop_domain
29
- end
30
-
31
- def recreate_scripttags!
32
- destroy_scripttags
33
- create_scripttags
34
- end
35
-
36
- def create_scripttags
37
- return unless required_scripttags.present?
38
-
39
- expanded_scripttags.each do |scripttag|
40
- create_scripttag(scripttag) unless scripttag_exists?(scripttag[:src])
41
- end
42
- end
43
-
44
- def destroy_scripttags
45
- scripttags = expanded_scripttags
46
- ShopifyAPI::ScriptTag.all.each do |tag|
47
- tag.delete if required_scripttag?(scripttags, tag)
48
- end
49
-
50
- @current_scripttags = nil
51
- end
52
-
53
- private
54
-
55
- def expanded_scripttags
56
- self.class.build_src(required_scripttags, shop_domain)
57
- end
58
-
59
- def required_scripttag?(scripttags, tag)
60
- scripttags.map { |w| w[:src] }.include?(tag.src)
61
- end
62
-
63
- def create_scripttag(attributes)
64
- scripttag = ShopifyAPI::ScriptTag.new
65
- attributes.each { |key, value| scripttag.public_send("#{key}=", value) }
66
-
67
- begin
68
- scripttag.save!
69
- rescue ShopifyAPI::Errors::HttpResponseError => e
70
- raise ::ShopifyApp::CreationFailed, e.message
71
- end
72
-
73
- scripttag
74
- end
75
-
76
- def scripttag_exists?(src)
77
- current_scripttags[src]
78
- end
79
-
80
- def current_scripttags
81
- @current_scripttags ||= ShopifyAPI::ScriptTag.all.index_by(&:src)
82
- end
83
- end
84
- end