shopify_app 14.4.4 → 18.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE/bug-report.md +63 -0
  4. data/.github/ISSUE_TEMPLATE/config.yml +1 -0
  5. data/.github/ISSUE_TEMPLATE/feature-request.md +33 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +17 -1
  7. data/.github/workflows/build.yml +41 -0
  8. data/.github/workflows/release.yml +24 -0
  9. data/.github/workflows/rubocop.yml +1 -7
  10. data/.gitignore +0 -2
  11. data/CHANGELOG.md +75 -0
  12. data/CONTRIBUTING.md +76 -0
  13. data/Gemfile.lock +268 -0
  14. data/README.md +73 -572
  15. data/app/assets/images/storage_access.svg +1 -2
  16. data/app/assets/javascripts/shopify_app/post_redirect.js +9 -0
  17. data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +26 -0
  18. data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +32 -0
  19. data/app/controllers/shopify_app/callback_controller.rb +34 -10
  20. data/app/controllers/shopify_app/sessions_controller.rb +19 -20
  21. data/app/views/shopify_app/partials/_button_styles.html.erb +41 -36
  22. data/app/views/shopify_app/partials/_card_styles.html.erb +3 -3
  23. data/app/views/shopify_app/partials/_empty_state_styles.html.erb +28 -59
  24. data/app/views/shopify_app/partials/_form_styles.html.erb +56 -0
  25. data/app/views/shopify_app/partials/_layout_styles.html.erb +16 -1
  26. data/app/views/shopify_app/partials/_typography_styles.html.erb +6 -6
  27. data/app/views/shopify_app/sessions/enable_cookies.html.erb +1 -1
  28. data/app/views/shopify_app/sessions/new.html.erb +38 -110
  29. data/app/views/shopify_app/sessions/request_storage_access.html.erb +1 -1
  30. data/app/views/shopify_app/sessions/top_level_interaction.html.erb +20 -15
  31. data/app/views/shopify_app/shared/post_redirect_to_auth_shopify.html.erb +13 -0
  32. data/config/locales/de.yml +11 -11
  33. data/config/locales/nl.yml +1 -1
  34. data/config/locales/vi.yml +22 -0
  35. data/config/locales/zh-CN.yml +1 -1
  36. data/docs/Quickstart.md +15 -77
  37. data/docs/Releasing.md +9 -6
  38. data/docs/Troubleshooting.md +147 -4
  39. data/docs/Upgrading.md +126 -0
  40. data/docs/shopify_app/authentication.md +124 -0
  41. data/docs/shopify_app/engine.md +82 -0
  42. data/docs/shopify_app/generators.md +127 -0
  43. data/docs/shopify_app/handling-access-scopes-changes.md +14 -0
  44. data/docs/shopify_app/script-tags.md +28 -0
  45. data/docs/shopify_app/session-repository.md +88 -0
  46. data/docs/shopify_app/testing.md +38 -0
  47. data/docs/shopify_app/webhooks.md +72 -0
  48. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +16 -7
  49. data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +10 -0
  50. data/lib/generators/shopify_app/home_controller/templates/index.html.erb +11 -11
  51. data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +2 -0
  52. data/lib/generators/shopify_app/install/install_generator.rb +36 -2
  53. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +2 -1
  54. data/lib/generators/shopify_app/install/templates/omniauth.rb +1 -0
  55. data/lib/generators/shopify_app/install/templates/shopify_app.js +1 -1
  56. data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +13 -4
  57. data/lib/generators/shopify_app/install/templates/shopify_provider.rb.tt +8 -0
  58. data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +27 -0
  59. data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +5 -0
  60. data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -1
  61. data/lib/generators/shopify_app/shopify_app_generator.rb +1 -1
  62. data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +5 -0
  63. data/lib/generators/shopify_app/user_model/templates/user.rb +1 -1
  64. data/lib/generators/shopify_app/user_model/user_model_generator.rb +27 -0
  65. data/lib/shopify_app/access_scopes/noop_strategy.rb +13 -0
  66. data/lib/shopify_app/access_scopes/shop_strategy.rb +24 -0
  67. data/lib/shopify_app/access_scopes/user_strategy.rb +41 -0
  68. data/lib/shopify_app/configuration.rb +25 -0
  69. data/lib/shopify_app/controller_concerns/itp.rb +0 -2
  70. data/lib/shopify_app/controller_concerns/login_protection.rb +14 -17
  71. data/lib/shopify_app/engine.rb +1 -0
  72. data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +1 -1
  73. data/lib/shopify_app/omniauth/omniauth_configuration.rb +64 -0
  74. data/lib/shopify_app/session/in_memory_shop_session_store.rb +9 -7
  75. data/lib/shopify_app/session/in_memory_user_session_store.rb +9 -7
  76. data/lib/shopify_app/session/jwt.rb +3 -1
  77. data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +58 -0
  78. data/lib/shopify_app/session/user_session_storage_with_scopes.rb +58 -0
  79. data/lib/shopify_app/utils.rb +12 -0
  80. data/lib/shopify_app/version.rb +1 -1
  81. data/lib/shopify_app.rb +11 -0
  82. data/package.json +1 -1
  83. data/service.yml +1 -4
  84. data/shopify_app.gemspec +5 -4
  85. data/translation.yml +1 -1
  86. data/yarn.lock +92 -123
  87. metadata +62 -16
  88. data/.github/ISSUE_TEMPLATE.md +0 -19
  89. data/.travis.yml +0 -27
  90. data/docs/install-on-dev-shop.png +0 -0
  91. data/docs/test-your-app.png +0 -0
  92. data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -20
