Search code examples
ruby-on-railscancan

Is it possible to raise an exception other than Access Denied with cancan?


I control permissions with cancan. I want to change the return destination(404,403) to a specific condition

But, I don't know how to make an exception other than CanCan::AccessDenied with cancan

Let me know if you could have a idea.

Below is my code.(If status is true, I want to return with 404, otherwise I want to return 403)

model

#app/models/ablity.rb
if current_user.status
  can :show, Organization # 404
else
  can :show, Organization # 403
end

controller

  def index

    authorize! :show, Organization
  rescue CanCan::AccessDenied => e
    render_403 # if status true
    render_404 # if status false
  end

Solution

  • I did some digging and it doesn't look like CanCan supports the kind of granularity for exceptions you require.

    So... why not use current_user.status in your controller as well?

    def index
      authorize! :show, Organization
    rescue CanCan::AccessDenied => e
      if current_user.status
        render_403
      else
        render_404
      end
    end
    

    (Or, if duplicate code/logic is a concern, put them both in a method you call both in your ability class and the controller.)

    Then simplify the snippet from your ability class down to the following:

    can :show, Organization
    

    BTW, CanCan hasn't been maintained in years. You may want to switch to the more actively maintained CanCanCan (but I think you'll require the same solution above).

    Also, if you end up showing different pages depending on the user's status (whatever that status may communicate), you may be inadvertently leaking information that users and/or non-users aren't supposed to see, similar to what's explained here.