This is a follow-up to another question as I noticed my problem is far more general than described there.

In a Rails app which uses JSONAPI::Resources and CanCanCan, I have a Caption model (belongs_to :video) and a Video model (has_many :captions). To define abilities, I use an ability.rb file which I boiled down to this for testing purposes:

class Ability
  include CanCan::Ability

  def initialize(person)
    guest_actions
    user_actions(person)
  end

  def guest_actions
    # Guests can only access those captions which belong to a published video
    can :read, Caption, video: { visible: true }
  end

  def author_actions(person)
    # Registered users are only allowed to add captions to their own videos
    can %i[create destroy], Caption, video: { creator: { id: person.id } }
  end
end

However, this is not working. These specific ability definitions seem not to be ignored, but interpreted in a wrong way:

  • Guests can actually access all captions. If I remove the above line in guest_actions, guests can't access any caption and receive 401 Unauthorized instead.
  • Users get 403 Forbidden when trying to create a caption unless I remove the condition on the video in author_actions.

Both CaptionController and VideoController extend ApplicationController, which contains load_and_authorize_resource only: %i[index show create update destroy].

There is one thing I noticed about this specific relationship: When I open the Rails console or run RSpec, there's an unexpected warning:

DEPRECATION WARNING: In CaptionResource you exposed a 'has_one' relationship using the 'belongs_to' class method. We think 'has_one' is more appropriate.

I'm surprised by this because my Caption model contains a video_id field. I temporarily changed the relationship to has_one (in the resource only as well as in the model and the resource), but it didn't make a difference in my tests.

What is wrong with my code? I have a few abilities defined in a similar way, and I just can't figure out what's the problem with Caption.

0

There are 0 best solutions below