shopify_app 13.0.0 → 17.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug-report.md +63 -0
- data/.github/ISSUE_TEMPLATE/config.yml +1 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +33 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.github/workflows/build.yml +38 -0
- data/.github/workflows/release.yml +24 -0
- data/.github/workflows/rubocop.yml +22 -0
- data/.gitignore +0 -2
- data/.rubocop.yml +14 -6
- data/CHANGELOG.md +132 -0
- data/CONTRIBUTING.md +76 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +256 -0
- data/README.md +72 -534
- data/Rakefile +1 -0
- data/SECURITY.md +59 -0
- data/app/assets/images/storage_access.svg +1 -2
- data/app/assets/javascripts/shopify_app/storage_access.js +2 -1
- data/app/assets/javascripts/shopify_app/top_level_interaction.js +1 -1
- data/app/controllers/concerns/shopify_app/authenticated.rb +1 -0
- data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +26 -0
- data/app/controllers/concerns/shopify_app/require_known_shop.rb +39 -0
- data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +32 -0
- data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
- data/app/controllers/shopify_app/callback_controller.rb +105 -18
- data/app/controllers/shopify_app/extension_verification_controller.rb +2 -7
- data/app/controllers/shopify_app/sessions_controller.rb +22 -10
- data/app/controllers/shopify_app/webhooks_controller.rb +6 -5
- data/app/views/shopify_app/partials/_button_styles.html.erb +41 -36
- data/app/views/shopify_app/partials/_card_styles.html.erb +3 -3
- data/app/views/shopify_app/partials/_empty_state_styles.html.erb +28 -59
- data/app/views/shopify_app/partials/_form_styles.html.erb +56 -0
- data/app/views/shopify_app/partials/_layout_styles.html.erb +16 -1
- data/app/views/shopify_app/partials/_typography_styles.html.erb +6 -6
- data/app/views/shopify_app/sessions/enable_cookies.html.erb +2 -7
- data/app/views/shopify_app/sessions/new.html.erb +38 -110
- data/app/views/shopify_app/sessions/request_storage_access.html.erb +1 -1
- data/app/views/shopify_app/sessions/top_level_interaction.html.erb +21 -22
- data/config/locales/de.yml +11 -11
- data/config/locales/fi.yml +1 -1
- data/config/locales/nl.yml +7 -7
- data/config/locales/th.yml +4 -4
- data/config/locales/vi.yml +22 -0
- data/config/locales/zh-CN.yml +1 -1
- data/config/routes.rb +1 -0
- data/docs/Quickstart.md +15 -87
- data/docs/Releasing.md +18 -14
- data/docs/Upgrading.md +110 -0
- data/docs/shopify_app/authentication.md +124 -0
- data/docs/shopify_app/engine.md +82 -0
- data/docs/shopify_app/generators.md +127 -0
- data/docs/shopify_app/handling-access-scopes-changes.md +8 -0
- data/docs/shopify_app/script-tags.md +28 -0
- data/docs/shopify_app/session-repository.md +88 -0
- data/docs/shopify_app/testing.md +38 -0
- data/docs/shopify_app/webhooks.md +72 -0
- data/karma.conf.js +1 -1
- data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +5 -3
- data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
- data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +2 -1
- data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +4 -4
- data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +5 -4
- data/lib/generators/shopify_app/add_webhook/templates/{webhook_job.rb → webhook_job.rb.tt} +5 -0
- data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +4 -3
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +3 -3
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +10 -9
- data/lib/generators/shopify_app/authenticated_controller/authenticated_controller_generator.rb +1 -1
- data/lib/generators/shopify_app/controllers/controllers_generator.rb +2 -1
- data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +31 -3
- data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +2 -0
- data/lib/generators/shopify_app/home_controller/templates/index.html.erb +66 -16
- data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +11 -0
- data/lib/generators/shopify_app/install/install_generator.rb +46 -11
- data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +1 -1
- data/lib/generators/shopify_app/install/templates/flash_messages.js +0 -2
- data/lib/generators/shopify_app/install/templates/omniauth.rb +3 -1
- data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +25 -0
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb.tt +8 -0
- data/lib/generators/shopify_app/install/templates/user_agent.rb +2 -1
- data/lib/generators/shopify_app/products_controller/products_controller_generator.rb +19 -0
- data/lib/generators/shopify_app/products_controller/templates/products_controller.rb +8 -0
- data/lib/generators/shopify_app/routes/routes_generator.rb +1 -0
- data/lib/generators/shopify_app/routes/templates/routes.rb +10 -9
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +39 -7
- data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +2 -1
- data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
- data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/user_model/templates/user.rb +2 -1
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +39 -7
- data/lib/generators/shopify_app/views/views_generator.rb +2 -1
- data/lib/shopify_app/access_scopes/noop_strategy.rb +13 -0
- data/lib/shopify_app/access_scopes/shop_strategy.rb +24 -0
- data/lib/shopify_app/access_scopes/user_strategy.rb +41 -0
- data/lib/shopify_app/configuration.rb +40 -8
- data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +3 -3
- data/lib/shopify_app/controller_concerns/csrf_protection.rb +15 -0
- data/lib/shopify_app/controller_concerns/embedded_app.rb +3 -2
- data/lib/shopify_app/controller_concerns/localization.rb +1 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +74 -16
- data/lib/shopify_app/controller_concerns/payload_verification.rb +24 -0
- data/lib/shopify_app/controller_concerns/webhook_verification.rb +3 -18
- data/lib/shopify_app/engine.rb +26 -0
- data/lib/shopify_app/jobs/scripttags_manager_job.rb +1 -1
- data/lib/shopify_app/jobs/webhooks_manager_job.rb +1 -1
- data/lib/shopify_app/managers/scripttags_manager.rb +4 -3
- data/lib/shopify_app/managers/webhooks_manager.rb +4 -3
- data/lib/shopify_app/middleware/jwt_middleware.rb +42 -0
- data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +2 -1
- data/lib/shopify_app/omniauth/omniauth_configuration.rb +64 -0
- data/lib/shopify_app/session/in_memory_session_store.rb +7 -3
- data/lib/shopify_app/session/in_memory_shop_session_store.rb +12 -0
- data/lib/shopify_app/session/in_memory_user_session_store.rb +12 -0
- data/lib/shopify_app/session/jwt.rb +63 -0
- data/lib/shopify_app/session/null_user_session_store.rb +22 -0
- data/lib/shopify_app/session/session_repository.rb +13 -16
- data/lib/shopify_app/session/session_storage.rb +1 -0
- data/lib/shopify_app/session/shop_session_storage.rb +21 -9
- data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +58 -0
- data/lib/shopify_app/session/user_session_storage.rb +19 -8
- data/lib/shopify_app/session/user_session_storage_with_scopes.rb +58 -0
- data/lib/shopify_app/test_helpers/all.rb +2 -0
- data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +17 -0
- data/lib/shopify_app/utils.rb +18 -5
- data/lib/shopify_app/version.rb +2 -1
- data/lib/shopify_app.rb +22 -5
- data/package.json +7 -8
- data/shopify_app.gemspec +13 -8
- data/translation.yml +1 -1
- data/yarn.lock +2120 -2168
- metadata +88 -16
- data/.github/ISSUE_TEMPLATE.md +0 -14
- data/.travis.yml +0 -27
- data/docs/install-on-dev-shop.png +0 -0
- data/docs/test-your-app.png +0 -0
- data/lib/generators/shopify_app/install/templates/shopify_app.rb +0 -15
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -20
- data/package-lock.json +0 -7245
data/docs/Releasing.md
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
-
Releasing ShopifyApp
|
1
|
+
# Releasing ShopifyApp
|
2
2
|
|
3
|
-
1.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
3
|
+
1. Make the code changes in a separate PR that doesn't modify the version.
|
4
|
+
1. After that is merged, check the Semantic Versioning page for info on how to version the new release: http://semver.org
|
5
|
+
1. Create a pull request with the following changes:
|
6
|
+
- Update the version of ShopifyApp in lib/shopify_app/version.rb
|
7
|
+
- Update the version of shopify_app in package.json
|
8
|
+
- Run `bundle` to update `Gemfile.lock`
|
9
|
+
- Add a CHANGELOG entry for the new release with the date
|
10
|
+
- Change the title of the PR to something like: "Packaging for release X.Y.Z"
|
11
|
+
1. Merge your pull request
|
12
|
+
1. Checkout and pull from master so you have the latest version of the shopify_app
|
13
|
+
1. Tag the HEAD with the version
|
14
|
+
```bash
|
15
|
+
$ git tag -f vX.Y.Z && git push --tags --force
|
16
|
+
```
|
17
|
+
1. Check that Create Release workflow successfully runs
|
18
|
+
1. Use Shipit to build and push the gem
|
15
19
|
|
16
|
-
If you see an error like 'You need to create the vX.Y.X tag first', clear
|
20
|
+
If you see an error like 'You need to create the vX.Y.X tag first', clear git
|
17
21
|
cache in Shipit settings
|
data/docs/Upgrading.md
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Upgrading
|
2
|
+
|
3
|
+
This file documents important changes needed to upgrade your app's Shopify App version to a new major version.
|
4
|
+
|
5
|
+
#### Table of contents
|
6
|
+
|
7
|
+
[Upgrading to `v13.0.0`](#upgrading-to-v1300)
|
8
|
+
|
9
|
+
[Upgrading to `v11.7.0`](#upgrading-to-v1170)
|
10
|
+
|
11
|
+
[Upgrading from `v8.6` to `v9.0.0`](#upgrading-from-v86-to-v900)
|
12
|
+
|
13
|
+
## Upgrading to `v13.0.0`
|
14
|
+
|
15
|
+
Version 13.0.0 adds the ability to use both user and shop sessions, concurrently. This however involved a large
|
16
|
+
change to how session stores work. Here are the steps to migrate to 13.x
|
17
|
+
|
18
|
+
### Changes to `config/initializers/shopify_app.rb`
|
19
|
+
|
20
|
+
- *REMOVE* `config.per_user_tokens = [true|false]` this is no longer needed
|
21
|
+
- *CHANGE* `config.session_repository = 'Shop'` To `config.shop_session_repository = 'Shop'`
|
22
|
+
- *ADD (optional)* User Session Storage `config.user_session_repository = 'User'`
|
23
|
+
|
24
|
+
### Shop Model Changes (normally `app/models/shop.rb`)
|
25
|
+
|
26
|
+
- *CHANGE* `include ShopifyApp::SessionStorage` to `include ShopifyApp::ShopSessionStorage`
|
27
|
+
|
28
|
+
### Changes to the @shop_session instance variable (normally in `app/controllers/*.rb`)
|
29
|
+
|
30
|
+
- *CHANGE* if you are using shop sessions, `@shop_session` will need to be changed to `@current_shopify_session`.
|
31
|
+
|
32
|
+
### Changes to Rails `session`
|
33
|
+
|
34
|
+
- *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.
|
35
|
+
|
36
|
+
### Changes to `ShopifyApp::LoginProtection`
|
37
|
+
|
38
|
+
`ShopifyApp::LoginProtection`
|
39
|
+
|
40
|
+
- CHANGE if you are using `ShopifyApp::LoginProtection#shopify_session` in your code, it will need to be
|
41
|
+
changed to `ShopifyApp::LoginProtection#activate_shopify_session`
|
42
|
+
- CHANGE if you are using `ShopifyApp::LoginProtection#clear_shop_session` in your code, it will need to be
|
43
|
+
changed to `ShopifyApp::LoginProtection#clear_shopify_session`
|
44
|
+
|
45
|
+
### Notes
|
46
|
+
You do not need a user model; a shop session is fine for most applications.
|
47
|
+
|
48
|
+
---
|
49
|
+
|
50
|
+
## Upgrading to `v11.7.0`
|
51
|
+
|
52
|
+
### Session storage method signature breaking change
|
53
|
+
If you override `def self.store(auth_session)` method in your session storage model (e.g. Shop), the method signature has changed to `def self.store(auth_session, *args)` in order to support user-based token storage. Please update your method signature to include the second argument.
|
54
|
+
|
55
|
+
---
|
56
|
+
|
57
|
+
## Upgrading from `v8.6` to `v9.0.0`
|
58
|
+
|
59
|
+
### Configuration change
|
60
|
+
|
61
|
+
Add an API version configuration in `config/initializers/shopify_app.rb`
|
62
|
+
Set this to the version you want to run against by default. See [Shopify API docs](https://help.shopify.com/en/api/versioning) for versions available.
|
63
|
+
```ruby
|
64
|
+
config.api_version = '2019-04'
|
65
|
+
```
|
66
|
+
|
67
|
+
### Session storage change
|
68
|
+
|
69
|
+
You will need to add an `api_version` method to your session storage object. The default implementation for this is.
|
70
|
+
```ruby
|
71
|
+
def api_version
|
72
|
+
ShopifyApp.configuration.api_version
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
### Generated file change
|
77
|
+
|
78
|
+
`embedded_app.html.erb` the usage of `shop_session.url` needs to be changed to `shop_session.domain`
|
79
|
+
```erb
|
80
|
+
<script type="text/javascript">
|
81
|
+
ShopifyApp.init({
|
82
|
+
apiKey: "<%= ShopifyApp.configuration.api_key %>",
|
83
|
+
|
84
|
+
shopOrigin: "<%= "https://#{ @shop_session.url }" if @shop_session %>",
|
85
|
+
|
86
|
+
debug: false,
|
87
|
+
forceRedirect: true
|
88
|
+
});
|
89
|
+
</script>
|
90
|
+
```
|
91
|
+
is changed to
|
92
|
+
```erb
|
93
|
+
<script type="text/javascript">
|
94
|
+
ShopifyApp.init({
|
95
|
+
apiKey: "<%= ShopifyApp.configuration.api_key %>",
|
96
|
+
|
97
|
+
shopOrigin: "<%= "https://#{ @shop_session.domain }" if @shop_session %>",
|
98
|
+
|
99
|
+
debug: false,
|
100
|
+
forceRedirect: true
|
101
|
+
});
|
102
|
+
</script>
|
103
|
+
```
|
104
|
+
|
105
|
+
### ShopifyAPI changes
|
106
|
+
|
107
|
+
You will need to also follow the ShopifyAPI [upgrade guide](https://github.com/Shopify/shopify_api/blob/master/README.md#-breaking-change-notice-for-version-700-) to ensure your app is ready to work with API versioning.
|
108
|
+
|
109
|
+
[dashboard]:https://partners.shopify.com
|
110
|
+
[app-bridge]:https://help.shopify.com/en/api/embedded-apps/app-bridge
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# Authentication
|
2
|
+
|
3
|
+
The Shopify App gem implements [OAuth 2.0](https://shopify.dev/tutorials/authenticate-with-oauth) to get [access tokens](https://shopify.dev/concepts/about-apis/authentication#api-access-modes). These are used to authenticate requests made by the app to the Shopify API.
|
4
|
+
|
5
|
+
By default, the gem generates an embedded app frontend that uses [Shopify App Bridge](https://shopify.dev/tools/app-bridge) to fetch [session tokens](https://shopify.dev/concepts/apps/building-embedded-apps-using-session-tokens). Session tokens are used by the embedded app to make authenticated requests to the app backend.
|
6
|
+
|
7
|
+
See [*Authenticate an embedded app using session tokens*](https://shopify.dev/tutorials/authenticate-your-app-using-session-tokens) to learn more.
|
8
|
+
|
9
|
+
> ⚠️ Be sure you understand the differences between the types of authentication schemes before reading this guide.
|
10
|
+
|
11
|
+
#### Table of contents
|
12
|
+
|
13
|
+
[OAuth callback](#oauth-callback)
|
14
|
+
|
15
|
+
[Run jobs after the OAuth flow](#run-jobs-after-the-oauth-flow)
|
16
|
+
|
17
|
+
[Rotate API credentials](#rotate-api-credentials)
|
18
|
+
|
19
|
+
[Available authentication mixins](#available-authentication-mixins)
|
20
|
+
* [`ShopifyApp::Authenticated`](#shopifyappauthenticated)
|
21
|
+
* [`ShopifyApp::EnsureAuthenticatedLinks`](#shopifyappensureauthenticatedlinks)
|
22
|
+
|
23
|
+
## OAuth callback
|
24
|
+
|
25
|
+
>️ **Note:** In Shopify App 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.
|
26
|
+
|
27
|
+
Upon completing the OAuth flow, Shopify calls the app at the `callback_path`. 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:
|
28
|
+
* Logging into the shop and resetting the session
|
29
|
+
* [Installing Webhooks](/docs/shopify_app/webhooks.md)
|
30
|
+
* [Setting Scripttags](/docs/shopify_app/script-tags.md)
|
31
|
+
* [Run jobs after the OAuth flow](#run-jobs-after-the-oauth-flow)
|
32
|
+
* Redirecting to the return address
|
33
|
+
|
34
|
+
## Run jobs after the OAuth flow
|
35
|
+
|
36
|
+
See [`ShopifyApp::AfterAuthenticateJob`](/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb).
|
37
|
+
|
38
|
+
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:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
ShopifyApp.configure do |config|
|
42
|
+
config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob" }
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
The job can be configured as either a class or a class name string.
|
47
|
+
|
48
|
+
If you need the job to run synchronously add the `inline` flag:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
ShopifyApp.configure do |config|
|
52
|
+
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true }
|
53
|
+
end
|
54
|
+
```
|
55
|
+
|
56
|
+
We've also provided a generator which creates a skeleton job and updates the initializer for you:
|
57
|
+
|
58
|
+
```
|
59
|
+
bin/rails g shopify_app:add_after_authenticate_job
|
60
|
+
```
|
61
|
+
|
62
|
+
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.
|
63
|
+
|
64
|
+
## Rotate API credentials
|
65
|
+
|
66
|
+
If your Shopify secret key is leaked, you can use the RotateShopifyTokenJob to perform [API Credential Rotation](https://help.shopify.com/en/api/getting-started/authentication/oauth/api-credential-rotation).
|
67
|
+
|
68
|
+
Before running the job, you'll need to generate a new secret key from your Shopify Partner dashboard, and update the `/config/initializers/shopify_app.rb` to hold your new and old secret keys:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
config.secret = Rails.application.secrets.shopify_secret
|
72
|
+
config.old_secret = Rails.application.secrets.old_shopify_secret
|
73
|
+
```
|
74
|
+
|
75
|
+
We've provided a generator which creates the job and an example rake task:
|
76
|
+
|
77
|
+
```sh
|
78
|
+
bin/rails g shopify_app:rotate_shopify_token_job
|
79
|
+
```
|
80
|
+
|
81
|
+
The generated rake task will be found at `lib/tasks/shopify/rotate_shopify_token.rake` and is provided strictly for example purposes. It might not work with your application out of the box without some configuration.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
85
|
+
```
|
86
|
+
|
87
|
+
> **Note:** If you are updating `shopify_app` from a version prior to 8.4.2 (and do not wish to run the default/install generator again), you will need to add [the following line](https://github.com/Shopify/shopify_app/blob/4f7e6cca2a472d8f7af44b938bd0fcafe4d8e88a/lib/generators/shopify_app/install/templates/shopify_provider.rb#L18) to `config/initializers/omniauth.rb`:
|
88
|
+
|
89
|
+
## Available authentication mixins
|
90
|
+
|
91
|
+
### `ShopifyApp::Authenticated`
|
92
|
+
|
93
|
+
The engine provides a [`ShopifyApp::Authenticated`](/app/controllers/concerns/shopify_app/authenticated.rb) concern which should be included in any controller that is intended to be behind Shopify OAuth. It adds `before_action`s to ensure that the user is authenticated and will redirect to the Shopify login page if not. It is best practice to include this concern in a base controller inheriting from your `ApplicationController`, from which all controllers that require Shopify authentication inherit.
|
94
|
+
|
95
|
+
*Example:*
|
96
|
+
|
97
|
+
```rb
|
98
|
+
class AuthenticatedController < ApplicationController
|
99
|
+
include ShopifyApp::Authenticated
|
100
|
+
end
|
101
|
+
|
102
|
+
class ApiController < AuthenticatedController
|
103
|
+
# Actions in this controller are protected
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
For backwards compatibility, the engine still provides a controller called `ShopifyApp::AuthenticatedController` which includes the `ShopifyApp::Authenticated` concern. Note that it inherits directly from `ActionController::Base`, so you will not be able to share functionality between it and your application's `ApplicationController`.
|
108
|
+
|
109
|
+
### `ShopifyApp::EnsureAuthenticatedLinks`
|
110
|
+
|
111
|
+
The [`ShopifyApp::EnsureAuthenticatedLinks`](/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb) concern helps authenticate users that access protected pages of your app directly.
|
112
|
+
|
113
|
+
Include this concern in your app's `AuthenticatedController` if your app uses session tokens with [Turbolinks](https://github.com/turbolinks/turbolinks). It adds a `before_action` filter that detects whether a session token is present or not. If a session token is not found, the user is redirected to your app's splash page path (`root_path`) along with `return_to` and `shop` parameters.
|
114
|
+
|
115
|
+
*Example:*
|
116
|
+
|
117
|
+
```rb
|
118
|
+
class AuthenticatedController < ApplicationController
|
119
|
+
include ShopifyApp::EnsureAuthenticatedLinks
|
120
|
+
include ShopifyApp::Authenticated
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
See [Authenticate server-side rendered embedded apps using Rails and Turbolinks](https://shopify.dev/tutorials/authenticate-server-side-rendered-embedded-apps-using-rails-and-turbolinks) for more information.
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Engine
|
2
|
+
|
3
|
+
#### Table of contents
|
4
|
+
|
5
|
+
[Customize the app login URL](#customize-the-app-login-url)
|
6
|
+
|
7
|
+
[Mount the Shopify App engine at nested routes](#mount-the-shopify-app-engine-at-nested-routes)
|
8
|
+
|
9
|
+
[Verify HTTP requests sent via an app proxy](#verify-http-requests-sent-via-an-app-proxy)
|
10
|
+
* [Recommended usage of `ShopifyApp::AppProxyVerification`](#recommended-usage-of-shopifyappappproxyverification)
|
11
|
+
|
12
|
+
## Customize the app login URL
|
13
|
+
|
14
|
+
While you can customize the login view by creating a `/app/views/shopify_app/sessions/new.html.erb` file, you may also want to customize the URL entirely. You can modify your `shopify_app.rb` initializer to provide a custom `login_url` e.g.:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
ShopifyApp.configure do |config|
|
18
|
+
config.login_url = 'https://my.domain.com/nested/login'
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
## Mount the Shopify App engine at nested routes
|
23
|
+
|
24
|
+
The engine may also be mounted at a nested route, for example:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
mount ShopifyApp::Engine, at: '/nested'
|
28
|
+
```
|
29
|
+
|
30
|
+
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.:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
ShopifyApp.configure do |config|
|
34
|
+
config.root_url = '/nested'
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
then update the omniauth initializer to include a custom `callback_path` e.g.:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
provider :shopify,
|
42
|
+
ShopifyApp.configuration.api_key,
|
43
|
+
ShopifyApp.configuration.secret,
|
44
|
+
scope: ShopifyApp.configuration.scope,
|
45
|
+
callback_path: '/nested/auth/shopify/callback'
|
46
|
+
```
|
47
|
+
|
48
|
+
You may also need to change your `config/routes.rb` to render a view for `/nested`, since this is what will be rendered in the Shopify Admin of any shops that have installed your app. The engine itself doesn't have a view for this, so you'll need something like this:
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# config/routes.rb
|
52
|
+
Rails.application.routes.draw do
|
53
|
+
root :to => 'something_else#index'
|
54
|
+
get "/nested", to: "home#index"
|
55
|
+
mount ShopifyApp::Engine, at: '/nested'
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
Finally, note that if you do this, to add your app to a store, you must navigate to `/nested` in order to render the `Enter your shop domain to log in or install this app.` UI.
|
60
|
+
|
61
|
+
## Verify HTTP requests sent via an app proxy
|
62
|
+
|
63
|
+
See [`ShopifyApp::AppProxyVerification`](/lib/shopify_app/controller_concerns/app_proxy_verification.rb).
|
64
|
+
|
65
|
+
The engine provides a mixin for verifying incoming HTTP requests sent via an App Proxy. Any controller that `include`s `ShopifyApp::AppProxyVerification` will verify that each request has a valid `signature` query parameter that is calculated using the other query parameters and the app's shared secret.
|
66
|
+
|
67
|
+
### Recommended usage of `ShopifyApp::AppProxyVerification`
|
68
|
+
|
69
|
+
The App Proxy Controller Generator automatically adds the mixin to the generated app_proxy_controller.rb
|
70
|
+
Additional controllers for resources within the App_Proxy namespace, will need to include the mixin like so:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# app/controllers/app_proxy/reviews_controller.rb
|
74
|
+
class ReviewsController < ApplicationController
|
75
|
+
include ShopifyApp::AppProxyVerification
|
76
|
+
# ...
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
Create your app proxy URL in the [Shopify Partners dashboard](https://partners.shopify.com/organizations), making sure to point it to `https://your_app_website.com/app_proxy`.
|
81
|
+
|
82
|
+
![Creating an App Proxy](/images/app-proxy-screenshot.png)
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Generators
|
2
|
+
|
3
|
+
> Listed below are the generators currently offered by the Shopify App gem. To learn more about how this gem creates an embedded app, start with the [default Shopify App generator](#-environment-rails-generate-shopify_app).
|
4
|
+
|
5
|
+
---
|
6
|
+
|
7
|
+
#### `$ [environment] rails generate shopify_app`
|
8
|
+
|
9
|
+
The default generator will run the [`install`](#-rails-generate-shopify_appinstall-flags), [`shop_model`](#-rails-generate-shopify_appshop_model), [`authenticated_controller`](#-rails-generate-shopify_appauthenticated_controller), and [`home_controller`](#-rails-generate-shopify_apphome_controller-flags) generators. This is the recommended way to start a new app from scratch.
|
10
|
+
|
11
|
+
##### Environment
|
12
|
+
|
13
|
+
###### `SHOPIFY_APP_DISABLE_WEBPACKER`
|
14
|
+
|
15
|
+
**[Optional]** Specify this environment variable if your app uses sprockets with Rails 6 or to generate a Shopify App without webpacker.
|
16
|
+
|
17
|
+
*Example:*
|
18
|
+
|
19
|
+
Run:
|
20
|
+
|
21
|
+
```terminal
|
22
|
+
$ SHOPIFY_APP_DISABLE_WEBPACKER=1 rails generate shopify_app
|
23
|
+
```
|
24
|
+
|
25
|
+
Add the following code to your ShopifyApp configuration block:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
ShopifyApp.configure do |config|
|
29
|
+
config.disable_webpacker = true
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
---
|
34
|
+
|
35
|
+
#### `$ rails generate shopify_app:install [flags]`
|
36
|
+
|
37
|
+
This generator adds ShopifyApp and the required initializers to the host Rails application. You can update any of these settings later.
|
38
|
+
|
39
|
+
##### Flags
|
40
|
+
|
41
|
+
###### `--application_name`
|
42
|
+
|
43
|
+
The name of your app. The flag can be supplied with or without double-quotes.
|
44
|
+
|
45
|
+
*Example:* `--application_name "My Shopify App"`
|
46
|
+
|
47
|
+
###### `--scope`
|
48
|
+
|
49
|
+
The [OAuth access scope(s)](https://shopify.dev/docs/admin-api/access-scopes) required by your app. Delimit multiple access scopes using a comma-space. The flag can be supplied with or without double-quotes.
|
50
|
+
|
51
|
+
*Example:* `--scope read_products, write_orders`
|
52
|
+
|
53
|
+
*Example:* `--scope "read_products, write_orders"`
|
54
|
+
|
55
|
+
###### `--embedded`
|
56
|
+
|
57
|
+
Specify whether the app is an embedded app. Apps are embedded by default.
|
58
|
+
|
59
|
+
*Example:* `--embedded false`
|
60
|
+
|
61
|
+
###### `--with-cookie-authentication`
|
62
|
+
|
63
|
+
**[Not recommended]** Specify whether the app uses cookies to authenticate. By default, the app is configured to use [session tokens](https://shopify.dev/concepts/apps/building-embedded-apps-using-session-tokens).
|
64
|
+
|
65
|
+
*Example:* `--with-cookie-authentication true`
|
66
|
+
|
67
|
+
---
|
68
|
+
|
69
|
+
#### `$ rails generate shopify_app:shop_model`
|
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.
|
72
|
+
|
73
|
+
---
|
74
|
+
|
75
|
+
#### `$ rails generate shopify_app:user_model`
|
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.
|
78
|
+
|
79
|
+
---
|
80
|
+
|
81
|
+
#### `$ rails generate shopify_app:authenticated_controller`
|
82
|
+
|
83
|
+
This generator creates a sample authenticated controller. By default, inheriting from this controller protects your app controllers using session tokens. See [*Authentication*](/docs/shopify_app/authentication.md) to learn more.
|
84
|
+
|
85
|
+
---
|
86
|
+
|
87
|
+
#### `$ rails generate shopify_app:home_controller [flags]`
|
88
|
+
|
89
|
+
This generator creates a sample home controller with a view that displays a shop's products. This generator also runs the [`products_controller`](#-rails-generate-shopify_appproducts_controller) generator.
|
90
|
+
|
91
|
+
##### Flags
|
92
|
+
|
93
|
+
###### `--with-cookie-authentication`
|
94
|
+
|
95
|
+
**[Not recommended]** This flag generates an authenticated home controller. Use this flag only if your app uses cookies to authenticate. By default, the home controller is unauthenticated.
|
96
|
+
|
97
|
+
---
|
98
|
+
|
99
|
+
#### `$ rails generate shopify_app:products_controller`
|
100
|
+
|
101
|
+
This generator creates a sample products API controller to fetch products using the Shopify REST API.
|
102
|
+
|
103
|
+
---
|
104
|
+
|
105
|
+
#### `$ rails generate shopify_app:add_after_authenticate_job`
|
106
|
+
|
107
|
+
**[Optional]** This generator creates a skeleton job that runs after the OAuth authorization flow. See [*Run jobs after the OAuth flow*](/docs/shopify_app/authentication.md#run-jobs-after-the-oauth-flow) for more information.
|
108
|
+
|
109
|
+
---
|
110
|
+
|
111
|
+
#### `$ rails generate shopify_app:app_proxy_controller`
|
112
|
+
|
113
|
+
**[Optional]** This generator creates the app proxy controller to handle proxy requests to the app from your shop storefront. It also modifies 'config/routes.rb' with a namespace route and creates a sample view that displays current shop information using the LiquidAPI. See [*Verify HTTP requests sent via an app proxy*](/docs/shopify_app/engine.md#verify-http-requests-sent-via-an-app-proxy) for more information.
|
114
|
+
|
115
|
+
---
|
116
|
+
|
117
|
+
#### `$ rails generate shopify_app:marketing_activity_extension`
|
118
|
+
|
119
|
+
**[Optional]** This generator creates a controller with the endpoints required to build a [marketing activities extension](https://shopify.dev/docs/marketing-activities). The extension is generated with the base URL `/marketing_activities`. This URL would need to be configured in the Shopify Partners dashboard.
|
120
|
+
|
121
|
+
---
|
122
|
+
|
123
|
+
#### `$ rails generate shopify_app:controllers`
|
124
|
+
|
125
|
+
**[Optional]** This generator is for your convenience. Run this generator if you would like to override code that is part of the Shopify App Rails engine.
|
126
|
+
|
127
|
+
*Example:* The Shopify App Rails engine provides a sample [`SessionsController`](/app/controllers/shopify_app/sessions_controller.rb). Running this generator copies this controller to your app so you can begin extending it. Routes and views follow the same pattern.
|