Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Always register webhooks with offline sessions
Browse files Browse the repository at this point in the history
paulomarg committed Feb 8, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 8fc434a commit e81bc92
Showing 3 changed files with 79 additions and 36 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Unreleased
----------
* Make type param for webhooks route optional. This will fix a bug with CLI initiated webhooks.[1786](https://github.com/Shopify/shopify_app/pull/1786)
* Always register webhooks with offline sessions.[1788](https://github.com/Shopify/shopify_app/pull/1788)

21.10.0 (January 24, 2024)
----------
8 changes: 6 additions & 2 deletions app/controllers/shopify_app/callback_controller.rb
Original file line number Diff line number Diff line change
@@ -130,8 +130,12 @@ def user_access_scopes_strategy
end

def perform_post_authenticate_jobs(session)
install_webhooks(session)
install_scripttags(session)
# Ensure we use the offline session to install webhooks and scripttags
offline_session = session.online? ? shop_session : session

install_webhooks(offline_session)
install_scripttags(offline_session)

perform_after_authenticate_job(session)
end

106 changes: 72 additions & 34 deletions test/controllers/callback_controller_test.rb
Original file line number Diff line number Diff line change
@@ -21,19 +21,21 @@ def perform; end
end

module ShopifyApp
SHOP_DOMAIN = "shop.myshopify.io"

class CallbackControllerTest < ActionController::TestCase
setup do
@routes = ShopifyApp::Engine.routes
ShopifyApp::SessionRepository.shop_storage = ShopifyApp::InMemoryShopSessionStore
ShopifyApp::SessionRepository.user_storage = nil
ShopifyAppConfigurer.setup_context
I18n.locale = :en
@stubbed_session = ShopifyAPI::Auth::Session.new(shop: "shop", access_token: "token")
@stubbed_session = ShopifyAPI::Auth::Session.new(shop: SHOP_DOMAIN, access_token: "token")
@stubbed_cookie = ShopifyAPI::Auth::Oauth::SessionCookie.new(value: "", expires: Time.now)
@host = "little-shoppe-of-horrors.#{ShopifyApp.configuration.myshopify_domain}"
host = Base64.strict_encode64(@host + "/admin")
@callback_params = {
shop: "shop",
shop: SHOP_DOMAIN,
code: "code",
state: "state",
timestamp: "timestamp",
@@ -47,17 +49,27 @@ class CallbackControllerTest < ActionController::TestCase
ShopifyApp::SessionRepository.stubs(:store_session)
end

teardown do
SessionRepository.shop_storage.clear
end

test "#callback flashes error in Spanish" do
I18n.expects(:t).with("could_not_log_in")
get :callback,
params: { shop: "shop", code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
params: { shop: SHOP_DOMAIN, code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
end

test "#callback rescued errors of ShopifyAPI::Error will not emit a deprecation notice" do
ShopifyAPI::Auth::Oauth.expects(:validate_auth_callback).raises(ShopifyAPI::Errors::MissingRequiredArgumentError)
assert_not_deprecated do
get :callback,
params: { shop: "shop", code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
get :callback, params: {
shop: SHOP_DOMAIN,
code: "code",
state: "state",
timestamp: "timestamp",
host: "host",
hmac: "hmac",
}
end
assert_equal flash[:error], "Could not log in to Shopify store"
end
@@ -69,7 +81,7 @@ class CallbackControllerTest < ActionController::TestCase

ShopifyApp::Logger.expects(:deprecated).never
get :callback,
params: { shop: "shop", code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
params: { shop: SHOP_DOMAIN, code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
end

test "#callback rescued non-shopify errors will be deprecated" do
@@ -86,7 +98,7 @@ class CallbackControllerTest < ActionController::TestCase
assert_within_deprecation_schedule(version)
ShopifyApp::Logger.expects(:deprecated).with(message, version)
get :callback,
params: { shop: "shop", code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
params: { shop: SHOP_DOMAIN, code: "code", state: "state", timestamp: "timestamp", host: "host", hmac: "hmac" }
end

test "#callback calls ShopifyAPI::Auth::Oauth.validate_auth_callback" do
@@ -118,29 +130,18 @@ class CallbackControllerTest < ActionController::TestCase
end

test "#callback sets the shopify_user_id in the Rails session when session is online" do
associated_user = ShopifyAPI::Auth::AssociatedUser.new(
id: 42,
first_name: "LeeeEEeeeeee3roy",
last_name: "Jenkins",
email: "[email protected]",
email_verified: true,
locale: "en",
collaborator: true,
account_owner: true,
)
mock_session = ShopifyAPI::Auth::Session.new(
shop: "shop",
access_token: "token",
is_online: true,
associated_user: associated_user,
)
mock_oauth(session: mock_session)
ShopifyApp::SessionRepository.shop_storage.store(@stubbed_session)
ShopifyApp::SessionRepository.user_storage = ShopifyApp::InMemoryUserSessionStore

mock_session = online_session
mock_oauth(session: online_session)

get :callback, params: @callback_params
assert_equal session[:shopify_user_id], associated_user.id
assert_equal session[:shopify_user_id], mock_session.associated_user.id
end

test "#callback DOES NOT set the shopify_user_id in the Rails session when session is offline" do
mock_session = ShopifyAPI::Auth::Session.new(shop: "shop", access_token: "token", is_online: false)
mock_session = ShopifyAPI::Auth::Session.new(shop: SHOP_DOMAIN, access_token: "token", is_online: false)
mock_oauth(session: mock_session)
get :callback, params: @callback_params
assert_nil session[:shopify_user_id]
@@ -166,7 +167,7 @@ class CallbackControllerTest < ActionController::TestCase
config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }]
end

ShopifyApp::WebhooksManager.expects(:queue).with("shop", "token")
ShopifyApp::WebhooksManager.expects(:queue).with(SHOP_DOMAIN, "token")

mock_oauth
get :callback, params: @callback_params
@@ -189,7 +190,7 @@ class CallbackControllerTest < ActionController::TestCase
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true }
end

Shopify::AfterAuthenticateJob.expects(:perform_now).with(shop_domain: "shop")
Shopify::AfterAuthenticateJob.expects(:perform_now).with(shop_domain: SHOP_DOMAIN)

mock_oauth
get :callback, params: @callback_params
@@ -200,7 +201,7 @@ class CallbackControllerTest < ActionController::TestCase
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: false }
end

Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: "shop")
Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN)

mock_oauth
get :callback, params: @callback_params
@@ -222,7 +223,7 @@ class CallbackControllerTest < ActionController::TestCase
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob }
end

Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: "shop")
Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN)

