shopify_app 12.0.2 → 12.0.7

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
  SHA256:
3
- metadata.gz: dd21d52fbb932f0fef8522975adfb22431ff103d7fa14e4591e0eb24bafeeaec
4
- data.tar.gz: da650fd1de45574447c28dca6803adf49063e0c879a0eab7d71b2823d3d1f15c
3
+ metadata.gz: c5acb9f9fb1606515013edfda25f981c36cf5ab4323572764ba9715018056532
4
+ data.tar.gz: e5499e7186fa12f37e01f975d7b67ed6a846d67679b580846a7191b53d81b3d3
5
5
  SHA512:
6
- metadata.gz: 04f13911597abebbc3e32bc72ac42f9cfe01e2370515935bac076ce9517a44767af1f6185260cbeaae6a5eb2f76f48eb19ff9f013d41504d144ba8b23fb7ca6a
7
- data.tar.gz: 3474caf61956e3bd8c3b4ae37fb326403493e3391805b85f3962aa753e080b0dfc3c3f82173991b099b804784123d5bf6d108e99ab4f1795c16f4f4cdd1ba862
6
+ metadata.gz: c9e736b65bf5091c6ebdca30073653dde86abc131cd77747f872c0d42972bc35abdd406301e5a5eb0dd4f9273c66264c75b28e119d05d203e440038bb19250d3
7
+ data.tar.gz: 264ed359e7e07cf7b0947cbafad738cabf220e470872c663f18c2507c17c7d994316af275f1d28820d5624df03fabadf6f213475fb793b4fd024de514b636cf0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ 12.0.7
2
+ ------
3
+ * Remove check for API_KEY in config that was throwing errors during install #919
4
+
5
+ 12.0.6
6
+ ------
7
+ * Adds changelog information and README updates for 8.4.0 #916
8
+
9
+ 12.0.5
10
+ ------
11
+ * Updating shopify_api gem to 9.0.1
12
+
13
+ 12.0.4
14
+ ------
15
+ * Reverts reverted PR (#895) #897
16
+
17
+ 12.0.3
18
+ ------
19
+ * Moves samesite middleware higher in the stack #898
20
+ * Fix issue where not redirecting user to granted storage page casues infinite loop #900
21
+
1
22
  12.0.2
2
23
  ------
3
24
  * Reverts "Fix for return_to in safari after enable_cookies/granted_storage_access" introduced in 12.0.1
@@ -178,6 +199,7 @@ Added support for rotating Shopify access tokens:
178
199
  8.4.0
179
200
  ----
180
201
  * Fix embedded app session management in Safari 12.1
202
+ * Note that with this change we have extracted the callback action in its own controller. If you are relying on it, see the README for more details: https://github.com/Shopify/shopify_app#callback
181
203
  * Shop names passed to OAuth are no longer case sensitive
182
204
 
183
205
  8.3.2
data/README.md CHANGED
@@ -91,7 +91,9 @@ SHOPIFY_API_KEY=your api key
91
91
  SHOPIFY_API_SECRET=your api secret
92
92
  ```
93
93
 
94
- These values can be found on the "App Setup" page in the [Shopify Partners Dashboard][dashboard]. If you are checking your code into a code repository, ensure your `.gitignore` prevents your `.env` file from being checked into any publicly accessible code.
94
+ These values can be found on the "App Setup" page in the [Shopify Partners Dashboard][dashboard]. If you are checking your code into a code repository, ensure your `.gitignore` prevents your `.env` file from being checked into any publicly accessible code.
95
+
96
+ **You will need to load the ENV variables into your enviroment, you can do this with the [dot-env](https://github.com/bkeepers/dotenv) gem or any other method you wish to.**
95
97
 
96
98
  ### Install Generator
97
99
 
@@ -211,6 +213,17 @@ end
211
213
  Authentication
212
214
  --------------
213
215
 
216
+ ### Callback
217
+
218
+ Upon completing the authentication flow Shopify calls the app at the `callback_path` mentioned before. If the app needs to do some extra work it can define and configure the route to a custom callback controller, inheriting from `ShopifyApp::CallbackController` and hook into or override any of the defined helper methods. The default callback controller already provides the following behaviour:
219
+ * Logging into the shop and resetting the session
220
+ * [Installing Webhooks](https://github.com/Shopify/shopify_app#webhooksmanager)
221
+ * [Setting Scripttags](https://github.com/Shopify/shopify_app#scripttagsmanager)
222
+ * [Performing the AfterAuthenticate Job](https://github.com/Shopify/shopify_app#afterauthenticatejob)
223
+ * Redirecting to the return address
224
+
225
+ **Note that starting with version 8.4.0, we have extracted the callback logic in its own controller. If you are upgrading from a version older than 8.4.0 the callback action and related helper methods were defined in `ShopifyApp::SessionsController` ==> you will have to extend `ShopifyApp::CallbackController` instead and port your logic to the new controller.**
226
+
214
227
  ### ShopifyApp::SessionRepository
215
228
 
216
229
  `ShopifyApp::SessionRepository` allows you as a developer to define how your sessions are stored and retrieved for shops. The `SessionRepository` is configured in the `config/initializers/shopify_app.rb` file and can be set to any object that implements `self.store(auth_session, *args)` which stores the session and returns a unique identifier and `self.retrieve(id)` which returns a `ShopifyAPI::Session` for the passed id. These methods are already implemented as part of the `ShopifyApp::SessionStorage` concern, but can be overridden for custom implementation.
@@ -287,6 +300,14 @@ bin/rails g shopify_app:add_after_authenticate_job
287
300
 
288
301
  If you want to perform that action only once, e.g. send a welcome email to the user when they install the app, you should make sure that this action is idempotent, meaning that it won't have an impact if run multiple times.
289
302
 
303
+ API Versioning
304
+ --------------
305
+
306
+ Shopify's API is versioned, and you can [read about that process in the Shopify Developers documentation page](https://shopify.dev/concepts/about-apis/versioning).
307
+
308
+ Since shopify_app gem version 1.11.0, the included shopify_api gem has also been updated to allow you to easily set and switch what version of the Shopify API you want your app or service to use, as well as surface warnings to Rails apps about [deprecated endpoints, GraphQL fields and more](https://shopify.dev/concepts/about-apis/versioning#deprecation-practices).
309
+
310
+ See the [shopify_api gem README](https://github.com/Shopify/shopify_api/) for more details.
290
311
 
291
312
  WebhooksManager
292
313
  ---------------
@@ -463,6 +484,7 @@ Questions or problems?
463
484
 
464
485
  - [Ask questions!](https://ecommerce.shopify.com/c/shopify-apis-and-technology)
465
486
  - [Read the docs!](https://help.shopify.com/api/guides)
487
+ - And don't forget to check the [Changelog](https://github.com/Shopify/shopify_app/blob/master/CHANGELOG.md) too!
466
488
 
467
489
  Upgrading to 11.7.0
468
490
  ---------------------------
@@ -28,8 +28,8 @@
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
33
  }
34
34
 
35
35
  StorageAccessHelper.prototype.sameSiteNoneIncompatible = function(ua) {
@@ -68,7 +68,7 @@
68
68
  if (!document.cookie) {
69
69
  throw 'Cannot set third-party cookie.'
70
70
  }
71
- this.redirectToAppHome();
71
+ this.redirectToAppTargetUrl();
72
72
  } catch (error) {
73
73
  console.warn('Third party cookies may be blocked.', error);
74
74
  this.redirectToAppTLD(ACCESS_DENIED_STATUS);
@@ -90,7 +90,7 @@
90
90
  StorageAccessHelper.prototype.handleHasStorageAccess = function() {
91
91
  if (sessionStorage.getItem('shopify.granted_storage_access')) {
92
92
  // If app was classified by ITP and used Storage Access API to acquire access
93
- this.redirectToAppHome();
93
+ this.redirectToAppTargetUrl();
94
94
  } else {
95
95
  // If app has not been classified by ITP and still has storage access
96
96
  this.redirectToAppTLD(ACCESS_GRANTED_STATUS);
@@ -20,11 +20,15 @@ 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
26
  has_storage_access_url: login_url_with_optional_shop(top_level: true),
26
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
27
- current_shopify_domain: current_shopify_domain,
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
 
@@ -38,8 +42,9 @@ module ShopifyApp
38
42
 
39
43
  session['shopify.granted_storage_access'] = true
40
44
 
41
- params = { shop: @shop }
42
- redirect_to("#{return_address}?#{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
@@ -54,7 +59,7 @@ 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
 
57
- session[:return_to] = params[:return_to] if params[:return_to]
62
+ copy_return_to_param_to_session
58
63
 
59
64
  if user_agent_can_partition_cookies
60
65
  authenticate_with_partitioning
@@ -93,6 +98,10 @@ module ShopifyApp
93
98
  true
94
99
  end
95
100
 
101
+ def copy_return_to_param_to_session
102
+ session[:return_to] = params[:return_to] if params[:return_to]
103
+ end
104
+
96
105
  def render_invalid_shop_error
97
106
  flash[:error] = I18n.t('invalid_shop_url')
98
107
  redirect_to return_address
@@ -133,11 +142,15 @@ module ShopifyApp
133
142
  layout: false,
134
143
  locals: {
135
144
  does_not_have_storage_access_url: top_level_interaction_path(
136
- shop: sanitized_shop_name
145
+ shop: sanitized_shop_name,
146
+ return_to: session[:return_to]
137
147
  ),
138
148
  has_storage_access_url: login_url_with_optional_shop(top_level: true),
139
- app_home_url: granted_storage_access_path(shop: sanitized_shop_name),
140
- current_shopify_domain: current_shopify_domain,
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
141
154
  }
142
155
  )
143
156
  end
@@ -32,7 +32,7 @@
32
32
  myshopifyUrl: "https://#{current_shopify_domain}",
33
33
  hasStorageAccessUrl: "#{has_storage_access_url}",
34
34
  doesNotHaveStorageAccessUrl: "#{does_not_have_storage_access_url}",
35
- appHomeUrl: "#{app_home_url}"
35
+ appTargetUrl: "#{app_target_url}"
36
36
  },
37
37
  },
38
38
  )
@@ -24,7 +24,7 @@
24
24
  myshopifyUrl: "https://#{current_shopify_domain}",
25
25
  hasStorageAccessUrl: "#{has_storage_access_url}",
26
26
  doesNotHaveStorageAccessUrl: "#{does_not_have_storage_access_url}",
27
- appHomeUrl: "#{app_home_url}"
27
+ appTargetUrl: "#{app_target_url}"
28
28
  },
29
29
  },
30
30
  )
@@ -5,7 +5,7 @@ module ShopifyApp
5
5
  # for the app in your Shopify Partners page. Change your settings in
6
6
  # `config/initializers/shopify_app.rb`
7
7
  attr_accessor :application_name
8
- attr_accessor :api_key
8
+ attr_accessor :api_key
9
9
  attr_accessor :secret
10
10
  attr_accessor :old_secret
11
11
  attr_accessor :scope
@@ -100,8 +100,10 @@ module ShopifyApp
100
100
  query_params = {}
101
101
  query_params[:shop] = sanitized_params[:shop] if params[:shop].present?
102
102
 
103
- if session[:return_to] && return_to_param_required?
104
- query_params[:return_to] = session[:return_to]
103
+ return_to = session[:return_to] || params[:return_to]
104
+
105
+ if return_to.present? && return_to_param_required?
106
+ query_params[:return_to] = return_to
105
107
  end
106
108
 
107
109
  has_referer_shop_name = referer_sanitized_shop_name.present?
@@ -165,5 +167,15 @@ module ShopifyApp
165
167
  def return_address
166
168
  session.delete(:return_to) || ShopifyApp.configuration.root_url
167
169
  end
170
+
171
+ def return_address_with_params(params)
172
+ uri = URI(return_address)
173
+ uri.query = CGI.parse(uri.query.to_s)
174
+ .symbolize_keys
175
+ .transform_values { |v| v.one? ? v.first : v }
176
+ .merge(params)
177
+ .to_query
178
+ uri.to_s
179
+ end
168
180
  end
169
181
  end
@@ -14,7 +14,7 @@ module ShopifyApp
14
14
  end
15
15
 
16
16
  initializer "shopify_app.middleware" do |app|
17
- app.config.middleware.insert_before(ActionDispatch::Cookies, ShopifyApp::SameSiteCookieMiddleware)
17
+ app.config.middleware.insert_after(::Rack::Runtime, ShopifyApp::SameSiteCookieMiddleware)
18
18
  end
19
19
  end
20
20
  end
@@ -1,60 +1,33 @@
1
1
  module ShopifyApp
2
2
  class SameSiteCookieMiddleware
3
+ COOKIE_SEPARATOR = "\n"
4
+
3
5
  def initialize(app)
4
6
  @app = app
5
7
  end
6
8
 
7
9
  def call(env)
8
- _status, headers, _body = @app.call(env)
9
- ensure
10
+ status, headers, body = @app.call(env)
10
11
  user_agent = env['HTTP_USER_AGENT']
11
12
 
12
- if headers && headers['Set-Cookie'] && !SameSiteCookieMiddleware.same_site_none_incompatible?(user_agent) &&
13
- ShopifyApp.configuration.enable_same_site_none
14
-
15
- cookies = headers['Set-Cookie'].split("\n").compact
16
-
17
- cookies.each do |cookie|
18
- unless cookie.include?("; SameSite")
19
- headers['Set-Cookie'] = headers['Set-Cookie'].gsub(cookie, "#{cookie}; secure; SameSite=None")
13
+ if headers && headers['Set-Cookie'] &&
14
+ BrowserSniffer.new(user_agent).same_site_none_compatible? &&
15
+ ShopifyApp.configuration.enable_same_site_none &&
16
+ Rack::Request.new(env).ssl?
17
+
18
+ set_cookies = headers['Set-Cookie']
19
+ .split(COOKIE_SEPARATOR)
20
+ .compact
21
+ .map do |cookie|
22
+ cookie << '; Secure' if not cookie =~ /;\s*secure/i
23
+ cookie << '; SameSite=None' unless cookie =~ /;\s*samesite=/i
24
+ cookie
20
25
  end
21
- end
22
- end
23
- end
24
26
 
25
- def self.same_site_none_incompatible?(user_agent)
26
- sniffer = BrowserSniffer.new(user_agent)
27
-
28
- webkit_same_site_bug?(sniffer) || drops_unrecognized_same_site_cookies?(sniffer)
29
- rescue
30
- true
31
- end
32
-
33
- def self.webkit_same_site_bug?(sniffer)
34
- (sniffer.os == :ios && sniffer.os_version.match(/^([0-9]|1[12])[\.\_]/)) ||
35
- (sniffer.os == :mac && sniffer.browser == :safari && sniffer.os_version.match(/^10[\.\_]14/))
36
- end
37
-
38
- def self.drops_unrecognized_same_site_cookies?(sniffer)
39
- (chromium_based?(sniffer) && sniffer.major_browser_version >= 51 && sniffer.major_browser_version <= 66) ||
40
- (uc_browser?(sniffer) && !uc_browser_version_at_least?(sniffer: sniffer, major: 12, minor: 13, build: 2))
41
- end
42
-
43
- def self.chromium_based?(sniffer)
44
- sniffer.browser_name.downcase.match(/chrom(e|ium)/)
45
- end
46
-
47
- def self.uc_browser?(sniffer)
48
- sniffer.user_agent.downcase.match(/uc\s?browser/)
49
- end
50
-
51
- def self.uc_browser_version_at_least?(sniffer:, major:, minor:, build:)
52
- digits = sniffer.browser_version.split('.').map(&:to_i)
53
- return false unless digits.count >= 3
27
+ headers['Set-Cookie'] = set_cookies.join(COOKIE_SEPARATOR)
28
+ end
54
29
 
55
- return digits[0] > major if digits[0] != major
56
- return digits[1] > minor if digits[1] != minor
57
- digits[2] >= build
30
+ [status, headers, body]
58
31
  end
59
32
  end
60
33
  end
@@ -1,3 +1,3 @@
1
1
  module ShopifyApp
2
- VERSION = '12.0.2'.freeze
2
+ VERSION = '12.0.7'.freeze
3
3
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shopify_app",
3
- "version": "12.0.2",
3
+ "version": "12.0.5",
4
4
  "repository": "git@github.com:Shopify/shopify_app.git",
5
5
  "author": "Shopify",
6
6
  "license": "MIT",
data/shopify_app.gemspec CHANGED
@@ -10,9 +10,9 @@ Gem::Specification.new do |s|
10
10
 
11
11
  s.required_ruby_version = ">= 2.3.1"
12
12
 
13
- s.add_runtime_dependency('browser_sniffer', '~> 1.1.3')
13
+ s.add_runtime_dependency('browser_sniffer', '~> 1.2.0')
14
14
  s.add_runtime_dependency('rails', '> 5.2.1')
15
- s.add_runtime_dependency('shopify_api', '~> 9.0')
15
+ s.add_runtime_dependency('shopify_api', '~> 9.0.1')
16
16
  s.add_runtime_dependency('omniauth-shopify-oauth2', '~> 2.2.0')
17
17
 
18
18
  s.add_development_dependency('rake')
@@ -29,4 +29,4 @@ Gem::Specification.new do |s|
29
29
  s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|example)/}) }
30
30
  s.test_files = `git ls-files -- {test}/*`.split("\n")
31
31
  s.require_paths = ["lib"]
32
- end
32
+ end
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: 12.0.2
4
+ version: 12.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-11 00:00:00.000000000 Z
11
+ date: 2020-03-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: browser_sniffer
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.1.3
19
+ version: 1.2.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.1.3
26
+ version: 1.2.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '9.0'
47
+ version: 9.0.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '9.0'
54
+ version: 9.0.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: omniauth-shopify-oauth2
57
57
  requirement: !ruby/object:Gem::Requirement