diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f08ebc..092bcc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master +- Fix implicit authorization target in anonymous controllers. ([@palkan][]) + - Improve default `ActionPolicy::Unauthorized` error message. ([@Spone][]) Before: `Not Authorized` / After: `Not authorized: UserPolicy#create? returns false` diff --git a/lib/action_policy/rails/controller.rb b/lib/action_policy/rails/controller.rb index d1b1294..db95a0f 100644 --- a/lib/action_policy/rails/controller.rb +++ b/lib/action_policy/rails/controller.rb @@ -56,7 +56,7 @@ def authorize!(record = :__undef__, to: nil, **options) # Tries to infer the resource class from controller name # (i.e. `controller_name.classify.safe_constantize`). def implicit_authorization_target - controller_name.classify.safe_constantize + controller_name&.classify&.safe_constantize end def verify_authorized diff --git a/test/action_policy/rails/controllers_test.rb b/test/action_policy/rails/controllers_test.rb index 402641c..0b81461 100644 --- a/test/action_policy/rails/controllers_test.rb +++ b/test/action_policy/rails/controllers_test.rb @@ -274,3 +274,36 @@ def test_index_authorized assert_equal "OK", response.body end end + +class TestAnonymousControllerIntegration < ActionController::TestCase + class UserPolicy < ::UserPolicy + authorize :user, allow_nil: true + + def index? = user.present? + end + + def test_nameless_controllers_work + controller_class = Class.new(ActionController::Base) do + authorize :user, through: :current_user + + def index + authorize! with: UserPolicy + head :ok + end + + def current_user + return unless params[:user] + @current_user ||= User.new(params[:user]) + end + end + + env = Rack::MockRequest.env_for("http://localhost:3000") + + assert_raises(ActionPolicy::Unauthorized) do + controller_class.action(:index).call(env) + end + + env = Rack::MockRequest.env_for("http://localhost:3000/?user=guest") + controller_class.action(:index).call(env) + end +end