shopify_app 18.0.2 → 19.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +4 -5
  3. data/.gitignore +1 -0
  4. data/.nvmrc +1 -1
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +52 -2
  7. data/CONTRIBUTING.md +6 -1
  8. data/Gemfile +3 -2
  9. data/Gemfile.lock +144 -164
  10. data/README.md +1 -0
  11. data/Rakefile +4 -3
  12. data/app/assets/javascripts/shopify_app/app_bridge_2.0.12.js +10 -0
  13. data/app/assets/javascripts/shopify_app/app_bridge_redirect.js +22 -0
  14. data/app/assets/javascripts/shopify_app/redirect.js +9 -11
  15. data/app/assets/javascripts/shopify_app/storage_access.js +4 -10
  16. data/app/controllers/concerns/shopify_app/authenticated.rb +3 -0
  17. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +16 -3
  18. data/app/controllers/concerns/shopify_app/require_known_shop.rb +1 -0
  19. data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +1 -1
  20. data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
  21. data/app/controllers/shopify_app/callback_controller.rb +49 -134
  22. data/app/controllers/shopify_app/sessions_controller.rb +26 -131
  23. data/app/controllers/shopify_app/webhooks_controller.rb +5 -24
  24. data/app/views/shopify_app/sessions/enable_cookies.html.erb +1 -1
  25. data/app/views/shopify_app/sessions/request_storage_access.html.erb +11 -11
  26. data/app/views/shopify_app/sessions/top_level_interaction.html.erb +1 -1
  27. data/app/views/shopify_app/shared/redirect.html.erb +2 -2
  28. data/config/locales/zh-CN.yml +1 -1
  29. data/config/routes.rb +20 -12
  30. data/docs/Troubleshooting.md +0 -3
  31. data/docs/Upgrading.md +116 -14
  32. data/docs/shopify_app/engine.md +2 -2
  33. data/docs/shopify_app/handling-access-scopes-changes.md +11 -1
  34. data/docs/shopify_app/script-tags.md +1 -1
  35. data/docs/shopify_app/webhooks.md +3 -3
  36. data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +10 -9
  37. data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
  38. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +4 -3
  39. data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +13 -12
  40. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt +9 -1
  41. data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +7 -6
  42. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +2 -1
  43. data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +1 -1
  44. data/lib/generators/shopify_app/authenticated_controller/authenticated_controller_generator.rb +3 -3
  45. data/lib/generators/shopify_app/controllers/controllers_generator.rb +4 -3
  46. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +11 -15
  47. data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +2 -2
  48. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +7 -3
  49. data/lib/generators/shopify_app/install/install_generator.rb +27 -72
  50. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +3 -1
  51. data/lib/generators/shopify_app/install/templates/session_store.rb +2 -1
  52. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +33 -5
  53. data/lib/generators/shopify_app/install/templates/shopify_app_importmap.js +13 -0
  54. data/lib/generators/shopify_app/products_controller/products_controller_generator.rb +3 -3
  55. data/lib/generators/shopify_app/products_controller/templates/products_controller.rb +1 -1
  56. data/lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb +4 -4
  57. data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake +1 -0
  58. data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +1 -1
  59. data/lib/generators/shopify_app/routes/routes_generator.rb +6 -5
  60. data/lib/generators/shopify_app/routes/templates/routes.rb +5 -5
  61. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +11 -10
  62. data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -0
  63. data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
  64. data/lib/generators/shopify_app/user_model/templates/user.rb +1 -0
  65. data/lib/generators/shopify_app/user_model/user_model_generator.rb +11 -10
  66. data/lib/generators/shopify_app/views/views_generator.rb +4 -3
  67. data/lib/shopify_app/access_scopes/shop_strategy.rb +2 -2
  68. data/lib/shopify_app/access_scopes/user_strategy.rb +4 -4
  69. data/lib/shopify_app/configuration.rb +33 -14
  70. data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +4 -3
  71. data/lib/shopify_app/controller_concerns/csrf_protection.rb +2 -1
  72. data/lib/shopify_app/controller_concerns/embedded_app.rb +4 -3
  73. data/lib/shopify_app/controller_concerns/ensure_billing.rb +254 -0
  74. data/lib/shopify_app/controller_concerns/itp.rb +3 -3
  75. data/lib/shopify_app/controller_concerns/localization.rb +1 -0
  76. data/lib/shopify_app/controller_concerns/login_protection.rb +82 -68
  77. data/lib/shopify_app/controller_concerns/payload_verification.rb +3 -2
  78. data/lib/shopify_app/controller_concerns/webhook_verification.rb +2 -1
  79. data/lib/shopify_app/engine.rb +7 -15
  80. data/lib/shopify_app/jobs/scripttags_manager_job.rb +2 -2
  81. data/lib/shopify_app/jobs/webhooks_manager_job.rb +4 -5
  82. data/lib/shopify_app/managers/scripttags_manager.rb +11 -4
  83. data/lib/shopify_app/managers/webhooks_manager.rb +42 -44
  84. data/lib/shopify_app/middleware/jwt_middleware.rb +5 -3
  85. data/lib/shopify_app/session/in_memory_session_store.rb +1 -0
  86. data/lib/shopify_app/session/in_memory_shop_session_store.rb +2 -1
  87. data/lib/shopify_app/session/in_memory_user_session_store.rb +1 -0
  88. data/lib/shopify_app/session/jwt.rb +12 -7
  89. data/lib/shopify_app/session/null_user_session_store.rb +2 -1
  90. data/lib/shopify_app/session/session_repository.rb +37 -0
  91. data/lib/shopify_app/session/session_storage.rb +4 -6
  92. data/lib/shopify_app/session/shop_session_storage.rb +6 -6
  93. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +7 -8
  94. data/lib/shopify_app/session/user_session_storage.rb +19 -6
  95. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +22 -9
  96. data/lib/shopify_app/test_helpers/all.rb +2 -1
  97. data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +4 -3
  98. data/lib/shopify_app/utils.rb +4 -10
  99. data/lib/shopify_app/version.rb +2 -1
  100. data/lib/shopify_app.rb +44 -40
  101. data/package.json +1 -1
  102. data/shopify_app.gemspec +22 -21
  103. data/translation.yml +1 -1
  104. data/yarn.lock +103 -88
  105. metadata +51 -60
  106. data/config/locales/hi.yml +0 -23
  107. data/config/locales/ms.yml +0 -22
  108. data/lib/generators/shopify_app/install/templates/omniauth.rb +0 -4
  109. data/lib/generators/shopify_app/install/templates/shopify_provider.rb.tt +0 -8
  110. data/lib/generators/shopify_app/install/templates/user_agent.rb +0 -6
  111. data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +0 -34
  112. data/lib/shopify_app/omniauth/omniauth_configuration.rb +0 -64
