shopify_app 12.0.0 → 13.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/README.md +67 -20
- data/app/assets/javascripts/shopify_app/itp_helper.js +6 -6
- data/app/assets/javascripts/shopify_app/storage_access.js +35 -6
- data/app/controllers/concerns/shopify_app/authenticated.rb +1 -1
- data/app/controllers/shopify_app/callback_controller.rb +14 -10
- data/app/controllers/shopify_app/sessions_controller.rb +49 -13
- data/app/views/shopify_app/sessions/enable_cookies.html.erb +1 -1
- data/app/views/shopify_app/sessions/request_storage_access.html.erb +1 -1
- data/config/locales/pt-BR.yml +1 -1
- data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +1 -5
- data/lib/generators/shopify_app/home_controller/templates/index.html.erb +1 -1
- data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +1 -1
- data/lib/generators/shopify_app/install/templates/shopify_app.rb +1 -1
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +1 -1
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +1 -1
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -1
- data/lib/generators/shopify_app/user_model/templates/user.rb +1 -1
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +1 -1
- data/lib/shopify_app/configuration.rb +12 -9
- data/lib/shopify_app/controller_concerns/login_protection.rb +39 -22
- data/lib/shopify_app/engine.rb +1 -1
- data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +18 -45
- data/lib/shopify_app/session/in_memory_shop_session_store.rb +4 -0
- data/lib/shopify_app/session/in_memory_user_session_store.rb +4 -0
- data/lib/shopify_app/session/session_repository.rb +38 -13
- data/lib/shopify_app/session/session_storage.rb +0 -10
- data/lib/shopify_app/session/{storage_strategies/shop_storage_strategy.rb → shop_session_storage.rb} +9 -2
- data/lib/shopify_app/session/{storage_strategies/user_storage_strategy.rb → user_session_storage.rb} +10 -3
- data/lib/shopify_app/version.rb +1 -1
- data/lib/shopify_app.rb +4 -2
- data/package-lock.json +1228 -1207
- data/package.json +2 -2
- data/shopify_app.gemspec +4 -4
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4e2d37f9112725500d1a9f36fe76b743e8981920eea4838024cafd6a71cb5eb
|
4
|
+
data.tar.gz: 3c52a0ee9a7f40433ad01b82bda3a0c6d30dd9bb45c319f1d457a0bd13c30fc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19a445a22b25b01f860a84128551234313bc44e7acd1583ec90bc96f59d65a8fac208feb1d5a6899453935dd19458196c5253605d85e3ac346be2fa405a50b4c
|
7
|
+
data.tar.gz: 526354098526753ade6d30a346ffa75b2280707638b66dba61c89b34a771e72dd4c23cfae8bda319de58a7a373e7c05d233a13a4f2f8325c7754cda1ed58d835
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
13.0.0
|
2
|
+
------
|
3
|
+
+ #887 Added concurrent user and shop session support (online/offline)
|
4
|
+
BREAKING, please see README for migration notes.
|
5
|
+
|
6
|
+
12.0.7
|
7
|
+
------
|
8
|
+
* Remove check for API_KEY in config that was throwing errors during install #919
|
9
|
+
|
10
|
+
12.0.6
|
11
|
+
------
|
12
|
+
* Adds changelog information and README updates for 8.4.0 #916
|
13
|
+
|
14
|
+
12.0.5
|
15
|
+
------
|
16
|
+
* Updating shopify_api gem to 9.0.1
|
17
|
+
|
18
|
+
12.0.4
|
19
|
+
------
|
20
|
+
* Reverts reverted PR (#895) #897
|
21
|
+
|
22
|
+
12.0.3
|
23
|
+
------
|
24
|
+
* Moves samesite middleware higher in the stack #898
|
25
|
+
* Fix issue where not redirecting user to granted storage page casues infinite loop #900
|
26
|
+
|
27
|
+
12.0.2
|
28
|
+
------
|
29
|
+
* Reverts "Fix for return_to in safari after enable_cookies/granted_storage_access" introduced in 12.0.1
|
30
|
+
|
31
|
+
12.0.1
|
32
|
+
------
|
33
|
+
* disable samesite cookie middleware in tests
|
34
|
+
* middleware compatibility for ruby 2.3
|
35
|
+
* samesite cookie fixes for javascript libraries
|
36
|
+
* change generators to add AppBridge instead of EASDK
|
37
|
+
* Fix for return_to in safari after enable_cookies/granted_storage_access
|
38
|
+
|
1
39
|
12.0.0
|
2
40
|
-----
|
3
41
|
* Updating shopify_api gem to 9.0.0
|
@@ -166,6 +204,7 @@ Added support for rotating Shopify access tokens:
|
|
166
204
|
8.4.0
|
167
205
|
----
|
168
206
|
* Fix embedded app session management in Safari 12.1
|
207
|
+
* Note that with this change we have extracted the callback action in its own controller. If you are relying on it, see the README for more details: https://github.com/Shopify/shopify_app#callback
|
169
208
|
* Shop names passed to OAuth are no longer case sensitive
|
170
209
|
|
171
210
|
8.3.2
|
data/README.md
CHANGED
@@ -25,6 +25,7 @@ Table of Contents
|
|
25
25
|
- [AppProxyVerification](#appproxyverification)
|
26
26
|
- [Troubleshooting](#troubleshooting)
|
27
27
|
- [Testing an embedded app outside the Shopify admin](#testing-an-embedded-app-outside-the-shopify-admin)
|
28
|
+
- [Migration to 13.0.0](#migrating-to-13)
|
28
29
|
- [Questions or problems?](#questions-or-problems-)
|
29
30
|
- [Rails 6 Compatibility](#rails-6-compatibility)
|
30
31
|
- [Upgrading from 8.6 to 9.0.0](#upgrading-from-86-to-900)
|
@@ -43,9 +44,9 @@ Become a Shopify App Developer
|
|
43
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
46
|
|
46
|
-
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.
|
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.
|
47
48
|
|
48
|
-
To create an application for development set your new app's `App URL` to the URL provided by [your tunnel](#app-tunneling), ensuring that you use `https://`. If you are not planning to embed your app inside the Shopify admin or receive webhooks, set your redirect URL to `http://localhost:3000/` and the `Whitelisted redirection URL(s)` to contain `<App URL>/auth/shopify/callback`.
|
49
|
+
To create an application for development set your new app's `App URL` to the URL provided by [your tunnel](#app-tunneling), ensuring that you use `https://`. If you are not planning to embed your app inside the Shopify admin or receive webhooks, set your redirect URL to `http://localhost:3000/` and the `Whitelisted redirection URL(s)` to contain `<App URL>/auth/shopify/callback`.
|
49
50
|
|
50
51
|
Installation
|
51
52
|
------------
|
@@ -80,7 +81,7 @@ The default generator will run the `install`, `shop`, and `home_controller` gene
|
|
80
81
|
$ rails generate shopify_app
|
81
82
|
```
|
82
83
|
|
83
|
-
After running the generator, you will need to run `rails db:migrate` to add new tables to your database. You can start your app with `bundle exec rails server` and install your app by visiting `http://localhost` in your web browser.
|
84
|
+
After running the generator, you will need to run `rails db:migrate` to add new tables to your database. You can start your app with `bundle exec rails server` and install your app by visiting `http://localhost` in your web browser.
|
84
85
|
|
85
86
|
### API Keys
|
86
87
|
|
@@ -91,7 +92,9 @@ SHOPIFY_API_KEY=your api key
|
|
91
92
|
SHOPIFY_API_SECRET=your api secret
|
92
93
|
```
|
93
94
|
|
94
|
-
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.
|
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
|
+
|
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.**
|
95
98
|
|
96
99
|
### Install Generator
|
97
100
|
|
@@ -211,12 +214,21 @@ end
|
|
211
214
|
Authentication
|
212
215
|
--------------
|
213
216
|
|
217
|
+
### Callback
|
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:
|
220
|
+
* Logging into the shop and resetting the session
|
221
|
+
* [Installing Webhooks](https://github.com/Shopify/shopify_app#webhooksmanager)
|
222
|
+
* [Setting Scripttags](https://github.com/Shopify/shopify_app#scripttagsmanager)
|
223
|
+
* [Performing the AfterAuthenticate Job](https://github.com/Shopify/shopify_app#afterauthenticatejob)
|
224
|
+
* Redirecting to the return address
|
225
|
+
|
226
|
+
**Note that starting with version 8.4.0, we have extracted the callback logic in its own controller. If you are upgrading from a version older than 8.4.0 the callback action and related helper methods were defined in `ShopifyApp::SessionsController` ==> you will have to extend `ShopifyApp::CallbackController` instead and port your logic to the new controller.**
|
227
|
+
|
214
228
|
### ShopifyApp::SessionRepository
|
215
229
|
|
216
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.
|
217
231
|
|
218
|
-
If you only run the install generator then by default you will have an in memory store but it **won't work** on multi-server environments including Heroku. For multi-server environments, implement one of the following token-storage strategies.
|
219
|
-
|
220
232
|
#### Shop-based token storage
|
221
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.
|
222
234
|
```sh
|
@@ -225,32 +237,35 @@ $ rails generate shopify_app:shop_model
|
|
225
237
|
This will generate a shop model which will be the storage for the tokens necessary for authentication.
|
226
238
|
|
227
239
|
#### User-based token storage
|
228
|
-
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.
|
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.
|
229
241
|
```sh
|
242
|
+
$ rails generate shopify_app:shop_model
|
230
243
|
$ rails generate shopify_app:user_model
|
231
244
|
```
|
232
|
-
This will generate a 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.
|
233
246
|
|
234
247
|
The current Shopify user will be stored in the rails session at `session[:shopify_user]`
|
235
248
|
|
236
|
-
|
237
|
-
|
238
|
-
This will change the type of token that Shopify returns and it will only be valid for a short time. Read more about `Online access` [here](https://help.shopify.com/api/getting-started/authentication/oauth). Note that this means you won't be able to use this token to respond to Webhooks.
|
249
|
+
Read more about Online vs. Offline access [here](https://help.shopify.com/api/getting-started/authentication/oauth).
|
239
250
|
|
240
251
|
#### Migrating from shop-based to user-based token strategy
|
241
|
-
|
242
|
-
|
252
|
+
1. Run the `user_model` generator as mentioned above.
|
253
|
+
2. Ensure that both your `Shop` model and `User` model includes the necessary concerns `ShopifyApp::ShopSessionStorage` and `ShopifyApp::UserSessionStorage`.
|
254
|
+
3. Make changes to 2 initializer files as shown below:
|
243
255
|
```ruby
|
244
256
|
# In the `omniauth.rb` initializer:
|
245
257
|
provider :shopify,
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
258
|
+
...
|
259
|
+
setup: lambda { |env|
|
260
|
+
...
|
261
|
+
# Add this line
|
262
|
+
strategy.options[:per_user_permissions] = strategy.session[:user_tokens]
|
263
|
+
...
|
264
|
+
}
|
250
265
|
|
251
266
|
# In the `shopify_app.rb` initializer:
|
252
|
-
config.
|
253
|
-
config.
|
267
|
+
config.shop_session_repository = {YOUR_SHOP_MODEL_CLASS}
|
268
|
+
config.user_session_repository = {YOUR_USER_MODEL_CLASS}
|
254
269
|
```
|
255
270
|
|
256
271
|
### Authenticated
|
@@ -287,6 +302,14 @@ bin/rails g shopify_app:add_after_authenticate_job
|
|
287
302
|
|
288
303
|
If you want to perform that action only once, e.g. send a welcome email to the user when they install the app, you should make sure that this action is idempotent, meaning that it won't have an impact if run multiple times.
|
289
304
|
|
305
|
+
API Versioning
|
306
|
+
--------------
|
307
|
+
|
308
|
+
Shopify's API is versioned, and you can [read about that process in the Shopify Developers documentation page](https://shopify.dev/concepts/about-apis/versioning).
|
309
|
+
|
310
|
+
Since shopify_app gem version 1.11.0, the included shopify_api gem has also been updated to allow you to easily set and switch what version of the Shopify API you want your app or service to use, as well as surface warnings to Rails apps about [deprecated endpoints, GraphQL fields and more](https://shopify.dev/concepts/about-apis/versioning#deprecation-practices).
|
311
|
+
|
312
|
+
See the [shopify_api gem README](https://github.com/Shopify/shopify_api/) for more details.
|
290
313
|
|
291
314
|
WebhooksManager
|
292
315
|
---------------
|
@@ -408,7 +431,7 @@ strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
|
408
431
|
App Tunneling
|
409
432
|
-------------
|
410
433
|
|
411
|
-
Your local app needs to be accessible from the public Internet in order to install it on a Shopify store, to use the [App Proxy Controller](#app-proxy-controller-generator) or receive Webhooks.
|
434
|
+
Your local app needs to be accessible from the public Internet in order to install it on a Shopify store, to use the [App Proxy Controller](#app-proxy-controller-generator) or receive Webhooks.
|
412
435
|
|
413
436
|
Use a tunneling service like [ngrok](https://ngrok.com/), [Forward](https://forwardhq.com/), [Beeceptor](https://beeceptor.com/), [Mockbin](http://mockbin.org/), or [Hookbin](https://hookbin.com/) to make your development environment accessible to the internet.
|
414
437
|
|
@@ -458,11 +481,35 @@ By default, loading your embedded app will redirect to the Shopify admin, with t
|
|
458
481
|
forceRedirect: <%= Rails.env.development? || Rails.env.test? ? 'false' : 'true' %>
|
459
482
|
```
|
460
483
|
|
484
|
+
Migrating to 13.0.0
|
485
|
+
-------------------
|
486
|
+
|
487
|
+
Version 13.0.0 adds the ability to use both user and shop sessions, concurrently. This however involved a large
|
488
|
+
change to how session stores work. Here are the steps to migrate to 13.x
|
489
|
+
|
490
|
+
### Changes to `config/initializers/shopify_app.rb`
|
491
|
+
- *REMOVE* `config.per_user_tokens = [true|false]` this is no longer needed
|
492
|
+
- *CHANGE* `config.session_repository = 'Shop'` To `config.shop_session_repository = 'Shop'`
|
493
|
+
- *ADD (optional)* User Session Storage `config.user_session_repository = 'User'`
|
494
|
+
|
495
|
+
### Shop Model Changes (normally `app/models/shop.rb`)
|
496
|
+
- *CHANGE* `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
|
497
|
+
|
498
|
+
### Changes to `ShopifyApp::LoginProtection`
|
499
|
+
`ShopifyApp::LoginProtection`
|
500
|
+
|
501
|
+
if you are using `ShopifyApp::LoginProtection#shop_session` in your code, it will need to be
|
502
|
+
changed to `ShopifyApp::LoginProtection#activate_shopify_session`
|
503
|
+
|
504
|
+
### Notes
|
505
|
+
You do not need a user model, a shop session is fine for most applications.
|
506
|
+
|
461
507
|
Questions or problems?
|
462
508
|
----------------------
|
463
509
|
|
464
510
|
- [Ask questions!](https://ecommerce.shopify.com/c/shopify-apis-and-technology)
|
465
511
|
- [Read the docs!](https://help.shopify.com/api/guides)
|
512
|
+
- And don't forget to check the [Changelog](https://github.com/Shopify/shopify_app/blob/master/CHANGELOG.md) too!
|
466
513
|
|
467
514
|
Upgrading to 11.7.0
|
468
515
|
---------------------------
|
@@ -4,31 +4,31 @@
|
|
4
4
|
this.itpAction = document.getElementById('TopLevelInteractionButton');
|
5
5
|
this.redirectUrl = opts.redirectUrl;
|
6
6
|
}
|
7
|
-
|
7
|
+
|
8
8
|
ITPHelper.prototype.redirect = function() {
|
9
9
|
sessionStorage.setItem('shopify.top_level_interaction', true);
|
10
10
|
window.location.href = this.redirectUrl;
|
11
11
|
}
|
12
|
-
|
12
|
+
|
13
13
|
ITPHelper.prototype.userAgentIsAffected = function() {
|
14
14
|
return Boolean(document.hasStorageAccess);
|
15
15
|
}
|
16
|
-
|
16
|
+
|
17
17
|
ITPHelper.prototype.canPartitionCookies = function() {
|
18
18
|
var versionRegEx = /Version\/12\.0\.?\d? Safari/;
|
19
19
|
return versionRegEx.test(navigator.userAgent);
|
20
20
|
}
|
21
|
-
|
21
|
+
|
22
22
|
ITPHelper.prototype.setUpContent = function(onClick) {
|
23
23
|
this.itpContent.style.display = 'block';
|
24
24
|
this.itpAction.addEventListener('click', this.redirect.bind(this));
|
25
25
|
}
|
26
|
-
|
26
|
+
|
27
27
|
ITPHelper.prototype.execute = function() {
|
28
28
|
if (!this.itpContent) {
|
29
29
|
return;
|
30
30
|
}
|
31
|
-
|
31
|
+
|
32
32
|
if (this.userAgentIsAffected()) {
|
33
33
|
this.setUpContent();
|
34
34
|
} else {
|
@@ -28,18 +28,47 @@
|
|
28
28
|
window.parent.location.href = this.redirectData.myshopifyUrl + '/admin/apps';
|
29
29
|
}
|
30
30
|
|
31
|
-
StorageAccessHelper.prototype.
|
32
|
-
window.location.href = this.redirectData.
|
31
|
+
StorageAccessHelper.prototype.redirectToAppTargetUrl = function() {
|
32
|
+
window.location.href = this.redirectData.appTargetUrl;
|
33
|
+
}
|
34
|
+
|
35
|
+
StorageAccessHelper.prototype.sameSiteNoneIncompatible = function(ua) {
|
36
|
+
return ua.includes("iPhone OS 12_") || ua.includes("iPad; CPU OS 12_") || //iOS 12
|
37
|
+
(ua.includes("UCBrowser/")
|
38
|
+
? this.isOlderUcBrowser(ua) //UC Browser < 12.13.2
|
39
|
+
: (ua.includes("Chrome/5") || ua.includes("Chrome/6"))) ||
|
40
|
+
ua.includes("Chromium/5") || ua.includes("Chromium/6") ||
|
41
|
+
(ua.includes(" OS X 10_14_") &&
|
42
|
+
((ua.includes("Version/") && ua.includes("Safari")) || //Safari on MacOS 10.14
|
43
|
+
ua.endsWith("(KHTML, like Gecko)"))); //Web view on MacOS 10.14
|
44
|
+
}
|
45
|
+
|
46
|
+
StorageAccessHelper.prototype.isOlderUcBrowser = function(ua) {
|
47
|
+
var match = ua.match(/UCBrowser\/(\d+)\.(\d+)\.(\d+)\./);
|
48
|
+
if (!match) return false;
|
49
|
+
var major = parseInt(match[1]);
|
50
|
+
var minor = parseInt(match[2]);
|
51
|
+
var build = parseInt(match[3]);
|
52
|
+
if (major != 12) return major < 12;
|
53
|
+
if (minor != 13) return minor < 13;
|
54
|
+
return build < 2;
|
55
|
+
}
|
56
|
+
|
57
|
+
StorageAccessHelper.prototype.setCookie = function(value) {
|
58
|
+
if(!this.sameSiteNoneIncompatible(navigator.userAgent)) {
|
59
|
+
value += '; secure; SameSite=None'
|
60
|
+
}
|
61
|
+
document.cookie = value;
|
33
62
|
}
|
34
63
|
|
35
64
|
StorageAccessHelper.prototype.grantedStorageAccess = function() {
|
36
65
|
try {
|
37
66
|
sessionStorage.setItem('shopify.granted_storage_access', true);
|
38
|
-
|
67
|
+
this.setCookie('shopify.granted_storage_access=true');
|
39
68
|
if (!document.cookie) {
|
40
69
|
throw 'Cannot set third-party cookie.'
|
41
70
|
}
|
42
|
-
this.
|
71
|
+
this.redirectToAppTargetUrl();
|
43
72
|
} catch (error) {
|
44
73
|
console.warn('Third party cookies may be blocked.', error);
|
45
74
|
this.redirectToAppTLD(ACCESS_DENIED_STATUS);
|
@@ -61,7 +90,7 @@
|
|
61
90
|
StorageAccessHelper.prototype.handleHasStorageAccess = function() {
|
62
91
|
if (sessionStorage.getItem('shopify.granted_storage_access')) {
|
63
92
|
// If app was classified by ITP and used Storage Access API to acquire access
|
64
|
-
this.
|
93
|
+
this.redirectToAppTargetUrl();
|
65
94
|
} else {
|
66
95
|
// If app has not been classified by ITP and still has storage access
|
67
96
|
this.redirectToAppTLD(ACCESS_GRANTED_STATUS);
|
@@ -107,7 +136,7 @@
|
|
107
136
|
}
|
108
137
|
|
109
138
|
StorageAccessHelper.prototype.setCookieAndRedirect = function() {
|
110
|
-
|
139
|
+
this.setCookie('shopify.cookies_persist=true');
|
111
140
|
var helper = this.setUpHelper();
|
112
141
|
helper.redirect();
|
113
142
|
}
|
@@ -8,6 +8,11 @@ module ShopifyApp
|
|
8
8
|
def callback
|
9
9
|
if auth_hash
|
10
10
|
login_shop
|
11
|
+
|
12
|
+
if ShopifyApp::SessionRepository.user_storage.present? && user_session.blank?
|
13
|
+
return redirect_to(login_url_with_optional_shop)
|
14
|
+
end
|
15
|
+
|
11
16
|
install_webhooks
|
12
17
|
install_scripttags
|
13
18
|
perform_after_authenticate_job
|
@@ -55,16 +60,15 @@ module ShopifyApp
|
|
55
60
|
token: token,
|
56
61
|
api_version: ShopifyApp.configuration.api_version
|
57
62
|
)
|
58
|
-
session[:shopify] = ShopifyApp::SessionRepository.store(session_store, user: associated_user)
|
59
|
-
session[:shopify_domain] = shop_name
|
60
|
-
session[:shopify_user] = associated_user
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
session[:
|
64
|
+
session[:shopify_user] = associated_user
|
65
|
+
if session[:shopify_user].present?
|
66
|
+
session[:user_id] = ShopifyApp::SessionRepository.store_user_session(session_store, associated_user)
|
67
|
+
else
|
68
|
+
session[:shop_id] = ShopifyApp::SessionRepository.store_shop_session(session_store)
|
67
69
|
end
|
70
|
+
session[:shopify_domain] = shop_name
|
71
|
+
session[:user_session] = auth_hash&.extra&.session
|
68
72
|
end
|
69
73
|
|
70
74
|
def install_webhooks
|
@@ -72,7 +76,7 @@ module ShopifyApp
|
|
72
76
|
|
73
77
|
WebhooksManager.queue(
|
74
78
|
shop_name,
|
75
|
-
token,
|
79
|
+
shop_session&.token || user_session.token,
|
76
80
|
ShopifyApp.configuration.webhooks
|
77
81
|
)
|
78
82
|
end
|
@@ -82,7 +86,7 @@ module ShopifyApp
|
|
82
86
|
|
83
87
|
ScripttagsManager.queue(
|
84
88
|
shop_name,
|
85
|
-
token,
|
89
|
+
shop_session&.token || user_session.token,
|
86
90
|
ShopifyApp.configuration.scripttags
|
87
91
|
)
|
88
92
|
end
|
@@ -3,6 +3,7 @@ module ShopifyApp
|
|
3
3
|
include ShopifyApp::LoginProtection
|
4
4
|
|
5
5
|
layout false, only: :new
|
6
|
+
|
6
7
|
after_action only: [:new, :create] do |controller|
|
7
8
|
controller.response.headers.except!('X-Frame-Options')
|
8
9
|
end
|
@@ -16,30 +17,35 @@ module ShopifyApp
|
|
16
17
|
end
|
17
18
|
|
18
19
|
def enable_cookies
|
19
|
-
return unless
|
20
|
+
return unless validate_shop_presence
|
20
21
|
|
21
22
|
render(:enable_cookies, layout: false, locals: {
|
22
23
|
does_not_have_storage_access_url: top_level_interaction_path(
|
23
|
-
shop: sanitized_shop_name
|
24
|
+
shop: sanitized_shop_name,
|
25
|
+
return_to: params[:return_to]
|
24
26
|
),
|
25
27
|
has_storage_access_url: login_url_with_optional_shop(top_level: true),
|
26
|
-
|
27
|
-
|
28
|
+
app_target_url: granted_storage_access_path(
|
29
|
+
shop: sanitized_shop_name,
|
30
|
+
return_to: params[:return_to]
|
31
|
+
),
|
32
|
+
current_shopify_domain: current_shopify_domain
|
28
33
|
})
|
29
34
|
end
|
30
35
|
|
31
36
|
def top_level_interaction
|
32
37
|
@url = login_url_with_optional_shop(top_level: true)
|
33
|
-
|
38
|
+
validate_shop_presence
|
34
39
|
end
|
35
40
|
|
36
41
|
def granted_storage_access
|
37
|
-
return unless
|
42
|
+
return unless validate_shop_presence
|
38
43
|
|
39
44
|
session['shopify.granted_storage_access'] = true
|
40
45
|
|
41
|
-
|
42
|
-
|
46
|
+
copy_return_to_param_to_session
|
47
|
+
|
48
|
+
redirect_to(return_address_with_params({ shop: @shop }))
|
43
49
|
end
|
44
50
|
|
45
51
|
def destroy
|
@@ -54,7 +60,9 @@ module ShopifyApp
|
|
54
60
|
return render_invalid_shop_error unless sanitized_shop_name.present?
|
55
61
|
session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
|
56
62
|
|
57
|
-
|
63
|
+
copy_return_to_param_to_session
|
64
|
+
|
65
|
+
set_user_tokens_option
|
58
66
|
|
59
67
|
if user_agent_can_partition_cookies
|
60
68
|
authenticate_with_partitioning
|
@@ -83,7 +91,27 @@ module ShopifyApp
|
|
83
91
|
end
|
84
92
|
end
|
85
93
|
|
86
|
-
def
|
94
|
+
def set_user_tokens_option
|
95
|
+
if shop_session.blank?
|
96
|
+
session[:user_tokens] = false
|
97
|
+
return
|
98
|
+
end
|
99
|
+
|
100
|
+
session[:user_tokens] = ShopifyApp::SessionRepository.user_storage.present?
|
101
|
+
|
102
|
+
ShopifyAPI::Session.temp(
|
103
|
+
domain: shop_session.domain,
|
104
|
+
token: shop_session.token,
|
105
|
+
api_version: shop_session.api_version
|
106
|
+
) do
|
107
|
+
ShopifyAPI::Metafield.find(:token_validity_bogus_check)
|
108
|
+
end
|
109
|
+
rescue ActiveResource::UnauthorizedAccess
|
110
|
+
session[:user_tokens] = false
|
111
|
+
rescue StandardError
|
112
|
+
end
|
113
|
+
|
114
|
+
def validate_shop_presence
|
87
115
|
@shop = sanitized_shop_name
|
88
116
|
unless @shop
|
89
117
|
render_invalid_shop_error
|
@@ -93,6 +121,10 @@ module ShopifyApp
|
|
93
121
|
true
|
94
122
|
end
|
95
123
|
|
124
|
+
def copy_return_to_param_to_session
|
125
|
+
session[:return_to] = params[:return_to] if params[:return_to]
|
126
|
+
end
|
127
|
+
|
96
128
|
def render_invalid_shop_error
|
97
129
|
flash[:error] = I18n.t('invalid_shop_url')
|
98
130
|
redirect_to return_address
|
@@ -133,11 +165,15 @@ module ShopifyApp
|
|
133
165
|
layout: false,
|
134
166
|
locals: {
|
135
167
|
does_not_have_storage_access_url: top_level_interaction_path(
|
136
|
-
shop: sanitized_shop_name
|
168
|
+
shop: sanitized_shop_name,
|
169
|
+
return_to: session[:return_to]
|
137
170
|
),
|
138
171
|
has_storage_access_url: login_url_with_optional_shop(top_level: true),
|
139
|
-
|
140
|
-
|
172
|
+
app_target_url: granted_storage_access_path(
|
173
|
+
shop: sanitized_shop_name,
|
174
|
+
return_to: session[:return_to]
|
175
|
+
),
|
176
|
+
current_shopify_domain: current_shopify_domain
|
141
177
|
}
|
142
178
|
)
|
143
179
|
end
|