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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c32f23c198e7bfcc44d3557857c11194ce71f2dc8a1a42ff0d220569c4eb4599
4
- data.tar.gz: cf430f7fb26c01592d68d5110a5690f290452ab18c5853dcc4602c5f1d5c0521
3
+ metadata.gz: e8f69498c3370637fc886cc8ca40f4a83262f6965249b703964eb79fff2d8bbf
4
+ data.tar.gz: 1d2e06d998ecdc4f864de34bb85b81354418af9c2c361d415a19757a29651962
5
5
  SHA512:
6
- metadata.gz: 4af6eb8ff59c68d9bc1089c577d90d40cfa2997550331314e90f620580da62898000e2b7568616b077fa15080878d0e8ddc9a09160490dea3a4ce719f4e814cd
7
- data.tar.gz: b3cf9731363e7df4b3cc78f057bd96204f25f9ab2832662e2cc7e98a3e52ad98ef68d142bcca6d9c96d232eac2cc1dbc2518a41d364f1470247100c2eddd92fc
6
+ metadata.gz: c6972f6068811592085cf2dcb2dadfefd6f7a95f7e1c46121e2c904fac5ab3d4527f5077cb223587be1704b271fccff483a859111bc66e390097953f0604c31b
7
+ data.tar.gz: d74aade09cf4bafaac2f4c4d7b9658738fbb469e5c02f6b9c7ee21dbd8ca427e94e9d5e737aa92aadab1deadf2707e6521e5e51f7786a542cfa8d7ae89f171b1
@@ -2,9 +2,8 @@ inherit_gem:
2
2
  rubocop-shopify: rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.4
5
+ TargetRubyVersion: 2.7
6
6
  Exclude:
7
- - 'lib/generators/**/*'
8
7
  - 'test/tmp/**/*'
9
8
 
10
9
  Style/MethodCallWithArgsParentheses:
@@ -13,9 +13,10 @@ cache:
13
13
  yarn: true
14
14
 
15
15
  rvm:
16
- - 2.4.3
17
- - 2.5.0
18
- - 2.6.2
16
+ - 2.4
17
+ - 2.5
18
+ - 2.6
19
+ - 2.7
19
20
 
20
21
  install:
21
22
  - bundle install
@@ -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 : 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.
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, so that the generator won't overwrite/delete your files.*
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 lastest version of shopify_app is compatible with Rails `>= 5`. Use version `<= v7.2.8` if you need to work with Rails 4.
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 enviroment, you can do this with the [dot-env](https://github.com/bkeepers/dotenv) gem or any other method you wish to.**
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, eg **read_products, write_orders**. *Multiple options* need to be delimited by a comma-space, and can be supplied with or without double-quotes
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, the arguments are simply for convenience.
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, but can be overridden for custom implementation.
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 to the store will have equal access levels to whatever the original user granted the app.
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, 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.
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
- where `-t` is the topic and `-a` is the address the webhook should be sent to.
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 in side you app `test/controllers/webhook_verification_test.rb`.
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
- or you can require in your `test/test_helper.rb`
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, a shop session is fine for most applications.
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 you session storage object. The default implementation for this is.
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
@@ -1,20 +1,20 @@
1
1
  ---
2
2
  nl:
3
- logged_out: u bent afgemeld
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: U moet cookies in deze browser handmatig inschakelen om %{app}
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 u verifiëren door uw voorkeuren en
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: Uw browser moet %{app} verifiëren
13
- top_level_interaction_body: Uw browser heeft apps nodig zoals %{app} om u toegang
14
- te vragen tot cookies voordat Shopify het voor u kan openen.
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 u verifiëren door uw persoonlijke
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.
@@ -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', 'require("shopify_app")')
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')
@@ -30,9 +30,13 @@ module ShopifyApp
30
30
  Rails.version.match(/\d\.\d/)[0]
31
31
  end
32
32
 
33
- # for generating a timestamp when using `create_migration`
34
- def self.next_migration_number(dir)
35
- ActiveRecord::Generators::Base.next_migration_number(dir)
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
- # for generating a timestamp when using `create_migration`
34
- def self.next_migration_number(dir)
35
- ActiveRecord::Generators::Base.next_migration_number(dir)
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(return_address)
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 && dest_host
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
- @payload, _ = parse_token_data(ShopifyApp.configuration.secret)
30
- configuration_old_secret = @payload && ShopifyApp.configuration
31
- @payload, _ = parse_token_data(ShopifyApp.configuration.old_secret) unless configuration_old_secret
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::DecodeError, ::JWT::VerificationError, ::JWT::ExpiredSignature, ::JWT::ImmatureSignature
37
- nil
38
- end
43
+ rescue ::JWT::VerificationError
44
+ raise unless old_secret
39
45
 
40
- def dest_host
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 iss_host
45
- @payload && ShopifyApp::Utils.sanitize_shop_domain(@payload['iss'])
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 +1,2 @@
1
+ # frozen_string_literal: true
1
2
  require 'shopify_app/test_helpers/webhook_verification_helper'
@@ -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!(params = {})
12
+ def unauthorized_webhook_verification_headers!
12
13
  @request.headers['HTTP_X_SHOPIFY_HMAC_SHA256'] = "invalid_hmac"
13
14
  end
14
15
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ShopifyApp
3
- VERSION = '13.0.1'
3
+ VERSION = '13.1.0'
4
4
  end
@@ -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.3.1"
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.1
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-14 00:00:00.000000000 Z
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.3.1
388
+ version: '2.4'
389
389
  required_rubygems_version: !ruby/object:Gem::Requirement
390
390
  requirements:
391
391
  - - ">="