Boire ou coder ... Pourquoi choisir?
Publié le 18 octobre 2009 22:00

Rails et ACL

Avec rails comme avec tout framework, vous allez rapidement avoir besoin de gérer l'identification des utilisateurs et leurs autorisations. Pour leur identification, il existe divers plugins. Notamment Restful Authentication, AuthLogic et (mon préféré) Clearance. Pour la gestion des autorisations, je vais vous parler de ACL9.

L'idée est simple. Après avoir identifié votre utilisateur, vous avez accès à un objet current_user, qui contient l'objet relatif à l'utilisateur actif (généralement une instance du model User. Mais cela peut être n'importe quoi). ACL9 va ajouter deux tables : - Role, qui contiendra tous les rôles utilisateurs existants. Un peu comme des groupes. Chaque rôle pouvant être associé à une instance d'un objet. Vous pourrez ainsi avoir un rôle "admin", global, qui permettra de définir les accès de l'administrateur. Et un rôle "éditeur", relatif uniquement à l'objet ayant pour id "1" du modèle "News".

- UserRole, qui fera la relation entre un rôle et un utilisateur (has_and_belongs_to_many).

Voici les migrations nécessaires pour ces deux tables :

create_table :roles, :force => true do |t|
    t.column   :name,                            :string,                    :limit => 40
    t.column      :authorizable_type",      :string,                    :limit => 40
    t.column      :authorizable_id,           :integer
    t.timestamps
end

create_table :roles_users", :id => false, :force => true do |t|
    t.column :user_id,                          :integer
    t.integer  :role_id,                           :integer
    t.timestamps
end

Vous devez bien évidemment créer un modèle "Role", qui représentera cette table. Il est inutile de créer un modèle RolesUser. Cela sera géré automatiquement par Rails.

class Role < ActiveRecord::Base
    acts_as_authorization_role
end

Vous noterez l'ajout de "acts_as_authorization_role", qui va implémenter les méthodes de rôles relatives à ACL9. Dans notre table user, nous allons également devoir ajouter un appel à une méthode spécifique de ACL9 afin d'ajouter les méthodes relatives à l'utilisateur.

class User < ActiveRecord::Base
    acts_as_authorization_subject
end

Et dans tous les modèles ou nous désirons avoir une gestion des droits d'accès, nous allons ajouter :

class Foo < ActiveRecord::Base
    acts_as_authorization_object
end

ACL9 vous a maintenant ajouté diveres méthodes dans vos objets : Dans votre modèle utilisateur :

  • has_role?(role, object = nil) - Retournera "true" si l'utilisateur a le rôle demandé en global ou sur l'objet précisé.
  • has_role!(role, object = nil) - Donnera le rôle nommé à l'utilisateur
  • has_no_role!(role, object = nil) - Supprimera le rôle nommé pour l'utilisateur
  • has_roles_for?(object) - Retourne true si l'utilisateur a un quelconque rôle sur l'objet
  • has_role_for?(object) - Alias de has_roles_for?
  • roles_for(object) - Retourne tous les rôles de l'utilisateur pour cet objet
  • has_no_roles_for!(object) - Supprime tous les rôles de l'utilisateur pour l'objet
  • has_no_roles! - Supprime tous les rôles de l'utilisateur

Et dans chacun de vos modèles objets (Foo plus haut) :

  • accepts_role?(role, subject) - Retourne true si subject a accès au rôle courant
  • accepts_role!(role, subject) - Donne accès à subject au rôle courant
  • accepts_no_role!(role, subject) - Supprime l'accès utilisateur au rôle
  • accepts_roles_by?(subject) - Retourne true si l'utilisateur a un rôle quelconque sur l'objet
  • accepts_role_by?(subject) - Alias de accepts_roles_by?
  • accepted_roles_by(subject) - Retourne tous les utilisateurs ayant un rôle pour cet objet

Maintenant que nous avons implémenté nos autorisations et que nous avons vu les diverses méthodes pour les utiliser, limitons les accès à nos actions !

class MyOwnController < ApplicationController
    access_control do
        # Autorise tous les utilisateurs ayant le rôle "superadmin" à accéder à l'objet
        allow :superadmin</p>

<p>        # Autorise tous les utilisateurs ayant le rôle "creator" sur @news
        allow :creator, :at => :news</p>

<p>        # Autorise les utilisateurs anonymes et ceux qui sont enregistrés sur la page d'accueil
        # Et refuse les utilisateurs ayant le rôle "banned"
        action :index do
            allow anonymous, logged_in
            deny :banned
        end</p>

<p>        # Autorise les utilisateurs ayant le rôle "manager" sur l'objet @news. Sauf pour l'action "destroy"
        allow :manager, :at => :news, :except => [:destroy]
    end</p>

<p>    def index
        @news = News.find_by_id params[:id]
        # Le code relatif à l'action "index"
    end
end

Du coup on peut maintenant gérer de manière particulièrement avancée les rôles dans notre application.

Commentaires

foohey
foohey dit: 18 novembre 2009 23:00 Site web

je cherchais un plugin pour la gestion des utilisateurs avec authlogic. ACL9 est très bon pour ça. merci pour ces explications.

J'ajoute aussi un petit bout de code utile pour l'erreur « Acl9::AccessDenied »

class ApplicationController :access_denied

# ...other stuff... private

def access_denied

if current_user
  render :template =&gt; 'home/access_denied'
else
  flash[:notice] = 'Access denied. Try to log in first.'
  redirect_to login_path
end

end end

Postez un commentaire

Markdown activé