Подтвердить что ты не робот

Безопасный и Railsiest путь в CanCan, чтобы выполнять разрешения Guest, User, Admin

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

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

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

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

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

Ищите совет по более элегантному способу этого.

Спасибо!

4b9b3361

Ответ 1

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

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

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

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

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

конец

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

Ответ 3

Если пользовательский объект не является 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

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

class User < ActiveRecord::Base
  # Alternatively, you can add an admin attribute flag
  def admin?
    ["[email protected]", "hisspouse.yourservice.com"].include?(email)
  end
end

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

Ответ 4

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

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

Ответ 5

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

Способность

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

User

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