-1

I have reviews set up similar to Airbnb.

These abilities should allow a guest to review a host, and a host to review a guest:

# ability.rb
can [:show], [Review] do |review|

  if review.reviewable_type == "Host" 
    review.booking.guest_id == user.guest.id 

  elsif review.reviewable_type == "Guest" 
    review.booking.host_id == user.host.id 

  end 
 
end

Here's the controller:

class ReviewsController < ApplicationController
  authorize_resource
  before_action :set_review, only: [:show]

  def show
  end

  private
    def set_review
      @review = Review.find_by_id(params[:id])
    end
end

When testing, everything works

host = Host.first

review = Review.first # A review of a host

ability = Ability.new(host.user)
ability.can?(:show, review)
# Returns false as expected

review2 = Review.second # A review of a guest
ability.can?(:show, review2)
# Returns true as expected

So everything's fine until this point.

But when I login as the host and visit the review for myself, I can review myself! The exact logic above denies access when it's tested in the console.

Why does cancancan prevent access in the console, but allow access in the browser?

stevec
  • 41,291
  • 27
  • 223
  • 311

1 Answers1

0

Total noob mistake.

I had

  authorize_resource
  before_action :set_review, only: [:show]

But authorize_resource should be called after the before_action that sets the model instance for the action.

So after this simple reordering, it works as expected:

  before_action :set_review, only: [:show]
  authorize_resource
stevec
  • 41,291
  • 27
  • 223
  • 311