Skip to content
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

Namespaced policy and controller can't find authorization target for index #170

Closed
robbevp opened this issue Jun 23, 2021 · 9 comments
Closed
Labels
question Further information is requested

Comments

@robbevp
Copy link

robbevp commented Jun 23, 2021

Tell us about your environment

Ruby Version: 3.0.1

Framework Version (Rails, whatever): Rails 6.1.3.1

Action Policy Version: 0.5.7

What did you do?

I created a controller and namespaced policy very similar to the example of nested modules in the docs.

My controller (simplified)

class Admin::Client::ReportsController < ApplicationController
  def index
    authorize!
    @reports = Report.all
  end

  def show
    @report = Report.find(params[:id])
    authorize! @report
  end
end

My policy

class Admin::Client::ReportPolicy < ApplicationPolicy
  def index?
    user&.admin?
  end

  def show?
    user&.admin?
  end
end

What did you expect to happen?

When calling either index or show, I expect the corresponding policy to be called.

What actually happened?

When calling show, the policy is found and correctly called. When calling index, i get the following error

ActionPolicy::NotFound (Couldn't find policy class for [#<Admin::Client::ReportsController:0x0000000004a8d0>, "Couldn't find implicit authorization target for Admin::Client::ReportsController. Please, provide policy class explicitly using `with` option or define the `implicit_authorization_target` method."] (Array)):

Any help? Since nested namespaces with an index action are mention explicitly in the docs, I thought that I should need to explicitly provde the authorization target

@ingnam
Copy link

ingnam commented Jun 28, 2021

I recently upgraded my rails version to 6.1.3.2 and I have started getting similar error:

Couldn't find policy class for #<GraphQL::Pagination::ActiveRecordRelationConnection:0x00007f8b55e74a18 @items=#<ActiveRecord::Relation [#<Brand id: 2, created_at: "2020-02-26 08:46:09.450541000 +1100", updated_at: "2021-02-08 11:19:24.364907000 +1100", name: "Adidas", description: "desc....">]>, @parent=nil, @context=#<Query::Context ...>, @field=#<Types::BaseField Query.brands(...): BrandConnection!>, @first_value=10, @after_value=nil, @last_value=nil, @before_value=nil, @arguments={:first=>10}, @edge_class=GraphQL::Pagination::Connection::Edge, @has_max_page_size_override=true, @max_page_size=100> (GraphQL::Pagination::ActiveRecordRelationConnection)

I'm using action_policy and action_policy-graphql gems.

@palkan
Copy link
Owner

palkan commented Jul 6, 2021

Hey @ingnam!

That looks like a different problem: GraphQL::Pagination::ActiveRecordRelationConnection instance is passed as the record, which we don't know how to resolve. Likely, related to some GraphQL-ruby changes or other GraphQL gems.

Could you please open a separate issue in https://github.com/palkan/action_policy-graphql ?

@palkan
Copy link
Owner

palkan commented Jul 6, 2021

@robbevp The problem is that controller_name.classify.safe_constantize returns nil for some reason (though we definitely have the Report class).

What if you add Report as an argument?

authorize! Report

(What surprises me more is that an array with exception message is passed as implicit target 🤔 it should raise an exception (unless #raise is overriden))

@palkan palkan added the question Further information is requested label Aug 27, 2021
@palkan
Copy link
Owner

palkan commented Aug 27, 2021

@robbevp Could you please take a look at the question above?

@robbevp
Copy link
Author

robbevp commented Sep 1, 2021

Hi @palkan
Sorry for my late response.

If I add the class as an argument, everything works as expected.

@palkan
Copy link
Owner

palkan commented Sep 1, 2021

Hm, interesting; could you share the results of the following expression (executed right before authorize!):

  • сontroller_name
  • controller_name.classify
  • controller_name.classify.constantize

@robbevp
Copy link
Author

robbevp commented Sep 1, 2021

The constantize seems to be the source of the problem:

сontroller_name: reports
сontroller_name.classify: Report

But constantizing throws uninitialized constant Report since my model is also namespaced under the same namespace as the controller/policy. Looking back, this seems to have been left out when I simplified my code - apologies.

Is there a way to make this work with action_policy (without explictly mentioning the model on authorize!)?

@palkan
Copy link
Owner

palkan commented Sep 2, 2021

my model is also namespaced under the same namespace as the controller/policy

Ok, that's the answer.

You can override the #implicit_authorization_target for your controllers to take into account namespacing like this:

def implicit_authorization_target
  controller_path.classify.safe_constantize
end

@niudage
Copy link

niudage commented Mar 6, 2023

thankyou

@palkan palkan closed this as completed Mar 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants