shopify_app 12.0.7 → 13.2.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 +4 -4
- data/.rubocop.yml +12 -6
- data/.travis.yml +4 -3
- data/CHANGELOG.md +33 -0
- data/Gemfile +3 -0
- data/README.md +98 -42
- data/Rakefile +1 -0
- data/app/controllers/concerns/shopify_app/authenticated.rb +1 -1
- data/app/controllers/shopify_app/authenticated_controller.rb +1 -0
- data/app/controllers/shopify_app/callback_controller.rb +50 -17
- data/app/controllers/shopify_app/sessions_controller.rb +36 -10
- data/app/controllers/shopify_app/webhooks_controller.rb +6 -5
- data/config/locales/fi.yml +1 -1
- data/config/locales/nl.yml +7 -7
- data/config/routes.rb +1 -0
- data/docs/Releasing.md +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 → webhook_job.rb.tt} +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/home_controller/templates/index.html.erb +1 -1
- data/lib/generators/shopify_app/install/install_generator.rb +10 -9
- data/lib/generators/shopify_app/install/templates/embedded_app.html.erb +1 -1
- data/lib/generators/shopify_app/install/templates/omniauth.rb +2 -1
- data/lib/generators/shopify_app/install/templates/{shopify_app.rb → shopify_app.rb.tt} +1 -1
- data/lib/generators/shopify_app/install/templates/shopify_provider.rb +1 -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 +12 -7
- data/lib/generators/shopify_app/shop_model/templates/shop.rb +2 -1
- data/lib/generators/shopify_app/shopify_app_generator.rb +4 -3
- data/lib/generators/shopify_app/user_model/templates/user.rb +2 -1
- data/lib/generators/shopify_app/user_model/user_model_generator.rb +12 -7
- data/lib/generators/shopify_app/views/views_generator.rb +1 -0
- data/lib/shopify_app.rb +11 -4
- data/lib/shopify_app/configuration.rb +21 -11
- 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 +71 -29
- data/lib/shopify_app/controller_concerns/webhook_verification.rb +2 -1
- data/lib/shopify_app/engine.rb +5 -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/jwt_middleware.rb +41 -0
- 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 +14 -0
- data/lib/shopify_app/session/in_memory_user_session_store.rb +14 -0
- data/lib/shopify_app/session/jwt.rb +61 -0
- data/lib/shopify_app/session/null_user_session_store.rb +22 -0
- data/lib/shopify_app/session/session_repository.rb +36 -14
- data/lib/shopify_app/session/session_storage.rb +1 -10
- data/lib/shopify_app/session/shop_session_storage.rb +42 -0
- data/lib/shopify_app/session/user_session_storage.rb +42 -0
- data/lib/shopify_app/test_helpers/all.rb +2 -0
- data/lib/shopify_app/test_helpers/webhook_verification_helper.rb +17 -0
- data/lib/shopify_app/utils.rb +6 -5
- data/lib/shopify_app/version.rb +2 -1
- data/package-lock.json +1231 -1210
- data/package.json +1 -1
- data/shopify_app.gemspec +13 -8
- data/yarn.lock +3 -3
- metadata +50 -14
- data/lib/shopify_app/session/storage_strategies/shop_storage_strategy.rb +0 -23
- data/lib/shopify_app/session/storage_strategies/user_storage_strategy.rb +0 -24
@@ -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
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class Engine < Rails::Engine
|
3
4
|
engine_name 'shopify_app'
|
@@ -15,6 +16,10 @@ module ShopifyApp
|
|
15
16
|
|
16
17
|
initializer "shopify_app.middleware" do |app|
|
17
18
|
app.config.middleware.insert_after(::Rack::Runtime, ShopifyApp::SameSiteCookieMiddleware)
|
19
|
+
|
20
|
+
if ShopifyApp.configuration.allow_jwt_authentication
|
21
|
+
app.config.middleware.insert_after(ShopifyApp::SameSiteCookieMiddleware, ShopifyApp::JWTMiddleware)
|
22
|
+
end
|
18
23
|
end
|
19
24
|
end
|
20
25
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class ScripttagsManager
|
3
4
|
class CreationFailed < StandardError; end
|
@@ -43,7 +44,7 @@ module ShopifyApp
|
|
43
44
|
def destroy_scripttags
|
44
45
|
scripttags = expanded_scripttags
|
45
46
|
ShopifyAPI::ScriptTag.all.each do |tag|
|
46
|
-
ShopifyAPI::ScriptTag.delete(tag.id) if
|
47
|
+
ShopifyAPI::ScriptTag.delete(tag.id) if required_scripttag?(scripttags, tag)
|
47
48
|
end
|
48
49
|
|
49
50
|
@current_scripttags = nil
|
@@ -55,8 +56,8 @@ module ShopifyApp
|
|
55
56
|
self.class.build_src(required_scripttags, shop_domain)
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
scripttags.map{ |w| w[:src] }.include?
|
59
|
+
def required_scripttag?(scripttags, tag)
|
60
|
+
scripttags.map { |w| w[:src] }.include?(tag.src)
|
60
61
|
end
|
61
62
|
|
62
63
|
def create_scripttag(attributes)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class WebhooksManager
|
3
4
|
class CreationFailed < StandardError; end
|
@@ -31,7 +32,7 @@ module ShopifyApp
|
|
31
32
|
|
32
33
|
def destroy_webhooks
|
33
34
|
ShopifyAPI::Webhook.all.to_a.each do |webhook|
|
34
|
-
ShopifyAPI::Webhook.delete(webhook.id) if
|
35
|
+
ShopifyAPI::Webhook.delete(webhook.id) if required_webhook?(webhook)
|
35
36
|
end
|
36
37
|
|
37
38
|
@current_webhooks = nil
|
@@ -39,8 +40,8 @@ module ShopifyApp
|
|
39
40
|
|
40
41
|
private
|
41
42
|
|
42
|
-
def
|
43
|
-
required_webhooks.map{ |w| w[:address] }.include?
|
43
|
+
def required_webhook?(webhook)
|
44
|
+
required_webhooks.map { |w| w[:address] }.include?(webhook.address)
|
44
45
|
end
|
45
46
|
|
46
47
|
def create_webhook(attributes)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ShopifyApp
|
2
|
+
class JWTMiddleware
|
3
|
+
TOKEN_REGEX = /^Bearer\s+(.*?)$/
|
4
|
+
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
return call_next(env) unless authorization_header(env)
|
11
|
+
|
12
|
+
token = extract_token(env)
|
13
|
+
return call_next(env) unless token
|
14
|
+
|
15
|
+
set_env_variables(token, env)
|
16
|
+
call_next(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def call_next(env)
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
def authorization_header(env)
|
26
|
+
env['HTTP_AUTHORIZATION']
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_token(env)
|
30
|
+
match = authorization_header(env).match(TOKEN_REGEX)
|
31
|
+
match && match[1]
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_env_variables(token, env)
|
35
|
+
jwt = ShopifyApp::JWT.new(token)
|
36
|
+
|
37
|
+
env['jwt.shopify_domain'] = jwt.shopify_domain
|
38
|
+
env['jwt.shopify_user_id'] = jwt.shopify_user_id
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class SameSiteCookieMiddleware
|
3
4
|
COOKIE_SEPARATOR = "\n"
|
@@ -19,7 +20,7 @@ module ShopifyApp
|
|
19
20
|
.split(COOKIE_SEPARATOR)
|
20
21
|
.compact
|
21
22
|
.map do |cookie|
|
22
|
-
cookie << '; Secure'
|
23
|
+
cookie << '; Secure' unless cookie =~ /;\s*secure/i
|
23
24
|
cookie << '; SameSite=None' unless cookie =~ /;\s*samesite=/i
|
24
25
|
cookie
|
25
26
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
3
|
+
# rubocop:disable Style/ClassVars
|
4
|
+
# Class var repo is needed here in order to share data between the 2 child classes.
|
2
5
|
class InMemorySessionStore
|
3
6
|
class EnvironmentError < StandardError; end
|
4
7
|
|
@@ -6,7 +9,7 @@ module ShopifyApp
|
|
6
9
|
repo[id]
|
7
10
|
end
|
8
11
|
|
9
|
-
def self.store(session, *
|
12
|
+
def self.store(session, *_args)
|
10
13
|
id = SecureRandom.uuid
|
11
14
|
repo[id] = session
|
12
15
|
id
|
@@ -18,10 +21,11 @@ module ShopifyApp
|
|
18
21
|
|
19
22
|
def self.repo
|
20
23
|
if Rails.env.production?
|
21
|
-
raise EnvironmentError
|
22
|
-
Please initialize ShopifyApp with a model that can store and retrieve sessions"
|
24
|
+
raise EnvironmentError, "Cannot use InMemorySessionStore in a Production environment. \
|
25
|
+
Please initialize ShopifyApp with a model that can store and retrieve sessions"
|
23
26
|
end
|
24
27
|
@@repo ||= {}
|
25
28
|
end
|
26
29
|
end
|
30
|
+
# rubocop:enable Style/ClassVars
|
27
31
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
class InMemoryShopSessionStore < InMemorySessionStore
|
4
|
+
def self.store(session, *args)
|
5
|
+
id = super
|
6
|
+
repo[session.domain] = session
|
7
|
+
id
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.retrieve_by_shopify_domain(shopify_domain)
|
11
|
+
repo[shopify_domain]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
class InMemoryUserSessionStore < InMemorySessionStore
|
4
|
+
def self.store(session, user)
|
5
|
+
id = super
|
6
|
+
repo[user.shopify_user_id] = session
|
7
|
+
id
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.retrieve_by_shopify_user_id(user_id)
|
11
|
+
repo[user_id]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
class JWT
|
4
|
+
class InvalidDestinationError < StandardError; end
|
5
|
+
class MismatchedHostsError < StandardError; end
|
6
|
+
class InvalidAudienceError < StandardError; end
|
7
|
+
|
8
|
+
WARN_EXCEPTIONS = [
|
9
|
+
::JWT::DecodeError,
|
10
|
+
::JWT::ExpiredSignature,
|
11
|
+
::JWT::ImmatureSignature,
|
12
|
+
::JWT::VerificationError,
|
13
|
+
InvalidAudienceError,
|
14
|
+
InvalidDestinationError,
|
15
|
+
MismatchedHostsError,
|
16
|
+
]
|
17
|
+
|
18
|
+
def initialize(token)
|
19
|
+
@token = token
|
20
|
+
set_payload
|
21
|
+
end
|
22
|
+
|
23
|
+
def shopify_domain
|
24
|
+
@payload && ShopifyApp::Utils.sanitize_shop_domain(@payload['dest'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def shopify_user_id
|
28
|
+
@payload && @payload['sub']
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def set_payload
|
34
|
+
payload, _ = parse_token_data(ShopifyApp.configuration&.secret, ShopifyApp.configuration&.old_secret)
|
35
|
+
@payload = validate_payload(payload)
|
36
|
+
rescue *WARN_EXCEPTIONS => error
|
37
|
+
Rails.logger.warn("[ShopifyApp::JWT] Failed to validate JWT: [#{error.class}] #{error}")
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse_token_data(secret, old_secret)
|
42
|
+
::JWT.decode(@token, secret, true, { algorithm: 'HS256' })
|
43
|
+
rescue ::JWT::VerificationError
|
44
|
+
raise unless old_secret
|
45
|
+
|
46
|
+
::JWT.decode(@token, old_secret, true, { algorithm: 'HS256' })
|
47
|
+
end
|
48
|
+
|
49
|
+
def validate_payload(payload)
|
50
|
+
dest_host = ShopifyApp::Utils.sanitize_shop_domain(payload['dest'])
|
51
|
+
iss_host = ShopifyApp::Utils.sanitize_shop_domain(payload['iss'])
|
52
|
+
api_key = ShopifyApp.configuration.api_key
|
53
|
+
|
54
|
+
raise InvalidAudienceError, "'aud' claim does not match api_key" unless payload['aud'] == api_key
|
55
|
+
raise InvalidDestinationError, "'dest' claim host not a valid shopify host" unless dest_host
|
56
|
+
raise MismatchedHostsError, "'dest' claim host does not match 'iss' claim host" unless dest_host == iss_host
|
57
|
+
|
58
|
+
payload
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
class NullUserSessionStore
|
4
|
+
class << self
|
5
|
+
def retrieve(_)
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def store(_, _)
|
10
|
+
raise SessionRepository::ConfigurationError, 'user_storage is not configured'
|
11
|
+
end
|
12
|
+
|
13
|
+
def retrieve_by_shopify_user_id(_)
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def blank?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,33 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
class SessionRepository
|
3
4
|
class ConfigurationError < StandardError; end
|
4
5
|
|
5
6
|
class << self
|
6
|
-
|
7
|
-
@storage = storage
|
7
|
+
attr_writer :shop_storage
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
attr_writer :user_storage
|
10
|
+
|
11
|
+
def retrieve_shop_session(id)
|
12
|
+
shop_storage.retrieve(id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def retrieve_user_session(id)
|
16
|
+
user_storage.retrieve(id)
|
12
17
|
end
|
13
18
|
|
14
|
-
def
|
15
|
-
|
19
|
+
def retrieve_shop_session_by_shopify_domain(shopify_domain)
|
20
|
+
shop_storage.retrieve_by_shopify_domain(shopify_domain)
|
16
21
|
end
|
17
22
|
|
18
|
-
def
|
19
|
-
|
23
|
+
def retrieve_user_session_by_shopify_user_id(user_id)
|
24
|
+
user_storage.retrieve_by_shopify_user_id(user_id)
|
20
25
|
end
|
21
26
|
|
22
|
-
def
|
23
|
-
|
27
|
+
def store_shop_session(session)
|
28
|
+
shop_storage.store(session)
|
29
|
+
end
|
30
|
+
|
31
|
+
def store_user_session(session, user)
|
32
|
+
user_storage.store(session, user)
|
33
|
+
end
|
34
|
+
|
35
|
+
def shop_storage
|
36
|
+
load_shop_storage || raise(ConfigurationError, "ShopifySessionRepository.shop_storage is not configured!")
|
37
|
+
end
|
38
|
+
|
39
|
+
def user_storage
|
40
|
+
load_user_storage
|
24
41
|
end
|
25
42
|
|
26
43
|
private
|
27
44
|
|
28
|
-
def
|
29
|
-
return unless @
|
30
|
-
@
|
45
|
+
def load_shop_storage
|
46
|
+
return unless @shop_storage
|
47
|
+
@shop_storage.respond_to?(:safe_constantize) ? @shop_storage.safe_constantize : @shop_storage
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_user_storage
|
51
|
+
return NullUserSessionStore unless @user_storage
|
52
|
+
@user_storage.respond_to?(:safe_constantize) ? @user_storage.safe_constantize : @user_storage
|
31
53
|
end
|
32
54
|
end
|
33
55
|
end
|
@@ -1,20 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ShopifyApp
|
2
3
|
module SessionStorage
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
5
6
|
included do
|
6
|
-
if ShopifyApp.configuration.per_user_tokens?
|
7
|
-
extend ShopifyApp::SessionStorage::UserStorageStrategy
|
8
|
-
else
|
9
|
-
extend ShopifyApp::SessionStorage::ShopStorageStrategy
|
10
|
-
end
|
11
|
-
|
12
7
|
validates :shopify_token, presence: true
|
13
8
|
validates :api_version, presence: true
|
14
|
-
validates :shopify_domain, presence: true,
|
15
|
-
if: Proc.new {|_| ShopifyApp.configuration.per_user_tokens? }
|
16
|
-
validates :shopify_domain, presence: true, uniqueness: { case_sensitive: false },
|
17
|
-
if: Proc.new {|_| !ShopifyApp.configuration.per_user_tokens? }
|
18
9
|
end
|
19
10
|
|
20
11
|
def with_shopify_session(&block)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
module ShopSessionStorage
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ::ShopifyApp::SessionStorage
|
6
|
+
|
7
|
+
included do
|
8
|
+
validates :shopify_domain, presence: true, uniqueness: { case_sensitive: false }
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
def store(auth_session, *_args)
|
13
|
+
shop = find_or_initialize_by(shopify_domain: auth_session.domain)
|
14
|
+
shop.shopify_token = auth_session.token
|
15
|
+
shop.save!
|
16
|
+
shop.id
|
17
|
+
end
|
18
|
+
|
19
|
+
def retrieve(id)
|
20
|
+
shop = find_by(id: id)
|
21
|
+
construct_session(shop)
|
22
|
+
end
|
23
|
+
|
24
|
+
def retrieve_by_shopify_domain(domain)
|
25
|
+
shop = find_by(shopify_domain: domain)
|
26
|
+
construct_session(shop)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def construct_session(shop)
|
32
|
+
return unless shop
|
33
|
+
|
34
|
+
ShopifyAPI::Session.new(
|
35
|
+
domain: shop.shopify_domain,
|
36
|
+
token: shop.shopify_token,
|
37
|
+
api_version: shop.api_version,
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ShopifyApp
|
3
|
+
module UserSessionStorage
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ::ShopifyApp::SessionStorage
|
6
|
+
|
7
|
+
included do
|
8
|
+
validates :shopify_domain, presence: true
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
def store(auth_session, user)
|
13
|
+
user = find_or_initialize_by(shopify_user_id: user[:id])
|
14
|
+
user.shopify_token = auth_session.token
|
15
|
+
user.shopify_domain = auth_session.domain
|
16
|
+
user.save!
|
17
|
+
user.id
|
18
|
+
end
|
19
|
+
|
20
|
+
def retrieve(id)
|
21
|
+
user = find_by(id: id)
|
22
|
+
construct_session(user)
|
23
|
+
end
|
24
|
+
|
25
|
+
def retrieve_by_shopify_user_id(user_id)
|
26
|
+
user = find_by(shopify_user_id: user_id)
|
27
|
+
construct_session(user)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def construct_session(user)
|
33
|
+
return unless user
|
34
|
+
ShopifyAPI::Session.new(
|
35
|
+
domain: user.shopify_domain,
|
36
|
+
token: user.shopify_token,
|
37
|
+
api_version: user.api_version,
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|