shopify_app 9.0.0 → 12.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -2
  3. data/CHANGELOG.md +145 -0
  4. data/README.md +180 -126
  5. data/app/assets/javascripts/shopify_app/itp_helper.js +6 -6
  6. data/app/assets/javascripts/shopify_app/storage_access.js +36 -7
  7. data/app/controllers/concerns/shopify_app/authenticated.rb +1 -1
  8. data/app/controllers/shopify_app/callback_controller.rb +14 -5
  9. data/app/controllers/shopify_app/extension_verification_controller.rb +20 -0
  10. data/app/controllers/shopify_app/sessions_controller.rb +44 -18
  11. data/app/views/shopify_app/sessions/enable_cookies.html.erb +3 -1
  12. data/app/views/shopify_app/sessions/request_storage_access.html.erb +2 -1
  13. data/app/views/shopify_app/sessions/top_level_interaction.html.erb +1 -0
  14. data/app/views/shopify_app/shared/redirect.html.erb +1 -0
  15. data/config/locales/cs.yml +23 -0
  16. data/config/locales/da.yml +20 -0
  17. data/config/locales/de.yml +5 -5
  18. data/config/locales/en.yml +1 -1
  19. data/config/locales/es.yml +3 -3
  20. data/config/locales/fi.yml +20 -0
  21. data/config/locales/fr.yml +3 -3
  22. data/config/locales/hi.yml +23 -0
  23. data/config/locales/it.yml +2 -3
  24. data/config/locales/ja.yml +1 -1
  25. data/config/locales/ko.yml +19 -0
  26. data/config/locales/ms.yml +22 -0
  27. data/config/locales/nb.yml +21 -0
  28. data/config/locales/nl.yml +3 -3
  29. data/config/locales/pl.yml +21 -0
  30. data/config/locales/pt-BR.yml +9 -10
  31. data/config/locales/pt-PT.yml +22 -0
  32. data/config/locales/sv.yml +21 -0
  33. data/config/locales/th.yml +20 -0
  34. data/config/locales/tr.yml +22 -0
  35. data/config/locales/zh-CN.yml +3 -3
  36. data/config/locales/zh-TW.yml +1 -2
  37. data/docs/Quickstart.md +44 -16
  38. data/docs/Releasing.md +0 -1
  39. data/docs/install-on-dev-shop.png +0 -0
  40. data/docs/test-your-app.png +0 -0
  41. data/karma.conf.js +1 -0
  42. data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +2 -2
  43. data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +39 -0
  44. data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +62 -0
  45. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +0 -6
  46. data/lib/generators/shopify_app/install/install_generator.rb +27 -11
  47. data/lib/generators/shopify_app/install/templates/_flash_messages.html.erb +1 -17
  48. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +11 -10
  49. data/lib/generators/shopify_app/install/templates/flash_messages.js +26 -0
  50. data/lib/generators/shopify_app/install/templates/shopify_app.js +15 -0
  51. data/lib/generators/shopify_app/install/templates/shopify_app.rb +6 -3
  52. data/lib/generators/shopify_app/install/templates/shopify_app_index.js +2 -0
  53. data/lib/generators/shopify_app/install/templates/shopify_provider.rb +1 -0
  54. data/lib/generators/shopify_app/install/templates/user_agent.rb +5 -0
  55. data/lib/generators/shopify_app/user_model/templates/db/migrate/create_users.erb +16 -0
  56. data/lib/generators/shopify_app/user_model/templates/user.rb +7 -0
  57. data/lib/generators/shopify_app/user_model/templates/users.yml +4 -0
  58. data/lib/generators/shopify_app/user_model/user_model_generator.rb +38 -0
  59. data/lib/shopify_app.rb +46 -29
  60. data/lib/shopify_app/configuration.rb +24 -9
  61. data/lib/shopify_app/controller_concerns/login_protection.rb +53 -7
  62. data/lib/shopify_app/engine.rb +4 -0
  63. data/lib/shopify_app/managers/webhooks_manager.rb +1 -1
  64. data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +33 -0
  65. data/lib/shopify_app/session/in_memory_session_store.rb +1 -1
  66. data/lib/shopify_app/session/session_repository.rb +2 -2
  67. data/lib/shopify_app/session/session_storage.rb +10 -22
  68. data/lib/shopify_app/session/storage_strategies/shop_storage_strategy.rb +23 -0
  69. data/lib/shopify_app/session/storage_strategies/user_storage_strategy.rb +24 -0
  70. data/lib/shopify_app/utils.rb +7 -0
  71. data/lib/shopify_app/version.rb +1 -1
  72. data/package-lock.json +7212 -11
  73. data/package.json +9 -9
  74. data/service.yml +1 -1
  75. data/shopify_app.gemspec +10 -5
  76. data/translation.yml +1 -1
  77. data/yarn.lock +2555 -1886
  78. metadata +115 -19
  79. data/lib/generators/shopify_app/home_controller/templates/shopify_app_ready_script.html.erb +0 -7
