shopify_app 7.4.0 → 8.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.babelrc +5 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/probots.yml +2 -0
- data/.gitignore +5 -0
- data/.nvmrc +1 -0
- data/.rubocop.yml +10 -0
- data/.ruby-version +1 -0
- data/.travis.yml +26 -3
- data/CHANGELOG.md +95 -0
- data/Gemfile +2 -0
- data/README.md +113 -56
- data/app/assets/images/storage_access.svg +2 -0
- data/app/assets/javascripts/shopify_app/enable_cookies.js +3 -0
- data/app/assets/javascripts/shopify_app/itp_helper.js +40 -0
- data/app/assets/javascripts/shopify_app/partition_cookies.js +7 -0
- data/app/assets/javascripts/shopify_app/redirect.js +33 -0
- data/app/assets/javascripts/shopify_app/request_storage_access.js +3 -0
- data/app/assets/javascripts/shopify_app/storage_access.js +121 -0
- data/app/assets/javascripts/shopify_app/storage_access_redirect.js +17 -0
- data/app/assets/javascripts/shopify_app/top_level.js +2 -0
- data/app/assets/javascripts/shopify_app/top_level_interaction.js +11 -0
- data/app/controllers/shopify_app/authenticated_controller.rb +3 -4
- data/{lib/shopify_app/sessions_concern.rb → app/controllers/shopify_app/callback_controller.rb} +27 -38
- data/app/controllers/shopify_app/sessions_controller.rb +120 -2
- data/app/controllers/shopify_app/webhooks_controller.rb +11 -3
- data/app/views/shopify_app/partials/_button_styles.html.erb +104 -0
- data/app/views/shopify_app/partials/_card_styles.html.erb +33 -0
- data/app/views/shopify_app/partials/_empty_state_styles.html.erb +129 -0
- data/app/views/shopify_app/partials/_layout_styles.html.erb +167 -0
- data/app/views/shopify_app/partials/_typography_styles.html.erb +35 -0
- data/app/views/shopify_app/sessions/enable_cookies.html.erb +59 -0
- data/app/views/shopify_app/sessions/new.html.erb +88 -60
- data/app/views/shopify_app/sessions/request_storage_access.html.erb +67 -0
- data/app/views/shopify_app/sessions/top_level_interaction.html.erb +63 -0
- data/app/views/shopify_app/shared/redirect.html.erb +22 -0
- data/config/locales/de.yml +21 -2
- data/config/locales/en.yml +12 -0
- data/config/locales/es.yml +21 -2
- data/config/locales/fr.yml +22 -2
- data/config/locales/it.yml +22 -0
- data/config/locales/ja.yml +16 -2
- data/config/locales/nl.yml +21 -0
- data/config/locales/pt-BR.yml +22 -0
- data/config/locales/zh-CN.yml +16 -0
- data/config/locales/zh-TW.yml +17 -0
- data/config/routes.rb +11 -1
- data/docs/Quickstart.md +26 -23
- data/docs/Releasing.md +1 -0
- data/karma.conf.js +43 -0
- data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +3 -1
- data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +1 -0
- data/lib/generators/shopify_app/home_controller/templates/index.html.erb +14 -0
- data/lib/generators/shopify_app/home_controller/templates/shopify_app_ready_script.html.erb +1 -5
- data/lib/generators/shopify_app/install/install_generator.rb +3 -13
- data/lib/generators/shopify_app/install/templates/_flash_messages.html.erb +13 -9
- data/lib/generators/shopify_app/install/templates/shopify_app.rb +4 -1
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +19 -4
- data/lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb +16 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake +17 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +42 -0
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +3 -3
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +0 -1
- data/lib/shopify_app.rb +21 -17
- data/lib/shopify_app/configuration.rb +26 -8
- data/lib/shopify_app/{app_proxy_verification.rb → controller_concerns/app_proxy_verification.rb} +1 -1
- data/lib/shopify_app/controller_concerns/embedded_app.rb +19 -0
- data/lib/shopify_app/controller_concerns/itp.rb +45 -0
- data/lib/shopify_app/{localization.rb → controller_concerns/localization.rb} +6 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +135 -0
- data/lib/shopify_app/{webhook_verification.rb → controller_concerns/webhook_verification.rb} +10 -6
- data/lib/shopify_app/engine.rb +10 -0
- data/lib/shopify_app/{scripttags_manager_job.rb → jobs/scripttags_manager_job.rb} +0 -0
- data/lib/shopify_app/{webhooks_manager_job.rb → jobs/webhooks_manager_job.rb} +0 -0
- data/lib/shopify_app/{scripttags_manager.rb → managers/scripttags_manager.rb} +0 -0
- data/lib/shopify_app/{webhooks_manager.rb → managers/webhooks_manager.rb} +0 -0
- data/lib/shopify_app/session/in_memory_session_store.rb +27 -0
- data/lib/shopify_app/{shopify_session_repository.rb → session/session_repository.rb} +0 -0
- data/lib/shopify_app/{session_storage.rb → session/session_storage.rb} +9 -0
- data/lib/shopify_app/utils.rb +2 -2
- data/lib/shopify_app/version.rb +1 -1
- data/package-lock.json +23 -0
- data/package.json +28 -0
- data/service.yml +7 -0
- data/shipit.rubygems.yml +2 -0
- data/shopify_app.gemspec +5 -4
- data/translation.yml +7 -0
- data/webpack.config.js +24 -0
- data/yarn.lock +4594 -0
- metadata +80 -27
- data/lib/generators/shopify_app/install/templates/shopify_session_repository.rb +0 -23
- data/lib/generators/shopify_app/shop_model/templates/shopify_session_repository.rb +0 -9
- data/lib/shopify_app/in_memory_session_store.rb +0 -25
- data/lib/shopify_app/login_protection.rb +0 -119
- data/lib/shopify_app/shop.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8fe2949f5e38db4532dbcab3c05f96e228e6285fdbb4b729ffefecd8e40b2aad
|
4
|
+
data.tar.gz: 2fefc3ce45bc58cd82c874d5217f6abfce0a70ba56cb9105084dbec011f033cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a435b2541e5198fad47a247a97b2a68ce6e741b2b29a4b0b7f2cc29d256fc382a7fd8a56801e982744258e9efdfd3879a13dd4dffc033c88d432ce44d525e44
|
7
|
+
data.tar.gz: 1df140b61ca82e090eba2fcabac5f079cc5d87e7cb64bab657cbc725ff1063360fbd88822d4ed76c9224d2fd4e9429ba197dd3c7f6a6312b3c8dbdb060c35f26
|
data/.github/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @shopify/platform-dev-tools-education
|
data/.github/probots.yml
ADDED
data/.gitignore
CHANGED
data/.nvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
8.10.0
|
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.0
|
data/.travis.yml
CHANGED
@@ -1,6 +1,29 @@
|
|
1
|
+
sudo: required
|
2
|
+
dist: trusty
|
3
|
+
addons:
|
4
|
+
chrome: stable
|
5
|
+
before_script:
|
6
|
+
- "sudo chown root /opt/google/chrome/chrome-sandbox"
|
7
|
+
- "sudo chmod 4755 /opt/google/chrome/chrome-sandbox"
|
1
8
|
language: ruby
|
2
|
-
|
3
|
-
|
9
|
+
before_install:
|
10
|
+
- gem update --system
|
11
|
+
cache:
|
12
|
+
bundler: true
|
13
|
+
directories:
|
14
|
+
- node_modules
|
15
|
+
yarn: true
|
4
16
|
|
5
17
|
rvm:
|
6
|
-
- 2.3.
|
18
|
+
- 2.3.6
|
19
|
+
- 2.4.3
|
20
|
+
- 2.5.0
|
21
|
+
|
22
|
+
install:
|
23
|
+
- bundle install
|
24
|
+
- nvm install node
|
25
|
+
- yarn
|
26
|
+
|
27
|
+
script:
|
28
|
+
- yarn test
|
29
|
+
- bundle exec rake test
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,104 @@
|
|
1
|
+
8.5.0
|
2
|
+
-----
|
3
|
+
Added support for rotating Shopify access tokens:
|
4
|
+
|
5
|
+
* Added a generator shopify_app:rotate_shopify_token_job for generating the job to perform token rotation
|
6
|
+
* Extend Shopify app configuration to support a new and old secret token
|
7
|
+
* Extended webhook validation code to support validating against new and old secret tokens
|
8
|
+
* See the README for more details: https://github.com/Shopify/shopify_app#rotateshopifytokenjob
|
9
|
+
|
10
|
+
8.4.2
|
11
|
+
-----
|
12
|
+
* Clear stale user session during auth callback
|
13
|
+
|
14
|
+
8.4.1
|
15
|
+
-----
|
16
|
+
* Update README and Releasing.md
|
17
|
+
* Allow user agent to not be set
|
18
|
+
* Remove legacy EASDK examples
|
19
|
+
* Add .ruby-version file
|
20
|
+
* Clean up omniauth setup and fix examples
|
21
|
+
* Fix infinite redirect loops if users have disabled 3rd party cookies in their browser
|
22
|
+
|
23
|
+
8.4.0
|
24
|
+
----
|
25
|
+
* Fix embedded app session management in Safari 12.1
|
26
|
+
* Shop names passed to OAuth are no longer case sensitive
|
27
|
+
|
28
|
+
8.3.2
|
29
|
+
----
|
30
|
+
* Removes `read_orders` from the default scopes provided upon app generation
|
31
|
+
|
32
|
+
8.3.1
|
33
|
+
----
|
34
|
+
* Adds the ability to customize the login URL through the initializer
|
35
|
+
|
36
|
+
8.3.0
|
37
|
+
----
|
38
|
+
* Fix embedded app session management in Safari 12
|
39
|
+
* Add support for translation platform
|
40
|
+
|
41
|
+
8.2.6
|
42
|
+
----
|
43
|
+
* Sanitize the shop query param to include `.myshopify.com` if no domain was provided
|
44
|
+
|
45
|
+
8.2.5
|
46
|
+
----
|
47
|
+
* fix iframe headers on session controller
|
48
|
+
|
49
|
+
8.2.4
|
50
|
+
-----
|
51
|
+
* Add CSRF protection through `protect_from_forgery with: :exception` on `ShopifyApp::AuthenticatedController`
|
52
|
+
|
53
|
+
8.2.3
|
54
|
+
-----
|
55
|
+
* Send head :forbidden instead of :unauthorized when AppProxyVerification fails
|
56
|
+
|
57
|
+
8.2.2
|
58
|
+
-----
|
59
|
+
* Changes how the ESDK concern allows iframes. Fixes an issue with the first request for some people
|
60
|
+
|
61
|
+
8.2.1
|
62
|
+
-----
|
63
|
+
* Bugfix: Don't logout shops from `login_again_if_different_shop` when Rails
|
64
|
+
params for a 'Shop' model are passed in [[#477]](https://github.com/Shopify/shopify_app/pull/477)
|
65
|
+
|
66
|
+
8.2.0
|
67
|
+
-----
|
68
|
+
Known bug: Shop logged out when submitting a form for 'Shop' objects, fixed in 8.2.1 [[See #480 for details]](https://github.com/Shopify/shopify_app/issues/480)
|
69
|
+
|
70
|
+
* Add `webhook_jobs_namespace` config option. [[#463]](https://github.com/Shopify/shopify_app/pull/463)
|
71
|
+
* Updates login page styles to match the [Polaris](https://polaris.shopify.com/) design system. [[#474]](https://github.com/Shopify/shopify_app/pull/474)
|
72
|
+
|
73
|
+
8.1.0
|
74
|
+
-----
|
75
|
+
Known bug: Shop logged out when submitting a form for 'Shop' objects, fixed in 8.2.1 [[See #480 for details]](https://github.com/Shopify/shopify_app/issues/480)
|
76
|
+
|
77
|
+
* Add support for per_user_authentication
|
78
|
+
* Pass the shop param in the session for authentication instead of a url param (prevents csrf). If you are upgrading from an older version of the gem you will need to update your omniauth.rb initializer file. Check the example app for what it what it should look like.
|
79
|
+
|
80
|
+
8.0.0
|
81
|
+
-----
|
82
|
+
Known bug: Shop logged out when submitting a form for 'Shop' objects, fixed in 8.2.1 [[See #480 for details]](https://github.com/Shopify/shopify_app/issues/480)
|
83
|
+
|
84
|
+
* Removed the `shopify_session_repository` initializer. The SessionRepository is now configured through the main ShopifyApp configuration object and the generated initializer
|
85
|
+
* Moved InMemorySessionStore into the ShopifyApp namespace
|
86
|
+
* Remove ShopifySession concern. This module made the code internal to this engine harder to follow and we want to discourage over-writing the auth code now that we have generic hooks for all extra tasks during install.
|
87
|
+
* Changed engine controllers to subclass ActionController::Base to avoid any possible conflict with the parent application
|
88
|
+
* Removed the `ShopifyApp::Shop` concern and added its methods to `ShopifyApp::SessionStorage`. To update for this change just remove this concern anywhere it is being used in your application.
|
89
|
+
* Add `ShopifyApp::EmbeddedApp` controller concern which handles setting the required headers for the ESDK. Previously this was done by injecting configuration into applicaton.rb which affects the entire app.
|
90
|
+
* Add webhooks to generated home controller. This should help new users debug issues.
|
91
|
+
|
1
92
|
7.4.0
|
2
93
|
-----
|
94
|
+
Known bug: Shop logged out when submitting a form for 'Shop' objects, fixed in 8.2.1 [[See #480 for details]](https://github.com/Shopify/shopify_app/issues/480)
|
95
|
+
|
3
96
|
* Add an after_authenticate job which will be run once the shop is authenticated. [[#431]](https://github.com/Shopify/shopify_app/pull/432)
|
4
97
|
|
5
98
|
7.3.0
|
6
99
|
-----
|
100
|
+
Known bug: Shop logged out when submitting a form for 'Shop' objects, fixed in 8.2.1 [[See #480 for details]](https://github.com/Shopify/shopify_app/issues/480)
|
101
|
+
|
7
102
|
* Bump required omniauth-shopify-oauth2 version to 1.2.0.
|
8
103
|
* Always expect params[:shop] to be a string.
|
9
104
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -8,12 +8,14 @@ Shopify App
|
|
8
8
|
|
9
9
|
Shopify Application Rails engine and generator
|
10
10
|
|
11
|
+
#### NOTE : Versions 8.0.0 through 8.2.3 contained a CSRF vulnerability that was addressed in version 8.2.4. Please update to version 8.2.4 if you're using an old version.
|
11
12
|
|
12
13
|
Table of Contents
|
13
14
|
-----------------
|
14
15
|
* [**Description**](#description)
|
15
16
|
* [**Quickstart**](#quickstart)
|
16
17
|
* [**Becoming a Shopify App Developer**](#becoming-a-shopify-app-developer)
|
18
|
+
* [**App Tunneling**](#app-tunneling)
|
17
19
|
* [**Installation**](#installation)
|
18
20
|
* [Rails Compatibility](#rails-compatibility)
|
19
21
|
* [**Generators**](#generators)
|
@@ -35,7 +37,6 @@ Table of Contents
|
|
35
37
|
* [**Troubleshooting**](#troubleshooting)
|
36
38
|
* [Generator shopify_app:install hangs](#generator-shopify_appinstall-hangs)
|
37
39
|
* [**Testing an embedded app outside the Shopify admin**](#testing-an-embedded-app-outside-the-shopify-admin)
|
38
|
-
* [**App Tunneling**](#app-tunneling)
|
39
40
|
* [**Questions or problems?**](#questions-or-problems)
|
40
41
|
|
41
42
|
|
@@ -53,30 +54,26 @@ Quickstart
|
|
53
54
|
|
54
55
|
Check out this screencast on how to create and deploy a new Shopify App to Heroku in 5 minutes:
|
55
56
|
|
56
|
-
[https://
|
57
|
+
[https://www.youtube.com/watch?v=yGxeoAHlQOg](https://www.youtube.com/watch?v=yGxeoAHlQOg)
|
57
58
|
|
58
59
|
Or if you prefer text instructions the steps in the video are written out [here](https://github.com/Shopify/shopify_app/blob/master/docs/Quickstart.md)
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
If you don't have a Shopify Partner account yet head over to http://shopify.com/partners to create one, you'll need it before you can start developing apps.
|
63
|
-
|
64
|
-
Once you have a Partner account create a new application to get an Api key and other Api credentials. To create a development application set the Application Callback URL to
|
61
|
+
App Tunneling
|
62
|
+
-------------
|
65
63
|
|
66
|
-
|
67
|
-
http://localhost:3000/
|
68
|
-
```
|
64
|
+
Your local app needs to be accessible from the public Internet in order to install it on a shop, use the [App Proxy Controller](#app-proxy-controller-generator) or receive Webhooks. Use a tunneling service like [ngrok](https://ngrok.com/), [Forward](https://forwardhq.com/), [Beeceptor](https://beeceptor.com/), [Mockbin](http://mockbin.org/), [Hookbin](https://hookbin.com/), etc.
|
69
65
|
|
70
|
-
|
66
|
+
For example with [ngrok](https://ngrok.com/), run this command to set up proxying to Rails' default port:
|
71
67
|
|
72
|
-
```
|
73
|
-
http
|
68
|
+
```sh
|
69
|
+
ngrok http 3000
|
74
70
|
```
|
75
71
|
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
Becoming a Shopify App Developer
|
73
|
+
--------------------------------
|
74
|
+
If you don't have a Shopify Partner account yet head over to http://shopify.com/partners to create one, you'll need it before you can start developing apps.
|
79
75
|
|
76
|
+
Once you have a Partner account create a new application to get an API key and other API credentials. To create a development application set the `App URL` to the URL provided by [your tunnel](#app-tunneling) or `http://localhost:3000/` if you are not embeddeding your app inside the admin or receiving webhooks and the `Whitelisted redirection URL(s)` to contain `<App URL>/auth/shopify/callback`. Ensure you are using `https://` URLs if you are using tunneling.
|
80
77
|
|
81
78
|
Installation
|
82
79
|
------------
|
@@ -111,6 +108,7 @@ The default generator will run the `install`, `shop`, and `home_controller` gene
|
|
111
108
|
$ rails generate shopify_app --api_key <your_api_key> --secret <your_app_secret>
|
112
109
|
```
|
113
110
|
|
111
|
+
After running the generator, you will need to run `rake db:migrate` to add tables to your database. You can start your app with `bundle exec rails server` and install your app by visiting localhost.
|
114
112
|
|
115
113
|
### Install Generator
|
116
114
|
|
@@ -123,9 +121,9 @@ $ rails generate shopify_app:install --api_key <your_api_key> --secret <your_app
|
|
123
121
|
```
|
124
122
|
|
125
123
|
Other options include:
|
126
|
-
* `application_name` - the name of your app, it can be supplied with or without double-quotes if a whitespace is present. (e.g. `--application_name Example App` or `--application_name "Example App"`)
|
127
|
-
* `scope` - the Oauth access scope required for your app, eg **read_products, write_orders**. *Multiple options* need to be delimited by a comma-space, and can be supplied with or without double-quotes
|
128
|
-
(e.g. `--scope read_products, write_orders, write_products` or `--scope "read_products, write_orders, write_products"`)
|
124
|
+
* `application_name` - the name of your app, it can be supplied with or without double-quotes if a whitespace is present. (e.g. `--application_name Example App` or `--application_name "Example App"`)
|
125
|
+
* `scope` - the Oauth access scope required for your app, eg **read_products, write_orders**. *Multiple options* need to be delimited by a comma-space, and can be supplied with or without double-quotes
|
126
|
+
(e.g. `--scope read_products, write_orders, write_products` or `--scope "read_products, write_orders, write_products"`)
|
129
127
|
For more information, refer the [docs](http://docs.shopify.com/api/tutorials/oauth).
|
130
128
|
* `embedded` - the default is to generate an [embedded app](http://docs.shopify.com/embedded-app-sdk), if you want a legacy non-embedded app then set this to false, `--embedded false`
|
131
129
|
|
@@ -142,7 +140,7 @@ After running the `install` generator, you can start your app with `bundle exec
|
|
142
140
|
$ rails generate shopify_app:shop_model
|
143
141
|
```
|
144
142
|
|
145
|
-
The install generator doesn't create any database models for you
|
143
|
+
The `install` generator doesn't create any database tables or models for you. If you are starting a new app its quite likely that you will want a shops table and model to store the tokens when your app is installed (most of our internally developed apps do!). This generator creates a shop model and a migration. This model includes the `ShopifyApp::SessionStorage` concern which adds two methods to make it compatible as a `SessionRepository`. After running this generator you'll notice the `session_repository` in your `config/initializers/shopify_app.rb` will be set to the `Shop` model. This means that internally ShopifyApp will try and load tokens from this model.
|
146
144
|
|
147
145
|
*Note that you will need to run rake db:migrate after this generator*
|
148
146
|
|
@@ -172,7 +170,7 @@ The last group of generators are for your convenience if you want to start overr
|
|
172
170
|
Mounting the Engine
|
173
171
|
-------------------
|
174
172
|
|
175
|
-
Mounting the Engine will provide the basic routes to authenticating a shop with your
|
173
|
+
Mounting the Engine will provide the basic routes to authenticating a shop with your application. By default it will provide:
|
176
174
|
|
177
175
|
| Verb | Route | Action |
|
178
176
|
|--------|-------------------------------|------------------------------|
|
@@ -182,31 +180,58 @@ Mounting the Engine will provide the basic routes to authenticating a shop with
|
|
182
180
|
|GET |'/logout' |Logout |
|
183
181
|
|POST |'/webhooks/:type' |Webhook Callback |
|
184
182
|
|
183
|
+
### Nested Routes
|
185
184
|
|
186
|
-
The
|
185
|
+
The engine may also be mounted at a nested route, for example:
|
187
186
|
|
188
187
|
```ruby
|
189
188
|
mount ShopifyApp::Engine, at: '/nested'
|
190
189
|
```
|
191
190
|
|
192
|
-
This will create the Shopify engine routes under the specified subpath
|
191
|
+
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.:
|
193
192
|
|
194
193
|
```ruby
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
scope: ShopifyApp.configuration.scope,
|
199
|
-
callback_path: '/nested/auth/shopify/callback'
|
194
|
+
ShopifyApp.configure do |config|
|
195
|
+
config.root_url = '/nested'
|
196
|
+
end
|
200
197
|
```
|
201
198
|
|
202
|
-
|
199
|
+
then update the omniauth initializer to include a custom `callback_path` e.g.:
|
203
200
|
|
204
201
|
```ruby
|
205
|
-
|
202
|
+
provider :shopify,
|
203
|
+
ShopifyApp.configuration.api_key,
|
204
|
+
ShopifyApp.configuration.secret,
|
205
|
+
scope: ShopifyApp.configuration.scope,
|
206
|
+
callback_path: '/nested/auth/shopify/callback'
|
207
|
+
```
|
208
|
+
|
209
|
+
### Custom login URL
|
206
210
|
|
207
|
-
shopify_app.
|
211
|
+
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.:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
ShopifyApp.configure do |config|
|
215
|
+
config.login_url = 'https://my.domain.com/nested/login'
|
216
|
+
end
|
208
217
|
```
|
209
218
|
|
219
|
+
Per User Authentication
|
220
|
+
-----------------------
|
221
|
+
To enable per user authentication you need to update the `omniauth.rb` initializer:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
provider :shopify,
|
225
|
+
ShopifyApp.configuration.api_key,
|
226
|
+
ShopifyApp.configuration.secret,
|
227
|
+
scope: ShopifyApp.configuration.scope,
|
228
|
+
per_user_permissions: true
|
229
|
+
```
|
230
|
+
|
231
|
+
The current Shopify user will be stored in the rails session at `session[:shopify_user]`
|
232
|
+
|
233
|
+
This will change the type of token that Shopify returns and it will only be valid for a short time. Read more about `Online access` [here](https://help.shopify.com/api/getting-started/authentication/oauth). Note that this means you won't be able to use this token to respond to Webhooks.
|
234
|
+
|
210
235
|
Managing Api Keys
|
211
236
|
-----------------
|
212
237
|
|
@@ -217,7 +242,7 @@ ShopifyApp.configure do |config|
|
|
217
242
|
config.application_name = 'Your app name' # Optional
|
218
243
|
config.api_key = ENV['SHOPIFY_CLIENT_API_KEY']
|
219
244
|
config.secret = ENV['SHOPIFY_CLIENT_API_SECRET']
|
220
|
-
config.scope = 'read_customers,
|
245
|
+
config.scope = 'read_customers, write_products'
|
221
246
|
config.embedded_app = true
|
222
247
|
end
|
223
248
|
```
|
@@ -226,7 +251,7 @@ end
|
|
226
251
|
WebhooksManager
|
227
252
|
---------------
|
228
253
|
|
229
|
-
ShopifyApp can manage your app's webhooks for you
|
254
|
+
ShopifyApp can manage your app's webhooks for you if you set which webhooks you require in the initializer:
|
230
255
|
|
231
256
|
```ruby
|
232
257
|
ShopifyApp.configure do |config|
|
@@ -238,7 +263,15 @@ end
|
|
238
263
|
|
239
264
|
When the oauth callback is completed successfully ShopifyApp will queue a background job which will ensure all the specified webhooks exist for that shop. Because this runs on every oauth callback it means your app will always have the webhooks it needs even if the user uninstalls and re-installs the app.
|
240
265
|
|
241
|
-
ShopifyApp also provides a WebhooksController that receives webhooks and queues a job based on the
|
266
|
+
ShopifyApp also provides a WebhooksController that receives webhooks and queues a job based on the received topic. For example if you register the webhook from above then all you need to do is create a job called `CartsUpdateJob`. The job will be queued with 2 params: `shop_domain` and `webhook` (which is the webhook body).
|
267
|
+
|
268
|
+
If you would like to namespace your jobs you may set `webhook_jobs_namespace` in the config. For example if your app handles webhooks from other ecommerce applications as well, and you want Shopify cart update webhooks to be processed by a job living in `jobs/shopify/webhooks/carts_update_job.rb` rather than `jobs/carts_update_job.rb`):
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
ShopifyApp.configure do |config|
|
272
|
+
config.webhook_jobs_namespace = 'shopify/webhooks'
|
273
|
+
end
|
274
|
+
```
|
242
275
|
|
243
276
|
If you are only interested in particular fields, you can optionally filter the data sent by Shopify by specifying the `fields` parameter in `config/webhooks`. Note that you will still receive a webhook request from Shopify every time the resource is updated, but only the specified fields will be sent.
|
244
277
|
|
@@ -250,20 +283,27 @@ ShopifyApp.configure do |config|
|
|
250
283
|
end
|
251
284
|
```
|
252
285
|
|
253
|
-
If you'd rather implement your own controller then you'll want to use the WebhookVerfication module to verify your webhooks:
|
286
|
+
If you'd rather implement your own controller then you'll want to use the WebhookVerfication module to verify your webhooks, example:
|
254
287
|
|
255
288
|
```ruby
|
256
289
|
class CustomWebhooksController < ApplicationController
|
257
290
|
include ShopifyApp::WebhookVerification
|
258
291
|
|
259
292
|
def carts_update
|
260
|
-
|
261
|
-
|
293
|
+
params.permit!
|
294
|
+
SomeJob.perform_later(shop_domain: shop_domain, webhook: webhook_params.to_h)
|
295
|
+
head :no_content
|
296
|
+
end
|
297
|
+
|
298
|
+
private
|
299
|
+
|
300
|
+
def webhook_params
|
301
|
+
params.except(:controller, :action, :type)
|
262
302
|
end
|
263
303
|
end
|
264
304
|
```
|
265
305
|
|
266
|
-
The module skips the `verify_authenticity_token` before_action and adds an action to verify that the webhook came from Shopify.
|
306
|
+
The module skips the `verify_authenticity_token` before_action and adds an action to verify that the webhook came from Shopify. You can now add a post route to your application pointing to the controller and action to accept the webhook data from Shopify.
|
267
307
|
|
268
308
|
The WebhooksManager uses ActiveJob, if ActiveJob is not configured then by default Rails will run the jobs inline. However it is highly recommended to configure a proper background processing queue like sidekiq or resque in production.
|
269
309
|
|
@@ -283,7 +323,7 @@ As with webhooks, ShopifyApp can manage your app's scripttags for you by setting
|
|
283
323
|
```ruby
|
284
324
|
ShopifyApp.configure do |config|
|
285
325
|
config.scripttags = [
|
286
|
-
{event:'onload', src: 'https://my-shopifyapp.herokuapp.com/fancy.js'}
|
326
|
+
{event:'onload', src: 'https://my-shopifyapp.herokuapp.com/fancy.js'},
|
287
327
|
{event:'onload', src: ->(domain) { dynamic_tag_url(domain) } }
|
288
328
|
]
|
289
329
|
end
|
@@ -306,7 +346,7 @@ If your app needs to perform specific actions after it is installed ShopifyApp c
|
|
306
346
|
|
307
347
|
```ruby
|
308
348
|
ShopifyApp.configure do |config|
|
309
|
-
config.
|
349
|
+
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob }
|
310
350
|
end
|
311
351
|
```
|
312
352
|
|
@@ -314,7 +354,7 @@ If you need the job to run synchronously add the `inline` flag:
|
|
314
354
|
|
315
355
|
```ruby
|
316
356
|
ShopifyApp.configure do |config|
|
317
|
-
config.
|
357
|
+
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true }
|
318
358
|
end
|
319
359
|
```
|
320
360
|
|
@@ -324,17 +364,43 @@ We've also provided a generator which creates a skeleton job and updates the ini
|
|
324
364
|
bin/rails g shopify_app:add_after_authenticate_job
|
325
365
|
```
|
326
366
|
|
367
|
+
RotateShopifyTokenJob
|
368
|
+
---------------------
|
369
|
+
|
370
|
+
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).
|
371
|
+
|
372
|
+
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:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
config.secret = Rails.application.secrets.shopify_secret
|
376
|
+
config.old_secret = Rails.application.secrets.old_shopify_secret
|
377
|
+
```
|
378
|
+
|
379
|
+
We've provided a generator which creates the job and an example rake task:
|
380
|
+
|
381
|
+
```sh
|
382
|
+
bin/rails g shopify_app:rotate_shopify_token_job
|
383
|
+
```
|
384
|
+
|
385
|
+
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.
|
386
|
+
|
387
|
+
⚠️ 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/intializers/omniauth.rb`:
|
388
|
+
|
389
|
+
```ruby
|
390
|
+
strategy.options[:old_client_secret] = ShopifyApp.configuration.old_secret
|
391
|
+
```
|
392
|
+
|
327
393
|
ShopifyApp::SessionRepository
|
328
394
|
-----------------------------
|
329
395
|
|
330
|
-
`ShopifyApp::SessionRepository` allows you as a developer to define how your sessions are retrieved and stored for
|
396
|
+
`ShopifyApp::SessionRepository` allows you as a developer to define how your sessions are retrieved and stored for shops. The `SessionRepository` is configured in the `config/initializers/shopify_app.rb` file and can be set to any object that implements `self.store(shopify_session)` which stores the session and returns a unique identifier and `self.retrieve(id)` which returns a `ShopifyAPI::Session` for the passed id. See either the `ShopifyApp::InMemorySessionStore` class or the `ShopifyApp::SessionStorage` concern for examples.
|
331
397
|
|
332
|
-
If you only run the install generator then by default you will have an in memory store but it **won't work** on multi-server environments including Heroku. If you ran all the generators including the shop_model generator then the Shop model itself will be the `SessionRepository`. If you look at the implementation of the generated shop model you'll see that this gem provides
|
398
|
+
If you only run the install generator then by default you will have an in memory store but it **won't work** on multi-server environments including Heroku. If you ran all the generators including the shop_model generator then the `Shop` model itself will be the `SessionRepository`. If you look at the implementation of the generated shop model you'll see that this gem provides a concern for the `SessionRepository`. You can use this concern on any model that responds to `shopify_domain` and `shopify_token`.
|
333
399
|
|
334
400
|
AuthenticatedController
|
335
401
|
-----------------------
|
336
402
|
|
337
|
-
The engine includes a controller called `ShopifyApp::AuthenticatedController` which inherits from `
|
403
|
+
The engine includes a controller called `ShopifyApp::AuthenticatedController` which inherits from `ActionController::Base`. It adds some before_filters which ensure the user is authenticated and will redirect to the login page if not. It is best practice to have all controllers that belong to the Shopify part of your app inherit from this controller. The HomeController that is generated already inherits from AuthenticatedController.
|
338
404
|
|
339
405
|
AppProxyVerification
|
340
406
|
--------------------
|
@@ -365,23 +431,14 @@ see [TROUBLESHOOTING.md](https://github.com/Shopify/shopify_app/blob/master/docs
|
|
365
431
|
Testing an embedded app outside the Shopify admin
|
366
432
|
-------------------------------------------------
|
367
433
|
|
368
|
-
By default, loading your embedded app will redirect to the Shopify admin, with the app view loaded in an `iframe`. If you need to load your app outside of the Shopify admin (e.g., for performance testing), you can change `forceRedirect:
|
434
|
+
By default, loading your embedded app will redirect to the Shopify admin, with the app view loaded in an `iframe`. If you need to load your app outside of the Shopify admin (e.g., for performance testing), you can change `forceRedirect: true` to `false` in `ShopifyApp.init` block in the `embedded_app` view. To keep the redirect on in production but off in your `development` and `test` environments, you can use:
|
369
435
|
|
370
436
|
```javascript
|
371
437
|
forceRedirect: <%= Rails.env.development? || Rails.env.test? ? 'false' : 'true' %>
|
372
438
|
```
|
373
439
|
|
374
|
-
App Tunneling
|
375
|
-
-------------
|
376
|
-
|
377
|
-
For certain features like Application Proxy or Webhooks to receive requests from Shopify, your app needs to be on a publicly visible URL. This can be a hurdle during development or testing on a local machine. Fortunately, this can be overcome by employing a tunneling service like [Forward](https://forwardhq.com/), [RequestBin](https://requestb.in/), [ngrok](https://ngrok.com/) etc. These tools allow you to create a secure tunnel from the public Internet to your local machine.
|
378
|
-
|
379
|
-
Tunneling is also useful for working the the embedded app sdk to solve mixed content issues since most tunnles provide ssl.
|
380
|
-
|
381
440
|
Questions or problems?
|
382
441
|
----------------------
|
383
|
-
http://api.shopify.com <= Read up on the possible API calls!
|
384
|
-
|
385
|
-
http://ecommerce.shopify.com/c/shopify-apis-and-technology <= Ask questions!
|
386
442
|
|
387
|
-
|
443
|
+
- [Ask questions!](https://ecommerce.shopify.com/c/shopify-apis-and-technology)
|
444
|
+
- [Read the docs!](https://help.shopify.com/api/guides)
|