shopify_app 22.3.1 → 22.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b4b936b4f5a91a7a73e53ec4e1df8d46d7cd75a67663ade6035524a32b01642
4
- data.tar.gz: b9b5b3b9cc461fdee3d9b6447f888e68ed2bcd7e504084550118d2c9929e5072
3
+ metadata.gz: d8a8d6fb5b227bbe3070fba9050497eb007e4191a782bc89b12a84546470ed65
4
+ data.tar.gz: 5f8d8e4486585b07a93ad7f6abddaebde7a263568dc78e757627476aba37d38b
5
5
  SHA512:
6
- metadata.gz: 5c0c813ac266810468a1100dfa7c9baf1af7c889f9a9dc865d796c19baea2d0bcaea7c8f79f6f27e1cbb7fa918f237563eac954735d4dcd77e6aa9f89038b34c
7
- data.tar.gz: fe5fdd935be6cf251ab74ecc110178c3a5a07cfdf5aafc7a568db34fea7568bbca218c99c8223d18555079cdc080bd96ba951c4f800937acb94809e3ae89ca0f
6
+ metadata.gz: 2a0b7ad073c42b6fbe5033aa686fa365050d8d56305507746b15f938a1511e979eecd49dcaefbe2793114c6ca4c4ef4f986085b743651115dc816faab404da15
7
+ data.tar.gz: a8896ed834816ef8fd35f17db67aef3efcd401fa2a46900e2a2bce8d5b96f863db3eaa0335e73d63b6c48e6382d52d9103c46fce7a7252568e1abe7e503d2075
@@ -12,7 +12,7 @@ jobs:
12
12
  name: Ruby ${{ matrix.version }}
13
13
  strategy:
14
14
  matrix:
15
- version: ['3.0', '3.1', '3.2']
15
+ version: ['3.0', '3.1', '3.2', '3.3']
16
16
 
17
17
  steps:
18
18
  - uses: actions/checkout@v3
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  Unreleased
2
2
  ----------
3
3
 
