shopify_app 6.4.2 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +13 -0
  3. data/ISSUE_TEMPLATE.md +14 -0
  4. data/QUICKSTART.md +6 -7
  5. data/README.md +38 -16
  6. data/Rakefile +2 -6
  7. data/app/controllers/shopify_app/authenticated_controller.rb +7 -0
  8. data/app/controllers/shopify_app/sessions_controller.rb +5 -0
  9. data/app/controllers/shopify_app/webhooks_controller.rb +27 -0
  10. data/app/views/{sessions → shopify_app/sessions}/new.html.erb +0 -0
  11. data/config/routes.rb +4 -0
  12. data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +61 -0
  13. data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb +8 -0
  14. data/lib/generators/shopify_app/controllers/controllers_generator.rb +1 -1
  15. data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +0 -1
  16. data/lib/generators/shopify_app/home_controller/templates/home_controller.rb +1 -1
  17. data/lib/generators/shopify_app/install/install_generator.rb +13 -19
  18. data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +2 -2
  19. data/lib/generators/shopify_app/install/templates/shopify_app.rb +3 -4
  20. data/lib/generators/shopify_app/install/templates/shopify_provider.rb +0 -1
  21. data/lib/generators/shopify_app/routes/templates/routes.rb +4 -0
  22. data/lib/generators/shopify_app/shopify_app_generator.rb +1 -7
  23. data/lib/shopify_app.rb +2 -3
  24. data/lib/shopify_app/configuration.rb +0 -1
  25. data/lib/shopify_app/engine.rb +1 -0
  26. data/lib/shopify_app/login_protection.rb +53 -5
  27. data/lib/shopify_app/{sessions_controller.rb → sessions_concern.rb} +5 -5
  28. data/lib/shopify_app/version.rb +1 -1
  29. data/lib/shopify_app/webhook_verification.rb +35 -0
  30. data/shopify_app.gemspec +1 -1
  31. metadata +11 -43
  32. data/CONTRIBUTING.md +0 -14
  33. data/app/controllers/authenticated_controller.rb +0 -5
  34. data/app/controllers/sessions_controller.rb +0 -3
  35. data/lib/shopify_app/controller.rb +0 -18
  36. data/lib/shopify_app/webhooks_controller.rb +0 -35
  37. data/test/app_templates/app/controllers/application_controller.rb +0 -2
  38. data/test/app_templates/config/application.rb +0 -24
  39. data/test/app_templates/config/initializers/shopify_app.rb +0 -6
  40. data/test/app_templates/config/routes.rb +0 -4
  41. data/test/controllers/sessions_controller_test.rb +0 -122
  42. data/test/controllers/sessions_routes_test.rb +0 -27
  43. data/test/dummy/Rakefile +0 -6
  44. data/test/dummy/app/controllers/application_controller.rb +0 -3
  45. data/test/dummy/app/controllers/home_controller.rb +0 -7
  46. data/test/dummy/config.ru +0 -4
  47. data/test/dummy/config/application.rb +0 -26
  48. data/test/dummy/config/boot.rb +0 -5
  49. data/test/dummy/config/database.yml +0 -25
  50. data/test/dummy/config/environment.rb +0 -5
  51. data/test/dummy/config/environments/test.rb +0 -42
  52. data/test/dummy/config/initializers/shopify_app.rb +0 -6
  53. data/test/dummy/config/routes.rb +0 -10
  54. data/test/dummy/config/secrets.yml +0 -17
  55. data/test/generators/controllers_generator_test.rb +0 -16
  56. data/test/generators/home_controller_generator_test.rb +0 -50
  57. data/test/generators/install_generator_test.rb +0 -87
  58. data/test/generators/routes_generator_test.rb +0 -26
  59. data/test/generators/shop_model_generator_test.rb +0 -39
  60. data/test/generators/shopify_app_generator.rb +0 -15
  61. data/test/generators/views_generator_test.rb +0 -15
  62. data/test/shopify_app/configuration_test.rb +0 -49
  63. data/test/shopify_app/in_memory_session_store_test.rb +0 -35
  64. data/test/shopify_app/login_protection_test.rb +0 -100
  65. data/test/shopify_app/shopify_session_repository_test.rb +0 -73
  66. data/test/shopify_app/utils_test.rb +0 -30
  67. data/test/shopify_app/webhooks_controller_test.rb +0 -50
  68. data/test/shopify_app/webhooks_manager_test.rb +0 -86
  69. data/test/support/generator_test_helpers.rb +0 -29
  70. data/test/test_helper.rb +0 -17
@@ -1,7 +1,6 @@
1
1
  ShopifyApp.configure do |config|
2
- config.api_key = "<%= opts[:api_key] %>"
3
- config.secret = "<%= opts[:secret] %>"
4
- config.redirect_uri = "<%= opts[:redirect_uri] %>"
5
- config.scope = "<%= opts[:scope] %>"
2
+ config.api_key = "<%= @api_key %>"
3
+ config.secret = "<%= @secret %>"
4
+ config.scope = "<%= @scope %>"
6
5
  config.embedded_app = <%= embedded_app? %>
7
6
  end
@@ -1,5 +1,4 @@
1
1
  provider :shopify,
2
2
  ShopifyApp.configuration.api_key,
3
3
  ShopifyApp.configuration.secret,
4
- redirect_uri: ShopifyApp.configuration.redirect_uri,
5
4
  scope: ShopifyApp.configuration.scope
@@ -5,3 +5,7 @@
5
5
  get 'auth/shopify/callback' => :callback
6
6
  get 'logout' => :destroy, :as => :logout
7
7
  end
8
+
9
+ namespace :webhooks do
10
+ post ':type' => :receive
11
+ end
@@ -1,7 +1,6 @@
1
1
  module ShopifyApp
2
2
  module Generators
3
3
  class ShopifyAppGenerator < Rails::Generators::Base
4
-
5
4
  def initialize(args, *options)
6
5
  @opts = options.first
7
6
  super(args, *options)
@@ -9,14 +8,9 @@ module ShopifyApp
9
8
 
10
9
  def run_all_generators
11
10
  generate "shopify_app:install #{@opts.join(' ')}"
12
- generate "shopify_app:home_controller"
13
11
  generate "shopify_app:shop_model"
14
-
15
- generate "shopify_app:controllers"
16
- generate "shopify_app:views"
17
- generate "shopify_app:routes"
12
+ generate "shopify_app:home_controller"
18
13
  end
19
-
20
14
  end
21
15
  end
22
16
  end
@@ -16,11 +16,10 @@ require 'shopify_app/webhooks_manager_job'
16
16
  # helpers and concerns
17
17
  require 'shopify_app/shop'
18
18
  require 'shopify_app/session_storage'
19
- require 'shopify_app/controller'
20
- require 'shopify_app/sessions_controller'
19
+ require 'shopify_app/sessions_concern'
21
20
  require 'shopify_app/login_protection'
22
21
  require 'shopify_app/webhooks_manager'
23
- require 'shopify_app/webhooks_controller'
22
+ require 'shopify_app/webhook_verification'
24
23
  require 'shopify_app/utils'
25
24
 
26
25
  # session repository
@@ -6,7 +6,6 @@ module ShopifyApp
6
6
  # `config/initializers/shopify_app.rb`
7
7
  attr_accessor :api_key
8
8
  attr_accessor :secret
9
- attr_accessor :redirect_uri
10
9
  attr_accessor :scope
11
10
  attr_accessor :embedded_app
12
11
  alias_method :embedded_app?, :embedded_app
@@ -1,5 +1,6 @@
1
1
  module ShopifyApp
2
2
  class Engine < Rails::Engine
3
3
  engine_name 'shopify_app'
4
+ isolate_namespace ShopifyApp
4
5
  end
5
6
  end
@@ -39,21 +39,69 @@ module ShopifyApp
39
39
  head :unauthorized
40
40
  else
41
41
  session[:return_to] = request.fullpath if request.get?
42
- redirect_to login_path(shop: params[:shop])
42
+ redirect_to_with_fallback main_or_engine_login_url(shop: params[:shop])
43
43
  end
44
44
  end
45
45
 
46
46
  def close_session
47
47
  session[:shopify] = nil
48
48
  session[:shopify_domain] = nil
49
- redirect_to login_path
49
+ redirect_to_with_fallback login_url
50
50
  end
51
51
 
52
- def login_path(params = {})
53
- main_app.login_path(params)
52
+ def main_or_engine_login_url(params = {})
53
+ main_app.login_url(params)
54
54
  rescue NoMethodError => e
