2011-03-18 24 views
5

El mantenimiento de una aplicación Rails v2.3.8 desplegado en Apache con mod_passengerrieles: el acceso. Sesión del usuario actual en un modelo (

Necesito acceso a la sesión del usuario actual en una de las modelos (un observador Auditor para ser exactos) Sé que esto rompe el principio de MVC. Pero tengo que violarlo ya que tengo un observador que necesita conocer al usuario que está conectado actualmente. Tengo muchos controladores y realizar la llamada al registrador de Auditor no sería muy SECO.

Estoy tratando de poder llamar a User.current con la sesión de usuario registrada actualmente. Sin embargo, he encontrado un problema con el almacenamiento en caché/thread-safety. El autor original usó una variable de clase (@@ actual) para almacenar el usuario actual. Pero esto no es seguro para subprocesos, así que lo convertí en este

class User < AR:Base 
    ... 
    def self.current 
    Thread.current[:user] 
    end 

    def self.current=(user) 
    Thread.current[:user] = user 
    end 
    ... 
end 

Por lo tanto, debe ser seguro para subprocesos. Y en Auditor observer tengo una llamada:

Auditor(subject, action, object) 

Donde paso en Usuario.corriente como asunto.

Este código funciona muy bien en el desarrollo, pero en las producciones obtengo valores incorrectos de User.current. A veces obtengo otro registro de usuario conectado y no el actual. Por lo tanto, existe un problema de seguridad de subprocesos/caché de clases que todavía existe, pero no puedo encontrar la manera de solucionarlo.

¿Alguna sugerencia? Gracias

Respuesta

3

ActiveRecord y ActionPack son completamente diferentes, por lo que no tiene acceso a la sesión/cookies en los modelos. Si necesita el usuario actual, tiene dos opciones.

Opción 1 - Pasar el usuario actual al modelo

En su controlador:

def index 
    Audit.get_current_user(current_user) 
    #where audit is your model that you will send the current_user to 
end 

Opción 2 - Disponer de un modelo de usuario que realiza la acción después de un objeto de usuario se modifica.

En su modelo de usuario:

before_save :adjust_user 

def adjust_user 
    #self will be the object that was just modified aka the current user 
end 
+0

Por eso creé el método getter/setter corriente que son seguros para subprocesos, sí permite a mí para almacenar/obtenga usuario actual. El problema surge cuando las llamadas al User.corrent se almacenan en caché (creo). – Swartz

+0

Para la opción 1: puedo pasar el usuario_actual del método del controlador directamente, no estoy seguro de por qué necesito get_current_user(). Pero específicamente deseo evitar tener muchas llamadas a Auditor() desde los controladores, ya que hay muchos lugares que requieren este tipo de llamada. Observer trabaja mucho más limpiamente. – Swartz

+0

Para la opción 2: No te estoy siguiendo ... Objeto de usuario no es lo único que se modifica. Tengo varios objetos que el usuario que ha iniciado sesión puede modificar (como Política, Permiso, etc.). Piense en Auditor como un registrador de alimentación de actividad. Los usuarios pueden tener políticas, permisos, etc. de CRUD. De modo que aún tengo que pasar el usuario actual al modelo de Auditor. – Swartz

Cuestiones relacionadas