The Security object provided by Play 2.0 out of the box and somehow the Secured one provided by the TypeSafe's plugin util.
The idea here is to leverage the actual functionality wich only enables to provide one Option[String] as result.
What I wanted at first is to satisfy my use case, which is : a lot of actions are secured and I need a username and its id. Where id is an Int.
Here we are, the actual Security and Secured don't permit me to have several extracted values, or to have an Int.
That's why I created this project : https://github.com/andypetrella/steal-play2.
The idea is to enable any actions to be preceded by some interceptors that are stealing values either from the request, the cache, the database (or...) and set them as the parameters of a closure that outputs an Action.
But we must also care of the cases when something went wrong during the stealing.
This trait is the core of the solution, it defines:
- the stealing operation: a function that takes (currently) the request and outputs a validated output (Validation from ScalaZ)
- the err callback: a function that takes the request and the failure (when computing the stolen value) and outputs a valid Result to send back to the client.
- apply: a closure that takes the result (not a Validation) and output an Action.
At this stage and looking at the code below (I've omitted the apply impl because not important here -- just wrapping and unwrapping), it's fairly simple to know how to define such interceptor.
I provided the simplest implementation of this trait that is a case class extending it by defining the two callbacks as fields. Like so:
So now we're armed to do stuff like that:
Where we defined two interceptors that takes a string from the cache and an Int form the cache also (just an illustration). After what, we combined them in an another Intercept using a for-comprehension.
So far, so good, now how to use such combined interceptor within an Action. Check this out:
With the help of Monoid (from ScalaZ) and if the case permits it, I defined an implementation of Interceptor that append the successive results one after the another. Reducing and simplifying the composition. Like so:
Note: we used the classical case class. Thanks to an implicit def that wraps the Intercept into the Monoid implementation, using the TypeClass bound declaration. see
What will come next
The next step I've already started is to try using Shapeless to avoid the composition boilerplate. Things are ongoing. Stay tune for that.
One step further, I'll add another parameter to the steal callback, which will be the optional result of the previous computations of other interceptors. That in order to combine them at the function and result levels.
And probably, add all boileplate my self that creates the tuples out-of-th-box in the compose function.
That's all folks!