55
- shopify_app.login_path(params)
55
+ shopify_app.login_url(params)
56
56
  end
57
57
 
58
+ def redirect_to_with_fallback(url)
59
+ url_json = url.to_json
60
+ url_json_no_quotes = url_json.gsub(/\A"|"\Z/, '')
61
+
62
+ render inline: %Q(
63
+ <!DOCTYPE html>
64
+ <html lang="en">
65
+ <head>
66
+ <meta charset="utf-8" />
67
+ <meta http-equiv="refresh" content="0; url=#{url_json_no_quotes}">
68
+ <title>Redirecting…</title>
69
+ <script type="text/javascript">
70
+ window.location.href = #{url_json};
71
+ </script>
72
+ </head>
73
+ <body>
74
+ <a href=#{url_json}>Continue</a>
75
+ </body>
76
+ </html>
77
+ ), status: 302, location: url
78
+ end
79
+
80
+ def fullpage_redirect_to(url)
81
+ url_json = url.to_json
82
+ url_json_no_quotes = url_json.gsub(/\A"|"\Z/, '')
83
+
84
+ if ShopifyApp.configuration.embedded_app?
85
+ render inline: %Q(
86
+ <!DOCTYPE html>
87
+ <html lang="en">
88
+ <head>
89
+ <meta charset="utf-8" />
90
+ <meta http-equiv="refresh" content="0; url=#{url_json_no_quotes}">
91
+ <base target="_top">
92
+ <title>Redirecting…</title>
93
+ <script type="text/javascript">
94
+ window.top.location.href = #{url_json};
95
+ </script>
96
+ </head>
97
+ <body>
98
+ <a href=#{url_json} target="_top">Continue</a>
99
+ </body>
100
+ </html>
101
+ )
102
+ else
103
+ redirect_to_with_fallback url
104
+ end
105
+ end
58
106
  end
59
107
  end
@@ -1,5 +1,5 @@
1
1
  module ShopifyApp
2
- module SessionsController
2
+ module SessionsConcern
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def new
@@ -22,10 +22,10 @@ module ShopifyApp
22
22
  WebhooksManager.queue(shop_name, token) if ShopifyApp.configuration.has_webhooks?
23
23
 
24
24
  flash[:notice] = "Logged in"
25
- redirect_to return_address
25
+ redirect_to_with_fallback return_address
26
26
  else
27
27
  flash[:error] = "Could not log in to Shopify store."
28
- redirect_to login_url
28
+ redirect_to_with_fallback login_url
29
29
  end
30
30
  end
31
31
 
@@ -33,7 +33,7 @@ module ShopifyApp
33
33
  session[:shopify] = nil
34
34
  session[:shopify_domain] = nil
35
35
  flash[:notice] = "Successfully logged out."
36
- redirect_to login_url
36
+ redirect_to_with_fallback login_url
37
37
  end
38
38
 
39
39
  protected
@@ -42,7 +42,7 @@ module ShopifyApp
42
42
  if shop_name = sanitize_shop_param(params)
43
43
  fullpage_redirect_to "#{main_app.root_path}auth/shopify?shop=#{shop_name}"
44
44
  else
45
- redirect_to return_address
45
+ redirect_to_with_fallback return_address
46
46
  end
47
47
  end
48
48
 
@@ -1,3 +1,3 @@
1
1
  module ShopifyApp
2
- VERSION = '6.4.2'
2
+ VERSION = '7.0.0'
3
3
  end
@@ -0,0 +1,35 @@
1
+ module ShopifyApp
2
+ module WebhookVerification
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ skip_before_action :verify_authenticity_token
7
+ before_action :verify_request
8
+ end
9
+
10
+ private
11
+
12
+ def verify_request
13
+ data = request.raw_post
14
+ return head :unauthorized unless hmac_valid?(data)
15
+ end
16
+
17
+ def hmac_valid?(data)
18
+ secret = ShopifyApp.configuration.secret
19
+ digest = OpenSSL::Digest.new('sha256')
20
+ ActiveSupport::SecurityUtils.variable_size_secure_compare(
21
+ shopify_hmac,
22
+ Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data)).strip
23
+ )
24
+ end
25
+
26
+ def shop_domain
27
+ request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']
28
+ end
29
+
30
+ def shopify_hmac
31
+ request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
32
+ end
33
+
34
+ end
35
+ end
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.add_development_dependency('minitest')
20
20
  s.add_development_dependency('mocha')
21
21
 
22
- s.files = `git ls-files`.split("\n")
22
+ s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|example)/}) }
23
23
  s.test_files = `git ls-files -- {test}/*`.split("\n")
24
24
  s.require_paths = ["lib"]
25
25
  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: 6.4.2
4
+ version: 7.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-29 00:00:00.000000000 Z
11
+ date: 2016-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -137,17 +137,20 @@ files:
137
137
  - ".gitignore"
138
138
  - ".travis.yml"
139
139
  - CHANGELOG
140
- - CONTRIBUTING.md
141
140
  - Gemfile
141
+ - ISSUE_TEMPLATE.md
142
142
  - LICENSE
143
143
  - QUICKSTART.md
144
144
  - README.md
145
145
  - RELEASING
146
146
  - Rakefile
147
- - app/controllers/authenticated_controller.rb
148
- - app/controllers/sessions_controller.rb
149
- - app/views/sessions/new.html.erb
147
+ - app/controllers/shopify_app/authenticated_controller.rb
148
+ - app/controllers/shopify_app/sessions_controller.rb
149
+ - app/controllers/shopify_app/webhooks_controller.rb
150
+ - app/views/shopify_app/sessions/new.html.erb
150
151
  - config/routes.rb
152
+ - lib/generators/shopify_app/add_webhook/add_webhook_generator.rb
153
+ - lib/generators/shopify_app/add_webhook/templates/webhook_job.rb
151
154
  - lib/generators/shopify_app/controllers/controllers_generator.rb
152
155
  - lib/generators/shopify_app/home_controller/home_controller_generator.rb
153
156
  - lib/generators/shopify_app/home_controller/templates/home_controller.rb
@@ -171,55 +174,20 @@ files:
171
174
  - lib/generators/shopify_app/views/views_generator.rb
172
175
  - lib/shopify_app.rb
173
176
  - lib/shopify_app/configuration.rb
174
- - lib/shopify_app/controller.rb
175
177
  - lib/shopify_app/engine.rb
176
178
  - lib/shopify_app/in_memory_session_store.rb
177
179
  - lib/shopify_app/login_protection.rb
178
180
  - lib/shopify_app/session_storage.rb
179
- - lib/shopify_app/sessions_controller.rb
181
+ - lib/shopify_app/sessions_concern.rb
180
182
  - lib/shopify_app/shop.rb
181
183
  - lib/shopify_app/shopify_session_repository.rb
182
184
  - lib/shopify_app/utils.rb
183
185
  - lib/shopify_app/version.rb
184
- - lib/shopify_app/webhooks_controller.rb
186
+ - lib/shopify_app/webhook_verification.rb
185
187
  - lib/shopify_app/webhooks_manager.rb
186
188
  - lib/shopify_app/webhooks_manager_job.rb
187
189
  - shipit.rubygems.yml
188
190
  - shopify_app.gemspec
189
- - test/app_templates/app/controllers/application_controller.rb
190
- - test/app_templates/config/application.rb
191
- - test/app_templates/config/initializers/shopify_app.rb
192
- - test/app_templates/config/routes.rb
193
- - test/controllers/sessions_controller_test.rb
194
- - test/controllers/sessions_routes_test.rb
195
- - test/dummy/Rakefile
196
- - test/dummy/app/controllers/application_controller.rb
197
- - test/dummy/app/controllers/home_controller.rb
198
- - test/dummy/config.ru
199
- - test/dummy/config/application.rb
200
- - test/dummy/config/boot.rb
201
- - test/dummy/config/database.yml
202
- - test/dummy/config/environment.rb
203
- - test/dummy/config/environments/test.rb
204
- - test/dummy/config/initializers/shopify_app.rb
205
- - test/dummy/config/routes.rb
206
- - test/dummy/config/secrets.yml
207
- - test/generators/controllers_generator_test.rb
208
- - test/generators/home_controller_generator_test.rb
209
- - test/generators/install_generator_test.rb
210
- - test/generators/routes_generator_test.rb
211
- - test/generators/shop_model_generator_test.rb
212
- - test/generators/shopify_app_generator.rb
213
- - test/generators/views_generator_test.rb
214
- - test/shopify_app/configuration_test.rb
215
- - test/shopify_app/in_memory_session_store_test.rb
216
- - test/shopify_app/login_protection_test.rb
217
- - test/shopify_app/shopify_session_repository_test.rb
218
- - test/shopify_app/utils_test.rb
219
- - test/shopify_app/webhooks_controller_test.rb
220
- - test/shopify_app/webhooks_manager_test.rb
221
- - test/support/generator_test_helpers.rb
222
- - test/test_helper.rb
223
191
  homepage:
