Определение способностей в более сложной среде с помощью ролевых и групповых моделей - PullRequest
1 голос
/ 20 августа 2011

в моем приложении rails (я использую devise и cancan) каждый (зарегистрированный) пользователь принадлежит ровно одной роли («Администратор» или «Пользователи»), но как минимум одна группа (что-то вроде «Семья», «Друзья», «Сотрудники»).Во время выполнения, когда создается новая папка (см. Ниже), может быть установлено отношение habtm к одной или нескольким группам, которое определяет, кто может получить доступ к папке.Выбор группы no вообще должен привести к общедоступной папке (т.е. пользователям не нужно входить в систему для доступа к этим папкам).Но сейчас я пока не знаю, как определить такие общедоступные папки в моем файлеility.rb, потому что я не знаю, как определить «может читать папки, с которыми не связаны группы».

Соответствующий фрагмент моего app/models/ability.rb выглядит следующим образом:

user ||= User.new
if user.role? :Administrator
  can :manage, :all
elsif user.role? :Users
  # user should only be able to read folders, whose associated groups they are member of
  can :read, Folder, :groups => { :id => user.group_ids }
else
  # here goes the world-wide-accessible-folders part, I guess
  # but I don't know how to define it:
  ## can :read, Folder, :groups => { 0 } ???
end

Соответствующий фрагмент моего app/controllers/folders_controller.rb выглядит следующим образом:

class FoldersController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource

Может кто-нибудь дать мненамек?

1 Ответ

4 голосов
/ 20 августа 2011

У меня была такая же проблема только на днях.Я разобрался с решением после прочтения Readme CanCan, что вы должны сделать, если вы еще не сделали.

Вы можете просмотреть мое решение здесь: Контекстно-зависимая авторизация с использованием CanCan

Чтобы получить ответ, более конкретный для вашего варианта использования, выполните следующие действия:

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

class ApplicationController < ActionController::Base
  check_authorization

  def current_ability
    if <no group selected logic> # Maybe: params[:controller] == 'groups'
      @current_ability = NoGroupSelectedAbility.new(current_user)
    else
      @current_ability = GroupSelectedAbility.new(current_user)
    end
  end

  # Application Controller Logic Below
end

Затем вам нужно будет создать новую способность (или способности) в вашей папке app / models /.Вы также можете делать классные вещи, как это:

if request.path_parameters[:controller] == groups
  @current_ability = GroupsAbility.new(current_group_relation)
end 

Где current_group_relation определяется в app / controllers / groups_controller.rb.Это даст вам определенные способности для конкретных контроллеров.Помните, что родительские классы могут вызывать методы в дочерних классах в Ruby.Вы можете определить метод в вашем контроллере и вызывать его из ApplicationController, если вы уверены, какой контроллер используется в настоящее время для обработки запроса.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ: Я хотел показать вам, как выглядит пользовательские способности.

# File path: app/models/group_ability.rb
class GroupsAbility
  include CanCan::Ability

  # This can take in whatever you want, you decide what to argument to 
  # use in your Application Controller
  def initialize(group_relation)
    group_relation ||= GroupRelation.new

    if group_relation.id.nil?
      # User does not have a relation to a group
      can :read, all
    elsif group_relation.moderator?
      # Allow a mod to manage all group relations associated with the mod's group.
      can :manage, :all, :id => group_relation.group.id
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...