shopify_app 8.2.6 → 8.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d2646af06c48a37cfbb95b06b993a766bb71ee40
4
- data.tar.gz: b5180bafe5d1a2dff0b504cc88d88dd2591b4ab9
3
+ metadata.gz: 67993e953b33ffe850f9db651c7ecc411d5933b2
4
+ data.tar.gz: ca5981beba2ea540681d77363dc1ae6c4bd009de
5
5
  SHA512:
6
- metadata.gz: f316a0447cb5bdcc47be2186183104b42767232e11eb3538b576479567fc930dfb24e17d911a1d1c6b5b5d56c6ffabf5e0b8891946b1f0b2506eefb0373dbf51
7
- data.tar.gz: 10bfeabacdee5645f6d1ee04177aeefb893ec25a7ea505f564a2ed04f28abdb03e81d8796e9a5859505a8bf1458e43a4154f47d371a27b1da148cb3823925b2a
6
+ metadata.gz: 7665bf0987e8738cbeb9d8c0e92fa3e3d2055ffe60c80d6b50795d7f2db83e18d7df4fb89da81fc6226cacfc6fbb7fe0059d34a36071d5e90f259cb870004444
7
+ data.tar.gz: 353060a370d4ba42c86ebc95b0d09f1ee32d3eb106db177df4dec3f2580e0acb30fef419715db35b3a023337d2dd7874718a2e3277ea0729fbb52676394ba72e
data/.gitignore CHANGED
@@ -9,3 +9,5 @@ doc/
9
9
  *.sqlite3
10
10
  test/tmp/*
11
11
  .idea
12
+ # ignore sprockets cache
13
+ /test/dummy/tmp/*
data/.rubocop.yml ADDED
@@ -0,0 +1,7 @@
1
+ LineLength:
2
+ Exclude:
3
+ - test/**/*
4
+
5
+ Metrics/ClassLength:
6
+ Exclude:
7
+ - test/**/*
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ 8.3.0
2
+ ----
3
+ * Fix embedded app session management in Safari 12
4
+ * Add support for translation platform
5
+
1
6
  8.2.6
2
7
  ----
3
8
  * Sanitize the shop query param to include `.myshopify.com` if no domain was provided
data/README.md CHANGED
@@ -143,7 +143,7 @@ After running the `install` generator, you can start your app with `bundle exec
143
143
  $ rails generate shopify_app:shop_model
144
144
  ```
145
145
 
146
- The install generator doesn't create any database tables or models for you. If you are starting a new app its quite likely that you will want a shops table and model to store the tokens when your app is installed (most of our internally developed apps do!). This generator creates a shop model and a migration. This model includes the `ShopifyApp::SessionStorage` concern which adds two methods to make it compatible as a `SessionRepository`. After running this generator you'll notice the `session_repository` in your `config/initializers/shopify_app.rb` will be set to the `Shop` model. This means that internally ShopifyApp will try and load tokens from this model.
146
+ The `install` generator doesn't create any database tables or models for you. If you are starting a new app its quite likely that you will want a shops table and model to store the tokens when your app is installed (most of our internally developed apps do!). This generator creates a shop model and a migration. This model includes the `ShopifyApp::SessionStorage` concern which adds two methods to make it compatible as a `SessionRepository`. After running this generator you'll notice the `session_repository` in your `config/initializers/shopify_app.rb` will be set to the `Shop` model. This means that internally ShopifyApp will try and load tokens from this model.
147
147
 
148
148
  *Note that you will need to run rake db:migrate after this generator*
149
149
 
@@ -413,8 +413,6 @@ Tunneling is also useful for working the the embedded app sdk to solve mixed con
413
413
 
414
414
  Questions or problems?
415
415
  ----------------------
416
- http://api.shopify.com <= Read up on the possible API calls!
417
416
 
