2012-01-18 9 views
7

He consultado declarative_authorization, CanCan y CanTango. Todos son buenos para agregar autorización a la aplicación, pero me preguntaba cómo se puede agregar una autorización a una instancia específica de un modelo, es decir, una persona puede tener acceso de administración en un proyecto y solo limitado (leer menos que administrar: actualización limitada, etc.) en otro.Autorización en Rails 3.1: CanCan, CanTango, declarative_authorization?

¿Podría por favor una mejor manera? Disculpas si mi pregunta suena demasiado trivial. Podría ser porque soy nuevo en RoR.

gracias, John

+0

En CanCan puedes definir habilidades a través de bloques con condiciones - https://github.com/ryanb/cancan/wiki/Defining-Abilities-with-Blocks. –

+0

1. TeamMembers tiene muchos usuarios, Roles 2. Los equipos tienen muchos TeamMembers 3. El proyecto tiene un equipo ... Con Blocks, la configuración anterior no proporciona un medio para filtrar una instancia específica de proyecto. Si crees que se puede hacer ... ¿Podrías darme un ejemplo? Gracias por adelantado. –

Respuesta

4

Como sé CanCan y declarative_authorization, e implementé autorizaciones basadas en roles tanto, recomiendo CanCan. Solo mis dos centavos.

Ejemplo (no probado, por desgracia no puedo probar aquí y no tengo acceso a mi código)

Así que vamos a decir que tenemos una estructura como esta:

class User < ActiveRecord::Base 
    belongs_to :role 
end 

class Role < ActiveRecord::Base 
    has_many :users 

    # attributes: project_read, project_create, project_update 
end 

Entonces, CanCan podía mirar de esta manera:

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    @user = user 
    @role = user.role 

    # user can see a project if he has project_read => true in his role 
    can :read, Project if role.project_read? 

    # same, but with create 
    can :create, Project if role.project_create? 

    # can do everything with projects if he is an admin 
    can :manage, Project if user.admin? 
    end 

end 

Puede encontrar toda la información que necesita en la wiki de CanCan en github. Recomendación personal para leer:

Básicamente sólo tiene que extender el ejemplo anterior para incluir sus funciones a través de sus relaciones. Para hacerlo simple, también puede crear métodos de ayuda adicionales en ability.rb.

La principal deficiencia media se podría caer por (al menos yo): Asegúrese de que el usuario puede hacer algo con un modelo antes de definir lo que el usuario no puede . De lo contrario, te sentirás frustrado y pensarás "¿pero por qué? Nunca escribí que el usuario no pueda". Sí. Pero también nunca escribió explícitamente que él puede ...

+0

He implementado cancan ... pero no entiendo cómo definir/restringir usuario para una instancia específica (por ejemplo, proyecto). Cualquier p. Ej. sería realmente útil. Existe una conexión indirecta entre el usuario y el proyecto ... 1. TeamMembers tiene muchos usuarios 2. Los equipos tienen muchos miembros del equipo 3. El proyecto tiene un equipo –

+0

actualizado con un ejemplo. – pduersteler

+0

¿necesito instalar cancan Y crear un modelo a seguir? No veo en la documentación de Cancan que sea necesaria. Puede usted explicar esto? gracias –

0
class User < ActiveRecord::Base 

    belongs_to :role 
    delegate :permissions, :to => :role 

    def method_missing(method_id, *args) 
    if match = matches_dynamic_role_check?(method_id) 
     tokenize_roles(match.captures.first).each do |check| 
     return true if role.name.downcase == check 
     end 
     return false 
    elsif match = matches_dynamic_perm_check?(method_id) 
     return true if permissions.find_by_name(match.captures.first) 
    else 
     super 
    end 
    end 


    private 

    def matches_dynamic_perm_check?(method_id) 
    /^can_([a-zA-Z]\w*)\?$/.match(method_id.to_s) 
    end 

    def matches_dynamic_role_check?(method_id) 
    /^is_an?_([a-zA-Z]\w*)\?$/.match(method_id.to_s) 
    end 

    def tokenize_roles(string_to_split) 
    string_to_split.split(/_or_/) 
    end 

end 

Uso:

user.is_an? admin

user.can_delete?