Should I skip authorization, with CanCan, of an action that instantiates a resource?

Posted by irkenInvader on Stack Overflow See other posts from Stack Overflow or by irkenInvader
Published on 2010-05-14T03:45:32Z Indexed on 2010/05/14 3:54 UTC
Read the original article Hit count: 224

Filed under:
|

I am writing a web app to pick random lists of cards from larger, complete sets of cards. I have a Card model and a CardSet model. Both models have a full RESTful set of 7 actions (:index, :new, :show, etc). The CardSetsController has an extra action for creating random sets: :random.

# app/models/card_set.rb
class CardSet < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :cards, :through => :memberships

# app/models/card.rb
class Card < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  has_many :memberships
  has_many :card_sets, :through => :memberships

I have added Devise for authentication and CanCan for authorizations. I have users with an 'editor' role. Editors are allowed to create new CardSets. Guest users (Users who have not logged in) can only use the :index and :show actions. These authorizations are working as designed. Editors can currently use both the :random and the :new actions without any problems. Guest users, as expected, cannot.

# app/controllers/card_sets_controller.rb
class CardSetsController < ApplicationController
  before_filter :authenticate_user!, :except => [:show, :index]
  load_and_authorize_resource

I want to allow guest users to use the :random action, but not the :new action. In other words, they can see new random sets, but not save them. The "Save" button on the :random action's view is hidden (as designed) from the guest users. The problem is, the first thing the :random action does is build a new instance of the CardSet model to fill out the view. When cancan tries to load_and_authorize_resource a new CardSet, it throws a CanCan::AccessDenied exception. Therefore, the view never loads and the guest user is served a "You need to sign in or sign up before continuing" message.

# app/controllers/card_sets_controllers.rb
def random
  @card_set = CardSet.new( :name => "New Set of 10", :set_type => "Set of 10" )

I realize that I can tell load_and_authorize_resource to skip the :random action by passing :except => :random to the call, but that just feels "wrong" for some reason.

What's the "right" way to do this? Should I create the new random set without instantiating a new CardSet? Should I go ahead and add the exception?

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about cancan