shopify_app 21.8.1 → 21.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +1 -1
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +56 -56
- data/docs/shopify_app/sessions.md +26 -17
- data/docs/shopify_app/webhooks.md +16 -2
- data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +6 -1
- data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_expires_at_column.erb +5 -0
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +20 -0
- data/lib/shopify_app/configuration.rb +8 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +8 -2
- data/lib/shopify_app/managers/webhooks_manager.rb +1 -0
- data/lib/shopify_app/session/session_repository.rb +12 -5
- data/lib/shopify_app/session/shop_session_storage.rb +4 -0
- data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +4 -0
- data/lib/shopify_app/session/user_session_storage.rb +4 -0
- data/lib/shopify_app/session/user_session_storage_with_scopes.rb +25 -0
- data/lib/shopify_app/version.rb +1 -1
- data/package.json +1 -1
- data/shopify_app.gemspec +1 -1
- data/yarn.lock +3 -3
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 927f0886c6d7be713738a4c38d2a1c5319593d2d8e4d200d854957abae73ac09
|
4
|
+
data.tar.gz: cca13c50d4cc99853ef10e119d4cb10cf96ba786ee9e146c2acacc12758d741f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db9c6d4fdee1744d974fcde46f54d4246c2886dafb4d31f3423d9c903566f730c06a0b3187a21cdd534d7ee63be95c1fa318e85c007b53f682cbf7a6d3184df2
|
7
|
+
data.tar.gz: eb437382bf4fba13da3d3780fd05e29360807c8d999239d129dd4ff5e92fc63de33dea382deb9ab9f0e9552d208a1405acb5aa68cb85c20a7310afd81681bcb0
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
Unreleased
|
2
2
|
----------
|
3
3
|
|
4
|
+
21.10.0 (January 24, 2024)
|
5
|
+
----------
|
6
|
+
* Fix session deletion for users with customized session storage[#1773](https://github.com/Shopify/shopify_app/pull/1773)
|
7
|
+
* Add configuration flag `check_session_expiry_date` to trigger a re-auth when the (user) session is expired. The session expiry date must be stored and retrieved for this flag to be effective. When the `UserSessionStorageWithScopes` concern is used, a DB migration can be generated with `rails generate shopify_app:user_model --skip` and should be applied before enabling that flag[#1757](https://github.com/Shopify/shopify_app/pull/1757)
|
8
|
+
|
9
|
+
21.9.0 (January 16, 2024)
|
10
|
+
----------
|
11
|
+
* Fix `add_webhook` generator to create the webhook jobs under the correct directory[#1748](https://github.com/Shopify/shopify_app/pull/1748)
|
12
|
+
* Add support for metafield_namespaces in webhook registration [#1745](https://github.com/Shopify/shopify_app/pull/1745)
|
13
|
+
* Bumps `shopify_api` to latest version (13.4.0), adds support for 2024-01 API version [#1776](https://github.com/Shopify/shopify_app/pull/1776)
|
14
|
+
|
4
15
|
21.8.1 (December 6, 2023)
|
16
|
+
----------
|
5
17
|
* Bump `shopify_api` to 13.3.1 [1763](https://github.com/Shopify/shopify-api-ruby/blob/main/CHANGELOG.md#1331)
|
6
18
|
|
7
19
|
21.8.0 (Dec 1, 2023)
|
data/Gemfile.lock
CHANGED
@@ -1,81 +1,81 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
shopify_app (21.
|
4
|
+
shopify_app (21.10.0)
|
5
5
|
activeresource
|
6
6
|
addressable (~> 2.7)
|
7
7
|
browser_sniffer (~> 2.0)
|
8
8
|
jwt (>= 2.2.3)
|
9
9
|
rails (> 5.2.1)
|
10
10
|
redirect_safely (~> 1.0)
|
11
|
-
shopify_api (~> 13.
|
11
|
+
shopify_api (~> 13.4)
|
12
12
|
sprockets-rails (>= 2.0.0)
|
13
13
|
|
14
14
|
GEM
|
15
15
|
remote: https://rubygems.org/
|
16
16
|
specs:
|
17
|
-
actioncable (6.1.7.
|
18
|
-
actionpack (= 6.1.7.
|
19
|
-
activesupport (= 6.1.7.
|
17
|
+
actioncable (6.1.7.6)
|
18
|
+
actionpack (= 6.1.7.6)
|
19
|
+
activesupport (= 6.1.7.6)
|
20
20
|
nio4r (~> 2.0)
|
21
21
|
websocket-driver (>= 0.6.1)
|
22
|
-
actionmailbox (6.1.7.
|
23
|
-
actionpack (= 6.1.7.
|
24
|
-
activejob (= 6.1.7.
|
25
|
-
activerecord (= 6.1.7.
|
26
|
-
activestorage (= 6.1.7.
|
27
|
-
activesupport (= 6.1.7.
|
22
|
+
actionmailbox (6.1.7.6)
|
23
|
+
actionpack (= 6.1.7.6)
|
24
|
+
activejob (= 6.1.7.6)
|
25
|
+
activerecord (= 6.1.7.6)
|
26
|
+
activestorage (= 6.1.7.6)
|
27
|
+
activesupport (= 6.1.7.6)
|
28
28
|
mail (>= 2.7.1)
|
29
|
-
actionmailer (6.1.7.
|
30
|
-
actionpack (= 6.1.7.
|
31
|
-
actionview (= 6.1.7.
|
32
|
-
activejob (= 6.1.7.
|
33
|
-
activesupport (= 6.1.7.
|
29
|
+
actionmailer (6.1.7.6)
|
30
|
+
actionpack (= 6.1.7.6)
|
31
|
+
actionview (= 6.1.7.6)
|
32
|
+
activejob (= 6.1.7.6)
|
33
|
+
activesupport (= 6.1.7.6)
|
34
34
|
mail (~> 2.5, >= 2.5.4)
|
35
35
|
rails-dom-testing (~> 2.0)
|
36
|
-
actionpack (6.1.7.
|
37
|
-
actionview (= 6.1.7.
|
38
|
-
activesupport (= 6.1.7.
|
36
|
+
actionpack (6.1.7.6)
|
37
|
+
actionview (= 6.1.7.6)
|
38
|
+
activesupport (= 6.1.7.6)
|
39
39
|
rack (~> 2.0, >= 2.0.9)
|
40
40
|
rack-test (>= 0.6.3)
|
41
41
|
rails-dom-testing (~> 2.0)
|
42
42
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
43
|
-
actiontext (6.1.7.
|
44
|
-
actionpack (= 6.1.7.
|
45
|
-
activerecord (= 6.1.7.
|
46
|
-
activestorage (= 6.1.7.
|
47
|
-
activesupport (= 6.1.7.
|
43
|
+
actiontext (6.1.7.6)
|
44
|
+
actionpack (= 6.1.7.6)
|
45
|
+
activerecord (= 6.1.7.6)
|
46
|
+
activestorage (= 6.1.7.6)
|
47
|
+
activesupport (= 6.1.7.6)
|
48
48
|
nokogiri (>= 1.8.5)
|
49
|
-
actionview (6.1.7.
|
50
|
-
activesupport (= 6.1.7.
|
49
|
+
actionview (6.1.7.6)
|
50
|
+
activesupport (= 6.1.7.6)
|
51
51
|
builder (~> 3.1)
|
52
52
|
erubi (~> 1.4)
|
53
53
|
rails-dom-testing (~> 2.0)
|
54
54
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
55
|
-
activejob (6.1.7.
|
56
|
-
activesupport (= 6.1.7.
|
55
|
+
activejob (6.1.7.6)
|
56
|
+
activesupport (= 6.1.7.6)
|
57
57
|
globalid (>= 0.3.6)
|
58
|
-
activemodel (6.1.7.
|
59
|
-
activesupport (= 6.1.7.
|
58
|
+
activemodel (6.1.7.6)
|
59
|
+
activesupport (= 6.1.7.6)
|
60
60
|
activemodel-serializers-xml (1.0.2)
|
61
61
|
activemodel (> 5.x)
|
62
62
|
activesupport (> 5.x)
|
63
63
|
builder (~> 3.1)
|
64
|
-
activerecord (6.1.7.
|
65
|
-
activemodel (= 6.1.7.
|
66
|
-
activesupport (= 6.1.7.
|
64
|
+
activerecord (6.1.7.6)
|
65
|
+
activemodel (= 6.1.7.6)
|
66
|
+
activesupport (= 6.1.7.6)
|
67
67
|
activeresource (6.0.0)
|
68
68
|
activemodel (>= 6.0)
|
69
69
|
activemodel-serializers-xml (~> 1.0)
|
70
70
|
activesupport (>= 6.0)
|
71
|
-
activestorage (6.1.7.
|
72
|
-
actionpack (= 6.1.7.
|
73
|
-
activejob (= 6.1.7.
|
74
|
-
activerecord (= 6.1.7.
|
75
|
-
activesupport (= 6.1.7.
|
71
|
+
activestorage (6.1.7.6)
|
72
|
+
actionpack (= 6.1.7.6)
|
73
|
+
activejob (= 6.1.7.6)
|
74
|
+
activerecord (= 6.1.7.6)
|
75
|
+
activesupport (= 6.1.7.6)
|
76
76
|
marcel (~> 1.0)
|
77
77
|
mini_mime (>= 1.1.0)
|
78
|
-
activesupport (6.1.7.
|
78
|
+
activesupport (6.1.7.6)
|
79
79
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
80
80
|
i18n (>= 1.6, < 2)
|
81
81
|
minitest (>= 5.1)
|
@@ -159,20 +159,20 @@ GEM
|
|
159
159
|
rack (2.2.7)
|
160
160
|
rack-test (2.1.0)
|
161
161
|
rack (>= 1.3)
|
162
|
-
rails (6.1.7.
|
163
|
-
actioncable (= 6.1.7.
|
164
|
-
actionmailbox (= 6.1.7.
|
165
|
-
actionmailer (= 6.1.7.
|
166
|
-
actionpack (= 6.1.7.
|
167
|
-
actiontext (= 6.1.7.
|
168
|
-
actionview (= 6.1.7.
|
169
|
-
activejob (= 6.1.7.
|
170
|
-
activemodel (= 6.1.7.
|
171
|
-
activerecord (= 6.1.7.
|
172
|
-
activestorage (= 6.1.7.
|
173
|
-
activesupport (= 6.1.7.
|
162
|
+
rails (6.1.7.6)
|
163
|
+
actioncable (= 6.1.7.6)
|
164
|
+
actionmailbox (= 6.1.7.6)
|
165
|
+
actionmailer (= 6.1.7.6)
|
166
|
+
actionpack (= 6.1.7.6)
|
167
|
+
actiontext (= 6.1.7.6)
|
168
|
+
actionview (= 6.1.7.6)
|
169
|
+
activejob (= 6.1.7.6)
|
170
|
+
activemodel (= 6.1.7.6)
|
171
|
+
activerecord (= 6.1.7.6)
|
172
|
+
activestorage (= 6.1.7.6)
|
173
|
+
activesupport (= 6.1.7.6)
|
174
174
|
bundler (>= 1.15.0)
|
175
|
-
railties (= 6.1.7.
|
175
|
+
railties (= 6.1.7.6)
|
176
176
|
sprockets-rails (>= 2.0.0)
|
177
177
|
rails-controller-testing (1.0.5)
|
178
178
|
actionpack (>= 5.0.1.rc1)
|
@@ -183,9 +183,9 @@ GEM
|
|
183
183
|
nokogiri (>= 1.6)
|
184
184
|
rails-html-sanitizer (1.5.0)
|
185
185
|
loofah (~> 2.19, >= 2.19.1)
|
186
|
-
railties (6.1.7.
|
187
|
-
actionpack (= 6.1.7.
|
188
|
-
activesupport (= 6.1.7.
|
186
|
+
railties (6.1.7.6)
|
187
|
+
actionpack (= 6.1.7.6)
|
188
|
+
activesupport (= 6.1.7.6)
|
189
189
|
method_source
|
190
190
|
rake (>= 12.2)
|
191
191
|
thor (~> 1.0)
|
@@ -217,7 +217,7 @@ GEM
|
|
217
217
|
ruby-progressbar (1.13.0)
|
218
218
|
ruby2_keywords (0.0.5)
|
219
219
|
securerandom (0.2.2)
|
220
|
-
shopify_api (13.
|
220
|
+
shopify_api (13.4.0)
|
221
221
|
activesupport
|
222
222
|
concurrent-ruby
|
223
223
|
hash_diff
|
@@ -4,23 +4,27 @@ Sessions are used to make contextual API calls for either a shop (offline sessio
|
|
4
4
|
|
5
5
|
#### Table of contents
|
6
6
|
|
7
|
-
- [Sessions](#sessions
|
8
|
-
|
9
|
-
- [
|
10
|
-
- [
|
11
|
-
- [
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
- [Sessions](#sessions)
|
8
|
+
- [Table of contents](#table-of-contents)
|
9
|
+
- [Sessions](#sessions-1)
|
10
|
+
- [Types of session tokens](#types-of-session-tokens)
|
11
|
+
- [Session token storage](#session-token-storage)
|
12
|
+
- [Shop (offline) token storage](#shop-offline-token-storage)
|
13
|
+
- [User (online) token storage](#user-online-token-storage)
|
14
|
+
- [In-memory Session Storage for testing](#in-memory-session-storage-for-testing)
|
15
|
+
- [Customizing Session Storage with `ShopifyApp::SessionRepository`](#customizing-session-storage-with-shopifyappsessionrepository)
|
16
|
+
- [⚠️ Custom Session Storage Requirements](#️--custom-session-storage-requirements)
|
17
|
+
- [Available `ActiveSupport::Concerns` that contains implementation of the above methods](#available-activesupportconcerns-that-contains-implementation-of-the-above-methods)
|
18
|
+
- [Loading Sessions](#loading-sessions)
|
15
19
|
- [Getting Sessions with Controller Concerns](#getting-sessions-with-controller-concerns)
|
16
|
-
- [Shop
|
17
|
-
- [User
|
18
|
-
- [Getting
|
19
|
-
- [Access scopes](#access-scopes)
|
20
|
-
|
21
|
-
|
22
|
-
- [Migrating from shop-based to user-based token strategy](#migrating-from-shop-based-to-user-based-token-strategy)
|
23
|
-
- [Migrating from ShopifyApi::Auth::SessionStorage to ShopifyApp::SessionStorage](#migrating-from-shopifyapiauthsessionstorage-to-shopifyappsessionstorage)
|
20
|
+
- [**Shop Sessions - `EnsureInstalled`**](#shop-sessions---ensureinstalled)
|
21
|
+
- [User Sessions - `EnsureHasSession`](#user-sessions---ensurehassession)
|
22
|
+
- [Getting sessions from a Shop or User model record - 'with\_shopify\_session'](#getting-sessions-from-a-shop-or-user-model-record---with_shopify_session)
|
23
|
+
- [Access scopes](#access-scopes)
|
24
|
+
- [`ShopifyApp::ShopSessionStorageWithScopes`](#shopifyappshopsessionstoragewithscopes)
|
25
|
+
- [`ShopifyApp::UserSessionStorageWithScopes`](#shopifyappusersessionstoragewithscopes)
|
26
|
+
- [Migrating from shop-based to user-based token strategy](#migrating-from-shop-based-to-user-based-token-strategy)
|
27
|
+
- [Migrating from `ShopifyApi::Auth::SessionStorage` to `ShopifyApp::SessionStorage`](#migrating-from-shopifyapiauthsessionstorage-to-shopifyappsessionstorage)
|
24
28
|
|
25
29
|
## Sessions
|
26
30
|
#### Types of session tokens
|
@@ -103,6 +107,7 @@ The custom **Shop** repository must implement the following methods:
|
|
103
107
|
| `self.store(auth_session)` | `auth_session` (ShopifyAPI::Auth::Session) | - |
|
104
108
|
| `self.retrieve(id)` | `id` (String) | ShopifyAPI::Auth::Session |
|
105
109
|
| `self.retrieve_by_shopify_domain(shopify_domain)` | `shopify_domain` (String) | ShopifyAPI::Auth::Session |
|
110
|
+
| `self.destroy_by_shopify_domain(shopify_domain)` | `shopify_domain` (String) | - |
|
106
111
|
|
107
112
|
The custom **User** repository must implement the following methods:
|
108
113
|
| Method | Parameters | Return Type |
|
@@ -110,6 +115,7 @@ The custom **User** repository must implement the following methods:
|
|
110
115
|
| `self.store(auth_session, user)` | <li>`auth_session` (ShopifyAPI::Auth::Session)<br><li>`user` (ShopifyAPI::Auth::AssociatedUser) | - |
|
111
116
|
| `self.retrieve(id)` | `id` (String) | `ShopifyAPI::Auth::Session` |
|
112
117
|
| `self.retrieve_by_shopify_user_id(user_id)` | `user_id` (String) | `ShopifyAPI::Auth::Session` |
|
118
|
+
| `self.destroy_by_shopify_user_id(user_id)` | `user_id` (String) | - |
|
113
119
|
|
114
120
|
|
115
121
|
These methods are already implemented as a part of the `User` and `Shop` models generated from this gem's generator.
|
@@ -153,7 +159,7 @@ end
|
|
153
159
|
```
|
154
160
|
|
155
161
|
##### User Sessions - `EnsureHasSession`
|
156
|
-
- [EnsureHasSession](https://github.com/Shopify/shopify_app/blob/main/app/controllers/concerns/shopify_app/ensure_has_session.rb) controller concern will load a user session via `current_shopify_session`. As part of loading this session, this concern will also ensure that the user session has the appropriate scopes needed for the application. If the user isn't found or has fewer permitted scopes than are required, they will be prompted to authorize the application.
|
162
|
+
- [EnsureHasSession](https://github.com/Shopify/shopify_app/blob/main/app/controllers/concerns/shopify_app/ensure_has_session.rb) controller concern will load a user session via `current_shopify_session`. As part of loading this session, this concern will also ensure that the user session has the appropriate scopes needed for the application and that it is not expired (when `check_session_expiry_date` is enabled). If the user isn't found or has fewer permitted scopes than are required, they will be prompted to authorize the application.
|
157
163
|
- This controller concern should be used if you don't need your app to make calls on behalf of a user. With that in mind, there are a few other embedded concerns that are mixed in to ensure that embedding, CSRF, localization, and billing allow the action for the user.
|
158
164
|
- Example
|
159
165
|
```ruby
|
@@ -228,6 +234,9 @@ class User < ActiveRecord::Base
|
|
228
234
|
end
|
229
235
|
```
|
230
236
|
|
237
|
+
## Expiry date
|
238
|
+
When the configuration flag `check_session_expiry_date` is set to true, the user session expiry date will be checked to trigger a re-auth and get a fresh user token when it is expired. This requires the `ShopifyAPI::Auth::Session` `expires` attribute to be stored. When the `User` model includes the `UserSessionStorageWithScopes` concern, a DB migration can be generated with `rails generate shopify_app:user_model --skip` to add the `expires_at` attribute to the model.
|
239
|
+
|
231
240
|
## Migrating from shop-based to user-based token strategy
|
232
241
|
|
233
242
|
1. Run the `user_model` generator as [mentioned above](#user-online-token-storage).
|
@@ -13,7 +13,7 @@ ShopifyApp can manage your app's webhooks for you if you set which webhooks you
|
|
13
13
|
```ruby
|
14
14
|
ShopifyApp.configure do |config|
|
15
15
|
config.webhooks = [
|
16
|
-
{topic: 'carts/update', path: 'webhooks/carts_update'}
|
16
|
+
{topic: 'carts/update', path: 'api/webhooks/carts_update'}
|
17
17
|
]
|
18
18
|
end
|
19
19
|
```
|
@@ -35,7 +35,21 @@ If you are only interested in particular fields, you can optionally filter the d
|
|
35
35
|
```ruby
|
36
36
|
ShopifyApp.configure do |config|
|
37
37
|
config.webhooks = [
|
38
|
-
{topic: 'products/update', path: 'webhooks/products_update', fields: ['title', 'vendor']}
|
38
|
+
{topic: 'products/update', path: 'api/webhooks/products_update', fields: ['title', 'vendor']}
|
39
|
+
]
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
If you need to read metafields, you can pass in the `metafield_namespaces` parameter in `config/webhooks`. Note if you are also using the `fields` parameter you will need to add `metafields` into that as well. Shopify documentation on metafields in webhooks can be found [here](https://shopify.dev/docs/api/admin-rest/2023-10/resources/webhook#resource-object).
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
ShopifyApp.configure do |config|
|
47
|
+
config.webhooks = [
|
48
|
+
{
|
49
|
+
topic: 'orders/create',
|
50
|
+
path: 'api/webhooks/order_create',
|
51
|
+
metafield_namespaces: ['app-namespace'],
|
52
|
+
},
|
39
53
|
]
|
40
54
|
end
|
41
55
|
```
|
@@ -39,7 +39,12 @@ module ShopifyApp
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def add_webhook_job
|
42
|
-
|
42
|
+
namespace = ShopifyApp.configuration.webhook_jobs_namespace
|
43
|
+
@job_file_name = if namespace.present?
|
44
|
+
"#{namespace}/#{job_file_name}_job"
|
45
|
+
else
|
46
|
+
"#{job_file_name}_job"
|
47
|
+
end
|
43
48
|
@job_class_name = @job_file_name.classify
|
44
49
|
template("webhook_job.rb", "app/jobs/#{@job_file_name}.rb")
|
45
50
|
end
|
@@ -40,6 +40,26 @@ module ShopifyApp
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
def create_expires_at_storage_in_user_model
|
44
|
+
expires_at_column_prompt = <<~PROMPT
|
45
|
+
It is highly recommended that apps record the User session expiry date. \
|
46
|
+
This will allow to check if the session has expired and re-authenticate \
|
47
|
+
without a first call to Shopify.
|
48
|
+
|
49
|
+
After running the migration, the `check_session_expiry_date` configuration can be enabled.
|
50
|
+
|
51
|
+
The following migration will add an `expires_at` column to the User model. \
|
52
|
+
Do you want to include this migration? [y/n]
|
53
|
+
PROMPT
|
54
|
+
|
55
|
+
if new_shopify_cli_app? || Rails.env.test? || yes?(expires_at_column_prompt)
|
56
|
+
migration_template(
|
57
|
+
"db/migrate/add_user_expires_at_column.erb",
|
58
|
+
"db/migrate/add_user_expires_at_column.rb",
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
43
63
|
def update_shopify_app_initializer
|
44
64
|
gsub_file("config/initializers/shopify_app.rb", "ShopifyApp::InMemoryUserSessionStore", "User")
|
45
65
|
end
|
@@ -20,6 +20,7 @@ module ShopifyApp
|
|
20
20
|
attr_accessor :api_version
|
21
21
|
|
22
22
|
attr_accessor :reauth_on_access_scope_changes
|
23
|
+
attr_accessor :check_session_expiry_date
|
23
24
|
attr_accessor :log_level
|
24
25
|
|
25
26
|
# customise urls
|
@@ -44,6 +45,9 @@ module ShopifyApp
|
|
44
45
|
# takes a ShopifyApp::BillingConfiguration object
|
45
46
|
attr_accessor :billing
|
46
47
|
|
48
|
+
# Work in Progress: enables token exchange authentication flow
|
49
|
+
attr_accessor :wip_new_embedded_auth_strategy
|
50
|
+
|
47
51
|
def initialize
|
48
52
|
@root_url = "/"
|
49
53
|
@myshopify_domain = "myshopify.com"
|
@@ -118,6 +122,10 @@ module ShopifyApp
|
|
118
122
|
def user_access_scopes
|
119
123
|
@user_access_scopes || scope
|
120
124
|
end
|
125
|
+
|
126
|
+
def use_new_embedded_auth_strategy?
|
127
|
+
wip_new_embedded_auth_strategy && embedded_app?
|
128
|
+
end
|
121
129
|
end
|
122
130
|
|
123
131
|
class BillingConfiguration
|
@@ -30,6 +30,12 @@ module ShopifyApp
|
|
30
30
|
return redirect_to_login
|
31
31
|
end
|
32
32
|
|
33
|
+
if ShopifyApp.configuration.check_session_expiry_date && current_shopify_session.expired?
|
34
|
+
ShopifyApp::Logger.debug("Session expired, redirecting to login")
|
35
|
+
clear_shopify_session
|
36
|
+
return redirect_to_login
|
37
|
+
end
|
38
|
+
|
33
39
|
if ShopifyApp.configuration.reauth_on_access_scope_changes &&
|
34
40
|
!ShopifyApp.configuration.user_access_scopes_strategy.covers_scopes?(current_shopify_session)
|
35
41
|
clear_shopify_session
|
@@ -280,8 +286,8 @@ module ShopifyApp
|
|
280
286
|
|
281
287
|
def requested_by_javascript?
|
282
288
|
request.xhr? ||
|
283
|
-
request.
|
284
|
-
request.
|
289
|
+
request.media_type == "text/javascript" ||
|
290
|
+
request.media_type == "application/javascript"
|
285
291
|
end
|
286
292
|
end
|
287
293
|
end
|
@@ -23,6 +23,14 @@ module ShopifyApp
|
|
23
23
|
user_storage.retrieve_by_shopify_user_id(user_id)
|
24
24
|
end
|
25
25
|
|
26
|
+
def destroy_shop_session_by_domain(shopify_domain)
|
27
|
+
shop_storage.destroy_by_shopify_domain(shopify_domain)
|
28
|
+
end
|
29
|
+
|
30
|
+
def destroy_user_session_by_shopify_user_id(user_id)
|
31
|
+
user_storage.destroy_by_shopify_user_id(user_id)
|
32
|
+
end
|
33
|
+
|
26
34
|
def store_shop_session(session)
|
27
35
|
shop_storage.store(session)
|
28
36
|
end
|
@@ -73,18 +81,17 @@ module ShopifyApp
|
|
73
81
|
def delete_session(id)
|
74
82
|
match = id.match(/^offline_(.*)/)
|
75
83
|
|
76
|
-
|
84
|
+
if match
|
77
85
|
domain = match[1]
|
78
86
|
ShopifyApp::Logger.debug("Destroying session by domain - domain: #{domain}")
|
79
|
-
|
87
|
+
destroy_shop_session_by_domain(domain)
|
88
|
+
|
80
89
|
else
|
81
90
|
shopify_user_id = id.split("_").last
|
82
91
|
ShopifyApp::Logger.debug("Destroying session by user - user_id: #{shopify_user_id}")
|
83
|
-
|
92
|
+
destroy_user_session_by_shopify_user_id(shopify_user_id)
|
84
93
|
end
|
85
94
|
|
86
|
-
record.destroy
|
87
|
-
|
88
95
|
true
|
89
96
|
end
|
90
97
|
|
@@ -15,6 +15,7 @@ module ShopifyApp
|
|
15
15
|
user.shopify_token = auth_session.access_token
|
16
16
|
user.shopify_domain = auth_session.shop
|
17
17
|
user.access_scopes = auth_session.scope.to_s
|
18
|
+
user.expires_at = auth_session.expires
|
18
19
|
|
19
20
|
user.save!
|
20
21
|
user.id
|
@@ -30,6 +31,10 @@ module ShopifyApp
|
|
30
31
|
construct_session(user)
|
31
32
|
end
|
32
33
|
|
34
|
+
def destroy_by_shopify_user_id(user_id)
|
35
|
+
destroy_by(shopify_user_id: user_id)
|
36
|
+
end
|
37
|
+
|
33
38
|
private
|
34
39
|
|
35
40
|
def construct_session(user)
|
@@ -52,6 +57,7 @@ module ShopifyApp
|
|
52
57
|
scope: user.access_scopes,
|
53
58
|
associated_user_scope: user.access_scopes,
|
54
59
|
associated_user: associated_user,
|
60
|
+
expires: user.expires_at,
|
55
61
|
)
|
56
62
|
end
|
57
63
|
end
|
@@ -67,5 +73,24 @@ module ShopifyApp
|
|
67
73
|
rescue NotImplementedError, NoMethodError
|
68
74
|
raise NotImplementedError, "#access_scopes= must be defined to hook into stored access scopes"
|
69
75
|
end
|
76
|
+
|
77
|
+
def expires_at=(expires_at)
|
78
|
+
super
|
79
|
+
rescue NotImplementedError, NoMethodError
|
80
|
+
if ShopifyApp.configuration.check_session_expiry_date
|
81
|
+
raise NotImplementedError,
|
82
|
+
"#expires_at= must be defined to handle storing the session expiry date"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def expires_at
|
87
|
+
super
|
88
|
+
rescue NotImplementedError, NoMethodError
|
89
|
+
if ShopifyApp.configuration.check_session_expiry_date
|
90
|
+
raise NotImplementedError, "#expires_at must be defined to check the session expiry date"
|
91
|
+
end
|
92
|
+
|
93
|
+
nil
|
94
|
+
end
|
70
95
|
end
|
71
96
|
end
|
data/lib/shopify_app/version.rb
CHANGED
data/package.json
CHANGED
data/shopify_app.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.add_runtime_dependency("jwt", ">= 2.2.3")
|
21
21
|
s.add_runtime_dependency("rails", "> 5.2.1")
|
22
22
|
s.add_runtime_dependency("redirect_safely", "~> 1.0")
|
23
|
-
s.add_runtime_dependency("shopify_api", "~> 13.
|
23
|
+
s.add_runtime_dependency("shopify_api", "~> 13.4")
|
24
24
|
s.add_runtime_dependency("sprockets-rails", ">= 2.0.0")
|
25
25
|
|
26
26
|
s.add_development_dependency("byebug")
|
data/yarn.lock
CHANGED
@@ -2040,9 +2040,9 @@ flatted@^3.2.7:
|
|
2040
2040
|
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
2041
2041
|
|
2042
2042
|
follow-redirects@^1.0.0:
|
2043
|
-
version "1.15.
|
2044
|
-
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.
|
2045
|
-
integrity sha512-
|
2043
|
+
version "1.15.4"
|
2044
|
+
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.4.tgz#cdc7d308bf6493126b17ea2191ea0ccf3e535adf"
|
2045
|
+
integrity sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==
|
2046
2046
|
|
2047
2047
|
fs-extra@^8.1.0:
|
2048
2048
|
version "8.1.0"
|
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: 21.
|
4
|
+
version: 21.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activeresource
|
@@ -100,14 +100,14 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '13.
|
103
|
+
version: '13.4'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '13.
|
110
|
+
version: '13.4'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: sprockets-rails
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -416,6 +416,7 @@ files:
|
|
416
416
|
- lib/generators/shopify_app/shop_model/templates/shops.yml
|
417
417
|
- lib/generators/shopify_app/shopify_app_generator.rb
|
418
418
|
- lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb
|
419
|
+
- lib/generators/shopify_app/user_model/templates/db/migrate/add_user_expires_at_column.erb
|
419
420
|
- lib/generators/shopify_app/user_model/templates/db/migrate/create_users.erb
|
420
421
|
- lib/generators/shopify_app/user_model/templates/user.rb
|
421
422
|
- lib/generators/shopify_app/user_model/templates/users.yml
|
@@ -488,7 +489,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
488
489
|
- !ruby/object:Gem::Version
|
489
490
|
version: '0'
|
490
491
|
requirements: []
|
491
|
-
rubygems_version: 3.4
|
492
|
+
rubygems_version: 3.5.4
|
492
493
|
signing_key:
|
493
494
|
specification_version: 4
|
494
495
|
summary: This gem is used to get quickly started with the Shopify API
|