shopify_app 8.3.2 → 8.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.babelrc +5 -0
- data/.github/CODEOWNERS +1 -0
- data/.github/probots.yml +2 -0
- data/.gitignore +1 -0
- data/.nvmrc +1 -0
- data/.travis.yml +24 -3
- data/CHANGELOG.md +5 -0
- data/README.md +1 -0
- 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/request_storage_access.js +3 -0
- data/app/assets/javascripts/shopify_app/storage_access.js +116 -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/callback_controller.rb +92 -0
- data/app/controllers/shopify_app/sessions_controller.rb +57 -84
- 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 +7 -334
- 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/config/locales/de.yml +10 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/es.yml +10 -0
- data/config/locales/fr.yml +11 -0
- data/config/locales/it.yml +11 -0
- data/config/locales/ja.yml +8 -0
- data/config/locales/pt-BR.yml +10 -0
- data/config/routes.rb +10 -1
- data/karma.conf.js +43 -0
- data/lib/shopify_app.rb +1 -0
- data/lib/shopify_app/controller_concerns/itp.rb +45 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +7 -11
- data/lib/shopify_app/engine.rb +4 -1
- data/lib/shopify_app/utils.rb +1 -1
- 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 +1 -0
- data/webpack.config.js +24 -0
- data/yarn.lock +4594 -0
- metadata +44 -3
- data/app/assets/javascripts/shopify_app/itp_polyfill.js +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45878b4b2df0d02183a741d202e4d3012ea371f0
|
4
|
+
data.tar.gz: 5526b90556c92908c0815d2373c54710a878396b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d70b9286c3e9b2cb0e4e06562b2ee0f77fb9e1ad3ebad9d6c70929da8befcc610637ca5e68a1ef240130b2add6da4d5810f0428f122335addc8f6c2b70abc8c6
|
7
|
+
data.tar.gz: ef0d81bc695c1f90c16972c08fda12904ce9305c209d540729c2b5d795d5607bb99313fe0e1ddc491dc2ac8b35a3ccca3a433d069388b51e2b7582d46c3ab4cf
|
data/.github/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @shopify/app-partner-dev-tools-education
|
data/.github/probots.yml
ADDED
data/.gitignore
CHANGED
data/.nvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
8.10.0
|
data/.travis.yml
CHANGED
@@ -1,9 +1,30 @@
|
|
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
|
-
before_install:
|
3
|
-
|
4
|
-
|
9
|
+
before_install:
|
10
|
+
- gem update --system
|
11
|
+
cache:
|
12
|
+
bundler: true
|
13
|
+
directories:
|
14
|
+
- node_modules
|
15
|
+
yarn: true
|
5
16
|
|
6
17
|
rvm:
|
7
18
|
- 2.3.6
|
8
19
|
- 2.4.3
|
9
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
|
30
|
+
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -112,6 +112,7 @@ The default generator will run the `install`, `shop`, and `home_controller` gene
|
|
112
112
|
$ rails generate shopify_app --api_key <your_api_key> --secret <your_app_secret>
|
113
113
|
```
|
114
114
|
|
115
|
+
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.
|
115
116
|
|
116
117
|
### Install Generator
|
117
118
|
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<svg enable-background="new 0 0 1920 1080" version="1.1" viewBox="0 0 1920 1080" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><polygon points="1345 330.75 1345 437.24 1224.7 437.24 1224.7 676.56 873.52 676.56 874.04 643.85 1203.2 330.23" fill="#fff"/><path d="m1095.7 677.54c-18.553 0.074-37.107 0.163-55.66 0.126-18.553 0.056-37.107-0.188-55.66-0.233l-13.915-0.063-13.915 0.044-27.83 0.094c-18.553 0.128-37.107-5e-3 -55.66-0.056l-1.266-3e-3 3e-3 -1.259 0.047-22.532-0.093-22.532-0.068-11.266 6e-3 -11.266 0.019-22.532h2.703l0.111 22.532c0.053 7.511 0.06 15.022 0.038 22.532l-0.094 45.065-1.407-1.407c18.553 7e-3 37.107-0.041 55.66 0.086l27.83 0.131 13.915 0.066 13.915-0.028c18.553-8e-3 37.107-0.151 55.66-0.019 18.553 0.099 37.107 0.049 55.66-0.181v2.701z" fill="#0C1238"/><path d="m1225 677.54c-9.24 0.123-18.48 0.187-27.72 0.077l-13.86-0.213c-2.31-0.051-4.62-0.023-6.93 1e-3l-6.93 0.062c-9.24 0.156-18.48 0.076-27.72-0.054-2.31-0.034-4.62 1e-3 -6.93 2e-3l-6.93 0.121c-4.62 0.062-9.24-2e-3 -13.86 3e-3v-2.703c4.62-0.048 9.24-0.165 13.86-0.157l6.93 0.025c2.31 0.027 4.62 0.088 6.93 0.076 9.24-0.024 18.48-0.031 27.72 0.145 4.62 0.038 9.24 0.163 13.86 0.126l13.86-0.081c4.62-0.04 9.24 0.088 13.86 0.101 2.31 0.047 4.62-0.048 6.93-0.065 2.31-0.026 4.62-0.07 6.93-0.169v2.703z" fill="#0C1238"/><path d="m871.68 561.78l-0.13-115.72 0.07-115.72 1e-3 -1.414 1.411 3e-3 117.9 0.228 117.9-0.138 58.951-0.061 58.951 0.072 117.9 0.09 1.218 1e-3 4e-3 1.221 0.156 53.426-0.026 53.426h-2.703l-0.154-53.426 0.04-53.426 1.466 1.466-235.8-0.148-117.9-0.193-117.9 0.087 1.212-1.212-0.084 115.72c-0.058 19.286 0.032 38.573 0.074 57.859l0.15 57.859h-2.705z" fill="#0C1238"/><g fill="#E6E8F0"><circle cx="891.37" cy="344.49" r="6.812"/><circle cx="912.86" cy="345.01" r="6.812"/><circle cx="934.34" cy="345.54" r="6.812"/><path d="m1202.7 352.87h-186.64c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h186.64c0.552 0 1 0.448 1 1v11.624c0 0.552-0.448 1-1 1z" stroke="#F0F3F5" stroke-miterlimit="10"/><rect x="1288.6" y="339.25" width="17.816" height="13.624"/><path d="m1327.4 352.87h-15.816c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h15.816c0.552 0 1 0.448 1 1v11.624c0 0.552-0.447 1-1 1z"/></g><g fill="none" stroke="#8891EA" stroke-miterlimit="10" stroke-width="8"><path d="m1098.3 576.8c-24.295 0-43.99-19.695-43.99-43.99v-29.485c0-2.209 1.791-4 4-4h79.98c2.209 0 4 1.791 4 4v29.485c0 24.295-19.695 43.99-43.99 43.99z"/><path d="m1066 499.33v-12.41c0-17.804 14.433-32.237 32.237-32.237s32.237 14.433 32.237 32.237v12.41"/></g><circle cx="1098.3" cy="529.08" r="8.966" fill="#8891EA"/><line x1="1098.3" x2="1098.3" y1="529.08" y2="546.68" fill="#fff" stroke="#8891EA" stroke-linecap="round" stroke-miterlimit="10" stroke-width="8"/><polygon points="1416.1 676.19 1358 748.57 1416.1 749.77 1225 749.77 1225 659.42 1416.1 437.19" fill="#fff"/><path d="m1415.2 497.07l-0.12-59.83 1.472 1.472-95.89-0.052-47.945-0.135c-15.982-0.023-31.963-0.14-47.945-0.085l1.2-1.2 0.139 78.077c0.086 26.026 4e-3 52.052-0.039 78.077l-0.076 78.077c0.056 26.026 0.201 52.052 0.145 78.077l-1.368-1.368 38.25 0.017v2.703l-38.251 0.1-1.444 4e-3 -6e-3 -1.454c-0.102-26.026-0.045-52.052-0.026-78.077l0.068-78.077 0.067-78.077 0.191-78.077 3e-3 -1.15h1.147l47.945-0.013 47.945-0.051 95.89 0.089 1.121 1e-3 4e-3 1.125 0.226 59.83h-2.703z" fill="#0C1238"/><path d="m1417.9 518.33c0.051 19.268 0.165 38.536 0.128 57.804l-0.022 28.902-0.134 28.902-0.134 28.902 0.061 28.902 0.087 28.902 0.046 14.451-0.034 14.451-3e-3 1.353-1.347-3e-3c-22.64-0.042-45.28-0.192-67.919-0.118l-33.96 0.144-33.96-0.025v-2.703l33.96-0.143 33.96 0.01c11.32 0.049 22.64 0.1 33.96 0.078l33.96-2e-3 -1.409 1.409c-0.03-19.268 0.125-38.536 0.178-57.804l0.103-28.902-0.051-28.902-0.051-28.902 0.081-28.902c0.128-19.268-0.116-38.536-0.204-57.804h2.704z" fill="#0C1238"/><path d="m1400.3 458.72h-160.44c-0.552 0-1-0.448-1-1v-11.624c0-0.552 0.448-1 1-1h160.44c0.552 0 1 0.448 1 1v11.624c0 0.552-0.448 1-1 1z" fill="#E6E8F0" stroke="#F0F3F5" stroke-miterlimit="10"/><path d="m1238.5 467.44c13.587-0.084 27.173-0.121 40.76-0.055l20.38 0.141c6.793 0.061 13.587-0.03 20.38-0.038 13.587-0.116 27.173-0.022 40.76 0.038 6.793 0.029 13.587-0.022 20.38-0.082 6.793-0.046 13.587 0 20.38-5e-3v1.802c-13.587 0.111-27.173 0.144-40.76 0.036-13.587 2e-3 -27.173 0.027-40.76-0.09-6.793-0.025-13.587-0.117-20.38-0.088l-20.38 0.054c-6.793 0.022-13.587-0.048-20.38-0.067-6.793-7e-3 -13.587 0.107-20.38 0.154v-1.8z" fill="#E6E8F0"/><path d="m891.69 362.56c36.392-0.084 72.784-0.121 109.18-0.055l54.588 0.141c18.196 0.062 36.392-0.034 54.588-0.043l218.35-0.043v1.802c-36.392 0.111-72.784 0.144-109.18 0.036l-109.18-0.09-54.588-0.088-54.588 0.054-54.588-0.067-54.588 0.154v-1.801z" fill="#E6E8F0"/><g fill="none" stroke="#8891EA" stroke-miterlimit="10" stroke-width="6"><path d="m1320.6 638.41c-17.878 0-32.371-14.493-32.371-32.371v-21.697c0-1.626 1.318-2.943 2.943-2.943h58.854c1.626 0 2.943 1.318 2.943 2.943v21.697c1e-3 17.878-14.491 32.371-32.369 32.371z"/><path d="m1296.9 581.4v-9.132c0-13.101 10.62-23.722 23.722-23.722 13.101 0 23.722 10.621 23.722 23.722v9.132"/></g><circle cx="1320.6" cy="604.5" r="5.88" fill="#8891EA"/><line x1="1320.6" x2="1320.6" y1="603.3" y2="616.25" fill="#fff" stroke="#8891EA" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/><path d="m966.35 697.36l-0.029 13.745c-0.01 1.145 0.011 2.291-0.023 3.436l-0.124 3.436c-0.103 2.291 0.022 4.582 0.121 6.872l-1.912-1.912c10.168-0.857 20.337-0.478 30.505-0.36 5.084 0.104 10.168 0.133 15.252 0.178 5.084 6e-3 10.168 0.199 15.252 0.287l7.626 0.168 7.626 0.264c2.542 0.09 5.084 0.032 7.626 0.023 2.542-0.035 5.084 0.047 7.626 0.065 10.168 0.377 20.337-0.052 30.505 0.201l7.626 0.04c2.542 6e-3 5.084-0.283 7.626-0.394 5.084-0.14 10.168-0.184 15.252-0.268 5.084-0.072 10.168-0.071 15.252-0.204 2.542-0.07 5.084-0.088 7.626-0.118 2.542-0.019 5.084 0.1 7.626 0.143 10.168 0.462 20.337-0.303 30.505 0.192 2.542 0.145 5.084 0.163 7.626 0.139 2.542 0 5.084-0.038 7.626-0.099l15.252-0.314v3.936l-15.252 0.106c-5.084 0.024-10.168 0.012-15.252 0.3-10.168 0.483-20.337-0.281-30.505-0.213-20.337-1.165-40.673 0.704-61.01-0.137-2.542 0.117-5.084 0.33-7.626 0.382-2.542 0.092-5.084 0.173-7.626-0.018s-5.084-0.219-7.626-0.183c-2.542-2e-3 -5.084 0.099-7.626 0.081-2.542-0.027-5.084 0.026-7.626-0.066-1.271-0.039-2.542-0.079-3.813-0.09-1.271-0.022-2.542-0.05-3.813 0.018-2.542 0.097-5.084 0.355-7.626 0.327-1.271-0.037-2.542-0.06-3.813-0.12l-3.813-0.238c-2.542-0.162-5.084-0.324-7.626-0.268-2.542 0.109-5.084-0.092-7.626-0.222-2.542-0.112-5.084-0.326-7.626-0.371-2.542-0.094-5.084-0.061-7.626-0.038-5.084 0.101-10.168 0.266-15.252 0.414-2.542 0.071-5.084 0.122-7.626 0.123l-7.626-0.19-1.598-0.04 0.032-1.527c0.047-2.291 0.153-4.582 9e-3 -6.872l-0.162-3.436c-0.047-1.145-0.04-2.291-0.062-3.436l-0.186-13.745h3.934z" fill="#E6E8F0"/><path d="m1434.8 722.88l16.096 0.019 8.048 0.01c2.683 0.018 5.365-0.029 8.048 0.05l-1.89 1.89c0.07-3.44 0.218-6.88 0.086-10.32l-0.312-10.32c-0.261-6.88-0.364-13.76-0.339-20.639l0.314-41.279c0.052-6.88 0.033-13.76 0.144-20.639l0.275-20.639c0.057-6.88 0.274-13.76 0.375-20.639 0.058-6.88-0.069-13.76 0.033-20.639l0.226-20.639-0.071-10.32-0.046-5.16 0.032-5.16 0.11-20.639c0.012-3.44 0.045-6.88-0.068-10.32-0.149-3.44-0.261-6.88-0.361-10.32l-0.328-41.279c-0.074-6.88-0.188-13.76-0.211-20.639 0.028-6.88 0.177-13.76 0.261-20.639l1.77 1.77c-4.37-0.095-8.74 1e-3 -13.111 1e-3l-13.111 0.063c-4.37 1e-3 -8.74 0.084-13.111 0.016l-13.111-0.231c-4.37-0.118-8.74-0.058-13.111-0.055-4.37-4e-3 -8.74 0.077-13.111 0.113l-26.221 0.29v-3.936l26.221-0.107 13.111-0.052c4.37-0.026 8.74 2e-3 13.111-0.14l13.111-0.262c4.37-0.066 8.74 0.04 13.111 0.051l26.221 0.283 2.211 0.024-0.016 2.172c-0.049 6.88-0.045 13.76-0.139 20.639-0.152 6.88-0.325 13.76-0.304 20.639l0.499 41.279c-0.024 1.72-0.037 3.44-0.138 5.16l-0.297 5.16c-0.137 3.44-0.045 6.88 0.01 10.32 0.12 6.88 0.479 13.76 0.59 20.639 0.273 6.88-0.127 13.76-0.227 20.639-0.014 6.88 0.146 13.76 0.091 20.639 0.051 6.88-0.202 13.76-0.162 20.639 0.04 3.44 0.226 6.88 0.324 10.32 0.061 3.44 4e-3 6.88-0.082 10.32l-0.356 10.32c-0.047 1.72-0.141 3.44-0.149 5.16l2e-3 5.16c-0.012 1.72 0.032 3.44-0.026 5.16l-0.164 5.16-0.335 10.32c-0.306 13.76 0.065 27.519 0.289 41.279 0.074 3.44 0.091 6.88 0.13 10.32 0.059 3.44-0.071 6.88-0.098 10.32l-0.153 10.32c-0.053 1.72 0.021 3.44 0.049 5.16l0.139 5.16 0.044 1.627-1.73 0.06c-2.683 0.093-5.365 0.065-8.048 0.1l-8.048 0.061-16.096 0.121v-3.941z" fill="#E6E8F0"/></svg>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
(function() {
|
2
|
+
function ITPHelper(opts) {
|
3
|
+
this.itpContent = document.getElementById('TopLevelInteractionContent');
|
4
|
+
this.itpAction = document.getElementById('TopLevelInteractionButton');
|
5
|
+
this.redirectUrl = opts.redirectUrl;
|
6
|
+
}
|
7
|
+
|
8
|
+
ITPHelper.prototype.redirect = function() {
|
9
|
+
sessionStorage.setItem('shopify.top_level_interaction', true);
|
10
|
+
window.location.href = this.redirectUrl;
|
11
|
+
}
|
12
|
+
|
13
|
+
ITPHelper.prototype.userAgentIsAffected = function() {
|
14
|
+
return Boolean(document.hasStorageAccess);
|
15
|
+
}
|
16
|
+
|
17
|
+
ITPHelper.prototype.canPartitionCookies = function() {
|
18
|
+
var versionRegEx = /Version\/12\.0\.?\d? Safari/;
|
19
|
+
return versionRegEx.test(navigator.userAgent);
|
20
|
+
}
|
21
|
+
|
22
|
+
ITPHelper.prototype.setUpContent = function(onClick) {
|
23
|
+
this.itpContent.style.display = 'block';
|
24
|
+
this.itpAction.addEventListener('click', this.redirect.bind(this));
|
25
|
+
}
|
26
|
+
|
27
|
+
ITPHelper.prototype.execute = function() {
|
28
|
+
if (!this.itpContent) {
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
if (this.userAgentIsAffected()) {
|
33
|
+
this.setUpContent();
|
34
|
+
} else {
|
35
|
+
this.redirect();
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
this.ITPHelper = ITPHelper;
|
40
|
+
})(window);
|
@@ -0,0 +1,116 @@
|
|
1
|
+
(function() {
|
2
|
+
var ACCESS_GRANTED_STATUS = 'storage_access_granted';
|
3
|
+
var ACCESS_DENIED_STATUS = 'storage_access_denied';
|
4
|
+
|
5
|
+
function StorageAccessHelper(redirectData) {
|
6
|
+
this.redirectData = redirectData;
|
7
|
+
}
|
8
|
+
|
9
|
+
StorageAccessHelper.prototype.setNormalizedLink = function(storageAccessStatus) {
|
10
|
+
return storageAccessStatus === ACCESS_GRANTED_STATUS ? this.redirectData.hasStorageAccessUrl : this.redirectData.doesNotHaveStorageAccessUrl;
|
11
|
+
}
|
12
|
+
|
13
|
+
StorageAccessHelper.prototype.redirectToAppTLD = function(storageAccessStatus) {
|
14
|
+
var normalizedLink = document.createElement('a');
|
15
|
+
|
16
|
+
normalizedLink.href = this.setNormalizedLink(storageAccessStatus);
|
17
|
+
|
18
|
+
data = JSON.stringify({
|
19
|
+
message: 'Shopify.API.remoteRedirect',
|
20
|
+
data: {
|
21
|
+
location: normalizedLink.href,
|
22
|
+
}
|
23
|
+
});
|
24
|
+
window.parent.postMessage(data, this.redirectData.myshopifyUrl);
|
25
|
+
}
|
26
|
+
|
27
|
+
StorageAccessHelper.prototype.redirectToAppsIndex = function() {
|
28
|
+
window.parent.location.href = this.redirectData.myshopifyUrl + '/admin/apps';
|
29
|
+
}
|
30
|
+
|
31
|
+
StorageAccessHelper.prototype.redirectToAppHome = function() {
|
32
|
+
window.location.href = this.redirectData.appHomeUrl;
|
33
|
+
}
|
34
|
+
|
35
|
+
StorageAccessHelper.prototype.grantedStorageAccess = function() {
|
36
|
+
sessionStorage.setItem('shopify.granted_storage_access', true);
|
37
|
+
document.cookie = 'shopify.granted_storage_access=true';
|
38
|
+
this.redirectToAppHome();
|
39
|
+
}
|
40
|
+
|
41
|
+
StorageAccessHelper.prototype.handleRequestStorageAccess = function() {
|
42
|
+
return document.requestStorageAccess().then(this.grantedStorageAccess.bind(this), this.redirectToAppsIndex.bind(this, ACCESS_DENIED_STATUS));
|
43
|
+
}
|
44
|
+
|
45
|
+
StorageAccessHelper.prototype.setupRequestStorageAccess = function() {
|
46
|
+
var requestContent = document.getElementById('RequestStorageAccess');
|
47
|
+
var requestButton = document.getElementById('TriggerAllowCookiesPrompt');
|
48
|
+
|
49
|
+
requestButton.addEventListener('click', this.handleRequestStorageAccess.bind(this));
|
50
|
+
requestContent.style.display = 'block';
|
51
|
+
}
|
52
|
+
|
53
|
+
StorageAccessHelper.prototype.handleHasStorageAccess = function() {
|
54
|
+
if (sessionStorage.getItem('shopify.granted_storage_access')) {
|
55
|
+
// If app was classified by ITP and used Storage Access API to acquire access
|
56
|
+
this.redirectToAppHome();
|
57
|
+
} else {
|
58
|
+
// If app has not been classified by ITP and still has storage access
|
59
|
+
this.redirectToAppTLD(ACCESS_GRANTED_STATUS);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
StorageAccessHelper.prototype.handleGetStorageAccess = function() {
|
64
|
+
if (sessionStorage.getItem('shopify.top_level_interaction')) {
|
65
|
+
// If merchant has been redirected to interact with TLD (requirement for prompting request to gain storage access)
|
66
|
+
this.setupRequestStorageAccess();
|
67
|
+
} else {
|
68
|
+
// If merchant has not been redirected to interact with TLD (requirement for prompting request to gain storage access)
|
69
|
+
this.redirectToAppTLD(ACCESS_DENIED_STATUS);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
StorageAccessHelper.prototype.manageStorageAccess = function() {
|
74
|
+
return document.hasStorageAccess().then(function(hasAccess) {
|
75
|
+
if (hasAccess) {
|
76
|
+
this.handleHasStorageAccess();
|
77
|
+
} else {
|
78
|
+
this.handleGetStorageAccess();
|
79
|
+
}
|
80
|
+
}.bind(this));
|
81
|
+
}
|
82
|
+
|
83
|
+
StorageAccessHelper.prototype.execute = function() {
|
84
|
+
if (ITPHelper.prototype.canPartitionCookies()) {
|
85
|
+
this.setUpCookiePartitioning();
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
if (ITPHelper.prototype.userAgentIsAffected()) {
|
90
|
+
this.manageStorageAccess();
|
91
|
+
} else {
|
92
|
+
this.grantedStorageAccess();
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
/* ITP 2.0 solution: handles cookie partitioning */
|
97
|
+
StorageAccessHelper.prototype.setUpHelper = function() {
|
98
|
+
return new ITPHelper({redirectUrl: window.shopOrigin + "/admin/apps/" + window.apiKey});
|
99
|
+
}
|
100
|
+
|
101
|
+
StorageAccessHelper.prototype.setCookieAndRedirect = function() {
|
102
|
+
document.cookie = "shopify.cookies_persist=true";
|
103
|
+
var helper = this.setUpHelper();
|
104
|
+
helper.redirect();
|
105
|
+
}
|
106
|
+
|
107
|
+
StorageAccessHelper.prototype.setUpCookiePartitioning = function() {
|
108
|
+
var itpContent = document.getElementById('CookiePartitionPrompt');
|
109
|
+
itpContent.style.display = 'block';
|
110
|
+
|
111
|
+
var button = document.getElementById('AcceptCookies');
|
112
|
+
button.addEventListener('click', this.setCookieAndRedirect.bind(this));
|
113
|
+
}
|
114
|
+
|
115
|
+
this.StorageAccessHelper = StorageAccessHelper;
|
116
|
+
})(window);
|
@@ -0,0 +1,17 @@
|
|
1
|
+
(function() {
|
2
|
+
function redirect() {
|
3
|
+
var redirectTargetElement = document.getElementById("redirection-target");
|
4
|
+
|
5
|
+
var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
|
6
|
+
|
7
|
+
if (window.top == window.self) {
|
8
|
+
// If the current window is the 'parent', change the URL by setting location.href
|
9
|
+
window.top.location.href = targetInfo.hasStorageAccessUrl;
|
10
|
+
} else {
|
11
|
+
var storageAccessHelper = new StorageAccessHelper(targetInfo);
|
12
|
+
storageAccessHelper.execute();
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
document.addEventListener("DOMContentLoaded", redirect);
|
17
|
+
})();
|
@@ -0,0 +1,11 @@
|
|
1
|
+
(function() {
|
2
|
+
function setUpTopLevelInteraction() {
|
3
|
+
var TopLevelInteraction = new ITPHelper({
|
4
|
+
redirectUrl: window.redirectUrl,
|
5
|
+
});
|
6
|
+
|
7
|
+
TopLevelInteraction.execute();
|
8
|
+
}
|
9
|
+
|
10
|
+
document.addEventListener("DOMContentLoaded", setUpTopLevelInteraction);
|
11
|
+
})();
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyApp
|
4
|
+
# Performs login after OAuth completes
|
5
|
+
class CallbackController < ActionController::Base
|
6
|
+
include ShopifyApp::LoginProtection
|
7
|
+
|
8
|
+
def callback
|
9
|
+
if auth_hash
|
10
|
+
login_shop
|
11
|
+
install_webhooks
|
12
|
+
install_scripttags
|
13
|
+
perform_after_authenticate_job
|
14
|
+
|
15
|
+
redirect_to return_address
|
16
|
+
else
|
17
|
+
flash[:error] = I18n.t('could_not_log_in')
|
18
|
+
redirect_to login_url
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def login_shop
|
25
|
+
reset_session_options
|
26
|
+
set_shopify_session
|
27
|
+
end
|
28
|
+
|
29
|
+
def auth_hash
|
30
|
+
request.env['omniauth.auth']
|
31
|
+
end
|
32
|
+
|
33
|
+
def shop_name
|
34
|
+
auth_hash.uid
|
35
|
+
end
|
36
|
+
|
37
|
+
def associated_user
|
38
|
+
return unless auth_hash['extra'].present?
|
39
|
+
|
40
|
+
auth_hash['extra']['associated_user']
|
41
|
+
end
|
42
|
+
|
43
|
+
def token
|
44
|
+
auth_hash['credentials']['token']
|
45
|
+
end
|
46
|
+
|
47
|
+
def reset_session_options
|
48
|
+
request.session_options[:renew] = true
|
49
|
+
session.delete(:_csrf_token)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_shopify_session
|
53
|
+
session_store = ShopifyAPI::Session.new(shop_name, token)
|
54
|
+
|
55
|
+
session[:shopify] = ShopifyApp::SessionRepository.store(session_store)
|
56
|
+
session[:shopify_domain] = shop_name
|
57
|
+
session[:shopify_user] = associated_user if associated_user.present?
|
58
|
+
end
|
59
|
+
|
60
|
+
def install_webhooks
|
61
|
+
return unless ShopifyApp.configuration.has_webhooks?
|
62
|
+
|
63
|
+
WebhooksManager.queue(
|
64
|
+
shop_name,
|
65
|
+
token,
|
66
|
+
ShopifyApp.configuration.webhooks
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def install_scripttags
|
71
|
+
return unless ShopifyApp.configuration.has_scripttags?
|
72
|
+
|
73
|
+
ScripttagsManager.queue(
|
74
|
+
shop_name,
|
75
|
+
token,
|
76
|
+
ShopifyApp.configuration.scripttags
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def perform_after_authenticate_job
|
81
|
+
config = ShopifyApp.configuration.after_authenticate_job
|
82
|
+
|
83
|
+
return unless config && config[:job].present?
|
84
|
+
|
85
|
+
if config[:inline] == true
|
86
|
+
config[:job].perform_now(shop_domain: session[:shopify_domain])
|
87
|
+
else
|
88
|
+
config[:job].perform_later(shop_domain: session[:shopify_domain])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module ShopifyApp
|
2
2
|
class SessionsController < ActionController::Base
|
3
3
|
include ShopifyApp::LoginProtection
|
4
|
+
|
4
5
|
layout false, only: :new
|
5
6
|
after_action only: [:new, :create] do |controller|
|
6
7
|
controller.response.headers.except!('X-Frame-Options')
|
@@ -15,22 +16,21 @@ module ShopifyApp
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def enable_cookies
|
18
|
-
|
19
|
-
render_invalid_shop_error unless @shop
|
19
|
+
validate_shop
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
install_scripttags
|
27
|
-
perform_after_authenticate_job
|
22
|
+
def top_level_interaction
|
23
|
+
@url = login_url(top_level: true)
|
24
|
+
validate_shop
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
def granted_storage_access
|
28
|
+
return unless validate_shop
|
29
|
+
|
30
|
+
session['shopify.granted_storage_access'] = true
|
31
|
+
|
32
|
+
params = { shop: @shop }
|
33
|
+
redirect_to "#{ShopifyApp.configuration.root_url}?#{params.to_query}"
|
34
34
|
end
|
35
35
|
|
36
36
|
def destroy
|
@@ -45,8 +45,16 @@ module ShopifyApp
|
|
45
45
|
return render_invalid_shop_error unless sanitized_shop_name.present?
|
46
46
|
session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
|
47
47
|
|
48
|
-
if
|
49
|
-
|
48
|
+
if user_agent_can_partition_cookies
|
49
|
+
authenticate_with_partitioning
|
50
|
+
else
|
51
|
+
authenticate_normally
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def authenticate_normally
|
56
|
+
if request_storage_access?
|
57
|
+
redirect_to_request_storage_access
|
50
58
|
elsif authenticate_in_context?
|
51
59
|
authenticate_in_context
|
52
60
|
else
|
@@ -54,97 +62,62 @@ module ShopifyApp
|
|
54
62
|
end
|
55
63
|
end
|
56
64
|
|
65
|
+
def authenticate_with_partitioning
|
66
|
+
if session['shopify.cookies_persist']
|
67
|
+
clear_top_level_oauth_cookie
|
68
|
+
authenticate_in_context
|
69
|
+
else
|
70
|
+
set_top_level_oauth_cookie
|
71
|
+
fullpage_redirect_to enable_cookies_path(shop: sanitized_shop_name)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate_shop
|
76
|
+
@shop = sanitized_shop_name
|
77
|
+
unless @shop
|
78
|
+
render_invalid_shop_error
|
79
|
+
return false
|
80
|
+
end
|
81
|
+
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
57
85
|
def render_invalid_shop_error
|
58
86
|
flash[:error] = I18n.t('invalid_shop_url')
|
59
87
|
redirect_to return_address
|
60
88
|
end
|
61
89
|
|
62
90
|
def authenticate_in_context
|
63
|
-
clear_top_level_oauth_cookie
|
64
91
|
redirect_to "#{main_app.root_path}auth/shopify"
|
65
92
|
end
|
66
93
|
|
67
94
|
def authenticate_at_top_level
|
68
|
-
set_top_level_oauth_cookie
|
69
95
|
fullpage_redirect_to login_url(top_level: true)
|
70
96
|
end
|
71
97
|
|
72
98
|
def authenticate_in_context?
|
73
99
|
return true unless ShopifyApp.configuration.embedded_app?
|
74
|
-
|
75
|
-
session['shopify.top_level_oauth']
|
100
|
+
params[:top_level]
|
76
101
|
end
|
77
102
|
|
78
|
-
def
|
103
|
+
def request_storage_access?
|
79
104
|
return false unless ShopifyApp.configuration.embedded_app?
|
80
105
|
return false if params[:top_level]
|
81
|
-
return false if
|
106
|
+
return false if user_agent_is_mobile
|
107
|
+
return false if user_agent_is_pos
|
82
108
|
|
83
|
-
|
84
|
-
end
|
85
|
-
|
86
|
-
def login_shop
|
87
|
-
sess = ShopifyAPI::Session.new(shop_name, token)
|
88
|
-
|
89
|
-
request.session_options[:renew] = true
|
90
|
-
session.delete(:_csrf_token)
|
91
|
-
|
92
|
-
session[:shopify] = ShopifyApp::SessionRepository.store(sess)
|
93
|
-
session[:shopify_domain] = shop_name
|
94
|
-
session[:shopify_user] = associated_user if associated_user.present?
|
95
|
-
end
|
96
|
-
|
97
|
-
def auth_hash
|
98
|
-
request.env['omniauth.auth']
|
99
|
-
end
|
100
|
-
|
101
|
-
def shop_name
|
102
|
-
auth_hash.uid
|
103
|
-
end
|
104
|
-
|
105
|
-
def associated_user
|
106
|
-
return unless auth_hash['extra'].present?
|
107
|
-
auth_hash['extra']['associated_user']
|
108
|
-
end
|
109
|
-
|
110
|
-
def token
|
111
|
-
auth_hash['credentials']['token']
|
112
|
-
end
|
113
|
-
|
114
|
-
def install_webhooks
|
115
|
-
return unless ShopifyApp.configuration.has_webhooks?
|
116
|
-
|
117
|
-
WebhooksManager.queue(
|
118
|
-
shop_name,
|
119
|
-
token,
|
120
|
-
ShopifyApp.configuration.webhooks
|
121
|
-
)
|
122
|
-
end
|
123
|
-
|
124
|
-
def install_scripttags
|
125
|
-
return unless ShopifyApp.configuration.has_scripttags?
|
126
|
-
|
127
|
-
ScripttagsManager.queue(
|
128
|
-
shop_name,
|
129
|
-
token,
|
130
|
-
ShopifyApp.configuration.scripttags
|
131
|
-
)
|
132
|
-
end
|
133
|
-
|
134
|
-
def perform_after_authenticate_job
|
135
|
-
config = ShopifyApp.configuration.after_authenticate_job
|
136
|
-
|
137
|
-
return unless config && config[:job].present?
|
138
|
-
|
139
|
-
if config[:inline] == true
|
140
|
-
config[:job].perform_now(shop_domain: session[:shopify_domain])
|
141
|
-
else
|
142
|
-
config[:job].perform_later(shop_domain: session[:shopify_domain])
|
143
|
-
end
|
109
|
+
!session['shopify.granted_storage_access']
|
144
110
|
end
|
145
111
|
|
146
|
-
def
|
147
|
-
|
112
|
+
def redirect_to_request_storage_access
|
113
|
+
render :request_storage_access, layout: false, locals: {
|
114
|
+
does_not_have_storage_access_url: top_level_interaction_path(
|
115
|
+
shop: sanitized_shop_name
|
116
|
+
),
|
117
|
+
has_storage_access_url: login_url(top_level: true),
|
118
|
+
app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
|
119
|
+
current_shopify_domain: current_shopify_domain
|
120
|
+
}
|
148
121
|
end
|
149
122
|
end
|
150
123
|
end
|