@@ -4,31 +4,31 @@
4
4
  this.itpAction = document.getElementById('TopLevelInteractionButton');
5
5
  this.redirectUrl = opts.redirectUrl;
6
6
  }
7
-
7
+
8
8
  ITPHelper.prototype.redirect = function() {
9
9
  sessionStorage.setItem('shopify.top_level_interaction', true);
10
10
  window.location.href = this.redirectUrl;
11
11
  }
12
-
12
+
13
13
  ITPHelper.prototype.userAgentIsAffected = function() {
14
14
  return Boolean(document.hasStorageAccess);
15
15
  }
16
-
16
+
17
17
  ITPHelper.prototype.canPartitionCookies = function() {
18
18
  var versionRegEx = /Version\/12\.0\.?\d? Safari/;
19
19
  return versionRegEx.test(navigator.userAgent);
20
20
  }
21
-
21
+
22
22
  ITPHelper.prototype.setUpContent = function(onClick) {
23
23
  this.itpContent.style.display = 'block';
24
24
  this.itpAction.addEventListener('click', this.redirect.bind(this));
25
25
  }
26
-
26
+
27
27
  ITPHelper.prototype.execute = function() {
28
28
  if (!this.itpContent) {
29
29
  return;
30
30
  }
31
-
31
+
32
32
  if (this.userAgentIsAffected()) {
33
33
  this.setUpContent();
34
34
  } else {
@@ -28,18 +28,47 @@
28
28
  window.parent.location.href = this.redirectData.myshopifyUrl + '/admin/apps';
29
29
  }
30
30
 
31
- StorageAccessHelper.prototype.redirectToAppHome = function() {
32
- window.location.href = this.redirectData.appHomeUrl;
31
+ StorageAccessHelper.prototype.redirectToAppTargetUrl = function() {
32
+ window.location.href = this.redirectData.appTargetUrl;
33
+ }
34
+
35
+ StorageAccessHelper.prototype.sameSiteNoneIncompatible = function(ua) {
36
+ return ua.includes("iPhone OS 12_") || ua.includes("iPad; CPU OS 12_") || //iOS 12
37
+ (ua.includes("UCBrowser/")
38
+ ? this.isOlderUcBrowser(ua) //UC Browser < 12.13.2
39
+ : (ua.includes("Chrome/5") || ua.includes("Chrome/6"))) ||
40
+ ua.includes("Chromium/5") || ua.includes("Chromium/6") ||
41
+ (ua.includes(" OS X 10_14_") &&
42
+ ((ua.includes("Version/") && ua.includes("Safari")) || //Safari on MacOS 10.14
43
+ ua.endsWith("(KHTML, like Gecko)"))); //Web view on MacOS 10.14
44
+ }
45
+
46
+ StorageAccessHelper.prototype.isOlderUcBrowser = function(ua) {
47
+ var match = ua.match(/UCBrowser\/(\d+)\.(\d+)\.(\d+)\./);
48
+ if (!match) return false;
49
+ var major = parseInt(match[1]);
50
+ var minor = parseInt(match[2]);
51
+ var build = parseInt(match[3]);
52
+ if (major != 12) return major < 12;
53
+ if (minor != 13) return minor < 13;
54
+ return build < 2;
55
+ }
56
+
57
+ StorageAccessHelper.prototype.setCookie = function(value) {
58
+ if(!this.sameSiteNoneIncompatible(navigator.userAgent)) {
59
+ value += '; secure; SameSite=None'
60
+ }
61
+ document.cookie = value;
33
62
  }
34
63
 
35
64
  StorageAccessHelper.prototype.grantedStorageAccess = function() {
36
65
  try {
37
66
  sessionStorage.setItem('shopify.granted_storage_access', true);
38
- document.cookie = 'shopify.granted_storage_access=true';
67
+ this.setCookie('shopify.granted_storage_access=true');
39
68
  if (!document.cookie) {
40
69
  throw 'Cannot set third-party cookie.'
41
70
  }
42
- this.redirectToAppHome();
71
+ this.redirectToAppTargetUrl();
43
72
  } catch (error) {
44
73
  console.warn('Third party cookies may be blocked.', error);
45
74
  this.redirectToAppTLD(ACCESS_DENIED_STATUS);
@@ -61,7 +90,7 @@
61
90
  StorageAccessHelper.prototype.handleHasStorageAccess = function() {
62
91
  if (sessionStorage.getItem('shopify.granted_storage_access')) {
63
92
  // If app was classified by ITP and used Storage Access API to acquire access
64
- this.redirectToAppHome();
93
+ this.redirectToAppTargetUrl();
65
94
  } else {
66
95
  // If app has not been classified by ITP and still has storage access
67
96
  this.redirectToAppTLD(ACCESS_GRANTED_STATUS);
@@ -103,11 +132,11 @@
103
132
 
104
133
  /* ITP 2.0 solution: handles cookie partitioning */
105
134
  StorageAccessHelper.prototype.setUpHelper = function() {
106
- return new ITPHelper({redirectUrl: window.shopOrigin + "/admin/apps/" + window.apiKey});
135
+ return new ITPHelper({redirectUrl: window.shopOrigin + "/admin/apps/" + window.apiKey + window.returnTo});
107
136
  }
108
137
 
109
138
  StorageAccessHelper.prototype.setCookieAndRedirect = function() {
110
- document.cookie = "shopify.cookies_persist=true";
139
+ this.setCookie('shopify.cookies_persist=true');
111
140
  var helper = this.setUpHelper();
112
141
  helper.redirect();
113
142
  }
@@ -8,7 +8,7 @@ module ShopifyApp
8
8
  include ShopifyApp::Localization
9
9
  include ShopifyApp::LoginProtection
10
10
  include ShopifyApp::EmbeddedApp
11
- before_action :login_again_if_different_shop
11
+ before_action :login_again_if_different_user_or_shop
12
12
  around_action :shopify_session
13
13
  end
14
14
  end
@@ -15,7 +15,7 @@ module ShopifyApp
15
15
  redirect_to return_address
16
16
  else
17
17
  flash[:error] = I18n.t('could_not_log_in')
18
- redirect_to login_url
18
+ redirect_to(login_url_with_optional_shop)
19
19
  end
20
20
  end
21
21
 
@@ -55,10 +55,16 @@ module ShopifyApp
55
55
  token: token,
56
56
  api_version: ShopifyApp.configuration.api_version
57
57
  )
58
-
59
- session[:shopify] = ShopifyApp::SessionRepository.store(session_store)
58
+ session[:shopify] = ShopifyApp::SessionRepository.store(session_store, user: associated_user)
60
59
  session[:shopify_domain] = shop_name
61
60
  session[:shopify_user] = associated_user
61
+
62
+ if ShopifyApp.configuration.per_user_tokens?
63
+ # Adds the user_session to the session to determine if the logged in user has changed
64
+ user_session = auth_hash&.extra&.session
65
+ raise IndexError, "Missing user session signature" if user_session.nil?
66
+ session[:user_session] = user_session
67
+ end
62
68
  end
63
69
 
64
70
  def install_webhooks
@@ -86,10 +92,13 @@ module ShopifyApp
86
92
 
87
93
  return unless config && config[:job].present?
88
94
 
95
+ job = config[:job]
96
+ job = job.constantize if job.is_a?(String)
97
+
89
98
  if config[:inline] == true
90
- config[:job].perform_now(shop_domain: session[:shopify_domain])
99
+ job.perform_now(shop_domain: session[:shopify_domain])
91
100
  else
92
- config[:job].perform_later(shop_domain: session[:shopify_domain])
101
+ job.perform_later(shop_domain: session[:shopify_domain])
93
102
  end
94
103
  end
95
104
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApp
4
+ class ExtensionVerificationController < ActionController::Base
5
+ protect_from_forgery with: :null_session
6
+ before_action :verify_request
7
+
8
+ private
9
+
10
+ def verify_request
11
+ hmac_header = request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
12
+ request_body = request.body.read
13
+ secret = ShopifyApp.configuration.secret
14
+ digest = OpenSSL::Digest.new('sha256')
15
+
16
+ expected_hmac = Base64.strict_encode64(OpenSSL::HMAC.digest(digest, secret, request_body))
17
+ head(:unauthorized) unless ActiveSupport::SecurityUtils.secure_compare(expected_hmac, hmac_header)
18
+ end
19
+ end
20
+ end
@@ -20,16 +20,20 @@ module ShopifyApp
20
20
 
21
21
  render(:enable_cookies, layout: false, locals: {
22
22
  does_not_have_storage_access_url: top_level_interaction_path(
23
- shop: sanitized_shop_name
23
+ shop: sanitized_shop_name,
24
+ return_to: params[:return_to]
24
25
  ),
25
- has_storage_access_url: login_url(top_level: true),
26
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
27
- current_shopify_domain: current_shopify_domain,
26
+ has_storage_access_url: login_url_with_optional_shop(top_level: true),
27
+ app_target_url: granted_storage_access_path(
28
+ shop: sanitized_shop_name,
29
+ return_to: params[:return_to]
30
+ ),
31
+ current_shopify_domain: current_shopify_domain
28
32
  })
29
33
  end
30
34
 
31
35
  def top_level_interaction
32
- @url = login_url(top_level: true)
36
+ @url = login_url_with_optional_shop(top_level: true)
33
37
  validate_shop
34
38
  end
35
39
 
@@ -38,14 +42,15 @@ module ShopifyApp
38
42
 
39
43
  session['shopify.granted_storage_access'] = true
40
44
 
41
- params = { shop: @shop }
42
- redirect_to "#{ShopifyApp.configuration.root_url}?#{params.to_query}"
45
+ copy_return_to_param_to_session
46
+
47
+ redirect_to(return_address_with_params({ shop: @shop }))
43
48
  end
44
49
 
45
50
  def destroy
46
51
  reset_session
47
52
  flash[:notice] = I18n.t('.logged_out')
48
- redirect_to login_url
53
+ redirect_to(login_url_with_optional_shop)
49
54
  end
50
55
 
51
56
  private
@@ -54,6 +59,8 @@ module ShopifyApp
54
59
  return render_invalid_shop_error unless sanitized_shop_name.present?
55
60
  session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
56
61
 
62
+ copy_return_to_param_to_session
63
+
57
64
  if user_agent_can_partition_cookies
58
65
  authenticate_with_partitioning
59
66
  else
@@ -77,7 +84,7 @@ module ShopifyApp
77
84
  authenticate_in_context
78
85
  else
79
86
  set_top_level_oauth_cookie
80
- fullpage_redirect_to enable_cookies_path(shop: sanitized_shop_name)
87
+ enable_cookie_access
81
88
  end
82
89
  end
83
90
 
@@ -91,17 +98,28 @@ module ShopifyApp
91
98
  true
92
99
  end
93
100
 
101
+ def copy_return_to_param_to_session
102
+ session[:return_to] = params[:return_to] if params[:return_to]
103
+ end
104
+
94
105
  def render_invalid_shop_error
95
106
  flash[:error] = I18n.t('invalid_shop_url')
96
107
  redirect_to return_address
97
108
  end
98
109
 
110
+ def enable_cookie_access
111
+ fullpage_redirect_to(enable_cookies_path(
112
+ shop: sanitized_shop_name,
113
+ return_to: session[:return_to]
114
+ ))
115
+ end
116
+
99
117
  def authenticate_in_context
100
118
  redirect_to "#{main_app.root_path}auth/shopify"
101
119
  end
102
120
 
103
121
  def authenticate_at_top_level
104
- fullpage_redirect_to login_url(top_level: true)
122
+ fullpage_redirect_to(login_url_with_optional_shop(top_level: true))
105
123
  end
106
124
 
107
125
  def authenticate_in_context?
@@ -119,14 +137,22 @@ module ShopifyApp
119
137
  end
120
138
 
121
139
  def redirect_to_request_storage_access
122
- render :request_storage_access, layout: false, locals: {
123
- does_not_have_storage_access_url: top_level_interaction_path(
124
- shop: sanitized_shop_name
125
- ),
126
- has_storage_access_url: login_url(top_level: true),
127
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
128
- current_shopify_domain: current_shopify_domain
129
- }
140
+ render(
141
+ :request_storage_access,
142
+ layout: false,
143
+ locals: {
144
+ does_not_have_storage_access_url: top_level_interaction_path(
145
+ shop: sanitized_shop_name,
146
+ return_to: session[:return_to]
147
+ ),
148
+ has_storage_access_url: login_url_with_optional_shop(top_level: true),
149
+ app_target_url: granted_storage_access_path(
150
+ shop: sanitized_shop_name,
151
+ return_to: session[:return_to]
152
+ ),
153
+ current_shopify_domain: current_shopify_domain
154
+ }
155
+ )
130
156
  end
131
157
  end
132
158
  end
@@ -2,6 +2,7 @@
2
2
  <html lang="<%= I18n.locale %>">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
6
  <base target="_top">
6
7
  <title>Redirecting…</title>
7
8
  <%= render 'shopify_app/partials/layout_styles' %>
@@ -16,6 +17,7 @@
16
17
  <script>
17
18
  window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
18
19
  window.shopOrigin = "https://<%= @shop %>";
20
+ window.returnTo = "<%= params[:return_to] %>"
19
21
  </script>
20
22
 
21
23
  <%= javascript_include_tag('shopify_app/enable_cookies', crossorigin: 'anonymous', integrity: true) %>
@@ -30,7 +32,7 @@
30
32
  myshopifyUrl: "https://#{current_shopify_domain}",
31
33
  hasStorageAccessUrl: "#{has_storage_access_url}",
32
34
  doesNotHaveStorageAccessUrl: "#{does_not_have_storage_access_url}",
33
- appHomeUrl: "#{app_home_url}"
35
+ appTargetUrl: "#{app_target_url}"
34
36
  },
35
37
  },
36
38
  )
@@ -2,6 +2,7 @@
2
2
  <html lang="<%= I18n.locale %>">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
6
  <base target="_top">
6
7
  <title>Redirecting…</title>
7
8
  <%= render 'shopify_app/partials/layout_styles' %>
@@ -23,7 +24,7 @@
23
24
  myshopifyUrl: "https://#{current_shopify_domain}",
24
25
  hasStorageAccessUrl: "#{has_storage_access_url}",
25
26
  doesNotHaveStorageAccessUrl: "#{does_not_have_storage_access_url}",
26
- appHomeUrl: "#{app_home_url}"
27
+ appTargetUrl: "#{app_target_url}"
27
28
  },
28
29
  },