224
192
  licenses: []
225
193
  metadata: {}
@@ -1,14 +0,0 @@
1
- Submitting Issues
2
- -----------------
3
-
4
- Please open an issue here if you encounter a specific bug with this gem or the generators
5
-
6
- General questions about the Shopify API should be posted on the [Shopify forums](https://ecommerce.shopify.com/c/shopify-apis-and-technology).
7
-
8
-
9
- Authentication Issues
10
- ---------------------
11
-
12
- A great deal of the issues surrounding this repo are around authenticating the generated app with Shopify.
13
-
14
- If you are experiencing issues with your app authenticating the best way to get help fast is to create a repo with the minimal amount of code to demonstrate the issue and a clearly documented set of steps you took to arrive there. This will help us solve your problem quicker since we won't need to spend any time figuring out how to reproduce the bug.
@@ -1,5 +0,0 @@
1
- class AuthenticatedController < ApplicationController
2
- before_action :login_again_if_different_shop
3
- around_filter :shopify_session
4
- layout ShopifyApp.configuration.embedded_app? ? 'embedded_app' : 'application'
5
- end
@@ -1,3 +0,0 @@
1
- class SessionsController < ApplicationController
2
- include ShopifyApp::SessionsController
3
- end
@@ -1,18 +0,0 @@
1
- require 'shopify_app/login_protection'
2
-
3
- module ShopifyApp
4
- module Controller
5
- extend ActiveSupport::Concern
6
-
7
- include ShopifyApp::LoginProtection
8
-
9
- def fullpage_redirect_to(url)
10
- if ShopifyApp.configuration.embedded_app?
11
- render inline: %Q(<script type="text/javascript">window.top.location.href = #{url.to_json};</script>)
12
- else
13
- redirect_to url
14
- end
15
- end
16
-
17
- end
18
- end
@@ -1,35 +0,0 @@
1
- module ShopifyApp
2
- module WebhooksController
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- skip_before_action :verify_authenticity_token
7
- before_action :verify_request
8
- end
9
-
10
- private
11
-
12
- def verify_request
13
- request.body.rewind
14
- data = request.body.read
15
-
16
- unless validate_hmac(ShopifyApp.configuration.secret, data)
17
- head :unauthorized
18
- end
19
- end
20
-
21
- def validate_hmac(secret, data)
22
- digest = OpenSSL::Digest.new('sha256')
23
- shopify_hmac == Base64.encode64(OpenSSL::HMAC.digest(digest, secret, data)).strip
24
- end
25
-
26
- def shop_domain
27
- request.headers['HTTP_X_SHOPIFY_SHOP_DOMAIN']
28
- end
29
-
30
- def shopify_hmac
31
- request.headers['HTTP_X_SHOPIFY_HMAC_SHA256']
32
- end
33
-
34
- end
35
- end
@@ -1,2 +0,0 @@
1
- class ApplicationController < ActionController::Base
2
- end
@@ -1,24 +0,0 @@
1
- require File.expand_path('../boot', __FILE__)
2
-
3
- require 'rails/all'
4
-
5
- Bundler.require(*Rails.groups)
6
-
7
- module AppTemplate
8
- class Application < Rails::Application
9
- # Settings in config/environments/* take precedence over those specified here.
10
- # Application configuration should go into files in config/initializers
11
- # -- all .rb files in that directory are automatically loaded.
12
-
13
- # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
14
- # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
15
- # config.time_zone = 'Central Time (US & Canada)'
16
-
17
- # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
18
- # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
19
- # config.i18n.default_locale = :de
20
-
21
- # Do not swallow errors in after_commit/after_rollback callbacks.
22
- config.active_record.raise_in_transactional_callbacks = true
23
- end
24
- end