@@ -1,2 +1 @@
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>
1
+ <svg width="140" height="140" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M79 55a9 9 0 00-18 0v8h18v-8zm6 8v-8a15 15 0 00-30 0v8h-5a2 2 0 00-2 2v20a15 15 0 0015 15h14a15 15 0 0015-15V65a2 2 0 00-2-2h-5zM70 90a3 3 0 01-3-3V75a3 3 0 116 0v12a3 3 0 01-3 3z" fill="#8C9196"/></svg>
@@ -0,0 +1,9 @@
1
+ (function() {
2
+ function redirect() {
3
+ var form = document.getElementById("redirect-form");
4
+ if (form) {
5
+ form.submit();
6
+ }
7
+ }
8
+ document.addEventListener("DOMContentLoaded", redirect);
9
+ })();
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApp
4
+ module EnsureAuthenticatedLinks
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ before_action :redirect_to_splash_page, if: :missing_expected_jwt?
9
+ end
10
+
11
+ private
12
+
13
+ def redirect_to_splash_page
14
+ splash_page_path = root_path(return_to: request.fullpath, shop: current_shopify_domain)
15
+ redirect_to(splash_page_path)
16
+ rescue ShopifyApp::LoginProtection::ShopifyDomainNotFound => error
17
+ Rails.logger.warn("[ShopifyApp::EnsureAuthenticatedLinks] Redirecting to login: [#{error.class}] "\
18
+ "Could not determine current shop domain")
19
+ redirect_to(ShopifyApp.configuration.login_url)
20
+ end
21
+
22
+ def missing_expected_jwt?
23
+ jwt_shopify_domain.blank?
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApp
4
+ module ShopAccessScopesVerification
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ before_action :login_on_scope_changes
9
+ end
10
+
11
+ protected
12
+
13
+ def login_on_scope_changes
14
+ redirect_to(shop_login) if scopes_mismatch?
15
+ end
16
+
17
+ private
18
+
19
+ def scopes_mismatch?
20
+ ShopifyApp.configuration.shop_access_scopes_strategy.update_access_scopes?(current_shopify_domain)
21
+ end
22
+
23
+ def current_shopify_domain
24
+ return if params[:shop].blank?
25
+ ShopifyApp::Utils.sanitize_shop_domain(params[:shop])
26
+ end
27
+
28
+ def shop_login
29
+ ShopifyApp::Utils.shop_login_url(shop: params[:shop], return_to: request.fullpath)
30
+ end
31
+ end
32
+ end
@@ -30,16 +30,12 @@ module ShopifyApp
30
30
  end
31
31
 
32
32
  def respond_with_user_token_flow
33
- Rails.logger.debug("[ShopifyApp::CallbackController] Redirecting for user token...")
34
33
  redirect_to(login_url_with_optional_shop)
