This project contains useful directives and utils for akka-http 2.x projects. In particular:
Just add the library to your sbt dependencies:
resolvers += sbt.Resolver.bintrayRepo("denigma", "denigma-releases"),
libraryDependencies += "org.denigma" %%% "akka-http-extensions" % "0.0.12"
Then you can simply extend AuthDirectives in your routes.
The project was initiated because we had several akka-http projects and wanted to share the most common features and patterns.
At the moment there are:
Login/registration is common for all apps. Here we provide some directives to make them easier as well encryption support (bcrypt is used to create password hashes).
Here how it looks like:
class Registration(
usernameLogin:(String,String)=>Future[LoginResult],
emailLogin:(String,String)=>Future[LoginResult],
register:(String,String,String)=>Future[RegistrationResult],
userByToken:String=>Option[LoginInfo],
makeToken:LoginInfo=>Future[String]
) extends AuthDirectives
with Directives
with WithLoginRejections
with WithRegistrationRejections
{
def routes: Route =
pathPrefix("users") {
pathPrefix("login") {
put {
handleRejections(loginRejectionHandlers) {
login(usernameLogin, emailLogin) { user =>
startSession(user, makeToken) {
complete(s"The user ${user.username} was logged in")
}
}
}
}
} ~
pathPrefix("register") {
put {
handleRejections(registerRejectionHandlers) {
registration(register) { user =>
startSession(user, makeToken) {
complete(s"The user ${user.username} has been registered")
}
}
}
}
} ~
pathPrefix("logout") {
logout{ c =>
c.complete(s"The user was logged out")
}
} ~
pathPrefix("status"){
this.authenticate(userByToken){user=>
complete(user.username)
}
}
}
}
PJax is a technique that makes it easier to load html pages without page reload. The idea is that P-JAX header is added to all your ajax requests. So backend looks at the headers and renders the whole html page if there is no P-JAX header or only a specific template if it is an AJAX request.
In Preview backend you can see P-JAX implementation for Twirl. Here is an example of test Router with PJax directive:
def test = pathPrefix("test"~Slash) { ctx=>
//here is an example with Twirl template. It the request is ajax one, then we return only template
//if it is ordinary URL request - we render whole html page and put the template inside
pjax[Twirl](Html(s"Some test code<h1>${ctx.unmatchedPath}</h1>"),loadPage){h=>c=>
val resp = HttpResponse( entity = HttpEntity(MediaTypes.`text/html`, h.body ))
c.complete(resp)
}(ctx)
}
akka-http-extensions provide cookie-based authentication where tokens are stored in a cookie.
pathPrefix("me"){
//here userByToken is just a function that you
//provide to extract LoginInfo by token value taken from the cookie
this.authenticate(userByToken){user=>
complete(user.username)
}
}
Permissions directives that allow to restrict access to some users.
allow directive is used to allow access only to a group of users in some realm.
pathPrefix("add") {
pathPrefix("drug") {
put
{
parameter("name"){ name =>
authenticate(sessionController.userByToken _){ user=>
allow(user, AdminRealm, checkRights _)
{
drugs = drugs + name
complete(s"drug $name added!")
}
}
}
}
}
}
Some inmemory controllers for testing logging and registration
BiMap - bidirectional map, it is missing in scala collections =(
This git repository contains some useful classes and directives for akka-http. akka.http.extensions are located in extensions subprojects. All other code is for previews.
The project contains 4 subprojects::
To run the project you must have SBT ( http://www.scala-sbt.org/ ) installed.
To run project:
sbt //to opens sbt console
re-start //Use this command **instead of** run to run the app
Open localhost:2222 to see the result, it should reload whenever any sources are change