Search code examples
ruby-on-railsruby-on-rails-4cancancancancan

How do I setup my CanCanCan permissions correctly?


I am a little confused about how to configure CanCanCan properly.

For starters, do I have to add load_and_authorize_resource to every controller resource I want to restrict access to?

This is what I would like to do:

  • Admin can manage and access all controllers and actions
  • Editor can read all, manage :newsroom, and can manage all Posts
  • Member can read every Post and can create & update Posts (not edit/delete/anything else), cannot access the newsroom. The difference between an update & edit post in our business rules is that an update is creating a new post that is a child post of the current post. So it isn't an edit. Just a new record with an ancestry association.
  • Guest can read every Post, but cannot create Posts nor access the Newsroom.

This is what my ability.rb looks like:

class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new # guest user (not logged in)
    #Admin
   if user.has_role? :admin
        can :manage, :all
        can :manage, :newsroom
   # Editor
    elsif user.has_role? :editor
      can :read, :all
      can :manage, :newsroom
      can :manage, Post
    #Member
    elsif user.has_role? :member
        can :read, :all
        can :create, Post
        can :status, Post
        can :update, Post do |post|
            post.try(:user) == user
        end
    #Guest
    else
        can :read, :all
        can :create, Post
        can :status, Post
    end    
  end
end

In my routes.rb I have this:

  authenticate :user, lambda { |u| u.has_role? :admin or :editor } do
    get 'newsroom', to: 'newsroom#index', as: "newsroom"
    get 'newsroom/published', to: 'newsroom#published'
    get 'newsroom/unpublished', to: 'newsroom#unpublished'    
  end

What is happening though, is when I am logged in with a user that has not been assigned any roles (i.e. what I want to be a "Guest"), they can access the Newsroom.

When I try to edit a post with the role of :member, it gives me a "Not authorized to edit post" error (which is correct).

I just can't quite lockdown the Newsroom and I am not sure why.


Solution

  • For what it's worth, I had to setup my NewsroomController like this:

    class NewsroomController < ApplicationController
      authorize_resource :class => false
    

    This is what the working version of my ability.rb looks like after I got it to work with the permissions I needed:

    #Roles
    #Admin
     if user.has_role? :admin
          can :manage, :all
     # Editor
      elsif user.has_role? :editor
        can :manage, :newsroom
        can :manage, Post
      #Member
      elsif user.has_role? :member
          can [:read, :create, :status], Post
          can :update, Post do |post|
            post.try(:user) == user
          end
      #Guest
      else
          can [:read, :status], Post
      end