Контекстная авторизация с использованием CanCan - PullRequest
7 голосов
/ 18 августа 2011

Я хочу использовать CanCan для обработки моих разрешений.Мой сайт имеет много разных уровней разрешений, и большинство из них являются контекстно-зависимыми.Например, вот отношения в моих 3 основных моделях:

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

Обратите внимание, LeagueRelations - это вложенный ресурс Лиг.Я хочу разрешить пользователю изменять лиги и оценивать авторизацию каждого пользователя на основе данных, хранящихся в league_relation.Затем я хотел бы, чтобы пользователь изменил отношение лиги, основываясь только на данных, хранящихся в пользовательской модели.

Чтобы быть кратким: я в основном хочу использовать LeagueRelations для авторизации действий Лиги, а пользователей - для авторизацииЛигаОтношения Действия.то есть league_relation.owner = true, чтобы удалить лигу, но user.owner?должно быть верно, чтобы удалить LeagueRelation.Как я могу авторизоваться на основе атрибутов league_relation внутри контроллера лиги и авторизовать другие действия в других контроллерах на других моделях.Пожалуйста, оставьте комментарий, если вам нужно больше разъяснений.

Спасибо.

1 Ответ

10 голосов
/ 19 августа 2011

Хорошо, я решил проблему. Мой вариант использования кратко упоминается в начале CanCan README, и я пропустил его. Вы можете определить новые классы Ability в app / models /, которые принимают другой параметр, отличный от current_user. Для этого вы помещаете в свой контроллер следующее:

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

Теперь вы можете создать league_ability.rb в приложении / models /.

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

Стоит отметить, что это зависит от того, как контроллер приложения вызывает метод в дочернем классе. Надеюсь, это поможет!

...