Context-sensitive authorization using CanCan

I want to use CanCan to process my rights. My site has many different permission levels, and most of them are familiar with the context. For example, here are the relationships in my three main models:

class User < ActiveRecord::Base has_many :league_relations has_many :leagues, :through => :league_relations end class League < ActiveRecord::Base has_many :league_relations has_many :users, :through => :league_relations end class LeagueRelation < ActiveRecord::Base belongs_to :user belongs_to :league end 

Note. LeagueRelations is an embedded League resource. What I want to do is let the user change the leagues and define each user authorization based on the data stored in league_relation. Then I would like the user to change the league ratio based only on the data stored in the user model.

To be brief: I basically want LeagueRelations to be used to authorize League actions and Users to be used to authorize LeagueRelations actions. i.e. league_relation.owner = true to remove the league, but user.owner? must be true to remove LeagueRelation. How can I allow based on league_relation attributes when inside a league controller, and allow other actions in other controllers on other models. Please leave a comment if you need more clarification.

Thanks.

+7
source share
1 answer

Ok, I solved the problem. My use case is briefly mentioned at the beginning of CanCan README, and I skipped it. You can define new skill classes in the / models / application that take a different parameter than current_user. To do this, add the following to the controller:

 def current_ability if params[:controller] == 'leagues' @current_ability = LeagueAbility.new(current_user_league_relation) elsif params[:controller] == 'league_relations' @current_ability = LeagueRelationAbility.new(current_user_league_relation) else @current_ability = Ability.new(current_user) end end 

Now you can create league_ability.rb in the / models / application.

 class LeagueAbility include CanCan::Ability def initialize(league_relation) league_relation ||= LeagueRelation.new if league_relation.owner? can :manage, League, :id => league_relation.league_id elsif league_relation.moderator? can :manage, League, :id => league_relation.league_id cannot [:delete, :destroy], League else can :read, League can :create, League end end end 

It should be noted that this depends on your application controller calling the method in the child class. Hope this helps!

+10
source

All Articles