mock_oauth
get :callback, params: @callback_params
@@ -233,7 +234,7 @@ class CallbackControllerTest < ActionController::TestCase
config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob", inline: false }
end

Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: "shop")
Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN)

mock_oauth
get :callback, params: @callback_params
@@ -296,10 +297,28 @@ class CallbackControllerTest < ActionController::TestCase
config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }]
end

ShopifyApp::WebhooksManager.expects(:queue).with("shop", "token")
ShopifyApp::WebhooksManager.expects(:queue).with(SHOP_DOMAIN, "token")

get :callback, params: @callback_params
assert_response 302
end

test "#callback performs install_webhook job with an offline session after an online session OAuth" do
ShopifyApp.configure do |config|
config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }]
end
ShopifyApp::SessionRepository.shop_storage.store(@stubbed_session)
ShopifyApp::SessionRepository.user_storage = ShopifyApp::InMemoryUserSessionStore

mock_oauth(session: online_session)

ShopifyApp::WebhooksManager.expects(:queue).with(SHOP_DOMAIN, "token")

get :callback, params: @callback_params
assert_response 302
rescue => e
shop_storage.clear
raise e
end

test "#callback performs install_scripttags job after authentication" do
@@ -309,7 +328,7 @@ class CallbackControllerTest < ActionController::TestCase
config.scripttags = [{ event: "onload", src: "https://example.com/fancy.js" }]
end

ShopifyApp::ScripttagsManager.expects(:queue).with("shop", "token", ShopifyApp.configuration.scripttags)
ShopifyApp::ScripttagsManager.expects(:queue).with(SHOP_DOMAIN, "token", ShopifyApp.configuration.scripttags)

get :callback, params: @callback_params
assert_response 302
@@ -322,7 +341,7 @@ class CallbackControllerTest < ActionController::TestCase
config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true }
end

Shopify::AfterAuthenticateJob.expects(:perform_now).with(shop_domain: "shop")
Shopify::AfterAuthenticateJob.expects(:perform_now).with(shop_domain: SHOP_DOMAIN)

get :callback, params: @callback_params
assert_response 302
@@ -348,5 +367,24 @@ def mock_oauth(cookie: @stubbed_cookie, session: @stubbed_session)
session: session,
})
end

def online_session
associated_user = ShopifyAPI::Auth::AssociatedUser.new(
id: 42,
first_name: "LeeeEEeeeeee3roy",
last_name: "Jenkins",
email: "[email protected]",
email_verified: true,
locale: "en",
collaborator: true,
account_owner: true,
)
ShopifyAPI::Auth::Session.new(
shop: SHOP_DOMAIN,
access_token: "online-token",
is_online: true,
associated_user: associated_user,
)
end
end
end

0 comments on commit e81bc92

Please sign in to comment.