4
+ 22.5.0 (November 28, 2024)
5
+ ----------
6
+ - Add support for filters in webhook registration [1923](https://github.com/Shopify/shopify_app/pull/1923)
7
+ - Make `ShopifyApp.configuration.scope` default to empty list `[]` [1913](https://github.com/Shopify/shopify_app/pull/1913)
8
+
9
+ 22.4.0 (August 22, 2024)
10
+ ----------
11
+ - Add the `unified_admin_domain` configuration option for the unified admin domain.
12
+ - Add new generators for webhook subscriptions defined in the `shopify.app.toml` file [1882](https://github.com/Shopify/shopify_app/pull/1882)
13
+ - Fix test stubbing for Token Exchange auth [1897](https://github.com/Shopify/shopify_app/pull/1897)
14
+
4
15
  22.3.1 (July 26, 2024)
5
16
  ----------
6
17
  - Handle edge case where we attempted to redirect to login when already at the top level [#1887](https://github.com/Shopify/shopify_app/pull/1887)
data/Gemfile.lock CHANGED
@@ -1,80 +1,80 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify_app (22.3.1)
4
+ shopify_app (22.5.0)
5
5
  activeresource
6
6
  addressable (~> 2.7)
7
7
  jwt (>= 2.2.3)
8
8
  rails (> 5.2.1)
9
9
  redirect_safely (~> 1.0)
10
- shopify_api (>= 14.3.0, < 15.0)
10
+ shopify_api (>= 14.7.0, < 15.0)
11
11
  sprockets-rails (>= 2.0.0)
12
12
 
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- actioncable (6.1.7.8)
17
- actionpack (= 6.1.7.8)
18
- activesupport (= 6.1.7.8)
16
+ actioncable (6.1.7.9)
17
+ actionpack (= 6.1.7.9)
18
+ activesupport (= 6.1.7.9)
19
19
  nio4r (~> 2.0)
20
20
  websocket-driver (>= 0.6.1)
21
- actionmailbox (6.1.7.8)
22
- actionpack (= 6.1.7.8)
23
- activejob (= 6.1.7.8)
24
- activerecord (= 6.1.7.8)
25
- activestorage (= 6.1.7.8)
26
- activesupport (= 6.1.7.8)
21
+ actionmailbox (6.1.7.9)
22
+ actionpack (= 6.1.7.9)
23
+ activejob (= 6.1.7.9)
24
+ activerecord (= 6.1.7.9)
25
+ activestorage (= 6.1.7.9)
26
+ activesupport (= 6.1.7.9)
27
27
  mail (>= 2.7.1)
28
- actionmailer (6.1.7.8)
29
- actionpack (= 6.1.7.8)
30
- actionview (= 6.1.7.8)
31
- activejob (= 6.1.7.8)
32
- activesupport (= 6.1.7.8)
28
+ actionmailer (6.1.7.9)
29
+ actionpack (= 6.1.7.9)
30
+ actionview (= 6.1.7.9)
31
+ activejob (= 6.1.7.9)
32
+ activesupport (= 6.1.7.9)
33
33
  mail (~> 2.5, >= 2.5.4)
34
34
  rails-dom-testing (~> 2.0)
35
- actionpack (6.1.7.8)
36
- actionview (= 6.1.7.8)
37
- activesupport (= 6.1.7.8)
35
+ actionpack (6.1.7.9)
36
+ actionview (= 6.1.7.9)
37
+ activesupport (= 6.1.7.9)
38
38
  rack (~> 2.0, >= 2.0.9)
39
39
  rack-test (>= 0.6.3)
40
40
  rails-dom-testing (~> 2.0)
41
41
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
42
- actiontext (6.1.7.8)
43
- actionpack (= 6.1.7.8)
44
- activerecord (= 6.1.7.8)
45
- activestorage (= 6.1.7.8)
46
- activesupport (= 6.1.7.8)
42
+ actiontext (6.1.7.9)
43
+ actionpack (= 6.1.7.9)
44
+ activerecord (= 6.1.7.9)
45
+ activestorage (= 6.1.7.9)
46
+ activesupport (= 6.1.7.9)
47
47
  nokogiri (>= 1.8.5)
48
- actionview (6.1.7.8)
49
- activesupport (= 6.1.7.8)
48
+ actionview (6.1.7.9)
49
+ activesupport (= 6.1.7.9)
50
50
  builder (~> 3.1)
51
51
  erubi (~> 1.4)
52
52
  rails-dom-testing (~> 2.0)
53
53
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
54
- activejob (6.1.7.8)
55
- activesupport (= 6.1.7.8)
54
+ activejob (6.1.7.9)
55
+ activesupport (= 6.1.7.9)
56
56
  globalid (>= 0.3.6)
57
- activemodel (6.1.7.8)
58
- activesupport (= 6.1.7.8)
57
+ activemodel (6.1.7.9)
58
+ activesupport (= 6.1.7.9)
59
59
  activemodel-serializers-xml (1.0.2)
60
60
  activemodel (> 5.x)
61
61
  activesupport (> 5.x)
62
62
  builder (~> 3.1)
63
- activerecord (6.1.7.8)
64
- activemodel (= 6.1.7.8)
65
- activesupport (= 6.1.7.8)
66
- activeresource (6.1.0)
63
+ activerecord (6.1.7.9)
64
+ activemodel (= 6.1.7.9)
65
+ activesupport (= 6.1.7.9)
66
+ activeresource (6.1.3)
67
67
  activemodel (>= 6.0)
68
68
  activemodel-serializers-xml (~> 1.0)
69
69
  activesupport (>= 6.0)
70
- activestorage (6.1.7.8)
71
- actionpack (= 6.1.7.8)
72
- activejob (= 6.1.7.8)
73
- activerecord (= 6.1.7.8)
74
- activesupport (= 6.1.7.8)
70
+ activestorage (6.1.7.9)
71
+ actionpack (= 6.1.7.9)
72
+ activejob (= 6.1.7.9)
73
+ activerecord (= 6.1.7.9)
74
+ activesupport (= 6.1.7.9)
75
75
  marcel (~> 1.0)
76
76
  mini_mime (>= 1.1.0)
77
- activesupport (6.1.7.8)
77
+ activesupport (6.1.7.9)
78
78
  concurrent-ruby (~> 1.0, >= 1.0.2)
79
79
  i18n (>= 1.6, < 2)
80
80
  minitest (>= 5.1)
@@ -88,21 +88,21 @@ GEM
88
88
  builder (3.3.0)
89
89
  byebug (11.1.3)
90
90
  coderay (1.1.3)
91
- concurrent-ruby (1.3.3)
91
+ concurrent-ruby (1.3.4)
92
92
  crack (0.4.5)
93
93
  rexml
94
94
  crass (1.0.6)
95
- date (3.3.3)
95
+ date (3.3.4)
96
96
  debug_inspector (1.1.0)
97
97
  erubi (1.13.0)
98
- globalid (1.1.0)
99
- activesupport (>= 5.0)
98
+ globalid (1.2.1)
99
+ activesupport (>= 6.1)
100
100
  hash_diff (1.1.1)
101
101
  hashdiff (1.0.1)
102
102
  httparty (0.21.0)
103
103
  mini_mime (>= 1.0.0)
104
104
  multi_xml (>= 0.5.2)
105
- i18n (1.14.5)
105
+ i18n (1.14.6)
106
106
  concurrent-ruby (~> 1.0)
107
107
  json (2.7.2)
108
108
  jwt (2.7.0)
@@ -117,26 +117,26 @@ GEM
117
117
  net-smtp
118
118
  marcel (1.0.2)
119
119
  method_source (1.0.0)
120
- mini_mime (1.1.2)
120
+ mini_mime (1.1.5)
121
121
  minitest (5.18.0)
122
122
  mocha (2.0.2)
123
123
  ruby2_keywords (>= 0.0.5)
124
124
  multi_xml (0.6.0)
125
- net-imap (0.3.4)
125
+ net-imap (0.4.17)
126
126
  date
127
127
  net-protocol
128
128
  net-pop (0.1.2)
129
129
  net-protocol
130
- net-protocol (0.2.1)
130
+ net-protocol (0.2.2)
131
131
  timeout
132
- net-smtp (0.3.3)
132
+ net-smtp (0.5.0)
133
133
  net-protocol
134
134
  nio4r (2.5.9)
135
- nokogiri (1.16.6-arm64-darwin)
135
+ nokogiri (1.16.7-arm64-darwin)
136
136
  racc (~> 1.4)
137
- nokogiri (1.16.6-x86_64-darwin)
137
+ nokogiri (1.16.7-x86_64-darwin)
138
138
  racc (~> 1.4)
139
- nokogiri (1.16.6-x86_64-linux)
139
+ nokogiri (1.16.7-x86_64-linux)
140
140
  racc (~> 1.4)
141
141
  oj (3.14.3)
142
142
  openssl (3.1.0)
@@ -154,24 +154,24 @@ GEM
154
154
  binding_of_caller (~> 1.0)
155
155
  pry (~> 0.13)
156
156
  public_suffix (5.0.1)
157
- racc (1.8.0)
158
- rack (2.2.9)
157
+ racc (1.8.1)
158
+ rack (2.2.10)
159
159
  rack-test (2.1.0)
160
160
  rack (>= 1.3)
161
- rails (6.1.7.8)
162
- actioncable (= 6.1.7.8)
163
- actionmailbox (= 6.1.7.8)
164
- actionmailer (= 6.1.7.8)
165
- actionpack (= 6.1.7.8)
166
- actiontext (= 6.1.7.8)
167
- actionview (= 6.1.7.8)
168
- activejob (= 6.1.7.8)
169
- activemodel (= 6.1.7.8)
170
- activerecord (= 6.1.7.8)
171
- activestorage (= 6.1.7.8)
172
- activesupport (= 6.1.7.8)
161
+ rails (6.1.7.9)
162
+ actioncable (= 6.1.7.9)
163
+ actionmailbox (= 6.1.7.9)
164
+ actionmailer (= 6.1.7.9)
165
+ actionpack (= 6.1.7.9)
166
+ actiontext (= 6.1.7.9)
167
+ actionview (= 6.1.7.9)
168
+ activejob (= 6.1.7.9)
169
+ activemodel (= 6.1.7.9)
170
+ activerecord (= 6.1.7.9)
171
+ activestorage (= 6.1.7.9)
172
+ activesupport (= 6.1.7.9)
173
173
  bundler (>= 1.15.0)
174
- railties (= 6.1.7.8)
174
+ railties (= 6.1.7.9)
175
175
  sprockets-rails (>= 2.0.0)
176
176
  rails-controller-testing (1.0.5)
177
177
  actionpack (>= 5.0.1.rc1)
@@ -184,9 +184,9 @@ GEM
184
184
  rails-html-sanitizer (1.6.0)
185
185
  loofah (~> 2.21)
186
186
  nokogiri (~> 1.14)
187
- railties (6.1.7.8)
188
- actionpack (= 6.1.7.8)
189
- activesupport (= 6.1.7.8)
187
+ railties (6.1.7.9)
188
+ actionpack (= 6.1.7.9)
189
+ activesupport (= 6.1.7.9)
190
190
  method_source
191
191
  rake (>= 12.2)
192
192
  thor (~> 1.0)
@@ -196,8 +196,7 @@ GEM
196
196
  redirect_safely (1.0.0)
197
197
  activemodel
198
198
  regexp_parser (2.9.0)
199
- rexml (3.3.2)
200
- strscan
199
+ rexml (3.3.9)
201
200
  rubocop (1.62.1)
202
201
  json (~> 2.3)
203
202
  language_server-protocol (>= 3.17.0)
@@ -220,7 +219,7 @@ GEM
220
219
  ruby-progressbar (1.13.0)
221
220
  ruby2_keywords (0.0.5)
222
221
  securerandom (0.2.2)
223
- shopify_api (14.3.0)
222
+ shopify_api (14.7.0)
224
223
  activesupport
225
224
  concurrent-ruby
226
225
  hash_diff
@@ -242,11 +241,10 @@ GEM
242
241
  sqlite3 (1.7.3-arm64-darwin)
243
242
  sqlite3 (1.7.3-x86_64-darwin)
244
243
  sqlite3 (1.7.3-x86_64-linux)
245
- strscan (3.1.0)
246
244
  syntax_tree (6.1.1)
247
245
  prettier_print (>= 1.2.0)
248
246
  thor (1.2.2)
249
- timeout (0.3.2)
247
+ timeout (0.4.1)
250
248
  tzinfo (2.0.6)
251
249
  concurrent-ruby (~> 1.0)
252
250
  unicode-display_width (2.5.0)
@@ -257,7 +255,7 @@ GEM
257
255
  websocket-driver (0.7.5)
258
256
  websocket-extensions (>= 0.1.0)
259
257
  websocket-extensions (0.1.5)
260
- zeitwerk (2.6.16)
258
+ zeitwerk (2.6.18)
261
259
 
262
260
  PLATFORMS
263
261
  arm64-darwin-21
data/README.md CHANGED
@@ -169,10 +169,11 @@ ShopifyApp.configure do |config|
169
169
  end
170
170
 
171
171
  ```
172
- 3. Handle special callback logic. If your app has overridden the OAuth CallbackController to run special tasks post authorization,
172
+ 3. Handle special callback logic. If your app has overridden the OAuth CallbackController to run special tasks post authorization,
173
173
  you'll need to create and configure a custom PostAuthenticateTasks class to run these tasks after the token exchange. The original
174
174
  OAuth CallbackController will not be triggered anymore. See [Post Authenticate Tasks documentation](/docs/shopify_app/authentication.md#post-authenticate-tasks) for more information.
175
- 4. Enjoy a smoother and faster app installation process.
175
+ 4. Make sure your `embedded_app` layout is correct. If your app has any controller which includes `ShopifyApp::EnsureInstalled`, they will now also include the `ShopifyApp::EmbeddedApp` concern, which sets `layout 'embedded_app'` for the current controller by default. In cases where the controller originally looked for another layout file, this can cause unexpected behavior. See [`EmbeddedApp` concern's documentation](/docs/shopify_app/controller-concerns.md#embeddedapp) for more information on the effects of this concern and how to disable the layout change if needed.
176
+ 5. Enjoy a smoother and faster app installation process.
176
177
 
177
178
  ### API Versioning
178
179
 
data/docs/Quickstart.md CHANGED
@@ -34,8 +34,15 @@ HOST='https://some-random-words.trycloudflare.com/'
34
34
 
35
35
  ## Use Shopify App Bridge to embed your app in the Shopify Admin
36
36
 
37
- A basic example of using [*Shopify App Bridge*](https://shopify.dev/tools/app-bridge) is included in the install generator. An instance Shopify App Bridge is automatically initialized in [shopify_app.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/shopify_app.js).
37
+ A basic example of using [*Shopify App Bridge*](https://shopify.dev/tools/app-bridge) is included in the install generator. An instance Shopify App Bridge is automatically initialized in [shopify_app.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/shopify_app.js).
38
38
 
39
- The [flash_messages.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/flash_messages.js) file converts Rails [flash messages](https://api.rubyonrails.org/classes/ActionDispatch/Flash.html) to App Bridge Toast actions automatically. By default, this library is included via [unpkg in the embedded_app layout](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/embedded_app.html.erb#L27).
39
+ If you are using the `shopify_app` gem **without** the [frontend react template](https://github.com/Shopify/shopify-frontend-template-react), the [flash_messages.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/flash_messages.js) file converts Rails [flash messages](https://api.rubyonrails.org/classes/ActionDispatch/Flash.html) to App Bridge Toast actions automatically. If your app is embedded and you want to display flash messages you will need to update the session storage to allow for 3rd party cookies. So that the flash messages can be save in the session cookie.
40
+
41
+ ```ruby
42
+ #session_store.rb
43
+ Rails.application.config.session_store(:cookie_store, key: '_example_session', expire_after: 14.days, secure: true, same_site: 'None')
44
+ ```
45
+
46
+ By default, this library is included via [unpkg in the embedded_app layout](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/embedded_app.html.erb#L27).
40
47
 
41
48
  For more advanced uses it is recommended to [install App Bridge via npm or yarn](https://help.shopify.com/en/api/embedded-apps/app-bridge/getting-started#set-up-shopify-app-bridge-in-your-app).
@@ -63,6 +63,26 @@ Using token exchange will ensure that the access token retrieved will always hav
63
63
  Authorization code grant flow is the OAuth flow that requires the app to redirect the user
64
64
  to Shopify for installation/authorization of the app to access the shop's data. It is still required for apps that are not embedded.
65
65
 
66
+ If your app is not using [Shopify managed installation](https://shopify.dev/docs/apps/auth/installation#shopify-managed-installation) with declared scopes in your `.toml` file, you can change the requested access scopes during OAuth flow
67
+ by adding the `scope` to your configurations - `ShopifyApp.configuration` & `ShopifyAPI::Context.setup`.
68
+
69
+
70
+ ```ruby
71
+ # config/initializers/shopify_app.rb
72
+
73
+ ShopifyApp.configure do |config|
74
+ ...
75
+ config.scope = ["read_discounts", "write_products"]
76
+ ...
77
+ end
78
+
79
+ ShopifyAPI::Context.setup(
80
+ ...
81
+ scope: ShopifyApp.configuration.scope,
82
+ ...
83
+ )
84
+ ```
85
+
66
86
  To perform [authorization code grant flow](https://shopify.dev/docs/apps/auth/get-access-tokens/authorization-code-grant), you app will need to handle
67
87
  [begin OAuth](#begin-oauth) and [OAuth callback](#oauth-callback) routes.
68
88
 
@@ -195,6 +215,17 @@ config.secret = Rails.application.secrets.shopify_secret
195
215
  config.old_secret = Rails.application.secrets.old_shopify_secret
196
216
  ```
197
217
 
218
+ Also make sure the old secret is specified when setting up `ShopifyAPI::Context` as well:
219
+
220
+ ```ruby
221
+ ShopifyAPI::Context.setup(
222
+ api_key: ShopifyApp.configuration.api_key,
223
+ api_secret_key: ShopifyApp.configuration.secret,
224
+ # ...
225
+ old_api_secret_key: ShopifyApp.configuration.old_secret,
226
+ )
227
+ ```
228
+
198
229
  We've provided a generator which creates the job and an example rake task:
199
230
 
200
231
  ```sh
@@ -2,13 +2,26 @@
2
2
 
3
3
  #### Table of contents
4
4
 
5
- [Manage webhooks using `ShopifyApp::WebhooksManager`](#manage-webhooks-using-shopifyappwebhooksmanager)
5
+ [App-specific webhooks in shopify.app.toml (recommended)](#subscribing-to-webhooks-in-the-app-configuration-file)
6
+ [Manage shop-specific webhooks using `ShopifyApp::WebhooksManager`](#manage-webhooks-using-shopifyappwebhooksmanager)
6
7
  [Mandatory Privacy Webhooks](#mandatory-privacy-webhooks)
7
8
 
8
- ## Manage webhooks using `ShopifyApp::WebhooksManager`
9
+ ## App-specific webhooks in shopify.app.toml (recommended)
10
+ You can specify app-specific webhooks to subscribe to in the `shopify.app.toml` file. These subscriptions are easier to manage because they are kept up to date by Shopify. In many cases they will be sufficient. Please read [app-specific vs shop-specific subscriptions](https://shopify.dev/docs/apps/build/webhooks/subscribe#app-specific-vs-shop-specific-subscriptions) to understand when you might need shop-specific webhooks.
9
11
 
10
- See [`ShopifyApp::WebhooksManager`](/lib/shopify_app/managers/webhooks_manager.rb)
11
- ShopifyApp can manage your app's webhooks for you if you set which webhooks you require in the initializer:
12
+ ### Consuming app-specific webhooks events
13
+ To consume app-specific webhooks events from the `shopify.app.toml` file, you can scaffold the necessary files by running the following generator.
14
+
15
+ ```bash
16
+ rails g shopify_app:add_declarative_webhook --topic carts/update --path webhooks/carts_update
17
+ ```
18
+
19
+ This will add a new controller, job, and route to your application. The controller will verify the webhook and queue the job to process the webhook. The job will be responsible for processing the webhook data.
20
+
21
+ ## Manage shop-specific webhooks using `ShopifyApp::WebhooksManager`
22
+
23
+ See [`ShopifyApp::WebhooksManager`](/lib/shopify_app/managers/webhooks_manager.rb).
24
+ ShopifyApp can manage your app's shop-specific webhooks for you if you set which webhooks you require in the initializer:
12
25
 
13
26
  ```ruby
14
27
  ShopifyApp.configure do |config|
@@ -18,6 +31,8 @@ ShopifyApp.configure do |config|
18
31
  end
19
32
  ```
20
33
 
34
+ This method should only be used if you have a good reason not to use app-specific webhooks (such as requiring different topics for different shops).
35
+
21
36
  When the [OAuth callback](/docs/shopify_app/authentication.md#oauth-callback) or token exchange is completed successfully, ShopifyApp will queue a background job which will ensure all the specified webhooks exist for that shop. Because this runs on every OAuth callback, it means your app will always have the webhooks it needs even if the user uninstalls and re-installs the app.
22
37
 
23
38
  ShopifyApp also provides a [WebhooksController](/app/controllers/shopify_app/webhooks_controller.rb) that receives webhooks and queues a job based on the received topic. For example, if you register the webhook from above, then all you need to do is create a job called `CartsUpdateJob`. The job will be queued with 2 params: `shop_domain` and `webhook` (which is the webhook body).
@@ -47,13 +62,27 @@ ShopifyApp.configure do |config|
47
62
  config.webhooks = [
48
63
  {
49
64
  topic: 'orders/create',
50
- path: 'api/webhooks/order_create',
65
+ path: 'api/webhooks/orders_create',
51
66
  metafield_namespaces: ['app-namespace'],
52
67
  },
53
68
  ]
54
69
  end
55
70
  ```
56
71
 
72
+ If you need to filter by webhook fields, you can register a webhook with a `filter` parameter. The documentation for Webhook filters can be found [here](https://shopify.dev/docs/apps/build/webhooks/customize/filters).
73
+
74
+ ```ruby
75
+ ShopifyApp.configure do |config|
76
+ config.webhooks = [
77
+ {
78
+ topic: 'products/update',
79
+ path: 'api/webhooks/products_update',
80
+ filter: "variants.price:>=10.00",
81
+ },
82
+ ]
83
+ end
84
+ ```
85
+
57
86
  If you'd rather implement your own controller then you'll want to use the [`ShopifyApp::WebhookVerification`](/lib/shopify_app/controller_concerns/webhook_verification.rb) module to verify your webhooks, example:
58
87
 
59
88
  ```ruby
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators/base"
4
+
5
+ module ShopifyApp
6
+ module Generators
7
+ class AddDeclarativeWebhookGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("../templates", __FILE__)
9
+ class_option :topic, type: :string, aliases: "-t", required: true
10
+ class_option :path, type: :string, aliases: "-p", required: true
11
+
12
+ hook_for :test_framework, as: :job, in: :rails do |instance, generator|
13
+ instance.invoke(generator, [instance.send(:file_name)])
14
+ end
15
+
16
+ def add_webhook_job
17
+ namespace = ShopifyApp.configuration.webhook_jobs_namespace
18
+ @job_file_name = if namespace.present?
19
+ "#{namespace}/#{file_name}_job"
20
+ else
21
+ "#{file_name}_job"
22
+ end
23
+ @job_class_name = @job_file_name.classify
24
+ template("webhook_job.rb", "app/jobs/#{@job_file_name}.rb")
25
+ end
26
+
27
+ def add_webhook_controller
28
+ @controller_file_name = "#{file_name}_controller"
29
+ @controller_class_name = @controller_file_name.classify
30
+ template("webhook_controller.rb", "app/controllers/webhooks/#{@controller_file_name}.rb")
31
+ end
32
+
33
+ def add_webhook_route
34
+ route = "\t\t\tpost '#{file_name}', to: '#{file_name}#receive'\n"
35
+ inject_into_file("config/routes.rb", route, after: /namespace :webhooks do\n/)
36
+ end
37
+
38
+ private
39
+
40
+ def file_name
41
+ path.split("/").last
42
+ end
43
+
44
+ def topic
45
+ options["topic"]
46
+ end
47
+
48
+ def path
49
+ options["path"]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Webhooks
4
+ class <%= @controller_class_name %> < ApplicationController
5
+ include ShopifyApp::WebhookVerification
6
+
7
+ def receive
8
+ webhook_request = ShopifyAPI::Webhooks::Request.new(raw_body: request.raw_post, headers: request.headers.to_h)
9
+ <%= @job_class_name %>.perform_later(shop_domain: webhook_request.shop, webhook: webhook_request.parsed_body)
10
+ head(:no_content)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class <%= @job_class_name %> < ActiveJob::Base
2
+
3
+ def perform(shop_domain:, webhook:)
4
+ shop = Shop.find_by(shopify_domain: shop_domain)
5
+
6
+ if shop.nil?
7
+ logger.error("#{self.class} failed: cannot find shop with domain '#{shop_domain}'")
8
+
9
+ raise ActiveRecord::RecordNotFound, "Shop Not Found"
10
+ end
11
+
12
+ shop.with_shopify_session do |session|
13
+ end
14
+ end
15
+ end
@@ -17,6 +17,7 @@ class <%= @job_class_name %> < ActiveJob::Base
17
17
  end
18
18
 
19
19
  shop.with_shopify_session do |session|
20
+ ## webhook processing logic
20
21
  end
21
22
  end
22
23
  end
@@ -39,6 +39,9 @@ module ShopifyApp
39
39
  # configure myshopify domain for local shopify development
40
40
  attr_accessor :myshopify_domain
41
41
 
42
+ # configure the unified admin domain for local shopify development
43
+ attr_accessor :unified_admin_domain
44
+
42
45
  # ability to have webpacker installed but not used in this gem and the generators
43
46
  attr_accessor :disable_webpacker
44
47
 
@@ -54,9 +57,11 @@ module ShopifyApp
54
57
  def initialize
55
58
  @root_url = "/"
56
59
  @myshopify_domain = "myshopify.com"
60
+ @unified_admin_domain = "shopify.com"
57
61
  @scripttags_manager_queue_name = Rails.application.config.active_job.queue_name
58
62
  @webhooks_manager_queue_name = Rails.application.config.active_job.queue_name
59
63
  @disable_webpacker = ENV["SHOPIFY_APP_DISABLE_WEBPACKER"].present?
64
+ @scope = []
60
65
 
61
66
  log_v23_deprecations
62
67
  end
@@ -8,7 +8,7 @@ module ShopifyApp
8
8
  content_security_policy do |policy|
9
9
  policy.frame_ancestors(-> do
10
10
  domain_host = current_shopify_domain || "*.#{::ShopifyApp.configuration.myshopify_domain}"
11
- "#{ShopifyAPI::Context.host_scheme}://#{domain_host} https://admin.shopify.com"
11
+ "#{ShopifyAPI::Context.host_scheme}://#{domain_host} https://admin.#{::ShopifyApp.configuration.unified_admin_domain}"
12
12
  end)
13
13
  end
14
14
  end
@@ -52,6 +52,7 @@ module ShopifyApp
52
52
  path: webhook_path,
53
53
  handler: delivery_method == :http ? webhook_job_klass(webhook_path) : nil,
54
54
  fields: attributes[:fields],
55
+ filter: attributes[:filter],
55
56
  metafield_namespaces: attributes[:metafield_namespaces],
56
57
  )
57
58
  end
@@ -7,6 +7,7 @@ module ShopifyApp
7
7
  ShopifyAPI::Auth::Session.new(id: session_id, shop: shop_domain).tap do |session|
8
8
  ShopifyApp::SessionRepository.stubs(:load_session).returns(session)
9
9
  ShopifyAPI::Utils::SessionUtils.stubs(:current_session_id).returns(session.id)
10
+ ShopifyAPI::Utils::SessionUtils.stubs(:session_id_from_shopify_id_token).returns(session.id)
10
11
  ShopifyAPI::Context.activate_session(session)
11
12
  end
12
13
  end
@@ -44,7 +44,7 @@ module ShopifyApp
44
44
  if spin_env
45
45
  "https://admin.web.#{spin_env}/store/#{shop}"
46
46
  else
47
- "https://admin.shopify.com/store/#{shop}"
47
+ "https://admin.#{unified_admin_domain}/store/#{shop}"
48
48
  end
49
49
  end
50
50
 
@@ -54,6 +54,10 @@ module ShopifyApp
54
54
  ShopifyApp.configuration.myshopify_domain
55
55
  end
56
56
 
57
+ def unified_admin_domain
58
+ ShopifyApp.configuration.unified_admin_domain
59
+ end
60
+
57
61
  def trusted_domains
58
62
  trusted_domains = TRUSTED_SHOPIFY_DOMAINS.dup
59
63
  trusted_domains.append(myshopify_domain).uniq! if myshopify_domain
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyApp
4
- VERSION = "22.3.1"
4
+ VERSION = "22.5.0"
5
5
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify_app",
3
- "version": "22.3.1",
3
+ "version": "22.5.0",
4
4
  "repository": "git@github.com:Shopify/shopify_app.git",
5
5
  "author": "Shopify",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "mocha": "^10.2.0",
19
19
  "sinon": "^9.0.3",
20
20
  "sinon-chai": "^3.2.0",
21
- "webpack": "^5.89.0"
21
+ "webpack": "^5.94.0"
22
22
  },
23
23
  "scripts": {
24
24
  "test": "./node_modules/.bin/karma start --browsers ChromeHeadless --single-run"