From 31f7477e7143dd782df8679e805e55bf0ab1c988 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Mon, 25 Mar 2024 15:39:33 -0600 Subject: [PATCH 01/22] Extract post authenticate tasks into a class to be reused --- .../shopify_app/callback_controller.rb | 28 +------- lib/shopify_app.rb | 3 + .../auth/post_authenticate_tasks.rb | 48 +++++++++++++ .../auth/post_authenticate_tasks_test.rb | 67 +++++++++++++++++++ 4 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 lib/shopify_app/auth/post_authenticate_tasks.rb create mode 100644 test/shopify_app/auth/post_authenticate_tasks_test.rb diff --git a/app/controllers/shopify_app/callback_controller.rb b/app/controllers/shopify_app/callback_controller.rb index cedd3369c..43fe6a7fc 100644 --- a/app/controllers/shopify_app/callback_controller.rb +++ b/app/controllers/shopify_app/callback_controller.rb @@ -138,33 +138,7 @@ def user_access_scopes_strategy end def perform_post_authenticate_jobs(session) - # Ensure we use the shop session to install webhooks - session_for_shop = session.online? ? shop_session : session - - install_webhooks(session_for_shop) - - perform_after_authenticate_job(session) - end - - def install_webhooks(session) - return unless ShopifyApp.configuration.has_webhooks? - - WebhooksManager.queue(session.shop, session.access_token) - end - - def perform_after_authenticate_job(session) - config = ShopifyApp.configuration.after_authenticate_job - - return unless config && config[:job].present? - - job = config[:job] - job = job.constantize if job.is_a?(String) - - if config[:inline] == true - job.perform_now(shop_domain: session.shop) - else - job.perform_later(shop_domain: session.shop) - end + ShopifyApp::Auth::PostAuthenticateTasks.perform(session) end end end diff --git a/lib/shopify_app.rb b/lib/shopify_app.rb index 2f109ec00..0880d3a67 100644 --- a/lib/shopify_app.rb +++ b/lib/shopify_app.rb @@ -54,6 +54,9 @@ def self.use_webpacker? require "shopify_app/controller_concerns/webhook_verification" require "shopify_app/controller_concerns/token_exchange" + # Auth helpers + require "shopify_app/auth/post_authenticate_tasks" + # jobs require "shopify_app/jobs/webhooks_manager_job" diff --git a/lib/shopify_app/auth/post_authenticate_tasks.rb b/lib/shopify_app/auth/post_authenticate_tasks.rb new file mode 100644 index 000000000..44a3cc8aa --- /dev/null +++ b/lib/shopify_app/auth/post_authenticate_tasks.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module ShopifyApp + module Auth + class PostAuthenticateTasks + class << self + def perform(session) + ShopifyApp::Logger.debug("Performing post authenticate tasks") + # Ensure we use the shop session to install webhooks + session_for_shop = session.online? ? shop_session(session) : session + + install_webhooks(session_for_shop) + + perform_after_authenticate_job(session) + end + + private + + def shop_session(session) + ShopifyApp::SessionRepository.retrieve_shop_session_by_shopify_domain(session.shop) + end + + def install_webhooks(session) + ShopifyApp::Logger.debug("PostAuthenticateTasks: Installing webhooks") + return unless ShopifyApp.configuration.has_webhooks? + + WebhooksManager.queue(session.shop, session.access_token) + end + + def perform_after_authenticate_job(session) + ShopifyApp::Logger.debug("PostAuthenticateTasks: Performing after_authenticate_job") + config = ShopifyApp.configuration.after_authenticate_job + + return unless config && config[:job].present? + + job = config[:job] + job = job.constantize if job.is_a?(String) + + if config[:inline] == true + job.perform_now(shop_domain: session.shop) + else + job.perform_later(shop_domain: session.shop) + end + end + end + end + end +end diff --git a/test/shopify_app/auth/post_authenticate_tasks_test.rb b/test/shopify_app/auth/post_authenticate_tasks_test.rb new file mode 100644 index 000000000..3215f4d9c --- /dev/null +++ b/test/shopify_app/auth/post_authenticate_tasks_test.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "test_helper" + +module Shopify + class AfterAuthenticateJob < ActiveJob::Base + def perform; end + end +end + +class CartsUpdateJob < ActiveJob::Base + extend ShopifyAPI::Webhooks::Handler + + class << self + def handle(topic:, shop:, body:) + perform_later(topic: topic, shop_domain: shop, webhook: body) + end + end + + def perform; end +end + +class PostAuthenticateTasksTest < ActiveSupport::TestCase + SHOP_DOMAIN = "shop.myshopify.io" + + setup do + ShopifyApp::SessionRepository.shop_storage = ShopifyApp::InMemoryShopSessionStore + ShopifyApp::SessionRepository.user_storage = ShopifyApp::InMemoryShopSessionStore + ShopifyAppConfigurer.setup_context + + @offline_session = ShopifyAPI::Auth::Session.new(shop: SHOP_DOMAIN, access_token: "offline_token") + @online_session = ShopifyAPI::Auth::Session.new(shop: SHOP_DOMAIN, access_token: "online_token", is_online: true) + + ShopifyApp::SessionRepository.store_shop_session(@offline_session) + end + + test "#perform triggers install_webhook job after authentication" do + ShopifyApp.configure do |config| + config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] + end + + ShopifyApp::WebhooksManager.expects(:queue).with(SHOP_DOMAIN, "offline_token") + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + + test "#perform triggers 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::WebhooksManager.expects(:queue).with(SHOP_DOMAIN, "offline_token") + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@online_session) + ensure + ShopifyApp::SessionRepository.shop_storage.clear + end + + test "#perform triggers after_authenticate job after authentication" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true } + end + + Shopify::AfterAuthenticateJob.expects(:perform_now).with(shop_domain: SHOP_DOMAIN) + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end +end From 81b76909ebbc7ab3668d99de3f40124b76f874a8 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Mon, 25 Mar 2024 16:02:17 -0600 Subject: [PATCH 02/22] Extract post_authenticate_task class into config --- lib/shopify_app/configuration.rb | 27 ++++++++++++++++ test/shopify_app/configuration_test.rb | 43 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/lib/shopify_app/configuration.rb b/lib/shopify_app/configuration.rb index 07299dabe..845063dc7 100644 --- a/lib/shopify_app/configuration.rb +++ b/lib/shopify_app/configuration.rb @@ -29,6 +29,9 @@ class Configuration attr_writer :login_callback_url attr_accessor :embedded_redirect_url + # customize post authenticate tasks + attr_accessor :custom_post_authenticate_tasks + # customise ActiveJob queue names attr_accessor :scripttags_manager_queue_name attr_accessor :webhooks_manager_queue_name @@ -129,6 +132,30 @@ def use_new_embedded_auth_strategy? def online_token_configured? !ShopifyApp.configuration.user_session_repository.blank? && ShopifyApp::SessionRepository.user_storage.present? + + def post_authenticate_tasks + @post_authenticate_tasks || begin + if custom_post_authenticate_tasks + custom_class = if custom_post_authenticate_tasks.respond_to?(:safe_constantize) + custom_post_authenticate_tasks.safe_constantize + else + custom_post_authenticate_tasks + end + end + + task_class = custom_class || ShopifyApp::Auth::PostAuthenticateTasks + + [ + :perform, + ].each do |method| + raise( + ::ShopifyApp::ConfigurationError, + "Missing method - '#{method}' for custom_post_authenticate_tasks", + ) unless task_class.respond_to?(method) + end + + task_class + end end end diff --git a/test/shopify_app/configuration_test.rb b/test/shopify_app/configuration_test.rb index fcbd95b5d..7447f8886 100644 --- a/test/shopify_app/configuration_test.rb +++ b/test/shopify_app/configuration_test.rb @@ -2,6 +2,18 @@ require "test_helper" +module Shopify + class CustomPostAuthenticateTasks + def self.perform + end + end + + class InvalidPostAuthenticateTasksClass + def self.not_perform + end + end +end + class ConfigurationTest < ActiveSupport::TestCase setup do ShopifyApp.configuration = nil @@ -270,5 +282,36 @@ class ConfigurationTest < ActiveSupport::TestCase ShopifyApp::SessionRepository.user_storage = nil refute ShopifyApp.configuration.online_token_configured? + + test "#post_authenticate_tasks defaults to ShopifyApp::Auth::PostAuthenticateTasks" do + assert_equal ShopifyApp::Auth::PostAuthenticateTasks, ShopifyApp.configuration.post_authenticate_tasks + end + + test "#post_authenticate_tasks can be set to a custom class" do + ShopifyApp.configure do |config| + config.custom_post_authenticate_tasks = Shopify::CustomPostAuthenticateTasks + end + + assert_equal Shopify::CustomPostAuthenticateTasks, ShopifyApp.configuration.post_authenticate_tasks + end + + test "#post_authenticate_tasks can be set to a custom class name" do + ShopifyApp.configure do |config| + config.custom_post_authenticate_tasks = "Shopify::CustomPostAuthenticateTasks" + end + + assert_equal Shopify::CustomPostAuthenticateTasks, ShopifyApp.configuration.post_authenticate_tasks + end + + test "post_authenticate_tasks raises an error if the custom class does not respond to perform" do + ShopifyApp.configure do |config| + config.custom_post_authenticate_tasks = Shopify::InvalidPostAuthenticateTasksClass + end + + error = assert_raises(ShopifyApp::ConfigurationError) do + ShopifyApp.configuration.post_authenticate_tasks + end + + assert_equal "Missing method - 'perform' for custom_post_authenticate_tasks", error.message end end From ae6e171d77ecbfe90b962696c5988e3d412e60bb Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Mon, 25 Mar 2024 16:05:21 -0600 Subject: [PATCH 03/22] Use configuration.post_authenticate_tasks --- app/controllers/shopify_app/callback_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shopify_app/callback_controller.rb b/app/controllers/shopify_app/callback_controller.rb index 43fe6a7fc..c34579ed2 100644 --- a/app/controllers/shopify_app/callback_controller.rb +++ b/app/controllers/shopify_app/callback_controller.rb @@ -138,7 +138,7 @@ def user_access_scopes_strategy end def perform_post_authenticate_jobs(session) - ShopifyApp::Auth::PostAuthenticateTasks.perform(session) + ShopifyApp.configuration.post_authenticate_tasks.perform(session) end end end From e73611c6aba9ad5dc0aac59a95eff6debc960e44 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 11:27:08 -0600 Subject: [PATCH 04/22] Copy more test from callback_controller_test --- .../auth/post_authenticate_tasks_test.rb | 65 ++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/test/shopify_app/auth/post_authenticate_tasks_test.rb b/test/shopify_app/auth/post_authenticate_tasks_test.rb index 3215f4d9c..235ebd3b2 100644 --- a/test/shopify_app/auth/post_authenticate_tasks_test.rb +++ b/test/shopify_app/auth/post_authenticate_tasks_test.rb @@ -34,7 +34,7 @@ class PostAuthenticateTasksTest < ActiveSupport::TestCase ShopifyApp::SessionRepository.store_shop_session(@offline_session) end - test "#perform triggers install_webhook job after authentication" do + test "#perform runs WebhooksManager job if webhooks are configured" do ShopifyApp.configure do |config| config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] end @@ -44,6 +44,17 @@ class PostAuthenticateTasksTest < ActiveSupport::TestCase ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) end + test "#perform doesn't run the WebhooksManager if no webhooks are configured" do + ShopifyApp.configure do |config| + config.webhooks = [] + end + ShopifyApp::WebhooksManager.add_registrations + + ShopifyApp::WebhooksManager.expects(:queue).never + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + test "#perform triggers 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" }] @@ -55,7 +66,7 @@ class PostAuthenticateTasksTest < ActiveSupport::TestCase ShopifyApp::SessionRepository.shop_storage.clear end - test "#perform triggers after_authenticate job after authentication" do + test "#perform calls AfterAuthenticateJob and performs inline when inline is true" do ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true } end @@ -64,4 +75,54 @@ class PostAuthenticateTasksTest < ActiveSupport::TestCase ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) end + + test "#perform calls AfterAuthenticateJob and performs asynchronous when inline isn't true" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: false } + end + + Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN) + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + + test "#perform doesn't call AfterAuthenticateJob if job is nil" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: nil, inline: false } + end + + Shopify::AfterAuthenticateJob.expects(:perform_later).never + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + + test "#perform calls AfterAuthenticateJob and performs async if inline isn't present" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob } + end + + Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN) + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + + test "#perform calls AfterAuthenticateJob constantizes from a string to a class" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob", inline: false } + end + + Shopify::AfterAuthenticateJob.expects(:perform_later).with(shop_domain: SHOP_DOMAIN) + + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + + test "#perform calls AfterAuthenticateJob raises if the string is not a valid job class" do + ShopifyApp.configure do |config| + config.after_authenticate_job = { job: "InvalidJobClassThatDoesNotExist", inline: false } + end + + assert_raise NameError do + ShopifyApp::Auth::PostAuthenticateTasks.perform(@offline_session) + end + end end From 7b5237ee1fcbbb8222338c467385f9e50203044c Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 11:54:09 -0600 Subject: [PATCH 05/22] Only call new post_authenticate_task if custom_post_authenticate_tasks is set in configuration --- .../shopify_app/callback_controller.rb | 41 ++++++++++++++- test/controllers/callback_controller_test.rb | 52 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/app/controllers/shopify_app/callback_controller.rb b/app/controllers/shopify_app/callback_controller.rb index c34579ed2..a47329273 100644 --- a/app/controllers/shopify_app/callback_controller.rb +++ b/app/controllers/shopify_app/callback_controller.rb @@ -23,7 +23,18 @@ def callback return respond_with_user_token_flow if start_user_token_flow?(api_session) - perform_post_authenticate_jobs(api_session) + # TODO: Remove before releasing v23.0.0 + # "perform_after_authenticate_job" and related methods (install_webhooks, perform_after_authenticate_job) + # will be deprecated in the next major release - 23.0.0 + # Set `custom_post_authenticate_tasks`from configuration instead to handle special cases. + if ShopifyApp.configuration.custom_post_authenticate_tasks.present? + ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) + else + perform_post_authenticate_jobs(api_session) + end + ########### When deprecating, replace the above block with: + # ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) + redirect_to_app if check_billing(api_session) end @@ -138,7 +149,33 @@ def user_access_scopes_strategy end def perform_post_authenticate_jobs(session) - ShopifyApp.configuration.post_authenticate_tasks.perform(session) + # Ensure we use the shop session to install webhooks + session_for_shop = session.online? ? shop_session : session + + install_webhooks(session_for_shop) + + perform_after_authenticate_job(session) + end + + def install_webhooks(session) + return unless ShopifyApp.configuration.has_webhooks? + + WebhooksManager.queue(session.shop, session.access_token) + end + + def perform_after_authenticate_job(session) + config = ShopifyApp.configuration.after_authenticate_job + + return unless config && config[:job].present? + + job = config[:job] + job = job.constantize if job.is_a?(String) + + if config[:inline] == true + job.perform_now(shop_domain: session.shop) + else + job.perform_later(shop_domain: session.shop) + end end end end diff --git a/test/controllers/callback_controller_test.rb b/test/controllers/callback_controller_test.rb index 96eb53846..1558eccfc 100644 --- a/test/controllers/callback_controller_test.rb +++ b/test/controllers/callback_controller_test.rb @@ -6,6 +6,13 @@ module Shopify class AfterAuthenticateJob < ActiveJob::Base def perform; end end + + class CustomPostAuthenticateTasks + class << self + def perform(session) + end + end + end end class CartsUpdateJob < ActiveJob::Base @@ -47,6 +54,7 @@ class CallbackControllerTest < ActionController::TestCase "AppleWebKit/537.36 (KHTML, like Gecko)"\ "Chrome/69.0.3497.100 Safari/537.36" ShopifyApp::SessionRepository.stubs(:store_session) + ShopifyApp.configuration.custom_post_authenticate_tasks = nil end teardown do @@ -163,6 +171,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback starts the WebhooksManager if webhooks are configured" do + log_deprecation ShopifyApp.configure do |config| config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] end @@ -174,6 +183,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback doesn't run the WebhooksManager if no webhooks are configured" do + log_deprecation ShopifyApp.configure do |config| config.webhooks = [] end @@ -186,6 +196,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs inline when inline is true" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true } end @@ -197,6 +208,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs asynchronous when inline isn't true" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: false } end @@ -208,6 +220,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback doesn't call #perform_after_authenticate_job if job is nil" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: nil, inline: false } end @@ -219,6 +232,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs async if inline isn't present" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob } end @@ -230,6 +244,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job constantizes from a string to a class" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob", inline: false } end @@ -241,6 +256,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job raises if the string is not a valid job class" do + log_deprecation ShopifyApp.configure do |config| config.after_authenticate_job = { job: "InvalidJobClassThatDoesNotExist", inline: false } end @@ -291,6 +307,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs install_webhook job after authentication" do + log_deprecation mock_oauth ShopifyApp.configure do |config| @@ -304,6 +321,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs install_webhook job with an offline session after an online session OAuth" do + log_deprecation ShopifyApp.configure do |config| config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] end @@ -321,6 +339,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs after_authenticate job after authentication" do + log_deprecation mock_oauth ShopifyApp.configure do |config| @@ -333,6 +352,32 @@ class CallbackControllerTest < ActionController::TestCase assert_response 302 end + test "#callback calls post_authenticate_tasks if custom_post_authenticate_tasks is set" do + mock_oauth + + ShopifyApp.configure do |_config| + ShopifyApp.configuration.custom_post_authenticate_tasks = Shopify::CustomPostAuthenticateTasks + end + + Shopify::CustomPostAuthenticateTasks.expects(:perform).with(@stubbed_session) + + get :callback, params: @callback_params + assert_response 302 + end + + test "#callback does not call post_authenticate_tasks if custom_post_authenticate_tasks is not set" do + mock_oauth + + ShopifyApp.configure do |_config| + ShopifyApp.configuration.custom_post_authenticate_tasks = nil + end + + Shopify::CustomPostAuthenticateTasks.expects(:perform).never + + get :callback, params: @callback_params + assert_response 302 + end + private def mock_oauth(cookie: @stubbed_cookie, session: @stubbed_session) @@ -372,5 +417,12 @@ def online_session associated_user: associated_user, ) end + + def log_deprecation + message = <<~EOS + TODO: Remove this test before releasing v23.0.0 - This logic is tested in PostAuthenticateTasksTest + EOS + puts message + end end end From 5ee1b12a167e5d0d538d9f8d30b857561079fa94 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 13:26:07 -0600 Subject: [PATCH 06/22] Update docs --- docs/shopify_app/authentication.md | 50 +++++++++++++++++++++--------- docs/shopify_app/webhooks.md | 2 +- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/docs/shopify_app/authentication.md b/docs/shopify_app/authentication.md index 0e9b95f07..ef3f4d521 100644 --- a/docs/shopify_app/authentication.md +++ b/docs/shopify_app/authentication.md @@ -26,15 +26,11 @@ The default callback controller [`ShopifyApp::CallbackController`](../../app/con 1. Logging into the shop and resetting the session 2. Storing the session to the `SessionRepository` -3. [Installing Webhooks](/docs/shopify_app/webhooks.md) -4. [Setting Scripttags](/docs/shopify_app/script-tags.md) -5. [Run jobs after the OAuth flow](#run-jobs-after-the-oauth-flow) -6. Redirecting to the return address - +3. [Post authenticate tasks](#post-authenticate-tasks) +4. Redirecting to the return address #### Customizing callback controller -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. +If you need to define a custom callback controller to handle your app's use case, you can configure the callback route to your controller. Example: @@ -42,11 +38,9 @@ Example: ```ruby # web/app/controllers/my_custom_callback_controller.rb -class MyCustomCallbackController < ShopifyApp::CallbackController - private - - def install_webhooks(session) - # My custom override/definition to install webhooks +class MyCustomCallbackController + def callback + # My custom callback logic end end ``` @@ -69,11 +63,39 @@ Rails.application.routes.draw do end ``` -### Run jobs after the OAuth flow +### Post Authenticate tasks +After authentication is complete, a few tasks are run by default by PostAuthenticateTasks: +1. [Installing Webhooks](/docs/shopify_app/webhooks.md) +2. [Run configured after_authenticate_job](#after_authenticate_job) + +The [PostAuthenticateTasks](https://github.com/Shopify/shopify_app/blob/main/lib/shopify_app/auth/post_authenticate_tasks.rb) +class is responsible for triggering the webhooks manager for webhooks registration, and enqueue jobs from [after_authenticate_job](#after_authenticate_job). + +If you simply need to enqueue more jobs to run after authenticate, use [after_authenticate_job](#after_authenticate_job) to define these jobs. + +If your post authentication tasks is more complex and is different than just installing webhooks and enqueuing jobs, +you can customize the post authenticate tasks by creating a new class that has a `self.perform(session)` method, +and configuring `custom_post_authenticate_tasks` in the initializer. + +```ruby +# my_custom_post_authenticate_task.rb +class MyCustomPostAuthenticateTask + def perform(session) + # This will be triggered after OAuth callback and token exchange completion + end +end + +# config/initializers/shopify_app.rb +ShopifyApp.configure do |config| + config.custom_post_authenticate_tasks = "MyCustomPostAuthenticateTask" +end +``` + +#### after_authenticate_job See [`ShopifyApp::AfterAuthenticateJob`](/lib/generators/shopify_app/add_after_authenticate_job/templates/after_authenticate_job.rb). -If your app needs to perform specific actions after the user is authenticated successfully (i.e. every time a new session is created), ShopifyApp can queue or run a job of your choosing (note that we already provide support for automatically creating Webhooks and Scripttags). To configure the after authenticate job, update your initializer as follows: +If your app needs to perform specific actions after the user is authenticated successfully (i.e. every time a new session is created), ShopifyApp can queue or run a job of your choosing. To configure the after authenticate job, update your initializer as follows: ```ruby ShopifyApp.configure do |config| diff --git a/docs/shopify_app/webhooks.md b/docs/shopify_app/webhooks.md index f1c0386c1..b47ce2898 100644 --- a/docs/shopify_app/webhooks.md +++ b/docs/shopify_app/webhooks.md @@ -18,7 +18,7 @@ ShopifyApp.configure do |config| end ``` -When the [OAuth callback](/docs/shopify_app/authentication.md#oauth-callback) is completed successfully, ShopifyApp will queue a background job which will ensure all the specified webhooks exist for that shop. Because this runs on every OAuth callback, it means your app will always have the webhooks it needs even if the user uninstalls and re-installs the app. +When the [OAuth callback](/docs/shopify_app/authentication.md#oauth-callback) or token exchange is completed successfully, ShopifyApp will queue a background job which will ensure all the specified webhooks exist for that shop. Because this runs on every OAuth callback, it means your app will always have the webhooks it needs even if the user uninstalls and re-installs the app. ShopifyApp also provides a [WebhooksController](/app/controllers/shopify_app/webhooks_controller.rb) that receives webhooks and queues a job based on the received topic. For example, if you register the webhook from above, then all you need to do is create a job called `CartsUpdateJob`. The job will be queued with 2 params: `shop_domain` and `webhook` (which is the webhook body). From d48ced0a681a017e7a5b1ed590cab5957c1d1001 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 13:47:11 -0600 Subject: [PATCH 07/22] Log method deprecation during configuration --- lib/shopify_app/configuration.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/shopify_app/configuration.rb b/lib/shopify_app/configuration.rb index 845063dc7..0442729aa 100644 --- a/lib/shopify_app/configuration.rb +++ b/lib/shopify_app/configuration.rb @@ -57,6 +57,8 @@ def initialize @scripttags_manager_queue_name = Rails.application.config.active_job.queue_name @webhooks_manager_queue_name = Rails.application.config.active_job.queue_name @disable_webpacker = ENV["SHOPIFY_APP_DISABLE_WEBPACKER"].present? + + log_callback_controller_method_deprecation end def login_url @@ -157,6 +159,23 @@ def post_authenticate_tasks task_class end end + + private + + def log_callback_controller_method_deprecation + return if Rails.env.test? + + # TODO: Remove this before releasing v23.0.0 + message = <<~EOS + ================================================ + => Upcoming deprecation in v23.0: + * 'CallbackController::perform_after_authenticate_job' and related methods 'install_webhooks', 'perform_after_authenticate_job' + * will be deprecated from CallbackController in the next major release. If you need to customize + * post authentication tasks, see https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks + ================================================ + EOS + puts message + end end class BillingConfiguration From 67954b1d4f1e1e790a6209d9afcedfd2e69673b0 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 16:11:25 -0600 Subject: [PATCH 08/22] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09f835b65..31daf8efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ Unreleased ---------- +* Extracted class - `PostAuthenticateTasks` to handle post authenticate tasks. To learn more, see [post authenticate tasks](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks). [1819](https://github.com/Shopify/shopify_app/pull/1819) 22.0.1 (March 12, 2024) ---------- From 5e8624793bb8e6e73c3f50f3f84e17a907e25df7 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 26 Mar 2024 17:51:17 -0600 Subject: [PATCH 09/22] Update doc example --- docs/shopify_app/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shopify_app/authentication.md b/docs/shopify_app/authentication.md index ef3f4d521..5c2911cae 100644 --- a/docs/shopify_app/authentication.md +++ b/docs/shopify_app/authentication.md @@ -80,7 +80,7 @@ and configuring `custom_post_authenticate_tasks` in the initializer. ```ruby # my_custom_post_authenticate_task.rb class MyCustomPostAuthenticateTask - def perform(session) + def self.perform(session) # This will be triggered after OAuth callback and token exchange completion end end From 8c9ddfb73cf118890e792397936866f332eeb535 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 12:52:34 -0600 Subject: [PATCH 10/22] Add missed 'end' from rebase --- lib/shopify_app/configuration.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/shopify_app/configuration.rb b/lib/shopify_app/configuration.rb index 0442729aa..4af727984 100644 --- a/lib/shopify_app/configuration.rb +++ b/lib/shopify_app/configuration.rb @@ -134,6 +134,7 @@ def use_new_embedded_auth_strategy? def online_token_configured? !ShopifyApp.configuration.user_session_repository.blank? && ShopifyApp::SessionRepository.user_storage.present? + end def post_authenticate_tasks @post_authenticate_tasks || begin From 74715ff1075540bb57d83c1c5c7c9333de41e2d7 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 12:59:11 -0600 Subject: [PATCH 11/22] remove unnecssary test setup --- test/controllers/callback_controller_test.rb | 1 - test/shopify_app/auth/post_authenticate_tasks_test.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/test/controllers/callback_controller_test.rb b/test/controllers/callback_controller_test.rb index 1558eccfc..7265fa7eb 100644 --- a/test/controllers/callback_controller_test.rb +++ b/test/controllers/callback_controller_test.rb @@ -187,7 +187,6 @@ class CallbackControllerTest < ActionController::TestCase ShopifyApp.configure do |config| config.webhooks = [] end - ShopifyApp::WebhooksManager.add_registrations ShopifyApp::WebhooksManager.expects(:queue).never diff --git a/test/shopify_app/auth/post_authenticate_tasks_test.rb b/test/shopify_app/auth/post_authenticate_tasks_test.rb index 235ebd3b2..2706f36a2 100644 --- a/test/shopify_app/auth/post_authenticate_tasks_test.rb +++ b/test/shopify_app/auth/post_authenticate_tasks_test.rb @@ -48,7 +48,6 @@ class PostAuthenticateTasksTest < ActiveSupport::TestCase ShopifyApp.configure do |config| config.webhooks = [] end - ShopifyApp::WebhooksManager.add_registrations ShopifyApp::WebhooksManager.expects(:queue).never From bbd3450f5c8716b43bbc38ffc828d5aee91eaeb9 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:05:48 -0600 Subject: [PATCH 12/22] Replace comment with version check --- .../shopify_app/callback_controller.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/app/controllers/shopify_app/callback_controller.rb b/app/controllers/shopify_app/callback_controller.rb index a47329273..17f30d912 100644 --- a/app/controllers/shopify_app/callback_controller.rb +++ b/app/controllers/shopify_app/callback_controller.rb @@ -23,18 +23,16 @@ def callback return respond_with_user_token_flow if start_user_token_flow?(api_session) - # TODO: Remove before releasing v23.0.0 - # "perform_after_authenticate_job" and related methods (install_webhooks, perform_after_authenticate_job) - # will be deprecated in the next major release - 23.0.0 - # Set `custom_post_authenticate_tasks`from configuration instead to handle special cases. - if ShopifyApp.configuration.custom_post_authenticate_tasks.present? - ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) + if ShopifyAPI::VERSION < "23.0" + # deprecated in 23.0 + if ShopifyApp.configuration.custom_post_authenticate_tasks.present? + ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) + else + perform_post_authenticate_jobs(api_session) + end else - perform_post_authenticate_jobs(api_session) + ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) end - ########### When deprecating, replace the above block with: - # ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) - redirect_to_app if check_billing(api_session) end From a70b0a578ff751b97093a8bf89c3ccf2a308fde4 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:05:59 -0600 Subject: [PATCH 13/22] Replace test log with comments --- test/controllers/callback_controller_test.rb | 29 ++++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/test/controllers/callback_controller_test.rb b/test/controllers/callback_controller_test.rb index 7265fa7eb..2b64c29e8 100644 --- a/test/controllers/callback_controller_test.rb +++ b/test/controllers/callback_controller_test.rb @@ -171,7 +171,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback starts the WebhooksManager if webhooks are configured" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] end @@ -183,7 +183,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback doesn't run the WebhooksManager if no webhooks are configured" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.webhooks = [] end @@ -195,7 +195,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs inline when inline is true" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: true } end @@ -207,7 +207,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs asynchronous when inline isn't true" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob, inline: false } end @@ -219,7 +219,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback doesn't call #perform_after_authenticate_job if job is nil" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: nil, inline: false } end @@ -231,7 +231,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job and performs async if inline isn't present" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: Shopify::AfterAuthenticateJob } end @@ -243,7 +243,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job constantizes from a string to a class" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: "Shopify::AfterAuthenticateJob", inline: false } end @@ -255,7 +255,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback calls #perform_after_authenticate_job raises if the string is not a valid job class" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.after_authenticate_job = { job: "InvalidJobClassThatDoesNotExist", inline: false } end @@ -306,7 +306,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs install_webhook job after authentication" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest mock_oauth ShopifyApp.configure do |config| @@ -320,7 +320,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs install_webhook job with an offline session after an online session OAuth" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest ShopifyApp.configure do |config| config.webhooks = [{ topic: "carts/update", address: "example-app.com/webhooks" }] end @@ -338,7 +338,7 @@ class CallbackControllerTest < ActionController::TestCase end test "#callback performs after_authenticate job after authentication" do - log_deprecation + # Deprecated in 23.0, tests moved to PostAuthenticateTasksTest mock_oauth ShopifyApp.configure do |config| @@ -416,12 +416,5 @@ def online_session associated_user: associated_user, ) end - - def log_deprecation - message = <<~EOS - TODO: Remove this test before releasing v23.0.0 - This logic is tested in PostAuthenticateTasksTest - EOS - puts message - end end end From 93b355a8fa4d86015ad0e0ff548cce61e7175294 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:20:03 -0600 Subject: [PATCH 14/22] Add extra test case --- test/controllers/callback_controller_test.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/controllers/callback_controller_test.rb b/test/controllers/callback_controller_test.rb index 2b64c29e8..86120e116 100644 --- a/test/controllers/callback_controller_test.rb +++ b/test/controllers/callback_controller_test.rb @@ -377,6 +377,20 @@ class CallbackControllerTest < ActionController::TestCase assert_response 302 end + test "#callback calls methods in callback controller if custom_post_authenticate_tasks is not set" do + mock_oauth + + ShopifyApp.configure do |_config| + ShopifyApp.configuration.custom_post_authenticate_tasks = nil + end + + CallbackController.any_instance.expects(:install_webhooks) + CallbackController.any_instance.expects(:perform_after_authenticate_job) + + get :callback, params: @callback_params + assert_response 302 + end + private def mock_oauth(cookie: @stubbed_cookie, session: @stubbed_session) From c1468e9ccff5448e0dc0e941cf403d9661191ebb Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:22:32 -0600 Subject: [PATCH 15/22] Add missed 'end' from rebase --- test/shopify_app/configuration_test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/shopify_app/configuration_test.rb b/test/shopify_app/configuration_test.rb index 7447f8886..fa2bf6ced 100644 --- a/test/shopify_app/configuration_test.rb +++ b/test/shopify_app/configuration_test.rb @@ -282,6 +282,7 @@ class ConfigurationTest < ActiveSupport::TestCase ShopifyApp::SessionRepository.user_storage = nil refute ShopifyApp.configuration.online_token_configured? + end test "#post_authenticate_tasks defaults to ShopifyApp::Auth::PostAuthenticateTasks" do assert_equal ShopifyApp::Auth::PostAuthenticateTasks, ShopifyApp.configuration.post_authenticate_tasks From 43311b250a42cebc7f9060b4934ce365a5d2210b Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:41:23 -0600 Subject: [PATCH 16/22] Using correct version check --- app/controllers/shopify_app/callback_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/shopify_app/callback_controller.rb b/app/controllers/shopify_app/callback_controller.rb index 17f30d912..6131521fe 100644 --- a/app/controllers/shopify_app/callback_controller.rb +++ b/app/controllers/shopify_app/callback_controller.rb @@ -23,7 +23,7 @@ def callback return respond_with_user_token_flow if start_user_token_flow?(api_session) - if ShopifyAPI::VERSION < "23.0" + if ShopifyApp::VERSION < "23.0" # deprecated in 23.0 if ShopifyApp.configuration.custom_post_authenticate_tasks.present? ShopifyApp.configuration.post_authenticate_tasks.perform(api_session) From da83fd898e45f3fac2dfa73be1562b19c5e33db3 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:47:42 -0600 Subject: [PATCH 17/22] Add upgrade note for unreleased version --- docs/Upgrading.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/Upgrading.md b/docs/Upgrading.md index 68c63c803..300cd6a2a 100644 --- a/docs/Upgrading.md +++ b/docs/Upgrading.md @@ -40,6 +40,17 @@ We also recommend the use of a staging site which matches your production enviro If you do run into issues, we recommend looking at our [debugging tips.](https://github.com/Shopify/shopify_app/blob/main/docs/Troubleshooting.md#debugging-tips) +## Unreleased +#### (v23.0.0) - Deprecated methods in CallbackController +The following methods from `ShopifyApp::CallbackController` have been deprecated in `v23.0.0` +- `perform_after_authenticate_job` +- `install_webhooks` +- `perform_post_authenticate_jobs` + +If you have overwritten these methods in your callback controller to modify the behavior of the inherited `CallbackController`, you will need to +update your app to use configurable option `config.custom_post_authenticate_tasks` instead. See [post authenticate tasks](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks) +for more information. + ## Upgrading to `v22.0.0` #### Dropped support for Ruby 2.x Support for Ruby 2.x has been dropped as it is no longer supported. You'll need to upgrade to 3.x.x From 6d0499ef4f0e4e77aca36b98e302482607fe57f3 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 13:52:38 -0600 Subject: [PATCH 18/22] Only log deprecation in development env --- lib/shopify_app/configuration.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/shopify_app/configuration.rb b/lib/shopify_app/configuration.rb index 4af727984..9fb2c425f 100644 --- a/lib/shopify_app/configuration.rb +++ b/lib/shopify_app/configuration.rb @@ -164,7 +164,7 @@ def post_authenticate_tasks private def log_callback_controller_method_deprecation - return if Rails.env.test? + return unless Rails.env.development? # TODO: Remove this before releasing v23.0.0 message = <<~EOS From 597a87b7759941462f63620c89699508b9dacad7 Mon Sep 17 00:00:00 2001 From: Zoey Lan <102243935+zzooeeyy@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:14:46 -0600 Subject: [PATCH 19/22] Use relative link Co-authored-by: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> --- docs/Upgrading.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Upgrading.md b/docs/Upgrading.md index 300cd6a2a..03c3b1828 100644 --- a/docs/Upgrading.md +++ b/docs/Upgrading.md @@ -48,7 +48,7 @@ The following methods from `ShopifyApp::CallbackController` have been deprecated - `perform_post_authenticate_jobs` If you have overwritten these methods in your callback controller to modify the behavior of the inherited `CallbackController`, you will need to -update your app to use configurable option `config.custom_post_authenticate_tasks` instead. See [post authenticate tasks](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks) +update your app to use configurable option `config.custom_post_authenticate_tasks` instead. See [post authenticate tasks](/docs/shopify_app/authentication.md#post-authenticate-tasks) for more information. ## Upgrading to `v22.0.0` From f21fe74524d3bc865d4ce3815d9fc5447d4c9ddf Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 16:16:31 -0600 Subject: [PATCH 20/22] Use relative links --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31daf8efc..0960288b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ Unreleased ---------- -* Extracted class - `PostAuthenticateTasks` to handle post authenticate tasks. To learn more, see [post authenticate tasks](https://github.com/Shopify/shopify_app/blob/main/docs/shopify_app/authentication.md#post-authenticate-tasks). [1819](https://github.com/Shopify/shopify_app/pull/1819) +* Extracted class - `PostAuthenticateTasks` to handle post authenticate tasks. To learn more, see [post authenticate tasks](/docs/shopify_app/authentication.md#post-authenticate-tasks). [1819](https://github.com/Shopify/shopify_app/pull/1819) 22.0.1 (March 12, 2024) ---------- From 33d8be46ec9c813a16cbad73abc1d3b156ebffa1 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Wed, 27 Mar 2024 16:21:45 -0600 Subject: [PATCH 21/22] Move config reset to test teardown instead --- test/controllers/callback_controller_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/controllers/callback_controller_test.rb b/test/controllers/callback_controller_test.rb index 86120e116..8c7dcb258 100644 --- a/test/controllers/callback_controller_test.rb +++ b/test/controllers/callback_controller_test.rb @@ -54,10 +54,10 @@ class CallbackControllerTest < ActionController::TestCase "AppleWebKit/537.36 (KHTML, like Gecko)"\ "Chrome/69.0.3497.100 Safari/537.36" ShopifyApp::SessionRepository.stubs(:store_session) - ShopifyApp.configuration.custom_post_authenticate_tasks = nil end teardown do + ShopifyApp.configuration.custom_post_authenticate_tasks = nil SessionRepository.shop_storage.clear end From 77de512277ca8b4d8eedbc8cfc6f2f0eec0bcd96 Mon Sep 17 00:00:00 2001 From: Zoey Lan Date: Tue, 2 Apr 2024 10:24:00 -0600 Subject: [PATCH 22/22] Fix markdown link --- docs/shopify_app/authentication.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/shopify_app/authentication.md b/docs/shopify_app/authentication.md index 5c2911cae..a466e7838 100644 --- a/docs/shopify_app/authentication.md +++ b/docs/shopify_app/authentication.md @@ -12,7 +12,7 @@ See [*Getting started with session token authentication*](https://shopify.dev/do * [OAuth callback](#oauth-callback) * [Customizing callback controller](#customizing-callback-controller) -* [Run jobs after the OAuth flow](#run-jobs-after-the-oauth-flow) +* [Run jobs after the OAuth flow](#post-authenticate-tasks) * [Rotate API credentials](#rotate-api-credentials) * [Making authenticated API requests after authorization](#making-authenticated-api-requests-after-authorization)