shopify_app 13.0.1 → 13.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -2
- data/.travis.yml +4 -3
- data/CHANGELOG.md +8 -0
- data/README.md +29 -29
- data/config/locales/nl.yml +7 -7
- data/lib/generators/shopify_app/add_webhook/templates/{webhook_job.rb → webhook_job.rb.tt} +0 -0
- data/lib/generators/shopify_app/install/install_generator.rb +1 -1
- data/lib/generators/shopify_app/install/templates/{shopify_app.rb → shopify_app.rb.tt} +0 -0
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +7 -3
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +7 -3
- data/lib/shopify_app/controller_concerns/login_protection.rb +7 -2
- data/lib/shopify_app/session/jwt.rb +35 -22
- data/lib/shopify_app/test_helpers/all.rb +1 -0
- data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +2 -1
- data/lib/shopify_app/version.rb +1 -1
- data/shopify_app.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8f69498c3370637fc886cc8ca40f4a83262f6965249b703964eb79fff2d8bbf
|
4
|
+
data.tar.gz: 1d2e06d998ecdc4f864de34bb85b81354418af9c2c361d415a19757a29651962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6972f6068811592085cf2dcb2dadfefd6f7a95f7e1c46121e2c904fac5ab3d4527f5077cb223587be1704b271fccff483a859111bc66e390097953f0604c31b
|
7
|
+
data.tar.gz: d74aade09cf4bafaac2f4c4d7b9658738fbb469e5c02f6b9c7ee21dbd8ca427e94e9d5e737aa92aadab1deadf2707e6521e5e51f7786a542cfa8d7ae89f171b1
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,16 @@
|
|
1
|
+
13.1.0
|
2
|
+
------
|
3
|
+
* Adds the shop URL as a parameter when redirecting after the callback
|
4
|
+
* Bump minimum Ruby version to 2.4
|
5
|
+
* Bug fixes
|
6
|
+
|
1
7
|
13.0.1
|
2
8
|
------
|
3
9
|
* Small addition to WebhookJob to return if the shop is nil #952
|
4
10
|
* Added Rubocop to the Repo #948
|
5
11
|
* Added a WebhookVerification test helper #950
|
12
|
+
* Fix for deprecation warning while loading session storage at startup
|
13
|
+
* Changes that will allow future JWT authentication
|
6
14
|
|
7
15
|
13.0.1
|
8
16
|
------
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Shopify App
|
|
8
8
|
|
9
9
|
Shopify Application Rails engine and generator
|
10
10
|
|
11
|
-
#### NOTE
|
11
|
+
#### NOTE: Versions 8.0.0 through 8.2.3 contained a CSRF vulnerability that was addressed in version 8.2.4. Please update to version 8.2.4 if you're using an old version.
|
12
12
|
|
13
13
|
Table of Contents
|
14
14
|
-----------------
|
@@ -34,7 +34,7 @@ Introduction
|
|
34
34
|
-----------
|
35
35
|
Get started with the [Shopify Admin API](https://help.shopify.com/en/api/getting-started) faster; This gem includes a Rails Engine and generators for writing Rails applications using the Shopify API. The Engine provides a SessionsController and all the required code for authenticating with a shop via Oauth (other authentication methods are not supported).
|
36
36
|
|
37
|
-
*Note: It's recommended to use this on a new Rails project
|
37
|
+
*Note: It's recommended to use this on a new Rails project so that the generator won't overwrite/delete your files.*
|
38
38
|
|
39
39
|
Learn how to create and deploy a new Shopify App to Heroku with our [quickstart guide](https://github.com/Shopify/shopify_app/blob/master/docs/Quickstart.md), or dive in in less than 5 minutes with this quickstart video:
|
40
40
|
|
@@ -42,7 +42,7 @@ Learn how to create and deploy a new Shopify App to Heroku with our [quickstart
|
|
42
42
|
|
43
43
|
Become a Shopify App Developer
|
44
44
|
--------------------------------
|
45
|
-
To become a Shopify App Developer you'll need a [Shopify Partner account.](http://shopify.com/partners) If you don't have a Shopify Partner account, head to http://shopify.com/partners to create one before you start.
|
45
|
+
To become a Shopify App Developer, you'll need a [Shopify Partner account.](http://shopify.com/partners) If you don't have a Shopify Partner account, head to http://shopify.com/partners to create one before you start.
|
46
46
|
|
47
47
|
Once you have a Partner account, [create a new application in the Partner Dashboard](https://help.shopify.com/en/api/tools/partner-dashboard/your-apps) to get an API key and other API credentials.
|
48
48
|
|
@@ -50,7 +50,7 @@ To create an application for development set your new app's `App URL` to the URL
|
|
50
50
|
|
51
51
|
Installation
|
52
52
|
------------
|
53
|
-
To get started add `shopify_app` to your Gemfile and run `bundle install`:
|
53
|
+
To get started, add `shopify_app` to your Gemfile and run `bundle install`:
|
54
54
|
|
55
55
|
``` sh
|
56
56
|
# Create a new rails app
|
@@ -67,7 +67,7 @@ Now we are ready to run any of the [generators](#generators) included with `shop
|
|
67
67
|
|
68
68
|
#### Rails Compatibility
|
69
69
|
|
70
|
-
The
|
70
|
+
The latest version of shopify_app is compatible with Rails `>= 5`. Use version `<= v7.2.8` if you need to work with Rails 4.
|
71
71
|
|
72
72
|
|
73
73
|
Generators
|
@@ -94,7 +94,7 @@ SHOPIFY_API_SECRET=your api secret
|
|
94
94
|
|
95
95
|
These values can be found on the "App Setup" page in the [Shopify Partners Dashboard][dashboard]. If you are checking your code into a code repository, ensure your `.gitignore` prevents your `.env` file from being checked into any publicly accessible code.
|
96
96
|
|
97
|
-
**You will need to load the ENV variables into your
|
97
|
+
**You will need to load the ENV variables into your environment, you can do this with the [dot-env](https://github.com/bkeepers/dotenv) gem or any other method you wish to.**
|
98
98
|
|
99
99
|
### Install Generator
|
100
100
|
|
@@ -108,12 +108,12 @@ $ rails generate shopify_app:install
|
|
108
108
|
|
109
109
|
Other options include:
|
110
110
|
* `application_name` - the name of your app, it can be supplied with or without double-quotes if a whitespace is present. (e.g. `--application_name Example App` or `--application_name "Example App"`)
|
111
|
-
* `scope` - the Oauth access scope required for your app,
|
111
|
+
* `scope` - the Oauth access scope required for your app, e.g. **read_products, write_orders**. *Multiple options* need to be delimited by a comma-space and can be supplied with or without double-quotes
|
112
112
|
(e.g. `--scope read_products, write_orders, write_products` or `--scope "read_products, write_orders, write_products"`)
|
113
113
|
For more information, refer the [docs](http://docs.shopify.com/api/tutorials/oauth).
|
114
114
|
* `embedded` - the default is to generate an [embedded app](http://docs.shopify.com/embedded-app-sdk), if you want a legacy non-embedded app then set this to false, `--embedded false`
|
115
115
|
|
116
|
-
You can update any of these settings later on easily
|
116
|
+
You can update any of these settings later on easily; the arguments are simply for convenience.
|
117
117
|
|
118
118
|
The generator adds ShopifyApp and the required initializers to the host Rails application.
|
119
119
|
|
@@ -126,7 +126,7 @@ After running the `install` generator, you can start your app with `bundle exec
|
|
126
126
|
$ rails generate shopify_app:home_controller
|
127
127
|
```
|
128
128
|
|
129
|
-
This generator creates an example home controller and view which fetches and displays products using the Shopify API
|
129
|
+
This generator creates an example home controller and view which fetches and displays products using the Shopify API.
|
130
130
|
|
131
131
|
|
132
132
|
### App Proxy Controller Generator
|
@@ -135,7 +135,7 @@ This generator creates an example home controller and view which fetches and dis
|
|
135
135
|
$ rails generate shopify_app:app_proxy_controller
|
136
136
|
```
|
137
137
|
|
138
|
-
This optional generator, not included with the default generator, creates the app proxy controller to handle proxy requests to the app from your shop storefront, modifies 'config/routes.rb' with a namespace route, and an example view which displays current shop information using the LiquidAPI
|
138
|
+
This optional generator, not included with the default generator, creates the app proxy controller to handle proxy requests to the app from your shop storefront, modifies 'config/routes.rb' with a namespace route, and an example view which displays current shop information using the LiquidAPI.
|
139
139
|
|
140
140
|
### Marketing Extension Generator
|
141
141
|
|
@@ -147,7 +147,7 @@ This will create a controller with the endpoints required to build a [marketing
|
|
147
147
|
|
148
148
|
### Controllers, Routes and Views
|
149
149
|
|
150
|
-
The last group of generators are for your convenience if you want to start overriding code included as part of the Rails engine. For example by default the engine provides a simple SessionController, if you run the `rails generate shopify_app:controllers` generator then this code gets copied out into your app so you can start adding to it. Routes and views follow the exact same pattern.
|
150
|
+
The last group of generators are for your convenience if you want to start overriding code included as part of the Rails engine. For example, by default the engine provides a simple SessionController, if you run the `rails generate shopify_app:controllers` generator then this code gets copied out into your app so you can start adding to it. Routes and views follow the exact same pattern.
|
151
151
|
|
152
152
|
Mounting the Engine
|
153
153
|
-------------------
|
@@ -170,7 +170,7 @@ The engine may also be mounted at a nested route, for example:
|
|
170
170
|
mount ShopifyApp::Engine, at: '/nested'
|
171
171
|
```
|
172
172
|
|
173
|
-
This will create the Shopify engine routes under the specified subpath. You'll also need to make some updates to your `shopify_app.rb` and `omniauth.rb` initializers. First update the shopify_app initializer to include a custom `root_url` e.g.:
|
173
|
+
This will create the Shopify engine routes under the specified subpath. You'll also need to make some updates to your `shopify_app.rb` and `omniauth.rb` initializers. First, update the shopify_app initializer to include a custom `root_url` e.g.:
|
174
174
|
|
175
175
|
```ruby
|
176
176
|
ShopifyApp.configure do |config|
|
@@ -216,7 +216,7 @@ Authentication
|
|
216
216
|
|
217
217
|
### Callback
|
218
218
|
|
219
|
-
Upon completing the authentication flow Shopify calls the app at the `callback_path` mentioned before. If the app needs to do some extra work it can define and configure the route to a custom callback controller, inheriting from `ShopifyApp::CallbackController` and hook into or override any of the defined helper methods. The default callback controller already provides the following behaviour:
|
219
|
+
Upon completing the authentication flow, Shopify calls the app at the `callback_path` mentioned before. If the app needs to do some extra work, it can define and configure the route to a custom callback controller, inheriting from `ShopifyApp::CallbackController` and hook into or override any of the defined helper methods. The default callback controller already provides the following behaviour:
|
220
220
|
* Logging into the shop and resetting the session
|
221
221
|
* [Installing Webhooks](https://github.com/Shopify/shopify_app#webhooksmanager)
|
222
222
|
* [Setting Scripttags](https://github.com/Shopify/shopify_app#scripttagsmanager)
|
@@ -227,22 +227,22 @@ Upon completing the authentication flow Shopify calls the app at the `callback_p
|
|
227
227
|
|
228
228
|
### ShopifyApp::SessionRepository
|
229
229
|
|
230
|
-
`ShopifyApp::SessionRepository` allows you as a developer to define how your sessions are stored and retrieved for shops. The `SessionRepository` is configured in the `config/initializers/shopify_app.rb` file and can be set to any object that implements `self.store(auth_session, *args)` which stores the session and returns a unique identifier and `self.retrieve(id)` which returns a `ShopifyAPI::Session` for the passed id. These methods are already implemented as part of the `ShopifyApp::SessionStorage` concern
|
230
|
+
`ShopifyApp::SessionRepository` allows you as a developer to define how your sessions are stored and retrieved for shops. The `SessionRepository` is configured in the `config/initializers/shopify_app.rb` file and can be set to any object that implements `self.store(auth_session, *args)` which stores the session and returns a unique identifier and `self.retrieve(id)` which returns a `ShopifyAPI::Session` for the passed id. These methods are already implemented as part of the `ShopifyApp::SessionStorage` concern but can be overridden for custom implementation.
|
231
231
|
|
232
232
|
#### Shop-based token storage
|
233
|
-
Storing tokens on the store model means that any user login associated
|
233
|
+
Storing tokens on the store model means that any user login associated with the store will have equal access levels to whatever the original user granted the app.
|
234
234
|
```sh
|
235
235
|
$ rails generate shopify_app:shop_model
|
236
236
|
```
|
237
237
|
This will generate a shop model which will be the storage for the tokens necessary for authentication.
|
238
238
|
|
239
239
|
#### User-based token storage
|
240
|
-
A more granular control over level of access per user on an app might be necessary, to which the shop-based token strategy is not sufficient. Shopify supports a user-based token storage strategy where a unique token to each user can be managed. Shop tokens must still be maintained if you are running background jobs so that you can make use of them when necessary.
|
240
|
+
A more granular control over the level of access per user on an app might be necessary, to which the shop-based token strategy is not sufficient. Shopify supports a user-based token storage strategy where a unique token to each user can be managed. Shop tokens must still be maintained if you are running background jobs so that you can make use of them when necessary.
|
241
241
|
```sh
|
242
242
|
$ rails generate shopify_app:shop_model
|
243
243
|
$ rails generate shopify_app:user_model
|
244
244
|
```
|
245
|
-
This will generate a shop model and user model which will be the storage for the tokens necessary for authentication.
|
245
|
+
This will generate a shop model and user model, which will be the storage for the tokens necessary for authentication.
|
246
246
|
|
247
247
|
The current Shopify user will be stored in the rails session at `session[:shopify_user]`
|
248
248
|
|
@@ -276,7 +276,7 @@ For backwards compatibility, the engine still provides a controller called `Shop
|
|
276
276
|
|
277
277
|
### AfterAuthenticate Job
|
278
278
|
|
279
|
-
If your app needs to perform specific actions after the user is authenticated successfully (i.e. every time a new session is created), ShopifyApp can queue or run a job of your choosing (note that we already provide support for automatically creating Webhooks and Scripttags). To configure the after authenticate job update your initializer as follows:
|
279
|
+
If your app needs to perform specific actions after the user is authenticated successfully (i.e. every time a new session is created), ShopifyApp can queue or run a job of your choosing (note that we already provide support for automatically creating Webhooks and Scripttags). To configure the after authenticate job, update your initializer as follows:
|
280
280
|
|
281
281
|
```ruby
|
282
282
|
ShopifyApp.configure do |config|
|
@@ -324,11 +324,11 @@ ShopifyApp.configure do |config|
|
|
324
324
|
end
|
325
325
|
```
|
326
326
|
|
327
|
-
When the oauth callback 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.
|
327
|
+
When the oauth callback 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.
|
328
328
|
|
329
|
-
ShopifyApp also provides a WebhooksController 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).
|
329
|
+
ShopifyApp also provides a WebhooksController 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).
|
330
330
|
|
331
|
-
If you would like to namespace your jobs you may set `webhook_jobs_namespace` in the config. For example if your app handles webhooks from other ecommerce applications as well, and you want Shopify cart update webhooks to be processed by a job living in `jobs/shopify/webhooks/carts_update_job.rb` rather than `jobs/carts_update_job.rb`):
|
331
|
+
If you would like to namespace your jobs, you may set `webhook_jobs_namespace` in the config. For example, if your app handles webhooks from other ecommerce applications as well, and you want Shopify cart update webhooks to be processed by a job living in `jobs/shopify/webhooks/carts_update_job.rb` rather than `jobs/carts_update_job.rb`):
|
332
332
|
|
333
333
|
```ruby
|
334
334
|
ShopifyApp.configure do |config|
|
@@ -366,9 +366,9 @@ class CustomWebhooksController < ApplicationController
|
|
366
366
|
end
|
367
367
|
```
|
368
368
|
|
369
|
-
The module skips the `verify_authenticity_token` before_action and adds an action to verify that the webhook came from Shopify. You can now add a post route to your application pointing to the controller and action to accept the webhook data from Shopify.
|
369
|
+
The module skips the `verify_authenticity_token` before_action and adds an action to verify that the webhook came from Shopify. You can now add a post route to your application, pointing to the controller and action to accept the webhook data from Shopify.
|
370
370
|
|
371
|
-
The WebhooksManager uses ActiveJob
|
371
|
+
The WebhooksManager uses ActiveJob. If ActiveJob is not configured then by default Rails will run the jobs inline. However, it is highly recommended to configure a proper background processing queue like sidekiq or resque in production.
|
372
372
|
|
373
373
|
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.
|
374
374
|
|
@@ -376,7 +376,7 @@ ShopifyApp can create webhooks for you using the `add_webhook` generator. This w
|
|
376
376
|
rails g shopify_app:add_webhook -t carts/update -a https://example.com/webhooks/carts_update
|
377
377
|
```
|
378
378
|
|
379
|
-
|
379
|
+
Where `-t` is the topic and `-a` is the address the webhook should be sent to.
|
380
380
|
|
381
381
|
ScripttagsManager
|
382
382
|
-----------------
|
@@ -475,7 +475,7 @@ see [TROUBLESHOOTING.md](https://github.com/Shopify/shopify_app/blob/master/docs
|
|
475
475
|
Using Test Helpers inside your Application
|
476
476
|
-----------------------------------------
|
477
477
|
|
478
|
-
A test helper that will allow you to test `ShopifyApp::WebhookVerification` in the controller from your app, to use this test, you need to `require` it directly
|
478
|
+
A test helper that will allow you to test `ShopifyApp::WebhookVerification` in the controller from your app, to use this test, you need to `require` it directly inside your app `test/controllers/webhook_verification_test.rb`.
|
479
479
|
|
480
480
|
```ruby
|
481
481
|
require 'test_helper'
|
@@ -484,7 +484,7 @@ A test helper that will allow you to test `ShopifyApp::WebhookVerification` in t
|
|
484
484
|
require 'shopify_app/test_helpers/webhook_verification_helper'
|
485
485
|
```
|
486
486
|
|
487
|
-
|
487
|
+
Or you can require in your `test/test_helper.rb`.
|
488
488
|
|
489
489
|
```ruby
|
490
490
|
ENV['RAILS_ENV'] ||= 'test'
|
@@ -521,7 +521,7 @@ change to how session stores work. Here are the steps to migrate to 13.x
|
|
521
521
|
- *CHANGE* `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
|
522
522
|
|
523
523
|
### Changes to the @shop_session instance variable (normally in `app/controllers/*.rb`)
|
524
|
-
- *CHANGE* if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session
|
524
|
+
- *CHANGE* if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session`.
|
525
525
|
|
526
526
|
### Changes to Rails `session`
|
527
527
|
- *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.
|
@@ -533,7 +533,7 @@ if you are using `ShopifyApp::LoginProtection#shop_session` in your code, it wil
|
|
533
533
|
changed to `ShopifyApp::LoginProtection#activate_shopify_session`
|
534
534
|
|
535
535
|
### Notes
|
536
|
-
You do not need a user model
|
536
|
+
You do not need a user model; a shop session is fine for most applications.
|
537
537
|
|
538
538
|
Questions or problems?
|
539
539
|
----------------------
|
@@ -579,7 +579,7 @@ config.api_version = '2019-04'
|
|
579
579
|
|
580
580
|
### Session storage change
|
581
581
|
|
582
|
-
You will need to add an `api_version` method to
|
582
|
+
You will need to add an `api_version` method to your session storage object. The default implementation for this is.
|
583
583
|
```ruby
|
584
584
|
def api_version
|
585
585
|
ShopifyApp.configuration.api_version
|
data/config/locales/nl.yml
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
---
|
2
2
|
nl:
|
3
|
-
logged_out:
|
3
|
+
logged_out: je bentafgemeld
|
4
4
|
could_not_log_in: Kon niet aanmelden bij Shopify-winkel
|
5
5
|
invalid_shop_url: Ongeldig winkeldomein
|
6
6
|
enable_cookies_heading: Schakel cookies in van %{app}
|
7
|
-
enable_cookies_body:
|
7
|
+
enable_cookies_body: Je moet cookies in deze browser handmatig inschakelen om %{app}
|
8
8
|
binnen Shopify te gebruiken.
|
9
|
-
enable_cookies_footer: Met cookies kan de app
|
9
|
+
enable_cookies_footer: Met cookies kan de app je verifiëren door je voorkeuren en
|
10
10
|
persoonlijke informatie tijdelijk op te slaan. Ze vervallen na 30 dagen.
|
11
11
|
enable_cookies_action: Schakel cookies in
|
12
|
-
top_level_interaction_heading:
|
13
|
-
top_level_interaction_body:
|
14
|
-
te vragen tot cookies voordat Shopify het voor
|
12
|
+
top_level_interaction_heading: Je browser moet %{app} verifiëren
|
13
|
+
top_level_interaction_body: Je browser heeft apps nodig zoals %{app} om je toegang
|
14
|
+
te vragen tot cookies voordat Shopify het voor je kan openen.
|
15
15
|
top_level_interaction_action: Doorgaan
|
16
16
|
request_storage_access_heading: "%{app} heeft toegang tot cookies nodig"
|
17
|
-
request_storage_access_body: Hiermee kan de app
|
17
|
+
request_storage_access_body: Hiermee kan de app je verifiëren door je persoonlijke
|
18
18
|
gegevens tijdelijk op te slaan. Klik op Doorgaan en sta cookies toe om de app
|
19
19
|
te gebruiken.
|
20
20
|
request_storage_access_footer: Cookies verlopen na 30 dagen.
|
File without changes
|
@@ -46,7 +46,7 @@ module ShopifyApp
|
|
46
46
|
copy_file('shopify_app.js', 'app/javascript/shopify_app/shopify_app.js')
|
47
47
|
copy_file('flash_messages.js', 'app/javascript/shopify_app/flash_messages.js')
|
48
48
|
copy_file('shopify_app_index.js', 'app/javascript/shopify_app/index.js')
|
49
|
-
append_to_file('app/javascript/packs/application.js',
|
49
|
+
append_to_file('app/javascript/packs/application.js', "require(\"shopify_app\")\n")
|
50
50
|
else
|
51
51
|
copy_file('shopify_app.js', 'app/assets/javascripts/shopify_app.js')
|
52
52
|
copy_file('flash_messages.js', 'app/assets/javascripts/flash_messages.js')
|
File without changes
|
@@ -30,9 +30,13 @@ module ShopifyApp
|
|
30
30
|
Rails.version.match(/\d\.\d/)[0]
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
class << self
|
34
|
+
private :next_migration_number
|
35
|
+
|
36
|
+
# for generating a timestamp when using `create_migration`
|
37
|
+
def next_migration_number(dir)
|
38
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
@@ -30,9 +30,13 @@ module ShopifyApp
|
|
30
30
|
Rails.version.match(/\d\.\d/)[0]
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
class << self
|
34
|
+
private :next_migration_number
|
35
|
+
|
36
|
+
# for generating a timestamp when using `create_migration`
|
37
|
+
def next_migration_number(dir)
|
38
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
39
|
+
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
@@ -108,7 +108,7 @@ module ShopifyApp
|
|
108
108
|
path = referer.path
|
109
109
|
query = "#{referer.query}&#{sanitized_params.to_query}"
|
110
110
|
end
|
111
|
-
session[:return_to] = "#{path}?#{query}"
|
111
|
+
session[:return_to] = query.blank? ? path.to_s : "#{path}?#{query}"
|
112
112
|
redirect_to(login_url_with_optional_shop)
|
113
113
|
end
|
114
114
|
end
|
@@ -205,11 +205,16 @@ module ShopifyApp
|
|
205
205
|
end
|
206
206
|
|
207
207
|
def return_address
|
208
|
+
return base_return_address unless ShopifyApp.configuration.allow_jwt_authentication
|
209
|
+
return_address_with_params(shop: current_shopify_domain)
|
210
|
+
end
|
211
|
+
|
212
|
+
def base_return_address
|
208
213
|
session.delete(:return_to) || ShopifyApp.configuration.root_url
|
209
214
|
end
|
210
215
|
|
211
216
|
def return_address_with_params(params)
|
212
|
-
uri = URI(
|
217
|
+
uri = URI(base_return_address)
|
213
218
|
uri.query = CGI.parse(uri.query.to_s)
|
214
219
|
.symbolize_keys
|
215
220
|
.transform_values { |v| v.one? ? v.first : v }
|
@@ -1,48 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module ShopifyApp
|
3
3
|
class JWT
|
4
|
+
class InvalidDestinationError < StandardError; end
|
5
|
+
class MismatchedHostsError < StandardError; end
|
6
|
+
class InvalidAudienceError < StandardError; end
|
7
|
+
|
8
|
+
WARN_EXCEPTIONS = [
|
9
|
+
::JWT::DecodeError,
|
10
|
+
::JWT::ExpiredSignature,
|
11
|
+
::JWT::ImmatureSignature,
|
12
|
+
::JWT::VerificationError,
|
13
|
+
InvalidAudienceError,
|
14
|
+
InvalidDestinationError,
|
15
|
+
MismatchedHostsError,
|
16
|
+
]
|
17
|
+
|
4
18
|
def initialize(token)
|
5
19
|
@token = token
|
6
20
|
set_payload
|
7
21
|
end
|
8
22
|
|
9
23
|
def shopify_domain
|
10
|
-
payload &&
|
24
|
+
@payload && ShopifyApp::Utils.sanitize_shop_domain(@payload['dest'])
|
11
25
|
end
|
12
26
|
|
13
27
|
def shopify_user_id
|
14
|
-
payload && payload['sub']
|
28
|
+
@payload && @payload['sub']
|
15
29
|
end
|
16
30
|
|
17
31
|
private
|
18
32
|
|
19
|
-
def payload
|
20
|
-
return unless @payload
|
21
|
-
return unless dest_host
|
22
|
-
return unless dest_host == iss_host
|
23
|
-
return unless @payload['aud'] == ShopifyApp.configuration.api_key
|
24
|
-
|
25
|
-
@payload
|
26
|
-
end
|
27
|
-
|
28
33
|
def set_payload
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
payload, _ = parse_token_data(ShopifyApp.configuration&.secret, ShopifyApp.configuration&.old_secret)
|
35
|
+
@payload = validate_payload(payload)
|
36
|
+
rescue *WARN_EXCEPTIONS => error
|
37
|
+
Rails.logger.warn("[ShopifyApp::JWT] Failed to validate JWT: [#{error.class}] #{error}")
|
38
|
+
nil
|
32
39
|
end
|
33
40
|
|
34
|
-
def parse_token_data(secret)
|
41
|
+
def parse_token_data(secret, old_secret)
|
35
42
|
::JWT.decode(@token, secret, true, { algorithm: 'HS256' })
|
36
|
-
rescue ::JWT::
|
37
|
-
|
38
|
-
end
|
43
|
+
rescue ::JWT::VerificationError
|
44
|
+
raise unless old_secret
|
39
45
|
|
40
|
-
|
41
|
-
@payload && ShopifyApp::Utils.sanitize_shop_domain(@payload['dest'])
|
46
|
+
::JWT.decode(@token, old_secret, true, { algorithm: 'HS256' })
|
42
47
|
end
|
43
48
|
|
44
|
-
def
|
45
|
-
|
49
|
+
def validate_payload(payload)
|
50
|
+
dest_host = ShopifyApp::Utils.sanitize_shop_domain(payload['dest'])
|
51
|
+
iss_host = ShopifyApp::Utils.sanitize_shop_domain(payload['iss'])
|
52
|
+
api_key = ShopifyApp.configuration.api_key
|
53
|
+
|
54
|
+
raise InvalidAudienceError, "'aud' claim does not match api_key" unless payload['aud'] == api_key
|
55
|
+
raise InvalidDestinationError, "'dest' claim host not a valid shopify host" unless dest_host
|
56
|
+
raise MismatchedHostsError, "'dest' claim host does not match 'iss' claim host" unless dest_host == iss_host
|
57
|
+
|
58
|
+
payload
|
46
59
|
end
|
47
60
|
end
|
48
61
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module TestHelpers
|
3
4
|
module WebhookVerificationHelper
|
@@ -8,7 +9,7 @@ module ShopifyApp
|
|
8
9
|
@request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = valid_hmac
|
9
10
|
end
|
10
11
|
|
11
|
-
def unauthorized_webhook_verification_headers!
|
12
|
+
def unauthorized_webhook_verification_headers!
|
12
13
|
@request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = "invalid_hmac"
|
13
14
|
end
|
14
15
|
end
|
data/lib/shopify_app/version.rb
CHANGED
data/shopify_app.gemspec
CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.author = "Shopify"
|
10
10
|
s.summary = 'This gem is used to get quickly started with the Shopify API'
|
11
11
|
|
12
|
-
s.required_ruby_version = ">= 2.
|
12
|
+
s.required_ruby_version = ">= 2.4"
|
13
13
|
|
14
14
|
s.metadata['allowed_push_host'] = 'https://rubygems.org'
|
15
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify_app
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 13.0
|
4
|
+
version: 13.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-04-
|
11
|
+
date: 2020-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: browser_sniffer
|
@@ -301,7 +301,7 @@ files:
|
|
301
301
|
- lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb
|
302
302
|
- lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb
|
303
303
|
- lib/generators/shopify_app/add_webhook/add_webhook_generator.rb
|
304
|
-
- lib/generators/shopify_app/add_webhook/templates/webhook_job.rb
|
304
|
+
- lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt
|
305
305
|
- lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb
|
306
306
|
- lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb
|
307
307
|
- lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb
|
@@ -319,7 +319,7 @@ files:
|
|
319
319
|
- lib/generators/shopify_app/install/templates/omniauth.rb
|
320
320
|
- lib/generators/shopify_app/install/templates/session_store.rb
|
321
321
|
- lib/generators/shopify_app/install/templates/shopify_app.js
|
322
|
-
- lib/generators/shopify_app/install/templates/shopify_app.rb
|
322
|
+
- lib/generators/shopify_app/install/templates/shopify_app.rb.tt
|
323
323
|
- lib/generators/shopify_app/install/templates/shopify_app_index.js
|
324
324
|
- lib/generators/shopify_app/install/templates/shopify_provider.rb
|
325
325
|
- lib/generators/shopify_app/install/templates/user_agent.rb
|
@@ -385,7 +385,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
385
385
|
requirements:
|
386
386
|
- - ">="
|
387
387
|
- !ruby/object:Gem::Version
|
388
|
-
version: 2.
|
388
|
+
version: '2.4'
|
389
389
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
390
390
|
requirements:
|
391
391
|
- - ">="
|