29
30
  )
@@ -2,6 +2,7 @@
2
2
  <html lang="<%= I18n.locale %>">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
6
  <base target="_top">
6
7
  <title>Redirecting…</title>
7
8
  <%= render 'shopify_app/partials/layout_styles' %>
@@ -2,6 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
6
  <base target="_top">
6
7
  <title>Redirecting…</title>
7
8
  <%= javascript_include_tag('shopify_app/redirect', crossorigin: 'anonymous', integrity: true) %>
@@ -0,0 +1,23 @@
1
+ ---
2
+ cs:
3
+ logged_out: Odhlášení proběhlo úspěšně
4
+ could_not_log_in: Nelze se přihlásit do obchodu Shopify
5
+ invalid_shop_url: Neplatná doména obchodu
6
+ enable_cookies_heading: Zapnout soubory cookie z aplikace %{app}
7
+ enable_cookies_body: Pokud chcete v Shopify používat aplikaci %{app}, musíte soubory
8
+ cookie v tomto prohlížeči povolit ručně.
9
+ enable_cookies_footer: Soubory cookie umožňují, aby vás aplikace ověřila pomocí
10
+ dočasného uchování preferencí a osobních údajů. Jejich platnost vyprší po 30 dnech.
11
+ enable_cookies_action: Povolit soubory cookie
12
+ top_level_interaction_heading: Váš prohlížeč potřebuje ověřit aplikaci %{app}
13
+ top_level_interaction_body: Váš prohlížeč vyžaduje, aby si od vás aplikace, jako
14
+ je %{app}, nejdřív vyžádaly přístup k souborům cookie, než je pro vás Shopify
15
+ otevře.
16
+ top_level_interaction_action: Pokračovat
17
+ request_storage_access_heading: Aplikace %{app} potřebuje získat přístup k souborům
18
+ cookie
19
+ request_storage_access_body: Tato aplikace vám umožní ověření prostřednictvím dočasného
20
+ uchování vašich osobních údajů. Pokud chcete používat tuto aplikaci, klikněte
21
+ na tlačítko Pokračovat a povolte soubory cookie.
22
+ request_storage_access_footer: Platnost souborů cookie vyprší po 30 dnech.
23
+ request_storage_access_action: Pokračovat
@@ -0,0 +1,20 @@
1
+ ---
2
+ da:
3
+ logged_out: Logget ud
4
+ could_not_log_in: Kunne ikke logge ind på Shopify-butik
5
+ invalid_shop_url: Ugyldig butiksdomæne
6
+ enable_cookies_heading: Aktivér cookies fra %{app}
7
+ enable_cookies_body: Du skal manuelt aktivere cookies i denne browser for at kunne
8
+ bruge %{app} i Shopify.
9
+ enable_cookies_footer: Cookies lader appen godkende dig ved at gemme dine præferencer
10
+ og personlige oplysninger midlertidigt. De udløber efter 30 dage.
11
+ enable_cookies_action: Aktivér cookies
12
+ top_level_interaction_heading: Din browser skal godkende %{app}
13
+ top_level_interaction_body: Din browser kræver, at apps som f.eks. %{app} spørger
14
+ dig om adgang til cookies, inden Shopify kan åbne den for dig.
15
+ top_level_interaction_action: Fortsæt
16
+ request_storage_access_heading: "%{app} skal have adgang til cookies"
17
+ request_storage_access_body: Det lader appen godkende dig ved at gemme dine personlige
18
+ oplysninger midlertidigt. Klik på forsæt, og tillad cookies for at bruge appen.
19
+ request_storage_access_footer: Cookies udløber efter 30 dage.
20
+ request_storage_access_action: Fortsæt
@@ -7,16 +7,16 @@ de:
7
7
  enable_cookies_body: Sie müssen Cookies in diesem Browser manuell aktivieren, um
8
8
  %{app} in Shopify verwenden zu können.
9
9
  enable_cookies_footer: Mithilfe von Cookies kann die App Sie authentifizieren, indem
10
- Ihre Einstellungen und persönlichen Informationen vorübergehend gespeichert werden.
10
+ Ihre Einstellungen und personenbezogenen Daten vorübergehend gespeichert werden.
11
11
  Sie laufen nach 30 Tagen ab.
12
12
  enable_cookies_action: Cookies aktivieren
13
13
  top_level_interaction_heading: Ihr Browser muss %{app} authentifizieren
14
- top_level_interaction_body: Ihr Browser verlangt, dass Apps von Drittanbietern wie
15
- %{app} Sie um Zugriff auf Cookies bitten, bevor Shopify sie für Sie öffnen kann.
14
+ top_level_interaction_body: Ihr Browser verlangt, dass Apps wie %{app} Sie um Zugriff
15
+ auf Cookies bitten, bevor Shopify sie für Sie öffnen kann.
16
16
  top_level_interaction_action: Weiter
17
17
  request_storage_access_heading: "%{app} braucht Zugriff auf Cookies"
18
18
  request_storage_access_body: Damit kann die App Sie authentifizieren, indem Ihre
19
- Einstellungen und persönlichen Informationen vorübergehend gespeichert werden.
20
- Klicken Sie auf "Weiter" und erlauben Sie den Cookies, die App zu verwenden.
19
+ Einstellungen und personenbezogenen Daten vorübergehend gespeichert werden. Klicken
20
+ Sie auf "Weiter" und erlauben Sie den Cookies, die App zu verwenden.
21
21
  request_storage_access_footer: Cookies laufen nach 30 Tagen ab.
22
22
  request_storage_access_action: Weiter
@@ -7,7 +7,7 @@ en:
7
7
  enable_cookies_footer: 'Cookies let the app authenticate you by temporarily storing your preferences and personal information. They expire after 30 days.'
8
8
  enable_cookies_action: 'Enable cookies'
9
9
  top_level_interaction_heading: "Your browser needs to authenticate %{app}"
10
- top_level_interaction_body: "Your browser requires third-party apps like %{app} to ask you for access to cookies before Shopify can open it for you."
10
+ top_level_interaction_body: "Your browser requires apps like %{app} to ask you for access to cookies before Shopify can open it for you."
11
11
  top_level_interaction_action: 'Continue'
12
12
  request_storage_access_heading: "%{app} needs access to cookies"
13
13
  request_storage_access_body: "This lets the app authenticate you by temporarily storing your personal information. Click continue and allow cookies to use the app."