Utilisation de déclarative_authorization pour limiter les résultats dans le modèle
-
28-10-2019 - |
Question
J'utilise la gemme d'autorisation déclarative pour les autorisations dans un projet rails et j'essaie de limiter la sortie du modèle en fonction des autorisations utilisateur.
Mon fichier d'autorisation abrégé ressemble à ceci:
roles do
role :supervisor
has_permission_on :people, :to => :manage_all
end
role :basic_user
has_permission_on :people, :to => :manage_subordinates
end
end
privileges do
privilege :manage_subordinates do
includes :subordinate_records
end
privilege :manage_all do
includes :all_records
end
end
def self.supervised_by(user)
if user.permitted_to? :all_records
#return all of the records
elsif user.permitted_to? :subordinate_records
#return some of the records
else
#return none of the records
end
end
Il semble que cela soit pris en charge à l'aide de l'objet AuthorizationInModel dans la documentation en utilisant with_permissions_to ou allowed_to.Je n'ai pas été en mesure de comprendre comment utiliser ces fonctions sur la base de la documentation ou comment renvoyer une liste des privilèges de l'utilisateur actuel sur le modèle actuel.
Des idées?
La solution
J'ai trouvé une solution alternative en utilisant la méthode if-attribute intégrée. À l'origine, je m'en suis éloigné parce que j'utilisais des modèles sans espace de nom et des contrôleurs et des vues avec un espace de nom. Cette structure est un artefact de la version originale du projet sur lequel je travaille. La plupart de mon travail a été obtenu l'autorisation déclarative pour gérer cette structure.
La principale information qui n'était pas claire pour moi était de savoir comment nommer les autorisations dans un environnement partiellement à espace de noms. Le modèle attendait le nom du modèle (: people), le contrôleur attendait l'espace de noms et le modèle (: staff_people), et les vues ne se souciaient pas tant que vous en choisissiez un. La solution que j'ai choisie était d'utiliser le nom du modèle et de définir explicitement le contexte dans chaque contrôleur. Si le contexte n'est pas défini dans le contrôleur, l'utilisation de filter_access_to ne fonctionne pas, car il rechercherait l'autorisation staff_people plutôt que l'autorisation correcte, people.
Dans le fichier de configuration des autorisations déclaratives, j'accorde des autorisations complètes à l'administration et des autorisations partielles au superviseur. person.supervised renvoie un tableau de lui-même et de toutes les autres personnes supervisées.
roles do
role :administrator
has_permission_on :people, :to => [:create, :read, :update, :delete]
end
role :supervisor
has_permission_on :people do
to => [:create, :read, :update, :delete]
if_attribute :id => is_in { Person.find_by_user_id(user.id).supervised }
end
end
end
Pour accéder à ces informations dans un contrôleur Namespaced, j'utilise filer_resource_access.
module Staff
class PeopleController < ApplicationController
filter_resource_access :context => :people
def index
@people = People.with_permissions_to(:read)
end
J'ai trouvé cela en utilisant
filter_access_to :all, :with_attribute => true
ne fonctionnait pas pour les méthodes qui doivent utiliser with_permissions_to et une autorisation if_attribute. Je ne sais pas pourquoi c'était un problème
Il est toujours nécessaire d'utiliser filter_access_to pour les actions de contrôleur non standard qui n'incluent pas d'identifiant récupérant un seul enregistrement dans le cadre des arguments. Par exemple, si une action appelée part_timers renvoie une liste de personnes, cette solution semble qu'elle devrait fonctionner:
filter_resource_access :context => :people, :additional_member => { :part_timers => :read }
La bonne solution est de garder le filter_resource_access tel quel et d'ajouter un filter_access_to pour cette action
filter_resource_access :context => :people
fitler_access_to :part_timers, :required => :read, :context => people
Autres conseils
Il y a peut-être une meilleure façon de faire cela, mais cela devrait fonctionner pour votre méthode supervised_by
si tout le reste est correctement configuré.
def self.supervised_by(user)
if Person.new.permitted_to? :all_records, :user=>user
#return all of the records
elsif Person.new.permitted_to? :subordinate_records, :user=>user
#return some of the records
else
#return none of the records
end
end