data/docs/Upgrading.md CHANGED
@@ -1,9 +1,13 @@
1
- # Upgrading
1
+ # Upgrading
2
2
 
3
3
  This file documents important changes needed to upgrade your app's Shopify App version to a new major version.
4
4
 
5
5
  #### Table of contents
6
6
 
7
+ [Upgrading to `v19.0.0`](#upgrading-to-v1900)
8
+
9
+ [Upgrading to `v18.1.2`](#upgrading-to-v1812)
10
+
7
11
  [Upgrading to `v17.2.0`](#upgrading-to-v1720)
8
12
 
9
13
  [Upgrading to `v13.0.0`](#upgrading-to-v1300)
@@ -12,11 +16,102 @@ This file documents important changes needed to upgrade your app's Shopify App v
12
16
 
13
17
  [Upgrading from `v8.6` to `v9.0.0`](#upgrading-from-v86-to-v900)
14
18
 
19
+ ## Upgrading to `v19.0.0`
20
+
21
+ This update moves API authentication logic from this gem to the [`shopify_api`](https://github.com/Shopify/shopify_api)
22
+ gem.
23
+
24
+ ### High-level process
25
+
26
+ - Delete `config/initializers/omniauth.rb` as apps no longer need to initialize `OmniAuth` directly.
27
+ - Delete `config/initializers/user_agent.rb` as `shopify_app` will set the right `User-Agent` header for interacting
28
+ with the Shopify API. If the app requires further information in the `User-Agent` header beyond what Shopify API
29
+ requires, specify this in the `ShopifyAPI::Context.user_agent_prefix` setting.
30
+ - Remove `allow_jwt_authentication=` and `allow_cookie_authentication=` invocations from
31
+ `config/initializers/shopify_app.rb` as the decision logic for which authentication method to use is now handled
32
+ internally by the `shopify_api` gem, using the `ShopifyAPI::Context.embedded_app` setting.
33
+ - `v19.0.0` updates the `shopify_api` dependency to `10.0.0`. This version of `shopify_api` has breaking changes. See
34
+ the documentation for addressing these breaking changes on GitHub [here](https://github.com/Shopify/shopify_api#breaking-change-notice-for-version-1000).
35
+
36
+ ### Specific cases
37
+
38
+ #### Shopify user id in session
39
+
40
+ Previously, we set the entire app user object in the `session` object.
41
+ As of v19, since we no longer save the app user to the session (but only the shopify user id), we now store it as `session[:shopify_user_id]`. Please make sure to update any references to that object.
42
+
43
+ #### Webhook Jobs
44
+
45
+ Add a new `handle` method to existing webhook jobs to go through the updated `shopify_api` gem.
46
+
47
+ ```ruby
48
+ class MyWebhookJob < ActiveJob::Base
49
+ extend ShopifyAPI::Webhooks::Handler
50
+
51
+ class << self
52
+ # new handle function
53
+ def handle(topic:, shop:, body:)
54
+ # delegate to pre-existing perform_later function
55
+ perform_later(topic: topic, shop_domain: shop, webhook: body)
56
+ end
57
+ end
58
+
59
+ # original perform function
60
+ def perform(topic:, shop_domain:, webhook:)
61
+ # ...
62
+ ```
63
+
64
+ #### Temporary sessions
65
+
66
+ The new `shopify_api` gem offers a utility to temporarily create sessions for interacting with the API within a block.
67
+ This is useful for interacting with the Shopify API outside of the context of a subclass of `AuthenticatedController`.
68
+
69
+ ```ruby
70
+ ShopifyAPI::Auth::Session.temp(shop: shop_domain, access_token: shop_token) do |session|
71
+ # make invocations to the API
72
+ end
73
+ ```
74
+
75
+ Within a subclass of `AuthenticatedController`, the `current_shopify_session` function will return the current active
76
+ Shopify API session, or `nil` if no such session is available.
77
+
78
+ #### Setting up `ShopifyAPI::Context`
79
+
80
+ The `shopify_app` initializer must configure the `ShopifyAPI::Context`. The Rails generator will
81
+ generate a block in the `shopify_app` initializer. To do so manually, ensure the following is
82
+ part of the `after_initialize` block in `shopify_app.rb`.
83
+
84
+ ```ruby
85
+ Rails.application.config.after_initialize do
86
+ if ShopifyApp.configuration.api_key.present? && ShopifyApp.configuration.secret.present?
87
+ ShopifyAPI::Context.setup(
88
+ api_key: ShopifyApp.configuration.api_key,
89
+ api_secret_key: ShopifyApp.configuration.secret,
90
+ api_version: ShopifyApp.configuration.api_version,
91
+ host_name: URI(ENV.fetch('HOST', '')).host || '',
92
+ scope: ShopifyApp.configuration.scope,
93
+ is_private: !ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', '').empty?,
94
+ is_embedded: ShopifyApp.configuration.embedded_app,
95
+ session_storage: ShopifyApp::SessionRepository,
96
+ logger: Rails.logger,
97
+ private_shop: ENV.fetch('SHOPIFY_APP_PRIVATE_SHOP', nil),
98
+ user_agent_prefix: "ShopifyApp/#{ShopifyApp::VERSION}"
99
+ )
100
+
101
+ ShopifyApp::WebhooksManager.add_registrations
102
+ end
103
+ end
104
+ ```
105
+
106
+ ## Upgrading to `v18.1.2`
107
+
108
+ Version 18.1.2 replaces the deprecated EASDK redirect with an App Bridge 2 redirect when attempting to break out of an iframe. This happens when an app is installed, requires new access scopes, or re-authentication because the login session is expired.
109
+
15
110
  ## Upgrading to `v17.2.0`
16
111
 
17
112
  ### Different SameSite cookie attribute behaviour
18
113
 
19
- To support Rails `v6.1`, the [`SameSiteCookieMiddleware`](/lib/shopify_app/middleware/same_site_cookie_middleware.rb) was updated to configure cookies to `SameSite=None` if the app is embedded. Before this release, cookies were configured to `SameSite=None` only if this attribute had not previously been set before.
114
+ To support Rails `v6.1`, the [`SameSiteCookieMiddleware`](/lib/shopify_app/middleware/same_site_cookie_middleware.rb) was updated to configure cookies to `SameSite=None` if the app is embedded. Before this release, cookies were configured to `SameSite=None` only if this attribute had not previously been set before.
20
115
 
21
116
  ```diff
22
117
  # same_site_cookie_middleware.rb
@@ -33,32 +128,33 @@ change to how session stores work. Here are the steps to migrate to 13.x
33
128
 
34
129
  ### Changes to `config/initializers/shopify_app.rb`
35
130
 
36
- - *REMOVE* `config.per_user_tokens = [true|false]` this is no longer needed
37
- - *CHANGE* `config.session_repository = 'Shop'` To `config.shop_session_repository = 'Shop'`
38
- - *ADD (optional)* User Session Storage `config.user_session_repository = 'User'`
131
+ - _REMOVE_ `config.per_user_tokens = [true|false]` this is no longer needed
132
+ - _CHANGE_ `config.session_repository = 'Shop'` To `config.shop_session_repository = 'Shop'`
133
+ - _ADD (optional)_ User Session Storage `config.user_session_repository = 'User'`
39
134
 
40
135
  ### Shop Model Changes (normally `app/models/shop.rb`)
41
136
 
42
- - *CHANGE* `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
137
+ - _CHANGE_ `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
43
138
 
44
139
  ### Changes to the @shop_session instance variable (normally in `app/controllers/*.rb`)
45
140
 
46
- - *CHANGE* if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session`.
141
+ - _CHANGE_ if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session`.
47
142
 
48
143
  ### Changes to Rails `session`
49
144
 
50
- - *CHANGE* `session[:shopify]` is no longer set. Use `session[:user_id]` if your app uses user based tokens, or `session[:shop_id]` if your app uses shop based tokens.
145
+ - _CHANGE_ `session[:shopify]` is no longer set. Use `session[:user_id]` if your app uses user based tokens, or `session[:shop_id]` if your app uses shop based tokens.
51
146
 
52
147
  ### Changes to `ShopifyApp::LoginProtection`
53
148
 
54
149
  `ShopifyApp::LoginProtection`
55
150
 
56
151
  - CHANGE if you are using `ShopifyApp::LoginProtection#shopify_session` in your code, it will need to be
57
- changed to `ShopifyApp::LoginProtection#activate_shopify_session`
152
+ changed to `ShopifyApp::LoginProtection#activate_shopify_session`
58
153
  - CHANGE if you are using `ShopifyApp::LoginProtection#clear_shop_session` in your code, it will need to be
59
- changed to `ShopifyApp::LoginProtection#clear_shopify_session`
154
+ changed to `ShopifyApp::LoginProtection#clear_shopify_session`
60
155
 
61
156
  ### Notes
157
+
62
158
  You do not need a user model; a shop session is fine for most applications.
63
159
 
64
160
  ---
@@ -66,6 +162,7 @@ You do not need a user model; a shop session is fine for most applications.
66
162
  ## Upgrading to `v11.7.0`
67
163
 
68
164
  ### Session storage method signature breaking change
165
+
69
166
  If you override `def self.store(auth_session)` method in your session storage model (e.g. Shop), the method signature has changed to `def self.store(auth_session, *args)` in order to support user-based token storage. Please update your method signature to include the second argument.
70
167
 
71
168
  ---
@@ -75,14 +172,16 @@ If you override `def self.store(auth_session)` method in your session storage mo
75
172
  ### Configuration change
76
173
 
77
174
  Add an API version configuration in `config/initializers/shopify_app.rb`
78
- Set this to the version you want to run against by default. See [Shopify API docs](https://help.shopify.com/en/api/versioning) for versions available.
175
+ Set this to the version you want to run against by default. See [Shopify API docs](https://help.shopify.com/api/versioning) for versions available.
176
+
79
177
  ```ruby
80
178
  config.api_version = '2019-04'
81
179
  ```
82
180
 
83
181
  ### Session storage change
84
182
 
85
- You will need to add an `api_version` method to your session storage object. The default implementation for this is.
183
+ You will need to add an `api_version` method to your session storage object. The default implementation for this is.
184
+
86
185
  ```ruby
87
186
  def api_version
88
187
  ShopifyApp.configuration.api_version
@@ -92,6 +191,7 @@ end
92
191
  ### Generated file change
93
192
 
94
193
  `embedded_app.html.erb` the usage of `shop_session.url` needs to be changed to `shop_session.domain`
194
+
95
195
  ```erb
96
196
  <script type="text/javascript">
97
197
  ShopifyApp.init({
@@ -104,7 +204,9 @@ end
104
204
  });
105
205
  </script>
106
206
  ```
207
+
107
208
  is changed to
209
+
108
210
  ```erb
109
211
  <script type="text/javascript">
110
212
  ShopifyApp.init({
@@ -122,5 +224,5 @@ is changed to
122
224
 
123
225
  You will need to also follow the ShopifyAPI [upgrade guide](https://github.com/Shopify/shopify_api/blob/master/README.md#-breaking-change-notice-for-version-700-) to ensure your app is ready to work with API versioning.
124
226
 
125
- [dashboard]:https://partners.shopify.com
126
- [app-bridge]:https://help.shopify.com/en/api/embedded-apps/app-bridge
227
+ [dashboard]: https://partners.shopify.com
228
+ [app-bridge]: https://shopify.dev/apps/tools/app-bridge
@@ -15,7 +15,7 @@ While you can customize the login view by creating a `/app/views/shopify_app/ses
15
15
 
16
16
  ```ruby
17
17
  ShopifyApp.configure do |config|
18
- config.login_url = 'https://my.domain.com/nested/login'
18
+ config.login_url = 'https://example.com/nested/login'
19
19
  end
20
20
  ```
21
21
 
@@ -77,6 +77,6 @@ class ReviewsController < ApplicationController
77
77
  end
78
78
  ```
79
79
 
80
- Create your app proxy URL in the [Shopify Partners dashboard](https://partners.shopify.com/organizations), making sure to point it to `https://your_app_website.com/app_proxy`.
80
+ Create your app proxy URL in the [Shopify Partners dashboard](https://partners.shopify.com/organizations), making sure to point it to `https://example.com/app_proxy`.
81
81
 
82
82
  ![Creating an App Proxy](/images/app-proxy-screenshot.png)
@@ -1,5 +1,15 @@
1
1
  # Handling changes in access scopes
2
- The Shopify App gem provides handling changes to scopes for both shop/offline and user/online tokens. To enable your app to login via OAuth on scope changes, you can set the following configuration flag in your `config/initializers/shopify_app.rb`:
2
+ ## Updating the list of scopes the app requests
3
+
4
+ Your app specifies the [access scopes](https://shopify.dev/api/usage/access-scopes) it requires in the Shopify App initializer, located at`config/initializers/shopify_app.rb`. To modify this list, update the comma-delimited configuration option:
5
+
6
+ ```ruby
7
+ config.scope = "read_products,write_discounts"
8
+ ```
9
+
10
+ ## Requesting new scopes from merchants
11
+
12
+ The Shopify App gem will automatically request new scopes from merchants for both shop/offline and user/online tokens. To enable your app to reauth via OAuth on scope changes, you can set the following configuration flag in your `config/initializers/shopify_app.rb`:
3
13
  ```ruby
4
14
  config.reauth_on_access_scope_changes = true
5
15
  ```
@@ -11,7 +11,7 @@ As with webhooks, ShopifyApp can manage your app's [ScriptTags](https://shopify-
11
11
  ```ruby
12
12
  ShopifyApp.configure do |config|
13
13
  config.scripttags = [
14
- {event:'onload', src: 'https://my-shopifyapp.herokuapp.com/fancy.js'},
14
+ {event:'onload', src: 'https://example.com/fancy.js'},
15
15
  {event:'onload', src: ->(domain) { dynamic_tag_url(domain) } }
16
16
  ]
17
17
  end
@@ -12,7 +12,7 @@ ShopifyApp can manage your app's webhooks for you if you set which webhooks you
12
12
  ```ruby
13
13
  ShopifyApp.configure do |config|
14
14
  config.webhooks = [
15
- {topic: 'carts/update', address: 'https://example-app.com/webhooks/carts_update'}
15
+ {topic: 'carts/update', address: 'https://example.com/webhooks/carts_update'}
16
16
  ]
17
17
  end
18
18
  ```
@@ -34,7 +34,7 @@ If you are only interested in particular fields, you can optionally filter the d
34
34
  ```ruby
35
35
  ShopifyApp.configure do |config|
36
36
  config.webhooks = [
37
- {topic: 'products/update', address: 'https://example-app.com/webhooks/products_update', fields: ['title', 'vendor']}
37
+ {topic: 'products/update', address: 'https://example.com/webhooks/products_update', fields: ['title', 'vendor']}
38
38
  ]
39
39
  end
40
40
  ```
@@ -66,7 +66,7 @@ The WebhooksManager uses ActiveJob. If ActiveJob is not configured then by defau
66
66
  ShopifyApp can create webhooks for you using the `add_webhook` generator. This will add the new webhook to your config and create the required job class for you.
67
67
 
68
68
  ```
69
- rails g shopify_app:add_webhook -t carts/update -a https://example.com/webhooks/carts_update
69
+ rails g shopify_app:add_webhook -t carts/update -a /webhooks/carts_update
70
70
  ```
71
71
 
72
72
  Where `-t` is the topic and `-a` is the address the webhook should be sent to.
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
6
7
  class AddAfterAuthenticateJobGenerator < Rails::Generators::Base
7
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
8
9
 
9
10
  hook_for :test_framework, as: :job, in: :rails do |instance, generator|
10
11
  instance.invoke(generator, [instance.send(:job_file_name)])
@@ -15,32 +16,32 @@ module ShopifyApp
15
16
 
16
17
  after_authenticate_job_config =
17
18
  " config.after_authenticate_job = "\
18
- "{ job: \"Shopify::AfterAuthenticateJob\", inline: false }\n"
19
+ "{ job: \"Shopify::AfterAuthenticateJob\", inline: false }\n"
19
20
 
20
21
  inject_into_file(
21
- 'config/initializers/shopify_app.rb',
22
+ "config/initializers/shopify_app.rb",
22
23
  after_authenticate_job_config,
23
- before: 'end'
24
+ before: "end"
24
25
  )
25
26
 
26
27
  unless initializer.include?(after_authenticate_job_config)
27
28
  shell.say("Error adding after_authenticate_job to config. Add this line manually: "\
28
- "#{after_authenticate_job_config}", :red)
29
+ "#{after_authenticate_job_config}", :red)
29
30
  end
30
31
  end
31
32
 
32
33
  def add_after_authenticate_job
33
- template('after_authenticate_job.rb', "app/jobs/#{job_file_name}_job.rb")
34
+ template("after_authenticate_job.rb", "app/jobs/#{job_file_name}_job.rb")
34
35
  end
35
36
 
36
37
  private
37
38
 
38
39
  def load_initializer
39
- File.read(File.join(destination_root, 'config/initializers/shopify_app.rb'))
40
+ File.read(File.join(destination_root, "config/initializers/shopify_app.rb"))
40
41
  end
41
42
 
42
43
  def job_file_name
43
- 'shopify/after_authenticate'
44
+ "shopify/after_authenticate"
44
45
  end
45
46
  end
46
47
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shopify
3
4
  class AfterAuthenticateJob < ActiveJob::Base
4
5
  def perform(shop_domain:)
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
6
7
  class AddMarketingActivityExtensionGenerator < Rails::Generators::Base
7
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
8
9
 
9
10
  def generate_app_extension
10
11
  template("marketing_activities_controller.rb", "app/controllers/marketing_activities_controller.rb")
@@ -15,7 +16,7 @@ module ShopifyApp
15
16
 
16
17
  def generate_routes
17
18
  inject_into_file(
18
- 'config/routes.rb',
19
+ "config/routes.rb",
19
20
  optimize_indentation(routes, 2),
20
21
  after: "root :to => 'home#index'\n"
21
22
  )
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
6
7
  class AddWebhookGenerator < Rails::Generators::Base
7
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
8
9
  class_option :topic, type: :string, aliases: "-t", required: true
9
10
  class_option :address, type: :string, aliases: "-a", required: true
10
11
 
@@ -17,15 +18,15 @@ module ShopifyApp
17
18
  return if initializer.include?("config.webhooks")
18
19
 
19
20
  inject_into_file(
20
- 'config/initializers/shopify_app.rb',
21
+ "config/initializers/shopify_app.rb",
21
22
  " config.webhooks = [\n ]\n",
22
- before: 'end'
23
+ after: /ShopifyApp\.configure.*\n/
23
24
  )
24
25
  end
25
26
 
26
27
  def inject_webhook_to_shopify_app_initializer
27
28
  inject_into_file(
28
- 'config/initializers/shopify_app.rb',
29
+ "config/initializers/shopify_app.rb",
29
30
  webhook_config,
30
31
  after: "config.webhooks = ["
31
32
  )
@@ -38,31 +39,31 @@ module ShopifyApp
38
39
  end
39
40
 
40
41
  def add_webhook_job
41
- @job_file_name = job_file_name + '_job'
42
+ @job_file_name = job_file_name + "_job"
42
43
  @job_class_name = @job_file_name.classify
43
- template('webhook_job.rb', "app/jobs/#{@job_file_name}.rb")
44
+ template("webhook_job.rb", "app/jobs/#{@job_file_name}.rb")
44
45
  end
45
46
 
46
47
  private
47
48
 
48
49
  def job_file_name
49
- address.split('/').last
50
+ address.split("/").last
50
51
  end
51
52
 
52
53
  def load_initializer
53
- File.read(File.join(destination_root, 'config/initializers/shopify_app.rb'))
54
+ File.read(File.join(destination_root, "config/initializers/shopify_app.rb"))
54
55
  end
55
56
 
56
57
  def webhook_config
57
- "\n {topic: '#{topic}', address: '#{address}', format: 'json'},"
58
+ "\n { topic: \"#{topic}\", address: \"#{address}\" },"
58
59
  end
59
60
 
60
61
  def topic
61
- options['topic']
62
+ options["topic"]
62
63
  end
63
64
 
64
65
  def address
65
- options['address']
66
+ options["address"]
66
67
  end
67
68
  end
68
69
  end
@@ -1,5 +1,13 @@
1
1
  class <%= @job_class_name %> < ActiveJob::Base
2
- def perform(shop_domain:, webhook:)
2
+ extend ShopifyAPI::Webhooks::Handler
3
+
4
+ class << self
5
+ def handle(topic:, shop:, body:)
6
+ perform_later(topic: topic, shop_domain: shop, webhook: body)
7
+ end
8
+ end
9
+
10
+ def perform(topic:, shop_domain:, webhook:)
3
11
  shop = Shop.find_by(shopify_domain: shop_domain)
4
12
 
5
13
  if shop.nil?
@@ -1,23 +1,24 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
6
7
  class AppProxyControllerGenerator < Rails::Generators::Base
7
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
8
9
 
9
10
  def create_app_proxy_controller
10
- template('app_proxy_controller.rb', 'app/controllers/app_proxy_controller.rb')
11
+ template("app_proxy_controller.rb", "app/controllers/app_proxy_controller.rb")
11
12
  end
12
13
 
13
14
  def create_app_proxy_index_view
14
- copy_file('index.html.erb', 'app/views/app_proxy/index.html.erb')
15
+ copy_file("index.html.erb", "app/views/app_proxy/index.html.erb")
15
16
  end
16
17
 
17
18
  def add_app_proxy_route
18
19
  inject_into_file(
19
- 'config/routes.rb',
20
- File.read(File.expand_path(find_in_source_paths('app_proxy_route.rb'))),
20
+ "config/routes.rb",
21
+ File.read(File.expand_path(find_in_source_paths("app_proxy_route.rb"))),
21
22
  after: "mount ShopifyApp::Engine, at: '/'\n"
22
23
  )
23
24
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class AppProxyController < ApplicationController
3
4
  include ShopifyApp::AppProxyVerification
4
5
 
5
6
  def index
6
- render(layout: false, content_type: 'application/liquid')
7
+ render(layout: false, content_type: "application/liquid")
7
8
  end
8
9
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :app_proxy do
4
- root action: 'index'
4
+ root action: "index"
5
5
  # simple routes without a specified controller will go to AppProxyController
6
6
 
7
7
  # more complex routes will go to controllers in the AppProxy namespace
@@ -1,14 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators/base'
3
+ require "rails/generators/base"
4
4
 
5
5
  module ShopifyApp
6
6
  module Generators
7
7
  class AuthenticatedControllerGenerator < Rails::Generators::Base
8
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
9
9
 
10
10
  def create_authenticated_controller
11
- template('authenticated_controller.rb', 'app/controllers/authenticated_controller.rb')
11
+ template("authenticated_controller.rb", "app/controllers/authenticated_controller.rb")
12
12
  end
13
13
  end
14
14
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
@@ -15,14 +16,14 @@ module ShopifyApp
15
16
  private
16
17
 
17
18
  def controllers
18
- files_within_root('.', 'app/controllers/shopify_app/*.*')
19
+ files_within_root(".", "app/controllers/shopify_app/*.*")
19
20
  end
20
21
 
21
22
  def files_within_root(prefix, glob)
22
23
  root = "#{self.class.source_root}/#{prefix}"
23
24
 
24
25
  Dir["#{root}/#{glob}"].sort.map do |full_path|
25
- full_path.sub(root, '.').gsub('/./', '/')
26
+ full_path.sub(root, ".").gsub("/./", "/")
26
27
  end
27
28
  end
28
29
  end
@@ -1,24 +1,24 @@
1
1
  # frozen_string_literal: true
2
- require 'rails/generators/base'
2
+
3
+ require "rails/generators/base"
3
4
 
4
5
  module ShopifyApp
5
6
  module Generators
6
7
  class HomeControllerGenerator < Rails::Generators::Base
7
- source_root File.expand_path('../templates', __FILE__)
8
+ source_root File.expand_path("../templates", __FILE__)
8
9
 
9
- class_option :with_cookie_authentication, type: :boolean, default: false
10
- class_option :embedded, type: :string, default: 'true'
10
+ class_option :embedded, type: :string, default: "true"
11
11
 
12
12
  def create_home_controller
13
- template(home_controller_template, 'app/controllers/home_controller.rb')
13
+ template(home_controller_template, "app/controllers/home_controller.rb")
14
14
  end
15
15
 
16
16
  def create_products_controller
17
- generate("shopify_app:products_controller") unless with_cookie_authentication?
17
+ generate("shopify_app:products_controller") if embedded? || embedded_app?
18
18
  end
19
19
 
20
20
  def create_home_index_view
21
- template('index.html.erb', 'app/views/home/index.html.erb')
21
+ template("index.html.erb", "app/views/home/index.html.erb")
22
22
  end
23
23
 
24
24
  def add_home_index_route
@@ -28,25 +28,21 @@ module ShopifyApp
28
28
  private
29
29
 
30
30
  def embedded?
31
- options['embedded'] == 'true'
31
+ options["embedded"] == "true"
32
32
  end
33
33
 
34
34
  def embedded_app?
35
35
  ShopifyApp.configuration.embedded_app?
36
36
  end
37
37
 
38
- def with_cookie_authentication?
39
- options['with_cookie_authentication']
40
- end
41
-
42
38
  def home_controller_template
43
- return 'unauthenticated_home_controller.rb' unless authenticated_home_controller_required?
39
+ return "unauthenticated_home_controller.rb" unless authenticated_home_controller_required?
44
40
 
45
- 'home_controller.rb'
41
+ "home_controller.rb"
46
42
  end
47
43
 
48
44
  def authenticated_home_controller_required?
49
- with_cookie_authentication? || !embedded? || !embedded_app?
45
+ !embedded? || !embedded_app?
50
46
  end
51
47
  end
52
48
  end
@@ -6,8 +6,8 @@ class HomeController < AuthenticatedController
6
6
  before_action :set_host
7
7
 
8
8
  def index
9
- @products = ShopifyAPI::Product.find(:all, params: { limit: 10 })
10
- @webhooks = ShopifyAPI::Webhook.find(:all)
9
+ @products = ShopifyAPI::Product.all(limit: 10)
10
+ @webhooks = ShopifyAPI::Webhook.all
11
11
  end
12
12
 
13
13
  private
@@ -7,8 +7,12 @@
7
7
  rel="stylesheet"
8
8
  href="https://unpkg.com/@shopify/polaris@4.25.0/styles.min.css"
9
9
  />
10
- <% unless with_cookie_authentication? %> <script>
10
+ <% if embedded_app? %> <script>
11
11
  document.addEventListener("DOMContentLoaded", async function() {
12
+ <% if ShopifyApp.use_importmap? %>
13
+ await import("lib/shopify_app")
14
+ <% end %>
15
+
12
16
  var SessionToken = window["app-bridge"].actions.SessionToken
13
17
  var app = window.app;
14
18
 
@@ -47,10 +51,10 @@
47
51
  <% end %> </head>
48
52
  <body>
49
53
  <h2>Products</h2>
50
- <% unless with_cookie_authentication? %> <div id="products"><br>Loading...</div><% else %>
54
+ <% if embedded_app? %> <div id="products"><br>Loading...</div><% else %>
51
55
  <ul>
52
56
  <%% @products.each do |product| %>
53
- <li><%%= link_to product.title, "https://#{@current_shopify_session.domain}/admin/products/#{product.id}", target: "_top" %></li>
57
+ <li><%%= link_to product.title, "https://#{@current_shopify_session.shop}/admin/products/#{product.id}", target: "_top" %></li>
54
58
  <%% end %>
55
59
  </ul>
56
60