418
- http://ecommerce.shopify.com/c/shopify-apis-and-technology <= Ask questions!
419
-
420
- http://docs.shopify.com/api/the-basics/getting-started <= Read the docs!
417
+ - [Ask questions!](https://ecommerce.shopify.com/c/shopify-apis-and-technology)
418
+ - [Read the docs!](https://help.shopify.com/api/guides)
@@ -0,0 +1,30 @@
1
+ (function() {
2
+ function setCookieAndRedirect() {
3
+ document.cookie = "shopify.cookies_persist=true";
4
+ window.location.href = window.shopOrigin + "/admin/apps/" + window.apiKey;
5
+ }
6
+
7
+ function shouldDisplayPrompt() {
8
+ if (navigator.userAgent.indexOf('com.jadedpixel.pos') !== -1) {
9
+ return false;
10
+ }
11
+
12
+ if (navigator.userAgent.indexOf('Shopify Mobile/iOS') !== -1) {
13
+ return false;
14
+ }
15
+
16
+ return Boolean(document.hasStorageAccess);
17
+ }
18
+
19
+ document.addEventListener("DOMContentLoaded", function() {
20
+ if (shouldDisplayPrompt()) {
21
+ var itpContent = document.querySelector('#CookiePartitionPrompt');
22
+ itpContent.style.display = 'block';
23
+
24
+ var button = document.querySelector('#AcceptCookies');
25
+ button.addEventListener('click', setCookieAndRedirect);
26
+ } else {
27
+ setCookieAndRedirect();
28
+ }
29
+ });
30
+ })();
@@ -1,19 +1,33 @@
1
- document.addEventListener("DOMContentLoaded", function() {
2
- var redirectTargetElement = document.getElementById("redirection-target");
3
- var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
1
+ (function() {
2
+ function redirect() {
3
+ var redirectTargetElement = document.getElementById("redirection-target");
4
4
 
5
- if (window.top == window.self) {
6
- // If the current window is the 'parent', change the URL by setting location.href
7
- window.top.location.href = targetInfo.url;
8
- } else {
9
- // If the current window is the 'child', change the parent's URL with postMessage
10
- normalizedLink = document.createElement('a');
11
- normalizedLink.href = targetInfo.url;
5
+ if (!redirectTargetElement) {
6
+ return;
7
+ }
12
8
 
13
- data = JSON.stringify({
14
- message: 'Shopify.API.remoteRedirect',
15
- data: { location: normalizedLink.href }
16
- });
17
- window.parent.postMessage(data, targetInfo.myshopifyUrl);
9
+ var targetInfo = JSON.parse(redirectTargetElement.dataset.target)
10
+
11
+ if (window.top == window.self) {
12
+ // If the current window is the 'parent', change the URL by setting location.href
13
+ window.top.location.href = targetInfo.url;
14
+ } else {
15
+ // If the current window is the 'child', change the parent's URL with postMessage
16
+ normalizedLink = document.createElement('a');
17
+ normalizedLink.href = targetInfo.url;
18
+
19
+ data = JSON.stringify({
20
+ message: 'Shopify.API.remoteRedirect',
21
+ data: {location: normalizedLink.href}
22
+ });
23
+ window.parent.postMessage(data, targetInfo.myshopifyUrl);
24
+ }
18
25
  }
19
- });
26
+
27
+ document.addEventListener("DOMContentLoaded", redirect);
28
+
29
+ // In the turbolinks context, neither DOMContentLoaded nor turbolinks:load
30
+ // consistently fires. This ensures that we at least attempt to fire in the
31
+ // turbolinks situation as well.
32
+ redirect();
33
+ })();
@@ -14,6 +14,11 @@ module ShopifyApp
14
14
  authenticate
15
15
  end
16
16
 
17
+ def enable_cookies
18
+ @shop = sanitized_shop_name
19
+ render_invalid_shop_error unless @shop
20
+ end
21
+
17
22
  def callback
18
23
  if auth_hash
19
24
  login_shop
@@ -37,15 +42,47 @@ module ShopifyApp
37
42
  private
38
43
 
39
44
  def authenticate
40
- if sanitized_shop_name.present?
41
- session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
42
- fullpage_redirect_to "#{main_app.root_path}auth/shopify"
45
+ return render_invalid_shop_error unless sanitized_shop_name.present?
46
+ session['shopify.omniauth_params'] = { shop: sanitized_shop_name }
47
+
48
+ if redirect_for_cookie_access?
49
+ fullpage_redirect_to enable_cookies_path(shop: sanitized_shop_name)
50
+ elsif authenticate_in_context?
51
+ authenticate_in_context
43
52
  else
44
- flash[:error] = I18n.t('invalid_shop_url')
45
- redirect_to return_address
53
+ authenticate_at_top_level
46
54
  end
47
55
  end
48
56
 
57
+ def render_invalid_shop_error
58
+ flash[:error] = I18n.t('invalid_shop_url')
59
+ redirect_to return_address
60
+ end
61
+
62
+ def authenticate_in_context
63
+ clear_top_level_oauth_cookie
64
+ redirect_to "#{main_app.root_path}auth/shopify"
65
+ end
66
+
67
+ def authenticate_at_top_level
68
+ set_top_level_oauth_cookie
69
+ fullpage_redirect_to login_url(top_level: true)
70
+ end
71
+
72
+ def authenticate_in_context?
73
+ return true unless ShopifyApp.configuration.embedded_app?
74
+ return true if params[:top_level]
75
+ session['shopify.top_level_oauth']
76
+ end
77
+
78
+ def redirect_for_cookie_access?
79
+ return false unless ShopifyApp.configuration.embedded_app?
80
+ return false if params[:top_level]
81
+ return false if session['shopify.cookies_persist']
82
+
83
+ true
84
+ end
85
+
49
86
  def login_shop
50
87
  sess = ShopifyAPI::Session.new(shop_name, token)
51
88
 
@@ -0,0 +1,386 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= I18n.locale %>">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <style>
6
+ html,
7
+ body {
8
+ min-height:100%;
9
+ height:100%;
10
+ font-size:1.5rem;
11
+ font-weight:400;
12
+ line-height:2rem;
13
+ text-transform:initial;
14
+ letter-spacing:initial;
15
+ font-weight:400;
16
+ color:#212b36;
17
+ font-family:-apple-system, BlinkMacSystemFont, San Francisco, Roboto, Segoe UI, Helvetica Neue, sans-serif;
18
+ }
19
+
20
+ @media (min-width: 40em) {
21
+ html,
22
+ body {
23
+ font-size:1.4rem;
24
+ }
25
+ }
26
+
27
+ html {
28
+ position:relative;
29
+ font-size:62.5%;
30
+ -webkit-font-smoothing:antialiased;
31
+ -moz-osx-font-smoothing:grayscale;
32
+ -webkit-text-size-adjust:100%;
33
+ -ms-text-size-adjust:100%;
34
+ text-size-adjust:100%;
35
+ text-rendering:optimizeLegibility;
36
+ }
37
+
38
+ body {
39
+ min-height:100%;
40
+ margin:0;
41
+ padding:0;
42
+ background-color:#f4f6f8;
43
+ }
44
+
45
+ *,
46
+ *::before,
47
+ *::after{
48
+ box-sizing:border-box; }
49
+
50
+ h1,
51
+ h2,
52
+ h3,
53
+ h4,
54
+ h5,
55
+ h6,
56
+ p {
57
+ margin:0;
58
+ font-size:1em;
59
+ font-weight:400;
60
+ }
61
+
62
+ #CookiePartitionPrompt {
63
+ display: none;
64
+ }
65
+
66
+ .Polaris-Page {
67
+ margin:0 auto;
68
+ padding:0;
69
+ max-width:99.8rem;
70
+ }
71
+
72
+ @media (min-width: 30.625em) {
73
+ .Polaris-Page {
74
+ padding:0 2rem;
75
+ }
76
+ }
77
+ @media (min-width: 46.5em) {
78
+ .Polaris-Page {
79
+ padding:0 3.2rem;
80
+ }
81
+ }
82
+
83
+ .Polaris-Page__Content {
84
+ margin:2rem 0;
85
+ }
86
+
87
+ @media (min-width: 46.5em) {
88
+ .Polaris-Page__Content {
89
+ margin-top:2rem;
90
+ }
91
+ }
92
+
93
+ @media (min-width: 46.5em) {
94
+ .Polaris-Page {
95
+ display: flex;
96
+ justify-content: center;
97
+ align-items: center;
98
+ height: 100vh;
99
+ }
100
+ }
101
+
102
+ .Polaris-Layout {
103
+ display:-webkit-box;
104
+ display:-ms-flexbox;
105
+ display:flex;
106
+ -ms-flex-wrap:wrap;
107
+ flex-wrap:wrap;
108
+ -webkit-box-pack:center;
109
+ -ms-flex-pack:center;
110
+ justify-content:center;
111
+ -webkit-box-align:start;
112
+ -ms-flex-align:start;
113
+ align-items:flex-start;
114
+ margin-top:-2rem;
115
+ margin-left:-2rem;
116
+ }
117
+
118
+ .Polaris-Layout__Section {
119
+ -webkit-box-flex:2;
120
+ -ms-flex:2 2 48rem;
121
+ flex:2 2 48rem;
122
+ min-width:51%;
123
+ }
124
+
125
+ .Polaris-Layout__Section--fullWidth {
126
+ -webkit-box-flex:1;
127
+ -ms-flex:1 1 100%;
128
+ flex:1 1 100%;
129
+ }
130
+
131
+ .Polaris-Layout__Section {
132
+ max-width:calc(100% - 2rem);
133
+ margin-top:2rem;
134
+ margin-left:2rem;
135
+ }
136
+
137
+ .Polaris-Stack {
138
+ margin-top:-1.6rem;
139
+ margin-left:-1.6rem;
140
+ display:-webkit-box;
141
+ display:-ms-flexbox;
142
+ display:flex;
143
+ -ms-flex-wrap:wrap;
144
+ flex-wrap:wrap;
145
+ -webkit-box-align:stretch;
146
+ -ms-flex-align:stretch;
147
+ align-items:stretch;
148
+ }
149
+
150
+ .Polaris-Stack > .Polaris-Stack__Item {
151
+ margin-top:1.6rem;
152
+ margin-left:1.6rem;
153
+ max-width:calc(100% - 1.6rem);
154
+ }
155
+
156
+ .Polaris-Stack__Item {
157
+ -webkit-box-flex:0;
158
+ -ms-flex:0 0 auto;
159
+ flex:0 0 auto;
160
+ min-width:0;
161
+ }
162
+
163
+ .Polaris-Heading {
164
+ font-size:1.7rem;
165
+ font-weight:600;
166
+ line-height:2.4rem;
167
+ margin:0;
168
+ }
169
+
170
+ @media (min-width: 40em) {
171
+ .Polaris-Heading {
172
+ font-size:1.6rem;
173
+ }
174
+ }
175
+
176
+ .Polaris-Card {
177
+ overflow:hidden;
178
+ background-color:white;
179
+ box-shadow:0 0 0 1px rgba(63, 63, 68, 0.05), 0 1px 3px 0 rgba(63, 63, 68, 0.15);
180
+ }
181
+
182
+ .Polaris-Card + .Polaris-Card {
183
+ margin-top:2rem;
184
+ }
185
+
186
+ @media (min-width: 30.625em) {
187
+ .Polaris-Card {
188
+ border-radius:3px;
189
+ }
190
+ }
191
+
192
+ .Polaris-Card__Header {
193
+ padding:2rem 2rem 0;
194
+ }
195
+
196
+ .Polaris-Card__Section {
197
+ padding:2rem;
198
+ }
199
+
200
+ .Polaris-Card__Section + .Polaris-Card__Section {
201
+ border-top:1px solid #dfe3e8;
202
+ }
203
+
204
+ .Polaris-Card__Section--subdued {
205
+ background-color:#f9fafb;
206
+ }
207
+
208
+
209
+ .Polaris-Stack--distributionTrailing {
210
+ -webkit-box-pack:end;
211
+ -ms-flex-pack:end;
212
+ justify-content:flex-end;
213
+ }
214
+
215
+ .Polaris-Stack--vertical {
216
+ -webkit-box-orient:vertical;
217
+ -webkit-box-direction:normal;
218
+ -ms-flex-direction:column;
219
+ flex-direction:column;
220
+ }
221
+
222
+ .Polaris-Button {
223
+ fill:#637381;
224
+ position:relative;
225
+ display:-webkit-inline-box;
226
+ display:-ms-inline-flexbox;
227
+ display:inline-flex;
228
+ -webkit-box-align:center;
229
+ -ms-flex-align:center;
230
+ align-items:center;
231
+ -webkit-box-pack:center;
232
+ -ms-flex-pack:center;
233
+ justify-content:center;
234
+ min-height:3.6rem;
235
+ min-width:3.6rem;
236
+ margin:0;
237
+ padding:0.7rem 1.6rem;
238
+ background:linear-gradient(to bottom, white, #f9fafb);
239
+ border:1px solid #c4cdd5;
240
+ box-shadow:0 1px 0 0 rgba(22, 29, 37, 0.05);
241
+ border-radius:3px;
242
+ line-height:1;
243
+ color:#212b36;
244
+ text-align:center;
245
+ cursor:pointer;
246
+ -webkit-user-select:none;
247
+ -moz-user-select:none;
248
+ -ms-user-select:none;
249
+ user-select:none;
250
+ text-decoration:none;
251
+ transition-property:background, border, box-shadow;
252
+ transition-duration:200ms;
253
+ transition-timing-function:cubic-bezier(0.64, 0, 0.35, 1);
254
+ }
255
+
256
+ .Polaris-Button:hover {
257
+ background:linear-gradient(to bottom, #f9fafb, #f4f6f8);
258
+ border-color:#c4cdd5;
259
+ }
260
+
261
+ .Polaris-Button:focus {
262
+ border-color:#5c6ac4;
263
+ outline:0;
264
+ box-shadow:0 0 0 1px #5c6ac4;
265
+ }
266
+
267
+ .Polaris-Button:active {
268
+ background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
269
+ border-color:#c4cdd5;
270
+ 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);
271
+ }
272
+
273
+ .Polaris-Button.Polaris-Button--disabled {
274
+ fill:#919eab;
275
+ transition:none;
276
+ background:linear-gradient(to bottom, #f4f6f8, #f4f6f8);
277
+ color:#919eab;
278
+ }
279
+
280
+ .Polaris-Button__Content {
281
+ font-size:1.5rem;
282
+ font-weight:400;
283
+ line-height:1.6rem;
284
+ text-transform:initial;
285
+ letter-spacing:initial;
286
+ position:relative;
287
+ display:-webkit-box;
288
+ display:-ms-flexbox;
289
+ display:flex;
290
+ -webkit-box-pack:center;
291
+ -ms-flex-pack:center;
292
+ justify-content:center;
293
+ -webkit-box-align:center;
294
+ -ms-flex-align:center;
295
+ align-items:center;
296
+ min-width:1px;
297
+ min-height:1px;
298
+ }
299
+
300
+ @media (min-width: 40em) {
301
+ .Polaris-Button__Content {
302
+ font-size:1.4rem;
303
+ }
304
+ }
305
+
306
+ .Polaris-Button--primary {
307
+ background:linear-gradient(to bottom, #6371c7, #5563c1);
308
+ border-color:#3f4eae;
309
+ box-shadow:inset 0 1px 0 0 #6774c8, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 0 transparent;
310
+ color:white;
311
+ fill:white;
312
+ }
313
+
314
+ .Polaris-Button--primary:hover {
315
+ background:linear-gradient(to bottom, #5c6ac4, #4959bd);
316
+ border-color:#3f4eae;
317
+ color:white;
318
+ text-decoration:none;
319
+ }
320
+
321
+ .Polaris-Button--primary:focus {
322
+ border-color:#202e78;
323
+ box-shadow:inset 0 1px 0 0 #6f7bcb, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 0 1px #202e78;
324
+ }
325
+
326
+ .Polaris-Button--primary:active {
327
+ background:linear-gradient(to bottom, #3f4eae, #3f4eae);
328
+ border-color:#38469b;
329
+ box-shadow:inset 0 0 0 0 transparent, 0 1px 0 0 rgba(22, 29, 37, 0.05), 0 0 1px 0 #38469b;
330
+ }
331
+
332
+ .Polaris-Button--primary.Polaris-Button--disabled {
333
+ fill:white;
334
+ background:linear-gradient(to bottom, #bac0e6, #bac0e6);
335
+ border-color:#a7aedf;
336
+ box-shadow:none;
337
+ color:white;
338
+ }
339
+ </style>
340
+ <base target="_top">
341
+ <title>Redirecting…</title>
342
+
343
+ <script>
344
+ window.apiKey = "<%= ShopifyApp.configuration.api_key %>";
345
+ window.shopOrigin = "https://<%= @shop %>";
346
+ </script>
347
+
348
+ <%= javascript_include_tag('shopify_app/itp_polyfill', crossorigin: 'anonymous', integrity: true) %>
349
+ </head>
350
+ <body>
351
+ <main id="CookiePartitionPrompt">
352
+ <div class="Polaris-Page">
353
+ <div class="Polaris-Page__Content">
354
+ <div class="Polaris-Layout">
355
+ <div class="Polaris-Layout__Section">
356
+ <div class="Polaris-Stack Polaris-Stack--vertical">
357
+ <div class="Polaris-Stack__Item">
358
+ <div class="Polaris-Card">
359
+ <div class="Polaris-Card__Header">
360
+ <h1 class="Polaris-Heading"><%= I18n.t('enable_cookies_heading', app: ShopifyApp.configuration.application_name) %></h1>
361
+ </div>
362
+ <div class="Polaris-Card__Section">
363
+ <p><%= I18n.t('enable_cookies_body', app: ShopifyApp.configuration.application_name) %></p>
364
+ </div>
365
+ <div class="Polaris-Card__Section Polaris-Card__Section--subdued">
366
+ <p><%= I18n.t('enable_cookies_footer') %></p>
367
+ </div>
368
+ </div>
369
+ </div>
370
+ <div class="Polaris-Stack__Item">
371
+ <div class="Polaris-Stack Polaris-Stack--distributionTrailing">
372
+ <div class="Polaris-Stack__Item">
373
+ <button type="button" class="Polaris-Button Polaris-Button--primary" id="AcceptCookies">
374
+ <span class="Polaris-Button__Content"><span><%= I18n.t('enable_cookies_action') %></span></span>
375
+ </button>
376
+ </div>
377
+ </div>
378
+ </div>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </main>
385
+ </body>
386
+ </html>
@@ -2,3 +2,7 @@ en:
2
2
  logged_out: 'Successfully logged out'
3
3
  could_not_log_in: 'Could not log in to Shopify store'
4
4
  invalid_shop_url: 'Invalid shop domain'
5
+ enable_cookies_heading: "Enable cookies from %{app}"
6
+ enable_cookies_body: "You must manually enable cookies in this browser in order to use %{app} within Shopify."
7
+ enable_cookies_footer: 'Cookies let the app authenticate you by temporarily storing your preferences and personal information. They expire after 30 days.'
8
+ enable_cookies_action: 'Enable cookies'
data/config/routes.rb CHANGED
@@ -2,6 +2,7 @@ ShopifyApp::Engine.routes.draw do
2
2
  controller :sessions do
3
3
  get 'login' => :new, :as => :login
4
4
  post 'login' => :create, :as => :authenticate
5
+ get 'enable_cookies' => :enable_cookies, :as => :enable_cookies
5
6
  get 'auth/shopify/callback' => :callback
6
7
  get 'logout' => :destroy, :as => :logout
7
8
  end
@@ -5,11 +5,11 @@
5
5
  if (!document.documentElement.hasAttribute("data-turbolinks-preview")) {
6
6
  document.addEventListener(eventName, function flash() {
7
7
  <% if flash[:notice] %>
8
- ShopifyApp.flashNotice("<%= j flash[:notice].html_safe %>");
8
+ ShopifyApp.flashNotice(<%== flash[:notice].to_json %>);
9
9
  <% end %>
10
10
 
11
11
  <% if flash[:error] %>
12
- ShopifyApp.flashError("<%= j flash[:error].html_safe %>");
12
+ ShopifyApp.flashError(<%== flash[:error].to_json %>);
13
13
  <% end %>
14
14
 
15
15
  document.removeEventListener(eventName, flash)
@@ -5,19 +5,19 @@ module ShopifyApp
5
5
  class ShopifyDomainNotFound < StandardError; end
6
6
 
7
7
  included do
8
+ after_action :set_test_cookie
8
9
  rescue_from ActiveResource::UnauthorizedAccess, :with => :close_session
9
10
  end
10
11
 
11
12
  def shopify_session
12
- if shop_session
13
- begin
14
- ShopifyAPI::Base.activate_session(shop_session)
15
- yield
16
- ensure
17
- ShopifyAPI::Base.clear_session
18
- end
19
- else
20
- redirect_to_login
13
+ return redirect_to_login unless shop_session
14
+ clear_top_level_oauth_cookie
15
+
16
+ begin
17
+ ShopifyAPI::Base.activate_session(shop_session)
18
+ yield
19
+ ensure
20
+ ShopifyAPI::Base.clear_session
21
21
  end
22
22
  end
23
23
 
@@ -28,8 +28,7 @@ module ShopifyApp
28
28
 
29
29
  def login_again_if_different_shop
30
30
  if shop_session && params[:shop] && params[:shop].is_a?(String) && (shop_session.url != params[:shop])
31
- session[:shopify] = nil
32
- session[:shopify_domain] = nil
31
+ clear_shop_session
33
32
  redirect_to_login
34
33
  end
35
34
  end
@@ -48,25 +47,42 @@ module ShopifyApp
48
47
  end
49
48
 
50
49
  def close_session
50
+ clear_shop_session
51
+ redirect_to login_url
52
+ end
53
+
54
+ def clear_shop_session
51
55
  session[:shopify] = nil
52
56
  session[:shopify_domain] = nil
53
- redirect_to login_url
57
+ session[:shopify_user] = nil
54
58
  end
55
59
 
56
- def login_url
60
+ def login_url(top_level: false)
57
61
  url = ShopifyApp.configuration.login_url
58
62
 
59
- if params[:shop].present?
60
- query = { shop: sanitized_params[:shop] }.to_query
61
- url = "#{url}?#{query}"
62
- end
63
+ query_params = login_url_params(top_level: top_level)
63
64
 
65
+ url = "#{url}?#{query_params.to_query}" if query_params.present?
64
66
  url
65
67
  end
66
68
 
69
+ def login_url_params(top_level:)
70
+ query_params = {}
71
+ query_params[:shop] = sanitized_params[:shop] if params[:shop].present?
72
+
73
+ has_referer_shop_name = referer_sanitized_shop_name.present?
74
+
75
+ if has_referer_shop_name
76
+ query_params[:shop] ||= referer_sanitized_shop_name
77
+ end
78
+
79
+ query_params[:top_level] = true if top_level
80
+ query_params
81
+ end
82
+
67
83
  def fullpage_redirect_to(url)
68
84
  if ShopifyApp.configuration.embedded_app?
69
- render 'shopify_app/shared/redirect', locals: { url: url, current_shopify_domain: current_shopify_domain }
85
+ render 'shopify_app/shared/redirect', layout: false, locals: { url: url, current_shopify_domain: current_shopify_domain }
70
86
  else
71
87
  redirect_to url
72
88
  end
@@ -83,6 +99,17 @@ module ShopifyApp
83
99
  @sanitized_shop_name ||= sanitize_shop_param(params)
84
100
  end
85
101
 
102
+ def referer_sanitized_shop_name
103
+ return unless request.referer.present?
104
+
105
+ @referer_sanitized_shop_name ||= begin
106
+ referer_uri = URI(request.referer)
107
+ query_params = Rack::Utils.parse_query(referer_uri.query)
108
+
109
+ sanitize_shop_param(query_params.with_indifferent_access)
110
+ end
111
+ end
112
+
86
113
  def sanitize_shop_param(params)
87
114
  return unless params[:shop].present?
88
115
  ShopifyApp::Utils.sanitize_shop_domain(params[:shop])
@@ -95,5 +122,18 @@ module ShopifyApp
95
122
  end
96
123
  end
97
124
  end
125
+
126
+ def set_test_cookie
127
+ return unless ShopifyApp.configuration.embedded_app?
128
+ session['shopify.cookies_persist'] = true
129
+ end
130
+
131
+ def clear_top_level_oauth_cookie
132
+ session.delete('shopify.top_level_oauth')
133
+ end
134
+
135
+ def set_top_level_oauth_cookie
136
+ session['shopify.top_level_oauth'] = true
137
+ end
98
138
  end
99
139
  end
@@ -4,7 +4,10 @@ module ShopifyApp
4
4
  isolate_namespace ShopifyApp
5
5
 
6
6
  initializer "shopify_app.assets.precompile" do |app|
7
- app.config.assets.precompile += %w( shopify_app/redirect.js )
7
+ app.config.assets.precompile += %w[
8
+ shopify_app/redirect.js
9
+ shopify_app/itp_polyfill.js
10
+ ]
8
11
  end
9
12
  end
10
13
  end
@@ -1,3 +1,3 @@
1
1
  module ShopifyApp
2
- VERSION = '8.2.6'.freeze
2
+ VERSION = '8.3.0'.freeze
3
3
  end
data/translation.yml ADDED
@@ -0,0 +1,7 @@
1
+ source_language: en
2
+ target_languages: [de, es, fr, it, ja, pt-BR]
3
+ components:
4
+ - name: 'merchant'
5
+ paths:
6
+ - config/locales/{{language}}.yml
7
+ - config/locales/**/{{language}}.yml
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_app
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.2.6
4
+ version: 8.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-09 00:00:00.000000000 Z
11
+ date: 2018-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -130,16 +130,19 @@ extra_rdoc_files: []
130
130
  files:
131
131
  - ".github/ISSUE_TEMPLATE.md"
132
132
  - ".gitignore"
133
+ - ".rubocop.yml"
133
134
  - ".travis.yml"
134
135
  - CHANGELOG.md
135
136
  - Gemfile
136
137
  - LICENSE
137
138
  - README.md
138
139
  - Rakefile
140
+ - app/assets/javascripts/shopify_app/itp_polyfill.js
139
141
  - app/assets/javascripts/shopify_app/redirect.js
140
142
  - app/controllers/shopify_app/authenticated_controller.rb
141
143
  - app/controllers/shopify_app/sessions_controller.rb
142
144
  - app/controllers/shopify_app/webhooks_controller.rb
145
+ - app/views/shopify_app/sessions/enable_cookies.html.erb
143
146
  - app/views/shopify_app/sessions/new.html.erb
144
147
  - app/views/shopify_app/shared/redirect.html.erb
145
148
  - config/locales/de.yml
@@ -198,6 +201,7 @@ files:
198
201
  - lib/shopify_app/version.rb
199
202
  - shipit.rubygems.yml
200
203
  - shopify_app.gemspec
204
+ - translation.yml
201
205
  homepage:
202
206
  licenses: []
203
207
  metadata: {}