Использование :attr_accessible с авторизацией на основе ролей
-
16-09-2019 - |
Вопрос
В моем интернет-магазине пользователям разрешено изменять определенные свойства своих заказов (например, адрес выставления счета), но не другие (например, IP-адрес отправителя).Администраторам, с другой стороны, разрешено изменять ВСЕ свойства заказа.
Учитывая это, как я могу использовать :attr_accessible
чтобы должным образом обезопасить мою модель заказа?Или мне придется использовать его, чтобы отметить доступными все атрибуты, которые администраторы могут изменять и воздерживаться от использования Order.update_attributes(params[:order])
в тех действиях контроллера, к которым могут получить доступ обычные пользователи?
Решение
Вообще говоря, attr_accessible - это не тот инструмент, который вы ищете, и Rails не поставляется с чем-либо встроенным, что делает то, что вы хотите.
Если вам нужен детальный контроль над тем, кто может обновлять определенные атрибуты в модели, вы могли бы сделать что-то вроде:
class Order < ActiveRecord::Base
def update_attributes_as_user(values, user)
values.each do |attribute, value|
# Update the attribute if the user is allowed to
@order.send("#{attribute}=", value) if user.can_modify?(attribute)
end
save
end
end
Тогда вы можете изменить свой Order.update_attributes(params[:order])
Для Order.update_attributes_as_user(params[:order], current_user)
и предполагая, что вы реализуете User#can_modify?
метод, возвращающий true в правильных случаях, он должен работать.
Другие советы
У меня была такая же проблема, и теперь я использую этот драгоценный камень http://github.com/dmitry/attr_accessible_block
Это просто и используется на каком-нибудь производственном веб-сайте.
Да, вам придется изменить действия, поэтому разрешения проверяются внутри действий.Зовущий Order#update_attributes
не будет работать для обычного пользователя.
Я не могу вспомнить плагин авторизации на основе ролей, который разрешал бы то, что вы ищете.Это связано с тем, что эти плагины подключаются к контроллерам, а не к моделям.Их также нужно было бы смешать с ActiveRecord::Base
чтобы проверить наличие attr_accesible
и т.д.