Система динамических ролей и разрешений в приложении Rails

Мне нужно создать системы разрешений на основе ролей в моем приложении Rails. Я был бы полностью доволен CanCan, но главная проблема - она ​​должна быть динамичной, поэтому администратор должен иметь возможность назначать разрешения и создавать новые роли. Разрешения могут быть простыми ограничениями для контроллера/действия и могут быть связаны с данными, например, некоторые пользователи могут редактировать только свои собственные профили, а некоторые из них могут редактировать профили всех пользователей в конкретной группе. И было бы неплохо позволить администратору создавать новые разрешения.

То, о чем я думаю, это хранить в db контроллер/действие и некоторые ограничения, связанные с данными (я действительно запутался здесь, чтобы определить их). Так что, пожалуйста, дайте мне несколько советов, как лучше всего организовать разрешения?

Любые мысли очень ценятся

Ответы

Ответ 1

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

https://github.com/ryanb/cancan/wiki/Abilities-in-Database

Если вы действительно, действительно хотите реализовать такую ​​систему самостоятельно. В зависимости от ваших потребностей я предлагаю вам как можно проще реализовать его.

В случае, если вам нужны только пользователи для доступа к модулям (определенные контроллеры). Вы можете сделать:

1) Хранить все разрешения пользователей точно так же, как сериализованные поля → http://apidock.com/rails/ActiveRecord/Base/serialize/class

class User
  serialize :permissions, Array

  def access_to?(module)
    permissions.include? module.to_s
  end
end

Некоторая проверка при установке этого поля будет приятной.

2) Просто сделайте проверку сверху каждого контроллера, если текущий пользователь имеет доступ к этому контроллеру (раздел)

class ApplicationController
   private

   def self.require_access_to(module)
      before_filter do |c|
        unless c.send(:current_user).try :access_to?(module)
          c.send :render_no_presmissions_page
        end
      end
   endposible
end

class AdminNewsController
   require_access_to :news
end

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

Ответ 2

[ РЕДАКТИРОВАТЬ Ссылка, предоставленная @RadoslavStankov, является лучшим ответом.]

Вы можете сделать это с CanCan легко. Просто создайте модель для разрешений (которая has_and_belongs_to_many :users), а в вашем Ability#initialize загрузите разрешения, соответствующие пользователю из модели, и скажите, что пользователь can выполняет их. Затем создайте соответствующий пользовательский интерфейс для администрирования этой модели.

Что-то вроде этого:

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new
    user.permissions.each do |permission|
      can permission.symbol, permission.scope
    end
    user.prohibitions.each do |permission|
      cannot permission.symbol, permission.scope
    end
  end
end

где scope возвращает что-то вроде :all для области nil или Object.const_get(@scope_name) в противном случае... Играйте с ним. Во всяком случае, это выполнимо.

Более сложные вещи CanCan, вероятно, будут более сложными (duh) - например, условные разрешения - но это тоже будет сука для администрирования, поэтому я думаю, этого должно быть достаточно для большинства приложений.