Самый безопасный и самый простой способ в CanCan сделать права гостя, пользователя, администратора - PullRequest
12 голосов
/ 01 марта 2011

Я относительно новичок в rails (3) и собираю приложение, используя CanCan, где есть 3 уровня пользователей.

  • Гость - незарегистрированный пользователь Пользователь
  • зарегистрирован и вошел в систему посетитель
  • Admin - зарегистрирован и авторизирован посетитель с флагом администратора

Моя способность прямо сейчас - скопированная из документов cancan, в основном определяющая роль гостя и роль администратора

class Ability

    include CanCan::Ability

    def initialize(user)
        user ||= User.new # Guest user

        if user.is_admin?
            can :manage, :all
        else
            can :read, [Asana,Image,User,Video,Sequence]
        end
    end

end

Я ищу, чтобы добавить в роли пользователя. Так как я создаю эту одноразовую пользовательскую модель, я подумал об использовании new_record? определить, вошел ли пользователь в систему или нет. Что-то вроде:

class Ability

    include CanCan::Ability

    def initialize(user)
        user ||= User.new # Guest user

        if !user.new_record? and user.is_admin?
            can :manage, :all
        elsif !user.new_record? and !user.is_admin?
            can {registered user-y permissions}
        else
            can :read, [Asana,Image,User,Video,Sequence]
        end
    end

end

Но это просто нехорошо. Кажется, что-то вроде отсоединения от, например, фактического входа в систему, и беспокоится о том, действительно ли это безопасно.

Нужны советы по более элегантному способу сделать это.

Спасибо!

Ответы [ 5 ]

21 голосов
/ 24 марта 2011

Хороший вопрос, я использую подход с более низкими разрешениями:

class Ability  
  include CanCan::Ability  

  def initialize(user)
    # Guest User 
    unless user 
      can :read, [Asana,Image,User,Video,Sequence]
    else
      # All registered users
      can {registered user-y permissions}
      # Admins 
      if user.is_admin?
        can :manage, :all
      end
    end 
  end  
end

Таким образом, если завтра у вас будут другие роли для интеграции, вы можете сделать это, добавив оператор case следующим образом:

class Ability  
  include CanCan::Ability  

  def initialize(user)
    # Guest User 
    unless user 
      can :read, [Asana,Image,User,Video,Sequence]
    else
      # All registered users
      can {registered user-y permissions}
      # Different roles
      case user.role
      when 'admin'
        can :manage, :all
      when 'manager'
        can :manage, [Video, Image, Sequence]
      end
    end 
  end  
end
2 голосов
/ 21 марта 2011

Итак, что вам в основном нужно, так это способности ни для одного из вошедших в систему пользователей, возможности для вошедшего в систему пользователя и затем возможности для вошедшего в систему администратора?

Поскольку текущая модель пользователя передается в инициализацию, выпридется тестировать на основе свойства пользователя, и имеет смысл использовать базовое свойство роли, хранящееся в пользовательской модели, например,

def initialize(user)
user ||= User.new # guest user (not logged in)
if user.role == 'admin'
  # Admin roles
  can :manage, :all
elsif user.role == 'user'
  # Signed in user permissions
else
  # Guest permissions
  can :read, :all
end

end

Таким образом, когда пользовательрегистрирует / регистрирует, что вы можете по умолчанию установить значение роли «user», а затем разрешить некоторому методу обновить его до «admin» в интерфейсе управления.Вы могли бы использовать одного администратора?проверьте пользователя, так как это будет ложным для гостей, а также для обычных пользователей, вошедших в систему.

1 голос
/ 22 марта 2011

Если объект пользователя не new_record, это означает, что он хранится в базе данных.Для меня этого достаточно, чтобы признать, что это вошедший в систему пользователь.

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new  

    # Guest users
    can :create, User

    # Members  
    unless user.new_record?
      can [:edit, :update], User, :id => user.id
    end

    # Admins
    if user.admin?
      can :manage, :all
    end
  end
end

Более того, иногда функциональность администратора не обязательно должна быть такой необычной - возможно, это все, что вам нужно?*

Наконец, хотя вы новичок в rails, я предлагаю вам написать код своей аутентификации с нуля.Использование драгоценных камней, таких как Devise и Authlogic, почти всегда имеет свои недостатки.И это не должно быть так сложно.Райан (автор cancan) сделал отличную заставку на эту тему: http://railscasts.com/episodes/250-authentication-from-scratch

0 голосов
/ 12 апреля 2013

Если вы используете наследование ролей, этот шаблон хорошо работает:

Способность

user ||= User::GUEST # guest user (not logged in)

# anyone
can [:read], Post

# any registered user
if user.role? :user
  can [:comment], Post
end

# editor
if user.role? :editor
  can [:create], Post
end

# admin
if user.role? :admin
  can [:manage], Post
end

Пользователь

GUEST = User.new.tap {|u| u.role = 'guest'}

ROLES = %w[guest user editor admin]
def role?(base_role)
  begin
    ROLES.index(base_role.to_s) <= ROLES.index(role.to_s)
  rescue
    raise "invalid role query '#{base_role}' against user role '#{role}'"
  end
end
0 голосов
/ 22 марта 2011

Если у вас на самом деле постоянная модель пользователя, то это зарегистрированный пользователь, в противном случае он является гостем. Может быть, вы обдумываете это?

class Ability
  include CanCan::Ability

  def initialize(user=nil)
    if user && user.is_admin?
      can :manage, :all
    elsif user
      can {registered user-y permissions}
    else # guest
      can :read, [Asana,Image,User,Video,Sequence]
    end
  end
end
...