1

I'm looking for a good solution to log DB changes in a web application developed using Play/Scala/ReactiveMongo. I need to know who changed what.

I have a separate layer namely Services in which all data access and business logics happens. All saves/updates/removes are done by certain methods so I can log them safely in just 3 or 4 methods but I need user identity there.

I don't have access to current user in services! There is no global HttpContext or Request or something like that which let me get the user identity (I think this way of getting user identity was incorrect of course).

I have a solution:

Add an implicit parameter to all methods of services which have side effects (change DB) and pass user identity to them.

def save(model: A)(implicit userIdentity: Option[UserIndentity] = None) = { ... }

As I wrapped default request, it can extend UserIdentity trait so that the implicit request matches the implicit parameters.

class MyRequest[A](...) extends WrappedRequest[A](request) extends UserIdentity

Finally, actions can use services like this:

def index() = MyAction { implicit request =>
    //...
    defaultService.save(model)
    //...
}

The bad thing is that I have to add implicit parameters to those service methods. Isn't there another solution to get current user without polluting method signatures.

Amir Karimi
  • 5,401
  • 4
  • 32
  • 51
  • You could use a thread-local variable, maybe by taking advantage of `scala.util.DynamicVariable`, but that will only work if everything is done in the same thread (no `Future`, etc.), and it is almost as evil as a global. – wingedsubmariner Apr 26 '14 at 03:44
  • My application is fully async so I can't use thread-local solution. – Amir Karimi Apr 26 '14 at 04:37

1 Answers1

0

What's the problem with simply adding UserIdentity as an argument to your functions? Knowing who the user is seems to be important for your business logic - after all, today you want to log who performed the operation, tomorrow you will want to make sure this particular user is allowed to do it.

And I would just use a real UserIdentity object, not some hack with WrappedRequest, your services don't need to mess with a WrappedRequest instance.

vptheron
  • 7,426
  • 25
  • 34