문제

역할/권한 기반 찾기를 구축하는 깔끔한 방법을 구축하는 가장 좋은 방법을 찾고 있습니까?

내 모델 스키마에서는 user 관리자, 지역 관리자, 영업 보조원과 같은 여러 (관리자가 정의한) 역할 중 하나를 가질 수 있습니다.

지역 관리자 역할을 갖고 지역 A에 가입한 사용자가 있는 경우, 그녀가 볼 수 있는 다른 사용자가 무엇인지 쿼리할 수 있기를 원합니다. 예:

regional_manager_for_region_a.users 
  => [...] # Array of users joined to region a

regional_manager_for_region_b.users(:all, conditions => { :active => true })
  => [...] # Array of active users joined to region b

administrator.users
  => [...] # Array of all users in system

감사합니다. 도움을 주시면 대단히 감사하겠습니다!

도움이 되었습니까?

해결책

내 생각에는 인증 메커니즘을 마련해야 할 것 같습니다.

내가 아는 최고의 보석은 다음과 같습니다. 선언적 승인.개인적으로 프로덕션 환경에서 사용해본 결과 만족스럽습니다.거기에 레일캐스트 그것에 대해서도요.

아이디어는 하나의 특정 파일(config/authorization_rules.rb) "역할 및 권한"."관리자는 연결된 클라이언트만 읽을 수 있습니다" 또는 "관리자는 모든 사용자를 읽고 쓸 수 있습니다"와 같은 말을 합니다.귀하의 경우 다음과 같습니다.

authorization do

  role :guest do
    # actions here can be done by everyone, even not logged in people
  end

  role :user do
    includes :guest
    # actions here can be done by logged people
  end

  role :manager do
    includes :user #managers do everything users do, plus:

    has_permission_on :sales_region, :to => :read do
      if_attribute :id => is_in {user.sales_region_ids}
    end

    has_permission_on :users, :to => [:update, :read] do
      if_attribute :id => is {user.user_ids_by_sales_region} #defined on the model
    end
  end

  role :admin do
    includes :user
    has_permission_on [:sales_regions, :users], :to :manage
  end

end

privileges do
  privilege :manage do
    includes :create, :read, :update, :delete
  end
end

이것이 지정되면 모델을 수정하여 다음을 사용하게 됩니다. declarative_authorization.또한 user_ids_by_sales_region 방법

class User < ActiveRecord::Base

  using_access_control # this enables DA

  def users_by_sales_region
    sales_regions.collect{ |sr| sr.users }.flatten.uniq
  end

  def user_ids_by_sales_region
    users_by_sales_region.collect{ |u| u.id }
  end
end

당신은 또한 current_user 방법 및 현재 사용자의 역할을 가져오는 방법이 있습니다."플러그인 요구 사항 제공" 섹션을 참조하세요. 읽어보기.

그러면 당신은 당신이 원하는 것을 할 수 있습니다 with_permissions_to :

manager = User.find(...)
manager.users.with_permissions_to(:read) # the users from his region
manager.users.with_permissions_to(:read).find(:all, conditions => { :active => true })
manager.users.with_permissions_to(:write) #returns no users, managers can't edit them

admin = User.find(...)
admin.users.with_permissions_to(:write) #will return all users

이는 처음에는 약간의 노력이 필요하지만 나중에는 응용 프로그램이 크게 단순화된다는 의미입니다.또한 현재 사용자의 권한에 따라 뷰의 일부를 숨기거나 표시하고 특정 컨트롤러 작업에 대한 액세스를 금지하는 등의 추가 기능도 있습니다.

또한 페이지 매김 등에서도 잘 작동합니다.

이라는 또 다른 선언적 인증 gem이 있습니다. 캉캉.나는 이것에 대한 경험이 없지만 Ryan Bates가 이 작업을 수행했다면 분명 좋을 것입니다. 레일캐스트 그것을 위해서도 마찬가지입니다).그러나 나는 그것이 지금 필요한 것처럼 보이는 모델 확장을 허용한다고 생각하지 않습니다.

다른 팁

아래 내 대답은 간단한 찾기에 적합합니다.그러나 유연성이 부족하고 다음과 호환되지 않습니다. will_paginate 플러그인.사용자 범위를 명확하게 지정하는 더 좋은 방법을 아는 사람이 있습니까? @current_user 관리할 수 있나요?

감사해요


아래와 같이 기본 연결 확장을 재정의하여 내 질문에 대답했습니다.그래도 의견이나 대안을 아는 것이 좋습니다!

class User < ActiveRecord::Base
  has_many :users do
    def find(*args)
      scope = args.first || :all
      options = args.extract_options!

      return User.find(args.first, options) if proxy_owner.admin?

      users = []
      proxy_owner.sales_regions.collect do |sales_region|
        users += sales_region.users
      end

      users.uniq
    end
  end
end

egarcia의 답변에 대한 내 의견을 따르기 위해 결국 다음과 같이 선언하기로 결정했습니다. named_scopes 제한된 모델에 대해.예를 들어:

# app/models/account.rb
class Account < ActiveRecord::Base
  named_scope :visible_to, lambda { |user| 
    return {} if user.can_see_all_accounts?
    { :conditions => ['sales_area_id IN (?)', user.sales_area_ids] } 
  }
end

# app/controllers/accounts_controller.rb
class AccountsController < ApplicationController
  def index
    @accounts = Account.visible_to(@current_user)
    ...
  end
end
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top