10

Estoy trabajando en la aplicación Rails 3.2 donde uso Devise para la autenticación. Decidí probar la herencia de tabla única para administrar roles de usuario, pero rápidamente encontré un problema. Actualmente tengo tres modelos de usuario, User < ActiveRecord, Admin < User y Collaborator < User. El administrador y el colaborador comparten la mayoría de las columnas de usuario, pero tienen comportamientos y privilegios ligeramente diferentes. Mis modelos actualmente se ve así:¿Cómo manejo la autenticación con Devise cuando uso múltiples modelos en la aplicación Rails 3.2

class User < ActiveRecord::Base 

    devise :database_authenticatable, :registerable, 
    :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :name, :password, :password_confirmation, :remember_me 

    before_save :ensure_authentication_token 

    [...] 

end 

class Admin < User 
    has_one :account, dependent: :destroy 
    attr_accessible :account_attributes 
    accepts_nested_attributes_for :account 
end 


class Collaborator < User 
    has_one :account 
end 

class Account < ActiveRecord::Base 
    attr_accessible :name 
    validates_presence_of :name 
    has_many :projects, dependent: :destroy 
    has_many :users 
end 

Los aries problema cuando intento para autenticar Administradores y Colaboradores en mi ProjectController (y otros controladores donde necesito autenticación):

# Causes problem, no one can access anything. 
before_filter :authenticate_admin! 
before_filter :authenticate_collaborator! 

Un problema similar que tenía fue con los métodos de ayuda del inventor para ie. current_user, ahora he current_admin y current_collaborator, I "resuelto" que mediante la creación de un antes filtro y método:

def set_current_user 
    @current_user = current_admin || current_collaborator 
end 

¿Existe una solución similar o simple para mi problema de autenticación con Idear, o tendría que recomendar otro enfoque que Herencia de tabla única, y ¿qué sería eso?

Mi objetivo es, 1. cuando los nuevos usuarios se registren, se convierten en administradores, cuando crean su cuenta, también se crea un modelo de cuenta. 2. El nuevo usuario (Administrador) puede invitar a usuarios adicionales a la Cuenta, que será Colaboradores. 3. Los administradores y colaboradores deben tener diferentes privilegios. Los colaboradores no crearán nuevas "Cuentas" cuando se registren (la compañía podría ser un mejor nombre para mi modelo de Cuenta), por lo que los Administradores y Colaboradores necesitarán formularios ligeramente diferentes para registrarse y editar.

Gracias.

actualización

yo un poco "resuelto" mediante la creación de una similar antes filtro:

def authenticate! 
    if @current_user == current_admin 
    :authenticate_admin! 
    elsif @current_user == current_collaborator 
    :authenticate_collaborator! 
    end 
end 

sugerencias sobre soluciones posiblemente más elegantes todavía sería apreciada.

+0

tener la oportunidad de probar mi respuesta? – blnc

Respuesta

1

Puede separar toda la lógica común del módulo y usar solo la misma tabla.

module UserMethods 
    #... 
end 

class User < ActiveRecord::Base 
    include UserMethods 
    devise ... 

end 

class Admin < ActiveRecord::Base 
    include UserMethods 
    self.table_name = "users" 
    devise ... 
end 

y configurar todos los modelo legado por separado en rutas, puntos de vista (si es necesario, consulte Configuring Views). En este caso, puede procesar fácilmente toda lógica diferente.

+0

Mm, gracias. Parece que eso funcionaría. Sin embargo, ¿cómo es esta solución mejor que mi solución actual? Perdón por mi nueva pregunta. Aquí viene otro. Estoy pensando en cambiar mi lógica un poco, y permitir que los usuarios tengan muchas cuentas, ya sean Administradores o Colaboradores para cada cuenta, una relación de muchos a muchos entre Usuario y Cuenta, ¿cómo podría lograr eso con su solución o la de la mina? y todavía tienen diferentes roles? ¡Gracias! – Anders

+0

En lugar de incluir el módulo, puede extraer toda la lógica del modelo común, por ejemplo, Usuario Base, coloque aquí todas las relaciones. Pero todas las diferentes lógicas, relacionadas con el diseño o los atributos, puede colocar para separar el modelo. Es decir. parece que tu y mi enfoque deberían combinarse. No me gustan las condiciones 'si' en los métodos, ya que no es el estilo OOP. – gayavat

3

No estoy seguro si esto todavía se necesita una solución a este ...

Una forma más elegante de tener los dobles autenticaciones podría ser hacer lo siguiente:

private 

def authenticate! 
    :authenticate_admin! || :authenticate_collaborator! 
    @current_user = admin_signed_in? ? current_admin : current_collaborator 
end 

luego llamar a before_filter: autenticar !

Si no necesita una variable universal '@current_user', simplemente omita la segunda línea.

Espero que esto ayude.

+0

Esta solución no funciona porque authenticate_admin redirigirá si falla ... alguna idea? No puedo hacer que funcione – Rafal

+0

tienes razón, en las versiones más nuevas esto ya no funciona. Veré si puedo encontrar un trabajo alternativo. – blnc

+0

He agregado una respuesta con mi solución – Rafal

5

usted puede solucionar esto usando la siguiente solución

 
def authenticate! 
    if modelA_user_signed_in? 
     @current_user = current_modelA 
     true 
    else 
     authenticate_modelB! 
    end 

    end 
Cuestiones relacionadas