From 57e2a84d09a24b2759f7e6dcaff510f4f8ea9b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janko=20Marohni=C4=87?= Date: Mon, 8 Apr 2024 22:30:10 +0200 Subject: [PATCH] Allow declaring controller callbacks for certain routes This makes it more convenient to execute callbacks only for certain routes, by allowing usage of `:only` and `:except` keyword arguments. This should play nicely with the recent instrumentation change, as the user will see route names in the logs. --- README.md | 2 +- lib/rodauth/rails/feature/callbacks.rb | 2 ++ test/integration/callbacks_test.rb | 22 +++++++++++++------ .../app/controllers/rodauth_controller.rb | 5 +++++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f23cbcb2..7deb45c1 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ end ``` ```rb class RodauthController < ApplicationController - before_action :set_locale # executes before Rodauth endpoints + before_action :verify_captcha, only: :login, if: -> { request.post? } # executes before Rodauth endpoints rescue_from("MyApp::SomeError") { |exception| ... } # rescues around Rodauth endpoints end ``` diff --git a/lib/rodauth/rails/feature/callbacks.rb b/lib/rodauth/rails/feature/callbacks.rb index fb0f2cd6..af9a7a8b 100644 --- a/lib/rodauth/rails/feature/callbacks.rb +++ b/lib/rodauth/rails/feature/callbacks.rb @@ -7,6 +7,8 @@ module Callbacks private def _around_rodauth + rails_controller_instance.instance_variable_set(:@_action_name, current_route.to_s) + rails_controller_around { super } end diff --git a/test/integration/callbacks_test.rb b/test/integration/callbacks_test.rb index a84ffbb5..6d083cf3 100644 --- a/test/integration/callbacks_test.rb +++ b/test/integration/callbacks_test.rb @@ -5,18 +5,26 @@ class CallbacksTest < IntegrationTest visit "/login" assert_match "login-form", page.html - assert_equal 200, page.status_code - assert_equal "true", page.response_headers["X-Before-Action"] - assert_equal "true", page.response_headers["X-After-Action"] - assert_equal "true", page.response_headers["X-Before-Around-Action"] - assert_equal "true", page.response_headers["X-After-Around-Action"] + assert_equal 200, page.status_code + assert_equal "true", page.response_headers["X-Before-Action"] + assert_equal "true", page.response_headers["X-After-Action"] + assert_equal "true", page.response_headers["X-Before-Around-Action"] + assert_equal "true", page.response_headers["X-After-Around-Action"] + end + + test "runs callbacks for specific actions" do + visit "/create-account" + assert_equal "true", page.response_headers["X-Before-Specific-Action"] + + visit "/login" + assert_nil page.response_headers["X-Before-Specific-Action"] end test "handles rendering in callback chain" do visit "/login?early_return=true&fail=true" assert_equal "early return", page.html - assert_equal 201, page.status_code - assert_equal "true", page.response_headers["X-Before-Action"] + assert_equal 201, page.status_code + assert_equal "true", page.response_headers["X-Before-Action"] end end diff --git a/test/rails_app/app/controllers/rodauth_controller.rb b/test/rails_app/app/controllers/rodauth_controller.rb index 86546a2f..0f72f20f 100644 --- a/test/rails_app/app/controllers/rodauth_controller.rb +++ b/test/rails_app/app/controllers/rodauth_controller.rb @@ -2,6 +2,7 @@ class RodauthController < ApplicationController before_action :before_route after_action :after_route around_action :around_route + before_action :before_specific_route, only: [:create_account] rescue_from NotImplementedError do render plain: "rescued response", status: 500 @@ -27,6 +28,10 @@ def around_route response.headers["X-After-Around-Action"] = "true" end + def before_specific_route + response.header["X-Before-Specific-Action"] = "true" + end + def some_method "controller method" end