shopify_app 13.0.0 → 13.0.1
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 +4 -4
- data/.rubocop.yml +13 -6
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -0
- data/README.md +32 -1
- data/Rakefile +1 -0
- data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
- data/app/controllers/shopify_app/callback_controller.rb +1 -1
- data/app/controllers/shopify_app/sessions_controller.rb +8 -5
- data/app/controllers/shopify_app/webhooks_controller.rb +6 -5
- data/config/locales/fi.yml +1 -1
- data/config/routes.rb +1 -0
- data/lib/generators/shopify_app/add_after_authenticate_job/add_after_authenticate_job_generator.rb +5 -3
- data/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb +1 -0
- data/lib/generators/shopify_app/add_marketing_activity_extension/add_marketing_activity_extension_generator.rb +2 -1
- data/lib/generators/shopify_app/add_marketing_activity_extension/templates/marketing_activities_controller.rb +4 -4
- data/lib/generators/shopify_app/add_webhook/add_webhook_generator.rb +5 -4
- data/lib/generators/shopify_app/add_webhook/templates/webhook_job.rb +5 -0
- data/lib/generators/shopify_app/app_proxy_controller/app_proxy_controller_generator.rb +4 -3
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_controller.rb +3 -3
- data/lib/generators/shopify_app/app_proxy_controller/templates/app_proxy_route.rb +10 -9
- data/lib/generators/shopify_app/controllers/controllers_generator.rb +1 -0
- data/lib/generators/shopify_app/home_controller/home_controller_generator.rb +4 -3
- data/lib/generators/shopify_app/install/install_generator.rb +9 -8
- data/lib/generators/shopify_app/install/templates/omniauth.rb +2 -1
- data/lib/generators/shopify_app/install/templates/user_agent.rb +2 -1
- data/lib/generators/shopify_app/routes/routes_generator.rb +1 -0
- data/lib/generators/shopify_app/routes/templates/routes.rb +10 -9
- data/lib/generators/shopify_app/shop_model/shop_model_generator.rb +5 -4
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +1 -0
- data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
- data/lib/generators/shopify_app/user_model/templates/user.rb +1 -0
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +5 -4
- data/lib/generators/shopify_app/views/views_generator.rb +1 -0
- data/lib/shopify_app.rb +7 -4
- data/lib/shopify_app/configuration.rb +15 -8
- data/lib/shopify_app/controller_concerns/app_proxy_verification.rb +3 -2
- data/lib/shopify_app/controller_concerns/embedded_app.rb +3 -2
- data/lib/shopify_app/controller_concerns/localization.rb +1 -0
- data/lib/shopify_app/controller_concerns/login_protection.rb +46 -11
- data/lib/shopify_app/controller_concerns/webhook_verification.rb +2 -1
- data/lib/shopify_app/engine.rb +1 -0
- data/lib/shopify_app/jobs/scripttags_manager_job.rb +1 -1
- data/lib/shopify_app/jobs/webhooks_manager_job.rb +1 -1
- data/lib/shopify_app/managers/scripttags_manager.rb +4 -3
- data/lib/shopify_app/managers/webhooks_manager.rb +4 -3
- data/lib/shopify_app/middleware/same_site_cookie_middleware.rb +2 -1
- data/lib/shopify_app/session/in_memory_session_store.rb +7 -3
- data/lib/shopify_app/session/in_memory_shop_session_store.rb +10 -0
- data/lib/shopify_app/session/in_memory_user_session_store.rb +10 -0
- data/lib/shopify_app/session/jwt.rb +48 -0
- data/lib/shopify_app/session/null_user_session_store.rb +22 -0
- data/lib/shopify_app/session/session_repository.rb +13 -16
- data/lib/shopify_app/session/session_storage.rb +1 -0
- data/lib/shopify_app/session/shop_session_storage.rb +21 -9
- data/lib/shopify_app/session/user_session_storage.rb +19 -8
- data/lib/shopify_app/test_helpers/all.rb +1 -0
- data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +16 -0
- data/lib/shopify_app/utils.rb +6 -5
- data/lib/shopify_app/version.rb +2 -1
- data/package-lock.json +4 -4
- data/package.json +1 -1
- data/shopify_app.gemspec +8 -4
- data/yarn.lock +3 -3
- metadata +22 -3
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rails/generators/base'
|
2
3
|
|
3
4
|
module ShopifyApp
|
@@ -16,7 +17,7 @@ module ShopifyApp
|
|
16
17
|
@scope = format_array_argument(options['scope'])
|
17
18
|
@api_version = options['api_version'] || ShopifyAPI::Meta.admin_versions.find(&:latest_supported).handle
|
18
19
|
|
19
|
-
template
|
20
|
+
template('shopify_app.rb', 'config/initializers/shopify_app.rb')
|
20
21
|
end
|
21
22
|
|
22
23
|
def create_session_store_initializer
|
@@ -24,22 +25,22 @@ module ShopifyApp
|
|
24
25
|
end
|
25
26
|
|
26
27
|
def create_and_inject_into_omniauth_initializer
|
27
|
-
unless File.exist?
|
28
|
-
copy_file
|
28
|
+
unless File.exist?("config/initializers/omniauth.rb")
|
29
|
+
copy_file('omniauth.rb', 'config/initializers/omniauth.rb')
|
29
30
|
end
|
30
31
|
|
31
32
|
inject_into_file(
|
32
33
|
'config/initializers/omniauth.rb',
|
33
34
|
File.read(File.expand_path(find_in_source_paths('shopify_provider.rb'))),
|
34
|
-
after: "Rails.application.config.middleware.use
|
35
|
+
after: "Rails.application.config.middleware.use(OmniAuth::Builder) do\n"
|
35
36
|
)
|
36
37
|
end
|
37
38
|
|
38
39
|
def create_embedded_app_layout
|
39
40
|
return unless embedded_app?
|
40
41
|
|
41
|
-
copy_file
|
42
|
-
copy_file
|
42
|
+
copy_file('embedded_app.html.erb', 'app/views/layouts/embedded_app.html.erb')
|
43
|
+
copy_file('_flash_messages.html.erb', 'app/views/layouts/_flash_messages.html.erb')
|
43
44
|
|
44
45
|
if ShopifyApp.use_webpacker?
|
45
46
|
copy_file('shopify_app.js', 'app/javascript/shopify_app/shopify_app.js')
|
@@ -53,11 +54,11 @@ module ShopifyApp
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def create_user_agent_initializer
|
56
|
-
template
|
57
|
+
template('user_agent.rb', 'config/initializers/user_agent.rb')
|
57
58
|
end
|
58
59
|
|
59
60
|
def mount_engine
|
60
|
-
route
|
61
|
+
route("mount ShopifyApp::Engine, at: '/'")
|
61
62
|
end
|
62
63
|
|
63
64
|
def insert_hosts_into_development_config
|
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
controller :sessions do
|
4
|
+
get 'login' => :new, :as => :login
|
5
|
+
post 'login' => :create, :as => :authenticate
|
6
|
+
get 'auth/shopify/callback' => :callback
|
7
|
+
get 'logout' => :destroy, :as => :logout
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
namespace :webhooks do
|
11
|
+
post ':type' => :receive
|
12
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rails/generators/base'
|
2
3
|
require 'rails/generators/active_record'
|
3
4
|
|
@@ -8,19 +9,19 @@ module ShopifyApp
|
|
8
9
|
source_root File.expand_path('../templates', __FILE__)
|
9
10
|
|
10
11
|
def create_shop_model
|
11
|
-
copy_file
|
12
|
+
copy_file('shop.rb', 'app/models/shop.rb')
|
12
13
|
end
|
13
14
|
|
14
15
|
def create_shop_migration
|
15
|
-
migration_template
|
16
|
+
migration_template('db/migrate/create_shops.erb', 'db/migrate/create_shops.rb')
|
16
17
|
end
|
17
18
|
|
18
19
|
def update_shopify_app_initializer
|
19
|
-
gsub_file
|
20
|
+
gsub_file('config/initializers/shopify_app.rb', 'ShopifyApp::InMemoryShopSessionStore', 'Shop')
|
20
21
|
end
|
21
22
|
|
22
23
|
def create_shop_fixtures
|
23
|
-
copy_file
|
24
|
+
copy_file('shops.yml', 'test/fixtures/shops.yml')
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module Generators
|
3
4
|
class ShopifyAppGenerator < Rails::Generators::Base
|
@@ -7,10 +8,10 @@ module ShopifyApp
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def run_all_generators
|
10
|
-
generate
|
11
|
-
generate
|
11
|
+
generate("shopify_app:install #{@opts.join(' ')}")
|
12
|
+
generate("shopify_app:shop_model")
|
12
13
|
generate("shopify_app:authenticated_controller")
|
13
|
-
generate
|
14
|
+
generate("shopify_app:home_controller")
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rails/generators/base'
|
2
3
|
require 'rails/generators/active_record'
|
3
4
|
|
@@ -8,19 +9,19 @@ module ShopifyApp
|
|
8
9
|
source_root File.expand_path('../templates', __FILE__)
|
9
10
|
|
10
11
|
def create_user_model
|
11
|
-
copy_file
|
12
|
+
copy_file('user.rb', 'app/models/user.rb')
|
12
13
|
end
|
13
14
|
|
14
15
|
def create_user_migration
|
15
|
-
migration_template
|
16
|
+
migration_template('db/migrate/create_users.erb', 'db/migrate/create_users.rb')
|
16
17
|
end
|
17
18
|
|
18
19
|
def update_shopify_app_initializer
|
19
|
-
gsub_file
|
20
|
+
gsub_file('config/initializers/shopify_app.rb', 'ShopifyApp::InMemoryUserSessionStore', 'User')
|
20
21
|
end
|
21
22
|
|
22
23
|
def create_user_fixtures
|
23
|
-
copy_file
|
24
|
+
copy_file('users.yml', 'test/fixtures/users.yml')
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
data/lib/shopify_app.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'shopify_app/version'
|
2
3
|
|
3
4
|
# deps
|
@@ -44,11 +45,13 @@ module ShopifyApp
|
|
44
45
|
require 'shopify_app/middleware/same_site_cookie_middleware'
|
45
46
|
|
46
47
|
# session
|
47
|
-
require 'shopify_app/session/session_storage'
|
48
|
-
require 'shopify_app/session/shop_session_storage'
|
49
|
-
require 'shopify_app/session/user_session_storage'
|
50
|
-
require 'shopify_app/session/session_repository'
|
51
48
|
require 'shopify_app/session/in_memory_session_store'
|
52
49
|
require 'shopify_app/session/in_memory_shop_session_store'
|
53
50
|
require 'shopify_app/session/in_memory_user_session_store'
|
51
|
+
require 'shopify_app/session/jwt'
|
52
|
+
require 'shopify_app/session/null_user_session_store'
|
53
|
+
require 'shopify_app/session/session_repository'
|
54
|
+
require 'shopify_app/session/session_storage'
|
55
|
+
require 'shopify_app/session/shop_session_storage'
|
56
|
+
require 'shopify_app/session/user_session_storage'
|
54
57
|
end
|
@@ -1,11 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class Configuration
|
3
|
-
|
4
4
|
# Shopify App settings. These values should match the configuration
|
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
|
8
|
+
attr_accessor :api_key
|
9
9
|
attr_accessor :secret
|
10
10
|
attr_accessor :old_secret
|
11
11
|
attr_accessor :scope
|
@@ -14,13 +14,11 @@ module ShopifyApp
|
|
14
14
|
attr_accessor :webhooks
|
15
15
|
attr_accessor :scripttags
|
16
16
|
attr_accessor :after_authenticate_job
|
17
|
-
attr_reader :shop_session_repository
|
18
|
-
attr_reader :user_session_repository
|
19
17
|
attr_accessor :api_version
|
20
18
|
|
21
19
|
# customise urls
|
22
20
|
attr_accessor :root_url
|
23
|
-
|
21
|
+
attr_writer :login_url
|
24
22
|
|
25
23
|
# customise ActiveJob queue names
|
26
24
|
attr_accessor :scripttags_manager_queue_name
|
@@ -36,7 +34,10 @@ module ShopifyApp
|
|
36
34
|
attr_accessor :webhook_jobs_namespace
|
37
35
|
|
38
36
|
# allow enabling of same site none on cookies
|
39
|
-
|
37
|
+
attr_writer :enable_same_site_none
|
38
|
+
|
39
|
+
# allow enabling jwt headers for authentication
|
40
|
+
attr_accessor :allow_jwt_authentication
|
40
41
|
|
41
42
|
def initialize
|
42
43
|
@root_url = '/'
|
@@ -51,15 +52,21 @@ module ShopifyApp
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def user_session_repository=(klass)
|
54
|
-
@user_session_repository = klass
|
55
55
|
ShopifyApp::SessionRepository.user_storage = klass
|
56
56
|
end
|
57
57
|
|
58
|
+
def user_session_repository
|
59
|
+
ShopifyApp::SessionRepository.user_storage
|
60
|
+
end
|
61
|
+
|
58
62
|
def shop_session_repository=(klass)
|
59
|
-
@shop_session_repository = klass
|
60
63
|
ShopifyApp::SessionRepository.shop_storage = klass
|
61
64
|
end
|
62
65
|
|
66
|
+
def shop_session_repository
|
67
|
+
ShopifyApp::SessionRepository.shop_storage
|
68
|
+
end
|
69
|
+
|
63
70
|
def has_webhooks?
|
64
71
|
webhooks.present?
|
65
72
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module AppProxyVerification
|
3
4
|
extend ActiveSupport::Concern
|
@@ -8,7 +9,7 @@ module ShopifyApp
|
|
8
9
|
end
|
9
10
|
|
10
11
|
def verify_proxy_request
|
11
|
-
return head
|
12
|
+
return head(:forbidden) unless query_string_valid?(request.query_string)
|
12
13
|
end
|
13
14
|
|
14
15
|
private
|
@@ -26,7 +27,7 @@ module ShopifyApp
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def calculated_signature(query_hash_without_signature)
|
29
|
-
sorted_params = query_hash_without_signature.collect{|k,v| "#{k}=#{Array(v).join(',')}"}.sort.join
|
30
|
+
sorted_params = query_hash_without_signature.collect { |k, v| "#{k}=#{Array(v).join(',')}" }.sort.join
|
30
31
|
|
31
32
|
OpenSSL::HMAC.hexdigest(
|
32
33
|
OpenSSL::Digest.new('sha256'),
|
@@ -1,11 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module EmbeddedApp
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
5
6
|
included do
|
6
7
|
if ShopifyApp.configuration.embedded_app?
|
7
|
-
after_action
|
8
|
-
layout
|
8
|
+
after_action(:set_esdk_headers)
|
9
|
+
layout('embedded_app')
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -11,7 +11,7 @@ module ShopifyApp
|
|
11
11
|
|
12
12
|
included do
|
13
13
|
after_action :set_test_cookie
|
14
|
-
rescue_from ActiveResource::UnauthorizedAccess, :
|
14
|
+
rescue_from ActiveResource::UnauthorizedAccess, with: :close_session
|
15
15
|
end
|
16
16
|
|
17
17
|
def activate_shopify_session
|
@@ -27,20 +27,38 @@ module ShopifyApp
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def current_shopify_session
|
30
|
-
|
31
|
-
|
32
|
-
else
|
33
|
-
@current_shopify_session ||= shop_session
|
30
|
+
@current_shopify_session ||= begin
|
31
|
+
user_session || shop_session
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
37
35
|
def user_session
|
38
|
-
|
36
|
+
user_session_by_jwt || user_session_by_cookie
|
37
|
+
end
|
38
|
+
|
39
|
+
def user_session_by_jwt
|
40
|
+
return unless ShopifyApp.configuration.allow_jwt_authentication
|
41
|
+
return unless jwt_shopify_user_id
|
42
|
+
ShopifyApp::SessionRepository.retrieve_user_session_by_shopify_user_id(jwt_shopify_user_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def user_session_by_cookie
|
46
|
+
return unless session[:user_id].present?
|
39
47
|
ShopifyApp::SessionRepository.retrieve_user_session(session[:user_id])
|
40
48
|
end
|
41
49
|
|
42
50
|
def shop_session
|
43
|
-
|
51
|
+
shop_session_by_jwt || shop_session_by_cookie
|
52
|
+
end
|
53
|
+
|
54
|
+
def shop_session_by_jwt
|
55
|
+
return unless ShopifyApp.configuration.allow_jwt_authentication
|
56
|
+
return unless jwt_shopify_domain
|
57
|
+
ShopifyApp::SessionRepository.retrieve_shop_session_by_shopify_domain(jwt_shopify_domain)
|
58
|
+
end
|
59
|
+
|
60
|
+
def shop_session_by_cookie
|
61
|
+
return unless session[:shop_id].present?
|
44
62
|
ShopifyApp::SessionRepository.retrieve_shop_session(session[:shop_id])
|
45
63
|
end
|
46
64
|
|
@@ -50,7 +68,9 @@ module ShopifyApp
|
|
50
68
|
|
51
69
|
end
|
52
70
|
|
53
|
-
if current_shopify_session &&
|
71
|
+
if current_shopify_session &&
|
72
|
+
params[:shop] && params[:shop].is_a?(String) &&
|
73
|
+
(current_shopify_session.domain != params[:shop])
|
54
74
|
clear_session = true
|
55
75
|
end
|
56
76
|
|
@@ -62,9 +82,23 @@ module ShopifyApp
|
|
62
82
|
|
63
83
|
protected
|
64
84
|
|
85
|
+
def jwt_shopify_domain
|
86
|
+
return unless jwt
|
87
|
+
@jwt_shopify_domain ||= JWT.new(jwt).shopify_domain
|
88
|
+
end
|
89
|
+
|
90
|
+
def jwt_shopify_user_id
|
91
|
+
return unless jwt
|
92
|
+
@jwt_user_id ||= JWT.new(jwt).shopify_user_id
|
93
|
+
end
|
94
|
+
|
95
|
+
def jwt
|
96
|
+
@jwt ||= authenticate_with_http_token { |token| token }
|
97
|
+
end
|
98
|
+
|
65
99
|
def redirect_to_login
|
66
100
|
if request.xhr?
|
67
|
-
head
|
101
|
+
head(:unauthorized)
|
68
102
|
else
|
69
103
|
if request.get?
|
70
104
|
path = request.path
|
@@ -128,9 +162,10 @@ module ShopifyApp
|
|
128
162
|
|
129
163
|
def fullpage_redirect_to(url)
|
130
164
|
if ShopifyApp.configuration.embedded_app?
|
131
|
-
render
|
165
|
+
render('shopify_app/shared/redirect', layout: false,
|
166
|
+
locals: { url: url, current_shopify_domain: current_shopify_domain })
|
132
167
|
else
|
133
|
-
redirect_to
|
168
|
+
redirect_to(url)
|
134
169
|
end
|
135
170
|
end
|
136
171
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module WebhookVerification
|
3
4
|
extend ActiveSupport::Concern
|
@@ -11,7 +12,7 @@ module ShopifyApp
|
|
11
12
|
|
12
13
|
def verify_request
|
13
14
|
data = request.raw_post
|
14
|
-
return head
|
15
|
+
return head(:unauthorized) unless hmac_valid?(data)
|
15
16
|
end
|
16
17
|
|
17
18
|
def hmac_valid?(data)
|
data/lib/shopify_app/engine.rb
CHANGED