shopify_app 21.9.0 → 22.00.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug-report.md +23 -18
  3. data/.github/workflows/build.yml +1 -1
  4. data/.github/workflows/release.yml +1 -1
  5. data/.github/workflows/rubocop.yml +2 -2
  6. data/CHANGELOG.md +20 -1
  7. data/CODE_OF_CONDUCT.md +46 -0
  8. data/Gemfile.lock +7 -9
  9. data/README.md +0 -1
  10. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +5 -1
  11. data/app/controllers/concerns/shopify_app/ensure_installed.rb +2 -2
  12. data/app/controllers/shopify_app/callback_controller.rb +15 -14
  13. data/config/routes.rb +1 -1
  14. data/docs/Upgrading.md +25 -1
  15. data/docs/shopify_app/controller-concerns.md +21 -0
  16. data/docs/shopify_app/generators.md +2 -2
  17. data/docs/shopify_app/sessions.md +26 -17
  18. data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_expires_at_column.erb +5 -0
  19. data/lib/generators/shopify_app/user_model/user_model_generator.rb +20 -0
  20. data/lib/shopify_app/configuration.rb +8 -0
  21. data/lib/shopify_app/controller_concerns/embedded_app.rb +12 -4
  22. data/lib/shopify_app/controller_concerns/login_protection.rb +15 -11
  23. data/lib/shopify_app/engine.rb +1 -2
  24. data/lib/shopify_app/session/session_repository.rb +12 -5
  25. data/lib/shopify_app/session/shop_session_storage.rb +4 -0
  26. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +4 -0
  27. data/lib/shopify_app/session/user_session_storage.rb +4 -0
  28. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +25 -0
  29. data/lib/shopify_app/version.rb +1 -1
  30. data/lib/shopify_app.rb +0 -3
  31. data/package.json +1 -1
  32. data/shopify_app.gemspec +2 -3
  33. metadata +8 -28
  34. data/app/controllers/concerns/shopify_app/authenticated.rb +0 -17
  35. data/app/controllers/concerns/shopify_app/require_known_shop.rb +0 -16
  36. data/docs/shopify_app/script-tags.md +0 -28
  37. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +0 -42
  38. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +0 -63
  39. data/lib/shopify_app/controller_concerns/itp.rb +0 -50
  40. data/lib/shopify_app/jobs/scripttags_manager_job.rb +0 -16
  41. data/lib/shopify_app/managers/scripttags_manager.rb +0 -85
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0235c0e9ef88bf1ffa1b0fde1d62f2af79c3d2bd2a0e45dfd454f9d26dc30b53
4
- data.tar.gz: 1f00756ed0f26034b996b24db4cc2297e56afeffd0b3f28b6d22ecdc7f78dbe9
3
+ metadata.gz: 3d5156af0790e87945886e2c5edd99822d04fb05b88ad318558ab7a71aec764e
4
+ data.tar.gz: e192e1581b1f9f183e3f10a9a8c4c8cb337202ea1bcf1325cc1c4ea5ba06a1f9
5
5
  SHA512:
6
- metadata.gz: a8c1116442619ef12195cf15ef38307f720640eb6993d2bfa174fb842878ff9af890a663271bf03aa556ee1fa86a7311956d6d29a8188e26276993c0d5e83057
7
- data.tar.gz: c6d78960aeba7353bea99a234adf87d772bf371f43d027dfcd32bb8e89d38aef00879b5a31aa655fcabe3f348a8d50c3553d87b845f8ac4b1e8f12eab8bb0385
6
+ metadata.gz: 951051cf5170c58847b8f2fde2e779916f66afa8fba6ea3be75d9aaee605f747b334fb28022d5149909cdb96b10741fa8be8f69ab98df631fe07d3d19c24484d
7
+ data.tar.gz: 45bff8811720fd20cf7141441cc8ee70b0b7ca046962670b4bbf4d91e480be08220f744185e98a8e8d71ff64532f698b513a8ab534e7fc0b30126cdebee93748
@@ -6,36 +6,41 @@ labels: "Type: Bug 🐛"
6
6
 