35
34
  end
36
35
 
37
36
  def store_access_token_and_build_session
38
37
  if native_browser_request?
39
- Rails.logger.debug("[ShopifyApp::CallbackController] Not a JWT request. Resetting session options...")
40
38
  reset_session_options
41
- else
42
- Rails.logger.debug("[ShopifyApp::CallbackController] JWT request detected. Setting shopify session...")
43
39
  end
44
40
  set_shopify_session
45
41
  end
@@ -62,23 +58,38 @@ module ShopifyApp
62
58
 
63
59
  def respond_with_error
64
60
  if jwt_request?
65
- Rails.logger.debug("[ShopifyApp::CallbackController] Invalid JWT auth detected.")
66
61
  head(:unauthorized)
67
62
  else
68
- Rails.logger.debug("[ShopifyApp::CallbackController] Invalid non JWT auth detected.")
69
63
  flash[:error] = I18n.t('could_not_log_in')
70
64
  redirect_to(login_url_with_optional_shop)
71
65
  end
72
66
  end
73
67
 
68
+ # Override user_session_by_cookie from LoginProtection to bypass allow_cookie_authentication
69
+ # setting check because session cookies are justified at top level
70
+ def user_session_by_cookie
71
+ return unless session[:user_id].present?
72
+ ShopifyApp::SessionRepository.retrieve_user_session(session[:user_id])
73
+ end
74
+
74
75
  def start_user_token_flow?
75
76
  if jwt_request?
76
77
  false
77
78
  else
78
- ShopifyApp::SessionRepository.user_storage.present? && user_session.blank?
79
+ return false unless ShopifyApp::SessionRepository.user_storage.present?
80
+ update_user_access_scopes?
79
81
  end
80
82
  end
81
83
 
84
+ def update_user_access_scopes?
85
+ return true if user_session.blank?
86
+ user_access_scopes_strategy.update_access_scopes?(user_id: session[:user_id])
87
+ end
88
+
89
+ def user_access_scopes_strategy
90
+ ShopifyApp.configuration.user_access_scopes_strategy
91
+ end
92
+
82
93
  def jwt_request?
83
94
  jwt_shopify_domain || jwt_shopify_user_id
84
95
  end
@@ -95,6 +106,14 @@ module ShopifyApp
95
106
  auth_hash.uid
96
107
  end
97
108
 
109
+ def offline_access_token
110
+ ShopifyApp::SessionRepository.retrieve_shop_session_by_shopify_domain(shop_name)&.token
111
+ end
112
+
113
+ def online_access_token
114
+ ShopifyApp::SessionRepository.retrieve_user_session_by_shopify_user_id(associated_user_id)&.token
115
+ end
116
+
98
117
  def associated_user
99
118
  return unless auth_hash.dig('extra', 'associated_user').present?
100
119
 
@@ -109,6 +128,10 @@ module ShopifyApp
109
128
  auth_hash['credentials']['token']
110
129
  end
111
130
 
131
+ def access_scopes
132
+ auth_hash.dig('extra', 'scope')
133
+ end
134
+
112
135
  def reset_session_options
113
136
  request.session_options[:renew] = true
114
137
  session.delete(:_csrf_token)
@@ -118,7 +141,8 @@ module ShopifyApp
118
141
  session_store = ShopifyAPI::Session.new(
119
142
  domain: shop_name,
120
143
  token: token,
121
- api_version: ShopifyApp.configuration.api_version
144
+ api_version: ShopifyApp.configuration.api_version,
145
+ access_scopes: access_scopes
122
146
  )
123
147
 
124
148
  session[:shopify_user] = associated_user
@@ -138,7 +162,7 @@ module ShopifyApp
138
162
 
139
163
  WebhooksManager.queue(
140
164
  shop_name,
141
- shop_session&.token || user_session.token,
165
+ offline_access_token || online_access_token,
142
166
  ShopifyApp.configuration.webhooks
143
167
  )
144
168
  end
@@ -148,7 +172,7 @@ module ShopifyApp
148
172
 
149
173
  ScripttagsManager.queue(
150
174
  shop_name,
151
- shop_session&.token || user_session.token,
175
+ offline_access_token || online_access_token,
152
176
  ShopifyApp.configuration.scripttags
153
177
  )
