Безопасный и 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
Но это просто не так. Кажется, что он отстранен от, как, собственно, зарегистрированный в журнале, и беспокоится о том, действительно ли он защищен.
Ищите совет по более элегантному способу этого.
Спасибо!
Ответы
Ответ 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