shopify_app 13.2.0 → 20.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -0
- data/.github/ISSUE_TEMPLATE/bug-report.md +63 -0
- data/.github/ISSUE_TEMPLATE/config.yml +1 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +33 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
- data/.github/workflows/build.yml +40 -0
- data/.github/workflows/cla.yml +22 -0
- data/.github/workflows/close-waiting-for-response-issues.yml +20 -0
- data/.github/workflows/release.yml +24 -0
- data/.github/workflows/remove-labels-on-activity.yml +16 -0
- data/.github/workflows/rubocop.yml +22 -0
- data/.github/workflows/stale.yml +31 -0
- data/.gitignore +1 -2
- data/.nvmrc +1 -1
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +221 -0
- data/CONTRIBUTING.md +81 -0
- data/Gemfile +5 -2
- data/Gemfile.lock +248 -0
- data/README.md +74 -563
- data/Rakefile +4 -3
- data/SECURITY.md +59 -0
- data/app/assets/images/storage_access.svg +1 -2
- data/app/assets/javascripts/shopify_app/app_bridge_3.1.1.js +10 -0
- data/app/assets/javascripts/shopify_app/app_bridge_redirect.js +22 -0
- data/app/assets/javascripts/shopify_app/app_bridge_utils_3.1.1.js +1 -0
- data/app/assets/javascripts/shopify_app/post_redirect.js +9 -0
- data/app/assets/javascripts/shopify_app/redirect.js +10 -14
- data/app/assets/javascripts/shopify_app/storage_access.js +5 -10
- data/app/assets/javascripts/shopify_app/top_level_interaction.js +1 -1
- data/app/controllers/concerns/shopify_app/authenticated.rb +4 -0
- data/app/controllers/concerns/shopify_app/ensure_authenticated_links.rb +39 -0
- data/app/controllers/concerns/shopify_app/require_known_shop.rb +48 -0
- data/app/controllers/concerns/shopify_app/shop_access_scopes_verification.rb +40 -0
- data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
- data/app/controllers/shopify_app/callback_controller.rb +56 -77
- data/app/controllers/shopify_app/extension_verification_controller.rb +2 -7
- data/app/controllers/shopify_app/sessions_controller.rb +33 -117
- data/app/controllers/shopify_app/webhooks_controller.rb +5 -26
- data/app/views/shopify_app/partials/_button_styles.html.erb +41 -36
- data/app/views/shopify_app/partials/_card_styles.html.erb +3 -3
- data/app/views/shopify_app/partials/_empty_state_styles.html.erb +28 -59
- data/app/views/shopify_app/partials/_form_styles.html.erb +56 -0
- data/app/views/shopify_app/partials/_layout_styles.html.erb +16 -1
- data/app/views/shopify_app/partials/_typography_styles.html.erb +6 -6
- data/app/views/shopify_app/sessions/enable_cookies.html.erb +2 -7
- data/app/views/shopify_app/sessions/new.html.erb +38 -110
- data/app/views/shopify_app/sessions/request_storage_access.html.erb +12 -12
- data/app/views/shopify_app/sessions/top_level_interaction.html.erb +21 -22
- data/app/views/shopify_app/shared/post_redirect_to_auth_shopify.html.erb +13 -0
- data/app/views/shopify_app/shared/redirect.html.erb +2 -2
- data/config/locales/de.yml +11 -11
- data/config/locales/ja.yml +4 -4
- data/config/locales/nl.yml +2 -2
- data/config/locales/th.yml +4 -4
- data/config/locales/vi.yml +22 -0
- data/config/locales/zh-CN.yml +2 -2
- data/config/routes.rb +20 -12
- data/docs/Quickstart.md +19 -83
- data/docs/Releasing.md +18 -15
- data/docs/Troubleshooting.md +140 -5
- data/docs/Upgrading.md +247 -0
- data/docs/shopify_app/authentication.md +128 -0
- data/docs/shopify_app/content-security-policy.md +10 -0
- data/docs/shopify_app/engine.md +82 -0
- data/docs/shopify_app/generators.md +127 -0
- data/docs/shopify_app/handling-access-scopes-changes.md +24 -0
- data/docs/shopify_app/script-tags.md +28 -0
- data/docs/shopify_app/session-repository.md +88 -0
- data/docs/shopify_app/testing.md +38 -0
- data/docs/shopify_app/webhooks.md +72 -0
- data/karma.conf.js +1 -1
- data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +10 -9
- data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
- data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +4 -3
- data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +15 -14
- data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb.tt +9 -1
- data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +7 -6
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +2 -1
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +1 -1
- data/lib/generators/shopify_app/authenticated_controller/authenticated_controller_generator.rb +4 -4
- data/lib/generators/shopify_app/controllers/controllers_generator.rb +5 -4
- data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +27 -4
- data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +12 -2
- data/lib/generators/shopify_app/home_controller/templates/index.html.erb +74 -16
- data/lib/generators/shopify_app/home_controller/templates/unauthenticated_home_controller.rb +16 -0
- data/lib/generators/shopify_app/install/install_generator.rb +52 -40
- data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +5 -2
- data/lib/generators/shopify_app/install/templates/flash_messages.js +0 -2
- data/lib/generators/shopify_app/install/templates/session_store.rb +2 -1
- data/lib/generators/shopify_app/install/templates/shopify_app.js +1 -1
- data/lib/generators/shopify_app/install/templates/shopify_app.rb.tt +43 -5
- data/lib/generators/shopify_app/install/templates/shopify_app_importmap.js +13 -0
- data/lib/generators/shopify_app/products_controller/products_controller_generator.rb +19 -0
- data/lib/generators/shopify_app/products_controller/templates/products_controller.rb +8 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/rotate_shopify_token_job_generator.rb +4 -4
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token.rake +1 -0
- data/lib/generators/shopify_app/rotate_shopify_token_job/templates/rotate_shopify_token_job.rb +1 -1
- data/lib/generators/shopify_app/routes/routes_generator.rb +6 -5
- data/lib/generators/shopify_app/routes/templates/routes.rb +5 -5
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +35 -7
- data/lib/generators/shopify_app/shop_model/templates/db/migrate/add_shop_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +2 -1
- data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
- data/lib/generators/shopify_app/user_model/templates/db/migrate/add_user_access_scopes_column.erb +5 -0
- data/lib/generators/shopify_app/user_model/templates/user.rb +2 -1
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +35 -7
- data/lib/generators/shopify_app/views/views_generator.rb +5 -4
- data/lib/shopify_app/access_scopes/noop_strategy.rb +13 -0
- data/lib/shopify_app/access_scopes/shop_strategy.rb +24 -0
- data/lib/shopify_app/access_scopes/user_strategy.rb +41 -0
- data/lib/shopify_app/configuration.rb +58 -11
- data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +4 -4
- data/lib/shopify_app/controller_concerns/csrf_protection.rb +16 -0
- data/lib/shopify_app/controller_concerns/embedded_app.rb +6 -3
- data/lib/shopify_app/controller_concerns/ensure_billing.rb +243 -0
- data/lib/shopify_app/controller_concerns/frame_ancestors.rb +16 -0
- data/lib/shopify_app/controller_concerns/itp.rb +3 -3
- data/lib/shopify_app/controller_concerns/localization.rb +1 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +105 -90
- data/lib/shopify_app/controller_concerns/payload_verification.rb +25 -0
- data/lib/shopify_app/controller_concerns/redirect_for_embedded.rb +36 -0
- data/lib/shopify_app/controller_concerns/sanitized_params.rb +36 -0
- data/lib/shopify_app/controller_concerns/webhook_verification.rb +3 -18
- data/lib/shopify_app/engine.rb +26 -11
- data/lib/shopify_app/errors.rb +34 -0
- data/lib/shopify_app/jobs/scripttags_manager_job.rb +2 -2
- data/lib/shopify_app/jobs/webhooks_manager_job.rb +4 -5
- data/lib/shopify_app/managers/scripttags_manager.rb +12 -6
- data/lib/shopify_app/managers/webhooks_manager.rb +62 -42
- data/lib/shopify_app/middleware/jwt_middleware.rb +6 -3
- data/lib/shopify_app/session/in_memory_session_store.rb +2 -3
- data/lib/shopify_app/session/in_memory_shop_session_store.rb +10 -7
- data/lib/shopify_app/session/in_memory_user_session_store.rb +10 -7
- data/lib/shopify_app/session/jwt.rb +19 -16
- data/lib/shopify_app/session/null_user_session_store.rb +2 -1
- data/lib/shopify_app/session/session_repository.rb +40 -2
- data/lib/shopify_app/session/session_storage.rb +4 -6
- data/lib/shopify_app/session/shop_session_storage.rb +6 -6
- data/lib/shopify_app/session/shop_session_storage_with_scopes.rb +57 -0
- data/lib/shopify_app/session/user_session_storage.rb +20 -7
- data/lib/shopify_app/session/user_session_storage_with_scopes.rb +71 -0
- data/lib/shopify_app/test_helpers/all.rb +2 -1
- data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +4 -3
- data/lib/shopify_app/utils.rb +14 -7
- data/lib/shopify_app/version.rb +2 -1
- data/lib/shopify_app.rb +52 -29
- data/package.json +7 -8
- data/service.yml +1 -5
- data/shopify_app.gemspec +22 -20
- data/translation.yml +1 -1
- data/yarn.lock +2173 -2206
- metadata +110 -56
- data/.github/ISSUE_TEMPLATE.md +0 -14
- data/.github/probots.yml +0 -2
- data/.travis.yml +0 -28
- data/config/locales/hi.yml +0 -23
- data/config/locales/ms.yml +0 -22
- data/docs/install-on-dev-shop.png +0 -0
- data/docs/test-your-app.png +0 -0
- data/lib/generators/shopify_app/install/templates/omniauth.rb +0 -3
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -20
- data/lib/generators/shopify_app/install/templates/user_agent.rb +0 -6
- data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +0 -34
- data/package-lock.json +0 -7245
@@ -5,6 +5,7 @@
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
6
6
|
<base target="_top">
|
7
7
|
<title>Redirecting…</title>
|
8
|
+
<%= render 'shopify_app/partials/card_styles' %>
|
8
9
|
<%= render 'shopify_app/partials/layout_styles' %>
|
9
10
|
<%= render 'shopify_app/partials/typography_styles' %>
|
10
11
|
<%= render 'shopify_app/partials/button_styles' %>
|
@@ -15,15 +16,9 @@
|
|
15
16
|
}
|
16
17
|
</style>
|
17
18
|
|
18
|
-
<script>
|
19
|
-
window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
|
20
|
-
window.shopOrigin = "https://<%= @shop %>";
|
21
|
-
window.redirectUrl = "<%= @url %>";
|
22
|
-
</script>
|
23
|
-
|
24
19
|
<%= javascript_include_tag('shopify_app/top_level', crossorigin: 'anonymous', integrity: true) %>
|
25
20
|
</head>
|
26
|
-
<body>
|
21
|
+
<body data-api-key="<%= ShopifyApp.configuration.api_key %>" data-shop-origin="https://<%= @shop %>" data-host="<%= @host %>" data-redirect-url="<%= @url %>">
|
27
22
|
<main id="TopLevelInteractionContent">
|
28
23
|
<div class="Polaris-Page">
|
29
24
|
<div class="Polaris-Page__Content">
|
@@ -31,26 +26,30 @@
|
|
31
26
|
<div class="Polaris-Layout__Section">
|
32
27
|
<div class="Polaris-Stack Polaris-Stack--vertical">
|
33
28
|
<div class="Polaris-Stack__Item">
|
34
|
-
<div class="Polaris-
|
35
|
-
<div class="Polaris-
|
36
|
-
<div class="Polaris-
|
37
|
-
<div class="Polaris-
|
38
|
-
<div class="Polaris-
|
39
|
-
<
|
40
|
-
|
41
|
-
|
29
|
+
<div class="Polaris-Card">
|
30
|
+
<div class="Polaris-Card__Section">
|
31
|
+
<div class="Polaris-EmptyState">
|
32
|
+
<div class="Polaris-EmptyState__Section">
|
33
|
+
<div class="Polaris-EmptyState__DetailsContainer">
|
34
|
+
<div class="Polaris-EmptyState__Details">
|
35
|
+
<div class="Polaris-TextContainer">
|
36
|
+
<h1 class="Polaris-DisplayText Polaris-DisplayText--sizeSmall"><%= I18n.t('top_level_interaction_heading', app: ShopifyApp.configuration.application_name) %></h1>
|
37
|
+
<div class="Polaris-EmptyState__Content">
|
38
|
+
<p><%= I18n.t('top_level_interaction_body', app: ShopifyApp.configuration.application_name) %></p>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<div class="Polaris-EmptyState__Actions">
|
42
|
+
<div class="Polaris-Stack Polaris-Stack--alignmentCenter">
|
43
|
+
<div class="Polaris-Stack__Item"><button type="button" id="TopLevelInteractionButton" class="Polaris-Button Polaris-Button--primary Polaris-Button--sizeLarge"><span class="Polaris-Button__Content"><span class="Polaris-Button__Icon"></span><span><%= I18n.t('top_level_interaction_action') %></span></span></button></div>
|
44
|
+
</div>
|
45
|
+
</div>
|
42
46
|
</div>
|
43
47
|
</div>
|
44
|
-
<div class="Polaris-
|
45
|
-
|
46
|
-
<div class="Polaris-Stack__Item"><button type="button" id="TopLevelInteractionButton" class="Polaris-Button Polaris-Button--primary Polaris-Button--sizeLarge"><span class="Polaris-Button__Content"><span class="Polaris-Button__Icon"></span><span><%= I18n.t('top_level_interaction_action') %></span></span></button></div>
|
47
|
-
</div>
|
48
|
+
<div class="Polaris-EmptyState__ImageContainer">
|
49
|
+
<%= image_tag 'storage_access.svg', role: "presentation", alt: "", class: "Polaris-EmptyState__Image" %>
|
48
50
|
</div>
|
49
51
|
</div>
|
50
52
|
</div>
|
51
|
-
<div class="Polaris-EmptyState__ImageContainer">
|
52
|
-
<%= image_tag 'storage_access.svg', role: "presentation", alt: "", class: "Polaris-EmptyState__Image" %>
|
53
|
-
</div>
|
54
53
|
</div>
|
55
54
|
</div>
|
56
55
|
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
6
|
+
<base target="_top">
|
7
|
+
<title>Redirecting…</title>
|
8
|
+
<%= javascript_include_tag('shopify_app/post_redirect', crossorigin: 'anonymous', integrity: true) %>
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<%= form_tag '/auth/shopify', id: 'redirect-form' %>
|
12
|
+
</body>
|
13
|
+
</html>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html lang="
|
2
|
+
<html lang="<%= I18n.locale %>">
|
3
3
|
<head>
|
4
4
|
<meta charset="utf-8" />
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<title>Redirecting…</title>
|
8
8
|
<%= javascript_include_tag('shopify_app/redirect', crossorigin: 'anonymous', integrity: true) %>
|
9
9
|
</head>
|
10
|
-
<body>
|
10
|
+
<body data-api-key="<%= ShopifyApp.configuration.api_key %>" data-shop-origin="<%= current_shopify_domain %>" data-host="<%= params[:host] %>" >
|
11
11
|
<%=
|
12
12
|
content_tag(:div, nil,
|
13
13
|
id: 'redirection-target',
|
data/config/locales/de.yml
CHANGED
@@ -4,19 +4,19 @@ de:
|
|
4
4
|
could_not_log_in: Shopify Store Login fehlgeschlagen
|
5
5
|
invalid_shop_url: Ungültige Shop-Domain
|
6
6
|
enable_cookies_heading: Cookies von %{app} aktivieren
|
7
|
-
enable_cookies_body:
|
8
|
-
|
9
|
-
enable_cookies_footer: Mithilfe von Cookies kann die App
|
10
|
-
|
11
|
-
Sie laufen nach 30 Tagen ab.
|
7
|
+
enable_cookies_body: Du musst Cookies in diesem Browser manuell aktivieren, um %{app}
|
8
|
+
in Shopify verwenden zu können.
|
9
|
+
enable_cookies_footer: Mithilfe von Cookies kann die App dich authentifizieren,
|
10
|
+
indem deine Einstellungen und personenbezogenen Daten vorübergehend gespeichert
|
11
|
+
werden. Sie laufen nach 30 Tagen ab.
|
12
12
|
enable_cookies_action: Cookies aktivieren
|
13
|
-
top_level_interaction_heading:
|
14
|
-
top_level_interaction_body:
|
15
|
-
auf Cookies bitten, bevor Shopify sie für
|
13
|
+
top_level_interaction_heading: Dein Browser muss %{app} authentifizieren
|
14
|
+
top_level_interaction_body: Dein Browser verlangt, dass Apps wie %{app} dich um
|
15
|
+
Zugriff auf Cookies bitten, bevor Shopify sie für dich öffnen kann.
|
16
16
|
top_level_interaction_action: Weiter
|
17
17
|
request_storage_access_heading: "%{app} braucht Zugriff auf Cookies"
|
18
|
-
request_storage_access_body: Damit kann die App
|
19
|
-
Einstellungen und personenbezogenen Daten vorübergehend gespeichert werden.
|
20
|
-
|
18
|
+
request_storage_access_body: Damit kann die App dich authentifizieren, indem deine
|
19
|
+
Einstellungen und personenbezogenen Daten vorübergehend gespeichert werden. Klicke
|
20
|
+
auf "Weiter" und erlaube Cookies, um die App zu verwenden.
|
21
21
|
request_storage_access_footer: Cookies laufen nach 30 Tagen ab.
|
22
22
|
request_storage_access_action: Weiter
|
data/config/locales/ja.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
---
|
2
2
|
ja:
|
3
|
-
logged_out:
|
3
|
+
logged_out: ログアウトに成功しました
|
4
4
|
could_not_log_in: Shopifyストアにログインできませんでした
|
5
5
|
invalid_shop_url: ショップのドメインが無効です
|
6
6
|
enable_cookies_heading: "%{app}からのCookieを有効にする"
|
@@ -10,8 +10,8 @@ ja:
|
|
10
10
|
top_level_interaction_heading: お使いのブラウザを更新する必要があります%{app}
|
11
11
|
top_level_interaction_body: Shopifyがアプリを開けるように、ブラウザーはCookieにアクセスするための%{app}のようなアプリが必要です。
|
12
12
|
top_level_interaction_action: 続ける
|
13
|
-
request_storage_access_heading: "%{app}
|
14
|
-
request_storage_access_body: Cookieを使用すると、個人情報を一時的に保存することで、アプリ認証を受けることができます。[
|
15
|
-
|
13
|
+
request_storage_access_heading: "%{app}はCookieへのアクセス許可が必要です"
|
14
|
+
request_storage_access_body: Cookieを使用すると、個人情報を一時的に保存することで、アプリ認証を受けることができます。[続ける]
|
15
|
+
をクリックすると、アプリはCookieを利用します。
|
16
16
|
request_storage_access_footer: Cookieは30日後に有効期限が切れます。
|
17
17
|
request_storage_access_action: 続ける
|
data/config/locales/nl.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
nl:
|
3
|
-
logged_out:
|
4
|
-
could_not_log_in: Kon niet
|
3
|
+
logged_out: Je bent afgemeld
|
4
|
+
could_not_log_in: Kon niet inloggen bij Shopify-winkel
|
5
5
|
invalid_shop_url: Ongeldig winkeldomein
|
6
6
|
enable_cookies_heading: Schakel cookies in van %{app}
|
7
7
|
enable_cookies_body: Je moet cookies in deze browser handmatig inschakelen om %{app}
|
data/config/locales/th.yml
CHANGED
@@ -3,12 +3,12 @@ th:
|
|
3
3
|
logged_out: ออกจากระบบสำเร็จ
|
4
4
|
could_not_log_in: ไม่สามารถเข้าสู่ระบบร้านค้า Shopify ได้
|
5
5
|
invalid_shop_url: โดเมนร้านค้าไม่ถูกต้อง
|
6
|
-
enable_cookies_heading:
|
7
|
-
enable_cookies_body:
|
8
|
-
|
6
|
+
enable_cookies_heading: เปิดใช้คุกกี้จาก %{app}
|
7
|
+
enable_cookies_body: คุณต้องเปิดใช้คุกกี้ด้วยตนเองในเบราว์เซอร์นี้เพื่อใช้งาน %{app}
|
8
|
+
ภายใน Shopify
|
9
9
|
enable_cookies_footer: คุกกี้ช่วยให้แอปตรวจสอบความถูกต้องของคุณด้วยการจัดเก็บความชื่นชอบและข้อมูลส่วนตัวของคุณชั่วคราว
|
10
10
|
คุกกี้จะหมดอายุหลังจาก 30 วัน
|
11
|
-
enable_cookies_action:
|
11
|
+
enable_cookies_action: เปิดใช้คุกกี้
|
12
12
|
top_level_interaction_heading: เบราว์เซอร์ของคุณต้องรับรองความถูกต้องของ %{app}
|
13
13
|
top_level_interaction_body: เบราว์เซอร์ของคุณต้องการแอปอย่าง %{app} เพื่อขอให้คุณเข้าถึงคุกกี้ก่อนที่
|
14
14
|
Shopify จะสามารถเปิดมันให้คุณได้
|
@@ -0,0 +1,22 @@
|
|
1
|
+
---
|
2
|
+
vi:
|
3
|
+
logged_out: Đã đăng xuất thành công
|
4
|
+
could_not_log_in: Không thể đăng nhập vào cửa hàng trên Shopify
|
5
|
+
invalid_shop_url: Miền cửa hàng không hợp lệ
|
6
|
+
enable_cookies_heading: Bật cookie từ %{app}
|
7
|
+
enable_cookies_body: Bạn phải bật cookie trong trình duyệt này theo cách thủ công
|
8
|
+
để sử dụng %{app} trong Shopify.
|
9
|
+
enable_cookies_footer: Cookie cho phép ứng dụng xác thực bạn bằng cách tạm thời
|
10
|
+
lưu trữ tùy chọn và thông tin cá nhân của bạn. Những thông tin này sẽ hết hạn
|
11
|
+
sau 30 ngày.
|
12
|
+
enable_cookies_action: Bật cookie
|
13
|
+
top_level_interaction_heading: Trình duyệt của bạn cần xác thực %{app}
|
14
|
+
top_level_interaction_body: Trình duyệt của bạn cần các ứng dụng như %{app} để yêu
|
15
|
+
cầu quyền truy cập vào cookie thì Shopify mới có thể mở giúp bạn.
|
16
|
+
top_level_interaction_action: Tiếp tục
|
17
|
+
request_storage_access_heading: "%{app} cần quyền truy cập cookie"
|
18
|
+
request_storage_access_body: Nhờ vậy, ứng dụng có thể xác thực bạn bằng cách tạm
|
19
|
+
thời lưu trữ thông tin cá nhân của bạn. Nhấp vào tiếp tục và cho phép cookie sử
|
20
|
+
dụng ứng dụng.
|
21
|
+
request_storage_access_footer: Cookie sẽ hết hạn sau 30 ngày.
|
22
|
+
request_storage_access_action: Tiếp tục
|
data/config/locales/zh-CN.yml
CHANGED
@@ -8,9 +8,9 @@ zh-CN:
|
|
8
8
|
enable_cookies_footer: Cookie 使此应用能够通过暂时存储您的偏好设置和个人信息来验证您的身份。这些信息将在 30 天后过期。
|
9
9
|
enable_cookies_action: 启用 Cookie
|
10
10
|
top_level_interaction_heading: 您的浏览器需要对 %{app} 进行验证
|
11
|
-
top_level_interaction_body: 您的浏览器要求类似 %{app}
|
11
|
+
top_level_interaction_body: 您的浏览器要求类似 %{app} 的应用向您申请访问 Cookie,之后 Shopify 才能为您打开它。
|
12
12
|
top_level_interaction_action: 继续
|
13
13
|
request_storage_access_heading: "%{app} 需要访问 Cookie"
|
14
|
-
request_storage_access_body:
|
14
|
+
request_storage_access_body: 这使此应用能够通过暂时存储您的个人信息来验证您的身份。点击继续并启用 Cookie 以使用此应用。
|
15
15
|
request_storage_access_footer: Cookie 将在 30 天后过期。
|
16
16
|
request_storage_access_action: 继续
|
data/config/routes.rb
CHANGED
@@ -1,23 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
ShopifyApp::Engine.routes.draw do
|
4
|
+
login_url = ShopifyApp.configuration.login_url.gsub(/^#{ShopifyApp.configuration.root_url}/, "")
|
5
|
+
login_callback_url = ShopifyApp.configuration.login_callback_url.gsub(/^#{ShopifyApp.configuration.root_url}/, "")
|
6
|
+
|
3
7
|
controller :sessions do
|
4
|
-
get
|
5
|
-
post
|
6
|
-
get
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
:
|
12
|
-
|
13
|
-
get 'logout' => :destroy, :as => :logout
|
8
|
+
get login_url => :new, :as => :login
|
9
|
+
post login_url => :create, :as => :authenticate
|
10
|
+
get "logout" => :destroy, :as => :logout
|
11
|
+
|
12
|
+
# Kept to prevent apps relying on these routes from breaking
|
13
|
+
if login_url.gsub(%r{^/}, "") != "login"
|
14
|
+
get "login" => :new, :as => :default_login
|
15
|
+
post "login" => :create, :as => :default_authenticate
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
controller :callback do
|
17
|
-
get
|
20
|
+
get login_callback_url => :callback
|
21
|
+
|
22
|
+
# Kept to prevent apps relying on these routes from breaking
|
23
|
+
if login_callback_url.gsub(%r{^/}, "") != "auth/shopify/callback"
|
24
|
+
get "auth/shopify/callback" => :default_callback
|
25
|
+
end
|
18
26
|
end
|
19
27
|
|
20
28
|
namespace :webhooks do
|
21
|
-
post
|
29
|
+
post ":type" => :receive
|
22
30
|
end
|
23
31
|
end
|
data/docs/Quickstart.md
CHANGED
@@ -1,103 +1,39 @@
|
|
1
|
-
Quickstart
|
2
|
-
==========
|
1
|
+
# Quickstart
|
3
2
|
|
4
|
-
|
3
|
+
This guide assumes you have completed the steps to create a new Rails app using the Shopify App gem found in the [*Usage*](/README.md#usage) section of the project's [*README*](/README.md).
|
5
4
|
|
6
|
-
|
7
|
-
--------------------------------
|
5
|
+
#### Table of contents
|
8
6
|
|
9
|
-
|
7
|
+
[Setup SSH tunnel for development](#setup-ssh-tunnel-for-development)
|
10
8
|
|
11
|
-
|
12
|
-
$ rails new test-app --database=postgresql
|
13
|
-
$ cd test-app
|
14
|
-
$ git init
|
15
|
-
$ git add .
|
16
|
-
$ git commit -m 'new rails app'
|
17
|
-
```
|
18
|
-
|
19
|
-
2. Create a new Heroku app
|
20
|
-
--------------------------
|
21
|
-
|
22
|
-
The next step is to create a new Heroku app to host your application. If you haven't got a Heroku account yet, create a free account [here](https://www.heroku.com/).
|
23
|
-
|
24
|
-
Head to the Heroku dashboard and create a new app, or run the following commands with the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli#download-and-install) installed, substituting `name` for the name of your own app:
|
25
|
-
|
26
|
-
CLI:
|
27
|
-
```sh
|
28
|
-
$ heroku create name
|
29
|
-
$ heroku git:remote -a name
|
30
|
-
```
|
31
|
-
|
32
|
-
Once you have created an app on Heroku, we need to let Git know where the Heroku server is so we can deploy to it later. Copy the app's name from your Heroku dashboard and substitute `appname.git` with the name you chose earlier:
|
9
|
+
[Use Shopify App Bridge to embed your app in the Shopify Admin](#use-shopify-app-bridge-to-embed-your-app-in-the-shopify-admin)
|
33
10
|
|
34
|
-
|
35
|
-
```sh
|
36
|
-
# https://dashboard.heroku.com/new
|
37
|
-
$ git remote add heroku git@heroku.com:appname.git
|
38
|
-
```
|
11
|
+
## Setup SSH tunnel for development
|
39
12
|
|
40
|
-
|
41
|
-
-----------------------------------------
|
42
|
-
* Create a Shopify app in the [Partners dashboard](https://partner.shopify.com). For this tutorial, you can choose either a public or custom app, but you can [learn about App Types here.](https://help.shopify.com/en/manual/apps/app-types)
|
43
|
-
[https://app.shopify.com/services/partners/api_clients](https://app.shopify.com/services/partners/api_clients)
|
44
|
-
* Set the callback url to `https://<appname>.herokuapp.com/`
|
45
|
-
* Choose an embedded app
|
46
|
-
* Set the app's `redirect_uri` to `https://<appname>.herokuapp.com/auth/shopify/callback`
|
13
|
+
Your local app needs to be accessible from the public Internet in order to install it on a Shopify store, to use the [App Proxy Controller](/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb) or receive [webhooks](/docs/shopify_app/webhooks.md).
|
47
14
|
|
48
|
-
|
49
|
-
----------------------------
|
15
|
+
In order to receive requests securely, you'll need to setup a tunnel from the internet to localhost. You can use [Cloudflare](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/run-tunnel/trycloudflare/) for this.
|
50
16
|
|
51
|
-
|
17
|
+
To do so, [install the `cloudflared` CLI tool](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation/), and run:
|
52
18
|
|
53
19
|
```sh
|
54
|
-
|
55
|
-
|
20
|
+
# The port must be the same as the one you run the Rails app on later. We use the Rails default below.
|
21
|
+
cloudflared tunnel --url http://localhost:3000
|
56
22
|
```
|
57
23
|
|
58
|
-
|
59
|
-
|
60
|
-
5. Run the ShopifyApp generator
|
61
|
-
-------------------------------
|
24
|
+
Keep this window running to keep the tunnel and make note of the URL this command prints out. The URL will look like `https://some-random-words.trycloudflare.com`.
|
62
25
|
|
63
|
-
|
26
|
+
Visit the "App Setup" section for your app in the [Shopify Partners dashboard](https://partners.shopify.com/organizations). Set the URL as "App URL" on this settings page and add it to the "Allowed redirection URL(s)", after appending `/auth/shopify/callback` to the end (e.g. `https://some-random-words.trycloudflare.com/auth/shopify/callback`).
|
64
27
|
|
28
|
+
Add the same URL as `HOST` in your `.env` file e.g.
|
65
29
|
```sh
|
66
|
-
|
67
|
-
$ rails generate shopify_app --api_key <shopify_api_key> --secret <shopify_api_secret>
|
68
|
-
$ git add .
|
69
|
-
$ git commit -m 'generated shopify app'
|
30
|
+
HOST='https://some-random-words.trycloudflare.com/'
|
70
31
|
```
|
71
32
|
|
72
|
-
|
73
|
-
|
74
|
-
We recommend adding a gem or utilizing environment variables (`.env`) to handle your keys before releasing your app. [Learn more about using environment variables.](https://www.honeybadger.io/blog/ruby-guide-environment-variables/)
|
75
|
-
|
76
|
-
6. Deploy your app
|
77
|
-
---------
|
78
|
-
|
79
|
-
Once you've generated your app, push it into your Heroku environment to see it up and running:
|
80
|
-
```sh
|
81
|
-
$ git push heroku
|
82
|
-
$ heroku run rake db:migrate
|
83
|
-
```
|
84
|
-
|
85
|
-
7. Install the App!
|
86
|
-
-------------------
|
87
|
-
|
88
|
-
Ensure you have created a [development store](https://help.shopify.com/en/api/getting-started/making-your-first-request#create-a-development-store) using the Shopify Partner Dashboard. If you don't already have one, [create one by following these instructions](https://help.shopify.com/en/api/getting-started/making-your-first-request#create-a-development-store).
|
89
|
-
|
90
|
-
##### Note: The following step will cause your store to become `transfer-disabled.` Read more about store transfer and why it's important [here](https://help.shopify.com/en/api/guides/store-transfers#transfer-disabled-stores). This is an irreversible change, so be sure you don't plan to transfer this store to a merchant.
|
91
|
-
|
92
|
-
Install the app onto your new development store using the Partner Dashboard. Log in to your account, visit the apps page, click the app you created earlier, and looking for the `Test your app` instructions where you can select a store to install your app on.
|
93
|
-
|
94
|
-
![Installing an app on the partners dashboard dropdown](/docs/install-on-dev-shop.png)
|
95
|
-
|
96
|
-
### OR
|
33
|
+
## Use Shopify App Bridge to embed your app in the Shopify Admin
|
97
34
|
|
98
|
-
|
35
|
+
A basic example of using [*Shopify App Bridge*](https://shopify.dev/tools/app-bridge) is included in the install generator. An instance Shopify App Bridge is automatically initialized in [shopify_app.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/shopify_app.js).
|
99
36
|
|
100
|
-
|
101
|
-
-------------------
|
37
|
+
The [flash_messages.js](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/flash_messages.js) file converts Rails [flash messages](https://api.rubyonrails.org/classes/ActionDispatch/Flash.html) to App Bridge Toast actions automatically. By default, this library is included via [unpkg in the embedded_app layout](https://github.com/Shopify/shopify_app/blob/master/lib/generators/shopify_app/install/templates/embedded_app.html.erb#L27).
|
102
38
|
|
103
|
-
|
39
|
+
For more advanced uses it is recommended to [install App Bridge via npm or yarn](https://help.shopify.com/en/api/embedded-apps/app-bridge/getting-started#set-up-shopify-app-bridge-in-your-app).
|
data/docs/Releasing.md
CHANGED
@@ -1,18 +1,21 @@
|
|
1
|
-
Releasing ShopifyApp
|
1
|
+
# Releasing ShopifyApp
|
2
2
|
|
3
|
-
1.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
1. Make the code changes in a separate PR that doesn't modify the version.
|
4
|
+
1. After that is merged, check the Semantic Versioning page for info on how to version the new release: http://semver.org
|
5
|
+
1. Create a pull request with the following changes:
|
6
|
+
- Update the version of ShopifyApp in lib/shopify_app/version.rb
|
7
|
+
- Update the version of shopify_app in package.json
|
8
|
+
- Run `bundle` to update `Gemfile.lock`
|
9
|
+
- Add a CHANGELOG entry for the new release with the date
|
10
|
+
- Change the title of the PR to something like: "Packaging for release X.Y.Z"
|
11
|
+
1. Merge your pull request
|
12
|
+
1. Checkout and pull from master so you have the latest version of the shopify_app
|
13
|
+
1. Tag the HEAD with the version
|
14
|
+
```bash
|
15
|
+
$ git tag -f vX.Y.Z && git push origin vX.Y.Z
|
16
|
+
```
|
17
|
+
1. Check that Create Release workflow successfully runs
|
18
|
+
1. Use Shipit to build and push the gem
|
16
19
|
|
17
|
-
If you see an error like 'You need to create the vX.Y.X tag first', clear
|
20
|
+
If you see an error like 'You need to create the vX.Y.X tag first', clear git
|
18
21
|
cache in Shipit settings
|
data/docs/Troubleshooting.md
CHANGED
@@ -1,16 +1,151 @@
|
|
1
|
-
Troubleshooting Shopify App
|
2
|
-
===========
|
1
|
+
# Troubleshooting Shopify App
|
3
2
|
|
4
|
-
|
3
|
+
#### Table of contents
|
4
|
+
|
5
|
+
[Generators](#generators)
|
6
|
+
* [The `shopify_app:install` generator hangs](#the-shopifyappinstall-generator-hangs)
|
7
|
+
|
8
|
+
[Rails](#rails)
|
9
|
+
* [Known issues with Rails `v6.1`](#known-issues-with-rails-v61)
|
10
|
+
|
11
|
+
[App installation](#app-installation)
|
12
|
+
* [My app won't install](#my-app-wont-install)
|
13
|
+
* [My app keeps redirecting to login](#my-app-keeps-redirecting-to-login)
|
14
|
+
* [My app returns 401 during oauth](#my-app-returns-401-during-oauth)
|
15
|
+
|
16
|
+
[JWT session tokens](#jwt-session-tokens)
|
17
|
+
* [My app is still using cookies to authenticate](#my-app-is-still-using-cookies-to-authenticate)
|
18
|
+
* [My app can't make requests to the Shopify API](#my-app-cant-make-requests-to-the-shopify-api)
|
19
|
+
* [I'm stuck in a redirect loop after OAuth](#im-stuck-in-a-redirect-loop-after-oauth)
|
20
|
+
|
21
|
+
## Generators
|
22
|
+
|
23
|
+
### The shopify_app:install generator hangs
|
5
24
|
|
6
25
|
Rails uses spring by default to speed up development. To run the generator, spring has to be stopped:
|
7
26
|
|
8
27
|
```sh
|
9
|
-
|
28
|
+
bundle exec spring stop
|
10
29
|
```
|
11
30
|
|
12
31
|
Run shopify_app generator again.
|
13
32
|
|
14
|
-
|
33
|
+
## Rails
|
34
|
+
|
35
|
+
### Known issues with Rails `v6.1`
|
36
|
+
|
37
|
+
If you recently upgraded your application's `Rails::Application` configuration to load the default configuration for Rails `v6.1`, then you will need to update the following `cookies_same_site_protection` ActionDispatch configuration.
|
38
|
+
|
39
|
+
```diff
|
40
|
+
# config/application.rb
|
41
|
+
|
42
|
+
require_relative 'boot'
|
43
|
+
|
44
|
+
require 'rails/all'
|
45
|
+
|
46
|
+
Bundler.require(*Rails.groups)
|
47
|
+
|
48
|
+
module AppName
|
49
|
+
class Application < Rails::Application
|
50
|
+
+ config.load_defaults 6.1
|
51
|
+
|
52
|
+
+ config.action_dispatch.cookies_same_site_protection = :none
|
53
|
+
...
|
54
|
+
end
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
As of Rails `v6.1`, the same-site cookie protection setting defaults to `Lax`. This does not allow an embedded app to make cross-domain requests in the Shopify Admin.
|
59
|
+
|
60
|
+
Alternatively, you can upgrade to [`v17.2.0` of the shopify_app gem](/docs/Upgrading.md#upgrading-to-v1720).
|
61
|
+
|
62
|
+
## App installation
|
63
|
+
|
64
|
+
### My app won't install
|
65
|
+
|
66
|
+
#### App installation fails with 'The page you’re looking for could not be found' if the app was installed before
|
15
67
|
|
16
68
|
This issue can occur when the session (the model you set as `ShopifyApp::SessionRepository.storage`) isn't deleted when the user uninstalls your app. A possible fix for this is listening to the `app/uninstalled` webhook and deleting the corresponding session in the webhook handler.
|
69
|
+
|
70
|
+
### My app returns 401 during oauth
|
71
|
+
|
72
|
+
If your local dev env uses the `cookie_store` session storage strategy, you may encounter 401 errors during oauth due to a race condition between asset requests and `/auth/shopify`. You should be able to work around for local testing by using a different browser or session storage strategy. [Read more about the status of this issue](https://github.com/Shopify/shopify_app/issues/1269).
|
73
|
+
|
74
|
+
## JWT session tokens
|
75
|
+
|
76
|
+
### My app is still using cookies to authenticate
|
77
|
+
|
78
|
+
#### `shopify_app` gem version
|
79
|
+
|
80
|
+
Ensure the app is using shopify_app gem v13.x.x+. See [*Upgrading to `v13.0.0`*](/docs/Upgrading.md#upgrading-to-v1300).
|
81
|
+
|
82
|
+
#### `shopify_app` gem Rails configuration
|
83
|
+
|
84
|
+
Edit `config/initializer/shopify_app.rb` and ensure the following configurations are set:
|
85
|
+
|
86
|
+
```diff
|
87
|
+
+ config.embedded_app = true
|
88
|
+
|
89
|
+
# This line should already exist if you're using shopify_app gem 13.x.x+
|
90
|
+
+ config.shop_session_repository = 'Shop'
|
91
|
+
```
|
92
|
+
|
93
|
+
#### Inspect server logs
|
94
|
+
|
95
|
+
If you have checked the configurations above, and the app is still using cookies, then it is possible that the `shopify_app` gem defaulted to relying on cookies. This would happen when your browser allows third-party cookies and a session token was not successfully found as part of your request.
|
96
|
+
|
97
|
+
In this case, check the server logs to see if the session token was invalid:
|
98
|
+
|
99
|
+
```los
|
100
|
+
[ShopifyApp::JWT] Failed to validate JWT: [JWT::<Error>] <Failure message>
|
101
|
+
```
|
102
|
+
|
103
|
+
*Example*
|
104
|
+
|
105
|
+
```
|
106
|
+
[ShopifyApp::JWT] Failed to validate JWT: [JWT::ImmatureSignature] Signature nbf has not been reached
|
107
|
+
```
|
108
|
+
|
109
|
+
**Note:** In a local development environment, you may want to temporarily update your `Gemfile` to point to a local instance of the `shopify_app` library instad of an installed gem. This will enable you to use a debugging tool like `byebug` to debug the library.
|
110
|
+
|
111
|
+
```diff
|
112
|
+
- gem 'shopify_app', '~> 14.2'
|
113
|
+
+ gem 'shopify_app', path: '/path/to/shopify_app'
|
114
|
+
```
|
115
|
+
|
116
|
+
### My app can't make requests to the Shopify API
|
117
|
+
|
118
|
+
> **Note:** Session tokens cannot be used to make authenticated requests to the Shopify API. Learn more about authenticating your backend requests to Shopify APIs at [Shopify API authentication](https://shopify.dev/concepts/about-apis/authentication).
|
119
|
+
|
120
|
+
#### The Shopify API returns `401 Unauthorized`
|
121
|
+
|
122
|
+
If your app uses [user-based token storage](/docs/shopify_app/session-repository.md#user-based-token-storage), then your app is configured to use **online** access tokens (see [API access modes](https://shopify.dev/concepts/about-apis/authentication#api-access-modes) to learn the difference between "online" and "offline" access tokens ). Unlike offline access tokens, online access tokens expire daily and cannot be used to make authenticated requests to the Shopify API once they expire.
|
123
|
+
|
124
|
+
Converting your app to use session tokens means that your app will most likely not go through the OAuth flow as often as it did when relying on cookie sessions. Since the online access tokens stored in your app's database are refreshed during OAuth, this may cause your app's user session repository to use expired online access tokens.
|
125
|
+
|
126
|
+
If the Shopify API returns `401 Unauthorized`, handle this error on your app by redirecting the user to your login path to start the OAuth flow. As a result, your app will be given a new online access token for the current user.
|
127
|
+
|
128
|
+
> **Note:** The following are examples to common app configurations. Your specific use-case may differ.
|
129
|
+
|
130
|
+
##### Example solution
|
131
|
+
|
132
|
+
Add the following line to your app's unauthorized response handler:
|
133
|
+
|
134
|
+
```diff
|
135
|
+
+ redirect_to(ShopifyApp.configuration.login_url, shop: current_shopify_domain)
|
136
|
+
```
|
137
|
+
|
138
|
+
_Example:_ If your embedded app cannot handle server-side XHR redirects, then configure your app's unauthorized response handler to set a response header:
|
139
|
+
|
140
|
+
```
|
141
|
+
X-Shopify-API-Request-Failure-Unauthorized: true
|
142
|
+
```
|
143
|
+
|
144
|
+
Then, use the [Shopify App Bridge Redirect](https://shopify.dev/tools/app-bridge/actions/navigation/redirect) action to redirect your app frontend to the app login URL if this header is set.
|
145
|
+
|
146
|
+
|
147
|
+
### I'm stuck in a redirect loop after OAuth
|
148
|
+
|
149
|
+
In previous versions of `ShopifyApp::Authenticated` controller concern, App Bridge embedded apps were able to include the `Authenticated` controller concern in the `HomeController` and other embedded controllers. This is no longer supported due to browsers blocking 3rd party cookies to increase privacy. App Bridge 3 is needed to handle all embedded sessions.
|
150
|
+
|
151
|
+
For more details on how to handle embeded sessions, refer to [the session token documentation](https://shopify.dev/apps/auth/oauth/session-tokens).
|