Question

Je recherche le meilleur moyen de créer un moyen propre de créer des outils de recherche basés sur le rôle / l’autorité?

Dans mon schéma de modèle, un utilisateur peut avoir un ou plusieurs rôles (définis par l'administrateur), tels que Administrateur, Gestionnaire régional, Assistant commercial:

Exemple Dans le cas d'un utilisateur doté d'un rôle de responsable régional et associé à une région A, j'aimerais pouvoir interroger les autres utilisateurs qu'elle pourrait voir, par exemple:

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

Merci d'apprécier grandement toute aide!

Était-ce utile?

La solution

Je pense que vous devez mettre en place un mécanisme d'autorisation.

Le meilleur bijou que je connaisse à cet égard est déclarative_authorization . Je l'ai personnellement utilisé dans un environnement de production et j'en suis satisfait. Il existe un railscast à ce sujet.

L'idée est que vous déclariez dans un fichier spécifique ( config / autorisation_rules.rb ) les "rôles et autorisations". Vous dites des choses comme "un responsable ne peut lire que les clients qui lui sont associés". ou "un administrateur peut lire et écrire tous les utilisateurs". Dans votre cas, cela ressemblerait à ceci:

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

Une fois que cela est spécifié, vous avez modifié vos modèles afin qu'ils utilisent declarative_authorization . Définissons également la méthode 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

Vous devez également avoir une méthode current_user et un moyen d'obtenir le (s) rôle (s) de l'utilisateur actuel. Reportez-vous à la section "Fournir les conditions requises pour le plug-in". section du fichier Lisez-moi .

Vous pouvez ensuite faire ce que vous voulez avec 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

Cela demande un peu d’effort au début, mais simplifie grandement l’application par la suite. Vous disposez également de fonctionnalités supplémentaires, telles que le masquage / l'affichage de parties de vues en fonction des autorisations dont dispose l'utilisateur actuel, ainsi que l'interdiction d'accès à certaines actions du contrôleur.

De plus, cela devrait fonctionner parfaitement avec les paginations, etc.

Il existe un autre joyau d'autorisation déclarative appelé cancan . Je n'ai pas d'expérience avec celui-ci, mais si c'est fait par Ryan Bates, ça doit être bon (il a un railscast ). Cependant, je ne pense pas que cela permette des extensions de modèle, ce dont vous semblez avoir besoin maintenant.

Autres conseils

Ma réponse ci-dessous convient aux chercheurs simples. Cependant, il n'est pas très flexible et n'est pas compatible avec le plugin will_paginate . Est-ce que quelqu'un connaît un meilleur moyen de gérer proprement les utilisateurs que @ utilisateur_current est capable de gérer?

Merci

Je viens de répondre à ma propre question, en remplaçant l'extension d'association par défaut comme ci-dessous. Ce serait quand même bien de connaître les commentaires ou les alternatives!

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

Juste pour faire suite à mon commentaire sur la réponse de egarcia, j’ai finalement décidé de déclarer named_scopes sur les modèles restreints. Par exemple:

# 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top