154
178
  end
@@ -10,19 +10,14 @@ module ShopifyApp
10
10
  end
11
11
 
12
12
  def new
13
- if sanitized_shop_name.present?
14
- Rails.logger.debug("[ShopifyApp::SessionsController] Sanitized shop name present. Authenticating...")
15
- authenticate
16
- end
13
+ authenticate if sanitized_shop_name.present?
17
14
  end
18
15
 
19
16
  def create
20
- Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating...")
21
17
  authenticate
22
18
  end
23
19
 
24
20
  def enable_cookies
25
- Rails.logger.debug("[ShopifyApp::SessionsController] Enabling cookies...")
26
21
  return unless validate_shop_presence
27
22
 
28
23
  render(:enable_cookies, layout: false, locals: {
@@ -45,7 +40,6 @@ module ShopifyApp
45
40
  end
46
41
 
47
42
  def granted_storage_access
48
- Rails.logger.debug("[ShopifyApp::SessionsController] Granted storage access.")
49
43
  return unless validate_shop_presence
50
44
 
51
45
  session['shopify.granted_storage_access'] = true
@@ -56,7 +50,6 @@ module ShopifyApp
56
50
  end
57
51
 
58
52
  def destroy
59
- Rails.logger.debug("[ShopifyApp::SessionsController] Resetting session.")
60
53
  reset_session
61
54
  flash[:notice] = I18n.t('.logged_out')
62
55
  redirect_to(login_url_with_optional_shop)
@@ -73,23 +66,18 @@ module ShopifyApp
73
66
  set_user_tokens_option
74
67
 
75
68
  if user_agent_can_partition_cookies
76
- Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating with partitioning...")
77
69
  authenticate_with_partitioning
78
70
  else
79
- Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating normally...")
80
71
  authenticate_normally
81
72
  end
82
73
  end
83
74
 
84
75
  def authenticate_normally
85
76
  if request_storage_access?
86
- Rails.logger.debug("[ShopifyApp::SessionsController] Redirecting to request storage access...")
87
77
  redirect_to_request_storage_access
88
78
  elsif authenticate_in_context?
89
- Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating in context...")
90
79
  authenticate_in_context
91
80
  else
92
- Rails.logger.debug("[ShopifyApp::SessionsController] Authenticating at top level...")
93
81
  authenticate_at_top_level
94
82
  end
95
83
  end
@@ -104,10 +92,18 @@ module ShopifyApp
104
92
  end
105
93
  end
106
94
 
95
+ # Override shop_session_by_cookie from LoginProtection to bypass allow_cookie_authentication
96
+ # setting check because session cookies are justified at top level
97
+ def shop_session_by_cookie
98
+ return unless session[:shop_id].present?
99
+ ShopifyApp::SessionRepository.retrieve_shop_session(session[:shop_id])
100
+ end
101
+
107
102
  # rubocop:disable Lint/SuppressedException
108
103
  def set_user_tokens_option
109
- if shop_session.blank?
110
- Rails.logger.debug("[ShopifyApp::SessionsController] Shop session is blank.")
104
+ current_shop_session = shop_session
105
+
106
+ if current_shop_session.blank?
111
107
  session[:user_tokens] = false
112
108
  return
113
109
  end
@@ -115,9 +111,9 @@ module ShopifyApp
115
111
  session[:user_tokens] = ShopifyApp::SessionRepository.user_storage.present?
116
112
 
117
113
  ShopifyAPI::Session.temp(
118
- domain: shop_session.domain,
119
- token: shop_session.token,
120
- api_version: shop_session.api_version
114
+ domain: current_shop_session.domain,
115
+ token: current_shop_session.token,
116
+ api_version: current_shop_session.api_version
121
117
  ) do
122
118
  ShopifyAPI::Metafield.find(:token_validity_bogus_check)
123
119
  end
@@ -130,7 +126,6 @@ module ShopifyApp
130
126
  def validate_shop_presence
131
127
  @shop = sanitized_shop_name
132
128
  unless @shop
133
- Rails.logger.debug("[ShopifyApp::SessionsController] Invalid shop detected.")
134
129
  render_invalid_shop_error
135
130
  return false
136
131
  end
@@ -155,7 +150,11 @@ module ShopifyApp
155
150
  end
156
151
 
157
152
  def authenticate_in_context
158
- redirect_to("#{main_app.root_path}auth/shopify")
153
+ post_redirect_to_auth_shopify
154
+ end
155
+
156
+ def post_redirect_to_auth_shopify
157
+ render('shopify_app/shared/post_redirect_to_auth_shopify', layout: false)
159
158
  end
160
159
 
161
160
  def authenticate_at_top_level
@@ -1,6 +1,5 @@
1
1
  <style>
2
2
  .Polaris-Button {
3
- fill:#637381;
4
3
  position:relative;
5
4
  display:-webkit-inline-box;
6
5
  display:-ms-inline-flexbox;
@@ -15,12 +14,14 @@
15
14
  min-width:3.6rem;
16
15
  margin:0;
17
16
  padding:0.7rem 1.6rem;
18
- background:linear-gradient(to bottom, white, #f9fafb);
19
- border:1px solid #c4cdd5;
20
- box-shadow:0 1px 0 0 rgba(22, 29, 37, 0.05);
21
- border-radius:3px;
17
+ background-color:#ffffff;
18
+ border:1px solid #babfc3;
19
+ border-top-color: #c9cccf;
20
+ border-bottom-color: #babfc4;
21
+ box-shadow:0 1px 0 0 rgba(0, 0, 0, 0.05);
22
+ border-radius:4px;
22
23
  line-height:1;
23
- color:#212b36;
24
+ color:#202223;
24
25
  text-align:center;
25
26
  cursor:pointer;
26
27
  -webkit-user-select:none;
@@ -29,30 +30,44 @@
29
30
  user-select:none;
30
31
  text-decoration:none;
31
32
  transition-property:background, border, box-shadow;
32
- transition-duration:200ms;
33
+ transition-duration:100ms;
33
34
  transition-timing-function:cubic-bezier(0.64, 0, 0.35, 1);
34
35
  }
35
36
 
36
37
  .Polaris-Button:hover {
37
- background:linear-gradient(to bottom, #f9fafb, #f4f6f8);
38
- border-color:#c4cdd5;
38
+ background-color:#f6f6f7;
39
39
  }
40
40
 
41
41
  .Polaris-Button:focus {
42
- border-color:#5c6ac4;
43
42
  outline:0;
44
- box-shadow:0 0 0 1px #5c6ac4;
43
+ }
44
+
45
+ .Polaris-Button:focus:after {
46
+ box-shadow:0 0 0 .2rem #448fff;
47
+ }
48
+
49
+ .Polaris-Button:after {
50
+ content:'';
51
+ position:absolute;
52
+ z-index:1;
53
+ top:-.2rem;
54
+ right:-.2rem;
55
+ bottom:-.2rem;
56
+ left:-.2rem;
57
+ display:block;
58
+ pointer-events:none;
59
+ box-shadow:0 0 0 -.2rem #448fff;
60
+ transition:box-shadow 100ms cubic-bezier(0.64, 0, 0.35, 1);
61
+ border-radius:5px;
45
62
  }
46
63
 
47
64
  .Polaris-Button:active {
48
- background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
49
- border-color:#c4cdd5;
50
- box-shadow:0 0 0 0 transparent, inset 0 1px 1px 0 rgba(99, 115, 129, 0.1), inset 0 1px 4px 0 rgba(99, 115, 129, 0.2);
65
+ background-color:#f1f2f3);
51
66
  }
52
67
 
53
68
  .Polaris-Button__Content {
54
- font-size:1.5rem;
55
- font-weight:400;
69
+ font-size:1.4rem;
70
+ font-weight:500;
56
71
  line-height:1.6rem;
57
72
  text-transform:initial;
58
73
  letter-spacing:initial;
@@ -70,35 +85,25 @@
70
85
  min-height:1px;
71
86
  }
72
87
 
73
- @media (min-width: 40em) {
74
- .Polaris-Button__Content {
75
- font-size:1.4rem;
76
- }
77
- }
78
-
79
88
  .Polaris-Button--primary {
80
- background:linear-gradient(to bottom, #6371c7, #5563c1);
81
- border-color:#3f4eae;
82
- box-shadow:inset 0 1px 0 0 #6774c8, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 0 transparent;
89
+ background-color:#008060;
90
+ border-color:transparent;
91
+ border-width:0;
83
92
  color:white;
84
- fill:white;
85
93
  }
86
94
 
87
95
  .Polaris-Button--primary:hover {
88
- background:linear-gradient(to bottom, #5c6ac4, #4959bd);
89
- border-color:#3f4eae;
96
+ background-color:#006e52;
97
+ border-color:transparent;
90
98
  color:white;
91
- text-decoration:none;
92
99
  }
93
100
 
94
- .Polaris-Button--primary:focus {
95
- border-color:#202e78;
96
- box-shadow:inset 0 1px 0 0 #6f7bcb, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 1px #202e78;
101
+ .Polaris-Button--primary:active {
102
+ background-color:#005e46;
103
+ border-color:transparent;
97
104
  }
98
105
 
99
- .Polaris-Button--primary:active {
100
- background:linear-gradient(to bottom, #3f4eae, #3f4eae);
101
- border-color:#38469b;
102
- box-shadow:inset 0 0 0 0 transparent, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 1px 0 #38469b;
106
+ .Polaris-Button--sizeLarge {
107
+ padding:1.1rem 2.4rem;
103
108
  }
104
109
  </style>
@@ -11,7 +11,7 @@
11
11
 
12
12
  @media (min-width: 30.625em) {
13
13
  .Polaris-Card {
14
- border-radius:3px;
14
+ border-radius:8px;
15
15
  }
16
16
  }
17
17
 
@@ -24,10 +24,10 @@
24
24
  }
25
25
 
26
26
  .Polaris-Card__Section + .Polaris-Card__Section {
27
- border-top:1px solid #dfe3e8;
27
+ border-top:.1rem solid #e4e5e7;
28
28
  }
29
29
 
30
30
  .Polaris-Card__Section--subdued {
31
- background-color:#f9fafb;
31
+ background-color:#fafbfb;
32
32
  }
33
33
  </style>
@@ -11,8 +11,8 @@
11
11
  -ms-flex-align:center;
12
12
  align-items:center;
13
13
  width:100%;
14
- margin:2rem auto 0 auto;
15
- padding:2rem 0;
14
+ margin:0 auto;
15
+ padding:2rem 0 6rem;
16
16
  max-width:99.8rem;
17
17
  }
18
18
 
@@ -24,33 +24,22 @@
24
24
  }
25
25
 
26
26
  .Polaris-EmptyState__Section {
27
- position:relative;
28
27
  display:-webkit-box;
29
28
  display:-ms-flexbox;
30
29
  display:flex;
31
30
  -webkit-box-orient:vertical;
32
- -webkit-box-direction:normal;
33
- -ms-flex-direction:column;
34
- flex-direction:column;
31
+ -webkit-box-direction:reverse;
32
+ -ms-flex-direction:column-reverse;
33
+ flex-direction:column-reverse;
35
34
  -webkit-box-flex:1;
36
35
  -ms-flex:1 1 auto;
37
36
  flex:1 1 auto;
37
+ -webkit-box-align:center;
38
+ -ms-flex-align:center;
39
+ align-items:center;
38
40
  width:100%;
39
41
  }
40
42
 
41
- @media (min-width: 46.5em) {
42
- .Polaris-EmptyState__Section {
43
- left:2rem;
44
- -webkit-box-orient:horizontal;
45
- -webkit-box-direction:normal;
46
- -ms-flex-direction:row;
47
- flex-direction:row;
48
- -webkit-box-align:center;
49
- -ms-flex-align:center;
50
- align-items:center;
51
- }
52
- }
53
-
54
43
  .Polaris-EmptyState__ImageContainer,
55
44
  .Polaris-EmptyState__DetailsContainer {
56
45
  -webkit-box-flex:1;
@@ -58,6 +47,7 @@
58
47
  flex:1 1 auto;
59
48
  padding:0;
60
49
  margin:0;
50
+ text-align:center;
61
51
  }
62
52
 
63
53
  @media (min-width: 46.5em) {
@@ -68,37 +58,32 @@
68
58
  }
69
59
  }
70
60
 
71
- @media (max-width: 30.625em) {
72
- .Polaris-EmptyState__ImageContainer,
73
- .Polaris-EmptyState__DetailsContainer {
74
- overflow-x:hidden;
75
- }
76
- }
77
-
78
61
  .Polaris-EmptyState__Details {
79
- position:relative;
80
- z-index:10;
81
- padding:0 1.6rem;
82
- width:33.6rem;
83
- }
84
-
85
- @media (min-width: 30.625em) {
86
- .Polaris-EmptyState__Details {
87
- padding:0;
88
- }
62
+ max-width:40rem;
63
+ display:-webkit-box;
64
+ display:-ms-flexbox;
65
+ display: flex;
66
+ -webkit-box-orient:vertical;
67
+ -webkit-box-direction:normal;
68
+ -ms-flex-direction:column;
69
+ flex-direction: column;
70
+ -webkit-box-align:center;
71
+ -ms-flex-align:center;
72
+ align-items: center;
89
73
  }
90
74
 
91
75
  .Polaris-EmptyState__Content {
92
- font-size:1.6rem;
76
+ margin-top: 1.6rem;
77
+ font-size:1.5rem;
93
78
  font-weight:400;
94
- line-height:2.4rem;
95
- color:#637381;
79
+ line-height:2rem;
80
+ color:#6d7175;
81
+ padding-bottom: .8rem;
96
82
  }
97
83
 
98
84
  @media (min-width: 40em) {
99
85
  .Polaris-EmptyState__Content {
100
- font-size:2rem;
101
- line-height:2.8rem;
86
+ font-size:1.4rem;
102
87
  }
103
88
  }
104
89
 
@@ -107,23 +92,7 @@
107
92
  }
108
93
 
109
94
  .Polaris-EmptyState__Image {
110
- display: none;
111
- }
112
-
113
- @media (min-width: 30.625em) {
114
- .Polaris-EmptyState__Image {
115
- display: block;
116
- margin-left:-60%;
117
- margin-top:-30%;
118
- width:200%;
119
- }
120
- }
121
-
122
- @media (min-width: 46.5em) {
123
- .Polaris-EmptyState__Image {
124
- margin-top:0;
125
- margin-left:-90%;
126
- width:200%;
127
- }
95
+ margin: 0;
96
+ width: auto;
128
97
  }
129
98
  </style>
@@ -0,0 +1,56 @@
1
+ <style>
2
+ .Polaris-Label {
3
+ margin-bottom:.4rem;
4
+ }
5
+
6
+ .Polaris-Label__Text {
7
+ -webkit-tap-highlight-color:transparent;
8
+ }
9
+
10
+ .Polaris-TextField {
11
+ position:relative;
12
+ margin-bottom:1.6rem;
13
+ }
14
+
15
+ .Polaris-TextField--InlineError {
16
+ margin-bottom:.4rem;
17
+ }
18
+
19
+ .Polaris-TextField__Input {
20
+ width:100%;
21
+ padding:.5rem 1.2rem;
22
+ border:1px solid #c9cccf;
23
+ border-top-color:#aeb4b9;
24
+ border-radius:4px;
25
+ box-shadow:none;
26
+ line-height:2.4rem;
27
+ }
28
+
29
+ .Polaris-TextField__Input:focus {
30
+ outline:none;
31
+ }
32
+
33
+ .Polaris-TextField__Backdrop:after {
34
+ content:'';
35
+ position:absolute;
36
+ z-index:1;
37
+ top:-.2rem;
38
+ right:-.2rem;
39
+ bottom:-.2rem;
40
+ left:-.2rem;
41
+ display:block;
42
+ pointer-events:none;
43
+ box-shadow:0 0 0 -.2rem #448fff;
44
+ transition:box-shadow .1s cubic-bezier(0.64, 0, 0.35, 1);
45
+ border-radius:5px;
46
+ }
47
+
48
+ .Polaris-TextField__Input:focus~.Polaris-TextField__Backdrop:after {
49
+ box-shadow:0 0 0 .2rem #448fff;
50
+ }
51
+
52
+ .Polaris-InlineError {
53
+ color:#d72c0d;
54
+ margin-bottom:1.6rem;
55
+ }
56
+ </style>