shopify_app 8.2.6 → 8.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: {}