سؤال

أنا أبحث عن أفضل طريقة لبناء نظيفة وسيلة لبناء دور/authorisaton على أساس المكتشفون?

في نموذج مخطط ، user يمكن أن يكون واحدا من عدة (المحدد من قبل المشرف) أدوار ، مثل مدير المدير الإقليمي للمبيعات مساعد:

على سبيل المثال إعطاء المستخدم مع المدير الإقليمي دور انضم إلى المنطقة ، أود أن تكون قادرة على استعلام ما المستخدمين الآخرين أنها يمكن أن نرى ، هـ.g:

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

شكرا يا نقدر أي مساعدة!

هل كانت مفيدة؟

المحلول

أعتقد أنك بحاجة إلى وضع بعض تفويض الآلية.

أفضل الأحجار الكريمة أنا أعرف هذا declarative_authorization.أنا شخصيا قد استخدمت على بيئة الإنتاج ، وأنا راض عن ذلك.هناك railscast عن ذلك أيضا.

الفكرة هي أنك تعلن في ملف معين (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

وهذا يعني قليلا من الجهد في البداية ، ولكن يبسط التطبيق إلى حد كبير في وقت لاحق.أيضا لديك وظائف إضافية ، مثل إخفاء/إظهار أجزاء من الآراء اعتمادا على أذونات المستخدم الحالي ، وكذلك منع وصول محددة تحكم الإجراءات.

أيضا, يجب أن تعمل على ما يرام مع paginations ، إلخ.

هناك آخر التعريفي إذن جوهرة تسمى كانكان.ليس لدي تجربة مع هذا واحد ، ولكن إذا كان يتم عن طريق ريان بيتس ، يجب أن تكون جيدة (لديه railscast من أجل ذلك أيضا).ومع ذلك لا أظن أنه يسمح نموذج امتداد ، وهو ما يبدو أنك بحاجة الآن.

نصائح أخرى

جوابي هو أقل غرامة بسيطة المكتشفون;ومع ذلك, أنها ليست مرنة جدا و ليس متوافق مع 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