7
7
  # Issue summary
8
8
 
9
- <!--
10
-
11
- Write a short description of the issue here. Please provide any details or logs that
12
- can help us debug it.
9
+ Before opening this issue, I have:
10
+
11
+ - [ ] Upgraded to the latest version of the package
12
+ - `shopify_app` version:
13
+ - Ruby version:
14
+ - Operating system:
15
+ - [ ] Set `log_level: :debug` [in my configuration](https://github.com/Shopify/shopify-api-ruby#setup-shopify-context), if applicable
16
+ - [ ] Found a reliable way to reproduce the problem that indicates it's a problem with the package
17
+ - [ ] Looked for similar issues in this repository
18
+ - [ ] Checked that this isn't an issue with a Shopify API
19
+ - If it is, please create a post in the [Shopify community forums](https://community.shopify.com/c/partners-and-developers/ct-p/appdev) or report it to [Shopify Partner Support](https://help.shopify.com/en/support/partners/org-select)
13
20
 
14
- Increase the logs as described in the README by setting log_level to :debug, and paste the relevant portion here.
15
-
16
- Learn more: https://github.com/Shopify/shopify-api-ruby#setup-shopify-context
21
+ <!--
22
+ Write a short description of the issue here.
17
23
 
24
+ We can only fix issues for which there is a clear reproduction scenario.
25
+ The more context you can provide, the easier it becomes for us to investigate and fix the issue.
18
26
  -->
19
27
 
20
- - `shopify_api` version:
21
- - `shopify_app` version:
22
- - Ruby version:
23
- - Operating system:
24
-
25
- ```
26
- // Paste any relevant logs here
27
- ```
28
-
29
28
  ## Expected behavior
30
29
 
31
- <!-- What do you think should happen? -->
30
+ What do you think should happen?
32
31
 
33
32
  ## Actual behavior
34
33
 
35
- <!-- What actually happens? -->
34
+ What actually happens?
36
35
 
37
36
  ## Steps to reproduce the problem
38
37
 
39
38
  1.
40
39
  1.
41
40
  1.
41
+
42
+ ## Debug logs
43
+
44
+ ```
45
+ // Paste any relevant logs here
46
+ ```
@@ -12,7 +12,7 @@ jobs:
12
12
  name: Ruby ${{ matrix.version }}
13
13
  strategy:
14
14
  matrix:
15
- version: ['2.7', '3.0', '3.1', '3.2']
15
+ version: ['3.0', '3.1', '3.2']
16
16
 
17
17
  steps:
18
18
  - uses: actions/checkout@v3
@@ -11,7 +11,7 @@ jobs:
11
11
  steps:
12
12
  - name: Extract tag name
13
13
  id: tag
14
- run: echo "::set-output name=value::${GITHUB_REF##*/}"
14
+ run: echo "value=${GITHUB_REF##*/}" >> "$GITHUB_OUTPUT"
15
15
  - uses: actions/checkout@v3
16
16
 
17
17
  - name: Create Release
@@ -8,10 +8,10 @@ jobs:
8
8
 
9
9
  steps:
10
10
  - uses: actions/checkout@v3
11
- - name: Set up Ruby 2.7
11
+ - name: Set up Ruby 3.2
12
12
  uses: ruby/setup-ruby@v1
13
13
  with:
14
- ruby-version: 2.7
14
+ ruby-version: 3.2
15
15
  bundler-cache: true
16
16
  - name: Install gems
17
17
  run: |
data/CHANGELOG.md CHANGED
@@ -1,7 +1,26 @@
1
1
  Unreleased
2
2
  ----------
3
3
 
4
- 21.9.0 (January 16, 2023)
4
+ 22.00.0 (March 5, 2024)
5
+ ----------
6
+ * ⚠️ [Breaking] Bumps minimum supported Ruby version to 3.0. Bumps `shopify_api` to 14.0 [1801](https://github.com/Shopify/shopify_app/pull/1801)
7
+ * ⚠️ [Breaking] Removes deprecated controller concerns that were renamed in `v21.10.0`. [1805](https://github.com/Shopify/shopify_app/pull/1805)
8
+ * ⚠️ [Breaking] Removes deprecated `ScripttagManager`. We realize there was communication error in our logging where we logged future deprecation instead of our inteded removal. Since we have been logging that for 2 years we felt we'd move forward with the removal instead pushing this off until the next major release. [1806](https://github.com/Shopify/shopify_app/pull/1806)
9
+ * ⚠️ [Breaking] Removes ITP controller concern and `browser_sniffer` dependency.[1810](https://github.com/Shopify/shopify_app/pull/1810)
10
+ * ⚠️ [Breaking] Removes Marketing Extensions generator [1810](https://github.com/Shopify/shopify_app/pull/1810)
11
+ * ⚠️ [Breaking] Thows an error if a controller includes incompatible concerns (LoginProtection/EnsureInstalled) [1809](https://github.com/Shopify/shopify_app/pull/1809)
12
+ * ⚠️ [Breaking] No longer rescues non-shopify API errors during OAuth
13
+ callback [1807](https://github.com/Shopify/shopify_app/pull/1807)
14
+ * Make type param for webhooks route optional. This will fix a bug with CLI initiated webhooks.[1786](https://github.com/Shopify/shopify_app/pull/1786)
15
+ * Fix redirecting to login when we catch a 401 response from Shopify, so that it can also handle cases where the app is already embedded when that happens.[1787](https://github.com/Shopify/shopify_app/pull/1787)
16
+ * Always register webhooks with offline sessions.[1788](https://github.com/Shopify/shopify_app/pull/1788)
17
+
18
+ 21.10.0 (January 24, 2024)
19
+ ----------
20
+ * Fix session deletion for users with customized session storage[#1773](https://github.com/Shopify/shopify_app/pull/1773)
21
+ * 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)
22
+
23
+ 21.9.0 (January 16, 2024)
5
24
  ----------
6
25
  * Fix `add_webhook` generator to create the webhook jobs under the correct directory[#1748](https://github.com/Shopify/shopify_app/pull/1748)
7
26
  * Add support for metafield_namespaces in webhook registration [#1745](https://github.com/Shopify/shopify_app/pull/1745)
@@ -0,0 +1,46 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, and in the interest of
4
+ fostering an open and welcoming community, we pledge to respect all
5
+ people who contribute through reporting issues, posting feature
6
+ requests, updating documentation, submitting pull requests or patches,
7
+ and other activities.
8
+
9
+ We are committed to making participation in this project a
10
+ harassment-free experience for everyone, regardless of level of
11
+ experience, gender, gender identity and expression, sexual orientation,
12
+ disability, personal appearance, body size, race, ethnicity, age,
13
+ religion, or nationality.
14
+
15
+ Examples of unacceptable behavior by participants include:
16
+
17
+ - The use of sexualized language or imagery
18
+ - Personal attacks
19
+ - Trolling or insulting/derogatory comments
20
+ - Public or private harassment
21
+ - Publishing other's private information, such as physical or electronic
22
+ addresses, without explicit permission
23
+ - Other unethical or unprofessional conduct
24
+
25
+ Project maintainers have the right and responsibility to remove, edit,
26
+ or reject comments, commits, code, wiki edits, issues, and other
27
+ contributions that are not aligned to this Code of Conduct, or to ban
28
+ temporarily or permanently any contributor for other behaviors that they
29
+ deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ By adopting this Code of Conduct, project maintainers commit themselves
32
+ to fairly and consistently applying these principles to every aspect of
33
+ managing this project. Project maintainers who do not follow or enforce
34
+ the Code of Conduct may be permanently removed from the project team.
35
+
36
+ This Code of Conduct applies both within project spaces and in public
37
+ spaces when an individual is representing the project or its community.
38
+
39
+ Instances of abusive, harassing, or otherwise unacceptable behavior may
40
+ be reported by contacting a project maintainer at <opensource@shopify.com>.
41
+ All complaints will be reviewed and investigated and will result in a response
42
+ that is deemed necessary and appropriate to the circumstances. Maintainers are
43
+ obligated to maintain confidentiality with regard to the reporter of an incident.
44
+
45
+ This Code of Conduct is adapted from the Contributor Covenant, version
46
+ 1.3.0, available from http://contributor-covenant.org/version/1/3/0/
data/Gemfile.lock CHANGED
@@ -1,14 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify_app (21.9.0)
4
+ shopify_app (22.00.0)
5
5
  activeresource
6
6
  addressable (~> 2.7)
7
- browser_sniffer (~> 2.0)
8
7
  jwt (>= 2.2.3)
9
8
  rails (> 5.2.1)
10
9
  redirect_safely (~> 1.0)
11
- shopify_api (~> 13.4)
10
+ shopify_api (~> 14)
12
11
  sprockets-rails (>= 2.0.0)
13
12
 
14
13
  GEM
@@ -86,7 +85,6 @@ GEM
86
85
  ast (2.4.2)
87
86
  binding_of_caller (1.0.0)
88
87
  debug_inspector (>= 0.0.1)
89
- browser_sniffer (2.2.0)
90
88
  builder (3.2.4)
91
89
  byebug (11.1.3)
92
90
  coderay (1.1.3)
@@ -134,11 +132,11 @@ GEM
134
132
  net-smtp (0.3.3)
135
133
  net-protocol
136
134
  nio4r (2.5.9)
137
- nokogiri (1.15.0-arm64-darwin)
135
+ nokogiri (1.16.2-arm64-darwin)
138
136
  racc (~> 1.4)
139
- nokogiri (1.15.0-x86_64-darwin)
137
+ nokogiri (1.16.2-x86_64-darwin)
140
138
  racc (~> 1.4)
141
- nokogiri (1.15.0-x86_64-linux)
139
+ nokogiri (1.16.2-x86_64-linux)
142
140
  racc (~> 1.4)
143
141
  oj (3.14.3)
144
142
  openssl (3.1.0)
@@ -155,7 +153,7 @@ GEM
155
153
  binding_of_caller (~> 1.0)
156
154
  pry (~> 0.13)
157
155
  public_suffix (5.0.1)
158
- racc (1.6.2)
156
+ racc (1.7.3)
159
157
  rack (2.2.7)
160
158
  rack-test (2.1.0)
161
159
  rack (>= 1.3)
@@ -217,7 +215,7 @@ GEM
217
215
  ruby-progressbar (1.13.0)
218
216
  ruby2_keywords (0.0.5)
219
217
  securerandom (0.2.2)
220
- shopify_api (13.4.0)
218
+ shopify_api (14.0.0)
221
219
  activesupport
222
220
  concurrent-ruby
223
221
  hash_diff
data/README.md CHANGED
@@ -106,7 +106,6 @@ You can find documentation on gem usage, concepts, mixins, installation, and mor
106
106
  * [Engine](/docs/shopify_app/engine.md)
107
107
  * [Controller Concerns](/docs/shopify_app/controller-concerns.md)
108
108
  * [Generators](/docs/shopify_app/generators.md)
109
- * [ScriptTags](/docs/shopify_app/script-tags.md)
110
109
  * [Sessions](/docs/shopify_app/sessions.md)
111
110
  * [Handling changes in access scopes](/docs/shopify_app/handling-access-scopes-changes.md)
112
111
  * [Testing](/docs/shopify_app/testing.md)
@@ -20,11 +20,15 @@ module ShopifyApp
20
20
  end
21
21
 
22
22
  def splash_page_with_params(params)
23
- uri = URI(root_path)
23
+ uri = URI(base_url)
24
24
  uri.query = params.compact.to_query
25
25
  uri.to_s
26
26
  end
27
27
 
28
+ def base_url
29
+ ShopifyApp.configuration.root_url.presence || root_path
30
+ end
31
+
28
32
  def redirect_to_splash_page
29
33
  redirect_to(splash_page)
30
34
  rescue ::ShopifyApp::ShopifyDomainNotFound => error
@@ -9,10 +9,10 @@ module ShopifyApp
9
9
  if defined?(ShopifyApp::LoginProtection) && ancestors.include?(ShopifyApp::LoginProtection)
10
10
  message = <<~EOS
11
11
  We detected the use of incompatible concerns (EnsureInstalled and LoginProtection) in #{name},
12
- which may lead to unpredictable behavior. In a future release of this library this will raise an error.
12
+ which leads to unpredictable behavior. You cannot include both concerns in the same controller.
13
13
  EOS
14
14
 
15
- ShopifyApp::Logger.deprecated(message, "22.0.0")
15
+ raise message
16
16
  end
17
17
 
18
18
  before_action :check_shop_domain
@@ -10,8 +10,12 @@ module ShopifyApp
10
10
  begin
11
11
  api_session, cookie = validated_auth_objects
12
12
  rescue => error
13
- deprecate_callback_rescue(error) unless error.class.module_parent == ShopifyAPI::Errors
14
- return respond_with_error
13
+ if error.class.module_parent == ShopifyAPI::Errors
14
+ callback_rescue(error)
15
+ return respond_with_error
16
+ else
17
+ raise error
18
+ end
15
19
  end
16
20
 
17
21
  save_session(api_session) if api_session
@@ -25,6 +29,10 @@ module ShopifyApp
25
29
 
26
30
  private
27
31
 
32
+ def callback_rescue(error)
33
+ ShopifyApp::Logger.debug("#{error.class} was rescued and redirected to login_url_with_optional_shop")
34
+ end
35
+
28
36
  def deprecate_callback_rescue(error)
29
37
  message = <<~EOS
30
38
  An error of type #{error.class} was rescued. This is not part of `ShopifyAPI::Errors`, which could indicate a
@@ -130,8 +138,11 @@ module ShopifyApp
130
138
  end
131
139
 
132
140
  def perform_post_authenticate_jobs(session)
133
- install_webhooks(session)
134
- install_scripttags(session)
141
+ # Ensure we use the shop session to install webhooks
142
+ session_for_shop = session.online? ? shop_session : session
143
+
144
+ install_webhooks(session_for_shop)
145
+
135
146
  perform_after_authenticate_job(session)
136
147
  end
137
148
 
@@ -141,16 +152,6 @@ module ShopifyApp
141
152
  WebhooksManager.queue(session.shop, session.access_token)
142
153
  end
143
154
 
144
- def install_scripttags(session)
145
- return unless ShopifyApp.configuration.has_scripttags?
146
-
147
- ScripttagsManager.queue(
148
- session.shop,
149
- session.access_token,
150
- ShopifyApp.configuration.scripttags,
151
- )
152
- end
153
-
154
155
  def perform_after_authenticate_job(session)
155
156
  config = ShopifyApp.configuration.after_authenticate_job
156
157
 
data/config/routes.rb CHANGED
@@ -26,6 +26,6 @@ ShopifyApp::Engine.routes.draw do
26
26
  end
27
27
 
28
28
  namespace :webhooks do
29
- post ":type" => :receive
29
+ post "(:type)" => :receive
30
30
  end
31
31
  end
data/docs/Upgrading.md CHANGED
@@ -8,6 +8,8 @@ This file documents important changes needed to upgrade your app's Shopify App v
8
8
 
9
9
  [Unreleased](#unreleased)
10
10
 
11
+ [Upgrading to `v22.0.0`](#upgrading-to-v2200)
12
+
11
13
  [Upgrading to `v20.3.0`](#upgrading-to-v2030)
12
14
 
13
15
  [Upgrading to `v20.2.0`](#upgrading-to-v2020)
@@ -38,8 +40,30 @@ We also recommend the use of a staging site which matches your production enviro
38
40
 
39
41
  If you do run into issues, we recommend looking at our [debugging tips.](https://github.com/Shopify/shopify_app/blob/main/docs/Troubleshooting.md#debugging-tips)
40
42
 
43
+ ## Upgrading to `v22.0.0`
44
+ #### Dropped support for Ruby 2.x
45
+ Support for Ruby 2.x has been dropped as it is no longer supported. You'll need to upgrade to 3.x.x
46
+
47
+ #### Renamed Controller Concerns
48
+ The following controller concerns have been renamed/replaced in `v21.10.0` and have now been removed. To upgrade, please rename any usage in your apps's controllers that include them to the following:
49
+
50
+ |Old Deprecated Controller Concern |Replaced By New Controller Concern|
51
+ |---|---|
52
+ |`Authenticated`|`EnsureHasSession`|
53
+ |`RequireKnownShop`|`EnsureInstalled`|
54
+
55
+ The new names better reflect what assurances the including the controller concern provide. The new concern provide similar if not identical functionality as the concerns they replaced.
56
+
57
+ #### Remove ScripttagManager
58
+ Script tag usage has largely been replaced with the adoption of [theme app extensions](https://shopify.dev/docs/apps/online-store/theme-app-extensions) and [thank you order status customization](https://shopify.dev/docs/apps/checkout/thank-you-order-status). The manager has been removed with this major release due to effective replacement and a goal to have parity in supported functionality across language stacks.
59
+
60
+ If you find yourself still using Scipt Tags and want to continue the pattern of declarative management of script tags this gem used to use, we recommend porting the logic [the manager used in prior versions](https://github.com/Shopify/shopify_app/blob/2336fabc6d0b45a4dee3f336455dace4d2d88bc4/lib/shopify_app/managers/scripttags_manager.rb#L4) and implementing it in a [post authentication job](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#run-jobs-after-the-oauth-flow). This is the recommended flow to create script tags (or any other logic) for stores that install your app.
61
+
62
+ #### No longer rescue non-shopify API errors during customized OAuth flow
63
+ If you have customized authentication logic and are counting on the `CallbackController` to catch your error and redirect to login, you'll need to catch that error and redirect to `login_url_with_optional_shop`.
64
+
41
65
  ## Upgrading to 21.3.0
42
- The `Itp` controller concern has been removed from `LoginProtection` which is included by the `Authenticated` controller concern.
66
+ The `Itp` controller concern has been removed from `LoginProtection` which is included by the `Authenticated`/`EnsureHasSession` controller concern.
43
67
  If any of your controllers are dependant on methods from `Itp` then you can include `ShopifyApp::Itp` directly.
44
68
  You may notice a deprecation notice saying, `Itp will be removed in an upcoming version`.
45
69
  This is because we intend on removing `Itp` completely in `v22.0.0`, but this will work in the meantime.
@@ -64,5 +64,26 @@ Implements Rails' [protect_from_forgery](https://api.rubyonrails.org/classes/Act
64
64
  #### EmbeddedApp
65
65
  If your ShopifyApp configuration has the `embedded_app` config set to true, [P3P header](https://www.w3.org/P3P/) and [content security policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) are handled for you.
66
66
 
67
+ By default, the `EmbeddedApp` concern also sets the layout file to be `app/views/layouts/embedded_app.html.erb`.
68
+
69
+ Sometimes one wants to run an embedded app in non-embedded mode. For example:
70
+
71
+ - When the remote environment is a CI;
72
+ - When the remote environment is a preview/PR app;
73
+ - When the developer wants to run the app in a non-embedded mode for testing.
74
+
75
+ To use the same application layout for every application controller, a developer can now overwrite the `#use_embedded_app_layout?` method.
76
+
77
+ ```ruby
78
+ class ApplicationController
79
+ # Ensures every controller is using the standard app/views/layouts/application.html.erb layout.
80
+ #
81
+ # @return [true, false]
82
+ def use_embedded_app_layout?
83
+ false
84
+ end
85
+ end
86
+ ```
87
+
67
88
  #### EnsureBilling
68
89
  If billing is enabled for the app, the active payment for the session is queried and enforced if needed. If billing is required the user will be redirected to a page requesting payment.
@@ -68,13 +68,13 @@ Specify whether the app is an embedded app. Apps are embedded by default.
68
68
 
69
69
  #### `$ rails generate shopify_app:shop_model`
70
70
 
71
- This generator creates a `Shop` model and a migration to store shop installation records. See [*Shop-based token strategy*](/docs/shopify_app/session-repository.md#shop-based-token-storage) to learn more.
71
+ This generator creates a `Shop` model and a migration to store shop installation records. See [*Shop-based token strategy*](/docs/shopify_app/sessions.md#shop-offline-token-storage) to learn more.
72
72
 
73
73
  ---
74
74
 
75
75
  #### `$ rails generate shopify_app:user_model`
76
76
 
77
- This generator creates a `User` model and a migration to store user records. See [*User-based token strategy*](/docs/shopify_app/session-repository.md#user-based-token-storage) to learn more.
77
+ This generator creates a `User` model and a migration to store user records. See [*User-based token strategy*](/docs/shopify_app/sessions.md#user-online-token-storage) to learn more.
78
78
 
79
79
  ---
80
80
 
@@ -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-1)
8
- - [Types of session tokens](#types-of-session-tokens) - Shop (offline) v.s. User (online)
9
- - [Session token storage](#session-token-storage)
10
- - [Shop (offline) token storage](#shop-offline-token-storage)
11
- - [User (online) token storage](#user-online-token-storage)
12
- - [In-Memory Session Storage for Testing](#in-memory-session-storage-for-testing)
13
- - [Customizing Session Storage with `ShopifyApp::SessionRepository`](#customizing-session-storage-with-shopifyappsessionrepository)
14
- - [Loading Sessions](#loading-sessions)
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 session - "EnsureInstalled" ](#shop-sessions---ensureinstalled)
17
- - [User session - "EnsureHasSession" ](#user-sessions---ensurehassession)
18
- - [Getting Sessions from a Shop or User model record - "with_shopify_session"](#getting-sessions-from-a-shop-or-user-model-record---with_shopify_session)
19
- - [Access scopes](#access-scopes)
20
- - [`ShopifyApp::ShopSessionStorageWithScopes`](#shopifyappshopsessionstoragewithscopes)
21
- - [``ShopifyApp::UserSessionStorageWithScopes``](#shopifyappusersessionstoragewithscopes)
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).
@@ -0,0 +1,5 @@
1
+ class AddUserExpiresAtColumn < ActiveRecord::Migration[<%= rails_migration_version %>]
2
+ def change
3
+ add_column :users, :expires_at, :datetime
4
+ end
5
+ 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
@@ -7,14 +7,22 @@ module ShopifyApp
7
7
  include ShopifyApp::FrameAncestors
8
8
 
9
9
  included do
10
- if ShopifyApp.configuration.embedded_app?
11
- after_action(:set_esdk_headers)
12
- layout("embedded_app")
13
- end
10
+ layout :embedded_app_layout
11
+ after_action :set_esdk_headers, if: -> { ShopifyApp.configuration.embedded_app? }
12
+ end
13
+
14
+ protected
15
+
16
+ def use_embedded_app_layout?
17
+ ShopifyApp.configuration.embedded_app?
14
18
  end
15
19
 
16
20
  private
17
21
 
22
+ def embedded_app_layout
23
+ "embedded_app" if use_embedded_app_layout?
24
+ end
25
+
18
26
  def set_esdk_headers
19
27
  response.set_header("P3P", 'CP="Not used"')
20
28
  response.headers.except!("X-Frame-Options")