Created
May 18, 2012 08:41
-
-
Save emiltin/2724033 to your computer and use it in GitHub Desktop.
cancan authorizing object depening on parent resource
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#theme.rb | |
class Theme < ActiveRecord::Base | |
belongs_to :challenge | |
end | |
#challenge.rb | |
class Challenge < ActiveRecord::Base | |
has_many :themes | |
has_many :roles, :as => :managed, :dependent => :destroy | |
end | |
#role.rb | |
class Role < ActiveRecord::Base | |
belongs_to :user | |
belongs_to :managed, :polymorphic => true | |
end | |
#user.rb | |
class User < ActiveRecord::Base | |
has_many :roles, :dependent => :destroy | |
end | |
#ability.rb | |
class Ability < ActiveRecord::Base | |
include CanCan::Ability | |
def initialize(user) | |
if user | |
can :manage, Challenge do |challenge| | |
challenge.roles.exists? :user_id => user.id | |
end | |
can :manage, Theme do |theme,challenge| | |
challenge.roles.exists? :user_id => user.id | |
end | |
end | |
end | |
end | |
#routes.rb | |
Sociallab::Application.routes.draw do | |
resources :challenges do | |
resources :themes | |
end | |
end | |
#themes_controller.rb | |
class ThemesController < ApplicationController | |
before_filter { @challenge = Challenge.find params[:challenge_id] } | |
#goal: only allow users to view a theme if she has a role to theme.challenge | |
def show | |
@theme = @challenge.themes.find params[:id] #implies @theme.challenge == @challenge | |
authorize! :show, @theme, @challenge #ok, challenge will be passed as an extra arg to the block in Ability | |
authorize! :show, @theme #alternatively, we could just pass the theme, and use theme.challenge in the block Ability | |
end | |
#goal: only allow users to index themes on a challenge if she has a role to the challenge | |
def index | |
authorize! :index, Theme, @challenge #doesn't work, because the block in Ability is not being called when the subject is a class | |
authorize! :index, Theme #not sufficient, since we need to check if the user has a role to @challenge | |
authorize! :index_themes, @challenge #this might work, but seems a bit clunky? | |
@themes = @challenge.themes | |
end | |
#goal: only allow users to create a new theme on a challenge if she has a role to the challenge | |
def new | |
@theme = @challenge.themes.build #implies @theme.challenge == @challenge | |
authorize! :new, Theme, @challenge #doesn't work, because the block in Ability is not being called when the subject is a class | |
authorize! :new, @theme, @challenge #works, but impractical to move to a before_filter since it depends on @theme | |
authorize! :new, Theme #not sufficient, since we need to check if the user has a role to @challenge | |
authorize! :manage, @challenge #insufficient as soon as we need different permissions on Challenges and Themes | |
authorize! :new_theme, @challenge #this might work, but seems a bit clunky? | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment