-
Notifications
You must be signed in to change notification settings - Fork 699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extract post authenticate tasks from CallbackController #1819
Conversation
27a1a91
to
02d14ba
Compare
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this is copied from CallbackController
shopify_app/app/controllers/shopify_app/callback_controller.rb
Lines 151 to 178 in 1f993c2
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a few thoughts but most of them are just me trying to understand things better so take them with a grain of salt :)
# 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we simplify this by adding a check for the version itself instead of adding the comments? We should still have a comment with the word deprecated
in it because that makes it easier to search / replace when we're releasing a new major version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: would it make more sense to have a post_authenticate_tasks
setting that defaults to the new class rather than a custom
setting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yess that does make sense, but in this pre-deprecation case we don't want to use the post_authenticate_tasks with a default if it's not manually set since we still want to call the old methods. I think it does make sense to have a single config with a default once we roll out the deprecation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah, fair. It wouldn't be ideal to change the setting name in the future though - so I think we should stick with what we add in this PR, whichever way we prefer to do it.
|
||
# TODO: Remove this before releasing v23.0.0 | ||
message = <<~EOS | ||
================================================ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this as a setup for logging general duplications - we might want to do that too when we go ahead with token exchange, so there might be an opportunity to make this a little bit more generic (like given an array of messages, log if it isn't empty).
Also, can we add some conditions to logging this? Is there any way we can detect that there is a controller that responds to the old methods we want to hide? We can probably build it back from the route path. It's more work but I think it would be worth it to not log every time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should make it more generic, but I think that could be done when we know we'll have another need for it? It's hard to know what specs to build for until we know how the new messages might look? e.g. is it generic messages or is it specific to deprecations...
and also, I disagree on conditionally logging this by checking for controllers in route.. I don't think that's worth the effort since it'll be deprecated in next release anyways, plus this will only be logged when you first start the server, so it's not tooo noisy. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. I think this comment is big enough that most folks would see it.
When I suggested we log this conditionally, I meant that ideally we wouldn't log it if there is no usage of the deprecated setup, i.e. if the app is configured in the "new" way, we just skip this to avoid confusion.
@@ -174,6 +183,7 @@ class CallbackControllerTest < ActionController::TestCase | |||
end | |||
|
|||
test "#callback doesn't run the WebhooksManager if no webhooks are configured" do | |||
log_deprecation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personal opinion, but I'm not sure I'd explicitly log these - just adding a comment saying they're deprecated (or better yet, adding actual deprecation logs) rather than puts
-ing might be enough. The logger call would actually error out so it would create actual test failures when we get there, which is nice.
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a very simple test here to ensure that the default behaviour gets called (even if we have to stub it)?
ShopifyApp.configure do |config| | ||
config.webhooks = [] | ||
end | ||
ShopifyApp::WebhooksManager.add_registrations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: why do we have to call add_registrations
here but not in the success tests? Makes me feel like there's a wrong check somewhere in the code :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ooops that's my oversight, I copied straight from CallbackControllTest LOL I'll also remove it from that test case
@@ -2,6 +2,18 @@ | |||
|
|||
require "test_helper" | |||
|
|||
module Shopify | |||
class CustomPostAuthenticateTasks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a question for my own benefit: will any class that defines a perform
method do here? Should we check if it extends a job class instead to standardize things a bit more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't put too much consideration there, because I didn't think the standardization is too necessary? This way it's more flexible, plus the configuration will raise a ConfigurationError if "perform" isn't a method.. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't think it matters too much, but I remember the documentation said it could "run this later", which I took to mean it would deal with a perform_later
type of thing. But just for the sake of standardization, I don't think it's necessary.
…s is set in configuration
1f993c2
to
5e86247
Compare
4c053fe
to
da83fd8
Compare
@@ -2,6 +2,18 @@ | |||
|
|||
require "test_helper" | |||
|
|||
module Shopify | |||
class CustomPostAuthenticateTasks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't think it matters too much, but I remember the documentation said it could "run this later", which I took to mean it would deal with a perform_later
type of thing. But just for the sake of standardization, I don't think it's necessary.
@@ -23,7 +23,16 @@ def callback | |||
|
|||
return respond_with_user_token_flow if start_user_token_flow?(api_session) | |||
|
|||
perform_post_authenticate_jobs(api_session) | |||
if ShopifyApp::VERSION < "23.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice that we can just compare it this way, makes this very easy to understand :)
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm yeah, fair. It wouldn't be ideal to change the setting name in the future though - so I think we should stick with what we add in this PR, whichever way we prefer to do it.
|
||
# TODO: Remove this before releasing v23.0.0 | ||
message = <<~EOS | ||
================================================ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair. I think this comment is big enough that most folks would see it.
When I suggested we log this conditionally, I meant that ideally we wouldn't log it if there is no usage of the deprecated setup, i.e. if the app is configured in the "new" way, we just skip this to avoid confusion.
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be the global test config value, so that other tests start with this as an assumption?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessary I only did it to "reset" the configuration state, but I can move that to the teardown so it doesn't become and assumption for other tests!
Co-authored-by: Paulo Margarido <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a general question, but if this is the way, LGTM
@@ -69,11 +63,39 @@ Rails.application.routes.draw do | |||
end | |||
``` | |||
|
|||
### Run jobs after the OAuth flow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this breaks the ToC at the top of this file :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is a bit late in the game, but isn't this essentially the same as enqueueing a special job that does these tasks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is very similar, but the after_authenticate_job only accepts a shop domain as the parameter, in which case it might not be enough for task customization?? If devs want to use the user session for whatever post auth task for their app, they wouldn't be able to since the task would only know the shop domain?? And since that's also setup in the configuration file, we'll need to somehow magically add this new special job to existing apps, and ensure there isn't conflict if they have already declared jobs?
What this PR does
https://github.com/Shopify/develop-app-access/issues/235
Extract common logic to run post authenticate task from CallbackController so that it can be used after the token exchange flow.
Added PostAuthenticateTasks to run the authenticated task
This is configurable as
config.custom_post_authenticate_tasks
, if that's not set, the defaultconfig.post_authenticate_tasks
will returnPostAuthenticateTasks
classUpdated docs on post authenticate tasks
Added deprecation warnings
Tophatting:
Deprecation warning in server start from configuration
Deprecation reminder in tests logs
When
config.custom_post_authenticate_tasks
is set, it will be used to handle post authenticate tasksChecklist
Before submitting the PR, please consider if any of the following are needed:
CHANGELOG.md
if the changes would impact usersREADME.md
, if appropriate./docs
, if necessary