How can I enforce scoping on singular resources using Pundit?

75 views Asked by At

I have a few singular resources in my app, e.g.:

# routes.rb
MySite::Application.routes.draw do
  resource :thing
end

# things_controller.rb
class ThingsController < ApplicationController
  def edit
    load_thing
  end

  def update
    load_thing
    if @thing.update_attributes(thing_params)
      ...
    else
      ...
    end
  end

  private

  def load_thing
    @thing ||= current_user.thing
  end

  def thing_params
    params.require(:thing).permit(...)
  end
end

I'm wondering how to enforce policy scoping using Pundit (before_action :verify_policy_scoped has been set in ApplicationController).

I'm not sure how to form my policy scope for singular resources, i.e.:

# thing_policy.rb
class ThingPolicy < ApplicationPolicy
  Scope < Scope
    def resolve
      # What to do here...
      # scope => ?
    end
  end
end

# things_controller.rb
def load_thing
  # ...and what to do here
  @thing ||= policy_scope(...)
end

According to Pundit's docs:

...the method resolve...should return some kind of result which can be iterated over.

However, with singular resources, this iterability clause isn't really valid and there is no AR-style scope as such... just a single record.

Anyone have any suggestions for how to go about this?

1

There are 1 answers

0
fylooi On

Scoping is generally performed on the index action to restrict the base set of records the user can access before filtering is applied. For individual records, you should authorize them instead.

In any case, you are already scoping @thing to current_user

Would suggest to limit before_action :verify_policy_scoped to only: [:index]