2011-06-29 12 views
5

Estoy construyendo una pista de auditoría que necesita saber qué usuario está realizando actualmente la solicitud. Mi pista de auditoría está construida usando ActiveSupport :: Notifications para recibir un par que necesita ser auditado.¿Cómo acceder a current_user desde una notificación de Rails?

Lo que me gustaría hacer es usar ActiveSupport :: Concern para encapsular la lógica para mis necesidades de auditoría, de modo que pueda agregar fácilmente la auditoría a cualquier modelo en mi sistema.

En general, esto es fácil de hacer. Yo incluso blogged about it a while back. Sin embargo, me está resultando difícil descifrar cómo hacer que el usuario actual que realiza la solicitud al servidor web me permita registrar quién está haciendo los cambios en mi pista de auditoría.

Sé que hay un montón de preguntas sobre "cómo obtengo current_user en mi modelo", pero no estoy preguntando sobre hacerlo en un modelo, así que espero que haya un mejor conjunto de respuestas. Como mi código de auditoría está relacionado con la infraestructura, espero que haya alguna manera de aprovechar la solicitud actual que se está procesando, o alguna otra cosa que definitivamente me diga quién está actualmente conectado/realizando la solicitud.

He leído muchas "respuestas" que dicen que debo usar el almacenamiento de subprocesos y poner el usuario_actual allí. No me gusta esta respuesta por muchas de las razones que otros no tienen, no hay garantía de que el almacenamiento de subprocesos sea seguro. podría sangrar en varias solicitudes si el servidor usa el mismo hilo para procesar solicitudes múltiples, etc.

así que ... dado que no estoy tratando de acceder a current_user desde mi modelo, sino desde ActiveSupport :: Concern o suscripción al evento ActiveSupport :: Notifications, ¿hay alguna buena opción para mí para saber quién es el usuario actual?

actualización

estoy usando diseñar para la autenticación, que utiliza Warden en la parte final. idear recupera el usuario_actual llamando al request.env['warden'].authenticate(:scope => :user) (asumiendo que utilizo un modelo de "Usuario" para la autenticación).

¿Hay alguna manera de acceder al objeto actual request desde mi solicitud o suscripción de notificación? De vuelta en mis días .NET, habría podido llamar al HttpContext.Current.Request y todo estaría bien. ¿Cuál es el equivalente en Rails?

+0

gracias por el link fix. :) estaba a punto de hacer eso ¡y vi que te habías ocupado de eso! –

+0

¿Encontró una solución para esto? Si lo hizo, por favor escriba al respecto. Gracias. – Shreyas

Respuesta

-1

Ya tiene la respuesta, lo que está haciendo es lo mismo que cuando las personas acceden a la solicitud en los modelos. El usuario_actual es solo un método definido en su ApplicationController. Cuando no estás en un controlador u otra clase que hereda de él, no puedes acceder a ese método.

HttpContext.Current.Request < < Apostaría mucho que esto utiliza el almacenamiento de subprocesos. Cualquier otra solución que encontremos también será un almacenamiento de subprocesos en algún nivel u otro.

Ya sea que extraiga lo que necesita de la solicitud en el controlador y lo transfiera como parámetros, o use el almacenamiento de subprocesos, pero esto es inherentemente peligroso de todos modos. ¿Qué sucede si comienza a usar un trabajo retrasado para hacer las notificaciones o algo?

+0

Resulta que esto es posible, usando la funcionalidad explícita de los rieles, sin necesidad de almacenamiento local de subprocesos, usando 'append_info_to_payload' – cluesque

0

Rails 'ActionController::Instrumentation tiene un soporte explícito para esto, usando append_info_to_payload.

añadir un método para su ApplicationController:

def append_info_to_payload(payload) 
    super 
    payload[:current_user_id] = current_user.try(&:id) 
end 

ahora, cuando el observador está llamado de nuevo, la información estará en el event.payload:

ActiveSupport::Notifications.subscribe /process_action.action_controller/ do |*args| 
    event = ActiveSupport::Notifications::Event.new(*args) 
    current_user_id = event.payload[:current_user_id] 
    # do something interesting with current_user_id here 
end 
Cuestiones relacionadas