Skip to content

Commit

Permalink
#2 Add Scalariform in build process
Browse files Browse the repository at this point in the history
  • Loading branch information
Toom committed Nov 16, 2016
1 parent c093457 commit 10b92b1
Show file tree
Hide file tree
Showing 46 changed files with 1,079 additions and 932 deletions.
3 changes: 2 additions & 1 deletion app/org/elastic4play/Errors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ case class MultiError(message: String, exceptions: Seq[Exception]) extends Excep

case class AttributeCheckingError(
tableName: String,
errors: Seq[AttributeError] = Nil)
errors: Seq[AttributeError] = Nil
)
extends Exception(errors.mkString("[", "][", "]")) {
override def toString = errors.mkString("[", "][", "]")
}
Expand Down
23 changes: 12 additions & 11 deletions app/org/elastic4play/JsonFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@ object JsonFormat {
val updateReadOnlyAttributeErrorWrites = Json.writes[UpdateReadOnlyAttributeError]
val missingAttributeErrorWrites = Json.writes[MissingAttributeError]

implicit val attributeCheckingExceptionWrites = Writes[AttributeCheckingError]((ace: AttributeCheckingError) => JsObject(Seq(
"tableName" -> JsString(ace.tableName),
"message" -> JsString(ace.toString),
"errors" -> JsArray(ace.errors.map {
case e: InvalidFormatAttributeError => invalidFormatAttributeErrorWrites.writes(e)
case e: UnknownAttributeError => unknownAttributeErrorWrites.writes(e)
case e: UpdateReadOnlyAttributeError => updateReadOnlyAttributeErrorWrites.writes(e)
case e: MissingAttributeError => missingAttributeErrorWrites.writes(e)
}))))
implicit val attributeCheckingExceptionWrites = Writes[AttributeCheckingError]((ace: AttributeCheckingError) JsObject(Seq(
"tableName" JsString(ace.tableName),
"message" JsString(ace.toString),
"errors" JsArray(ace.errors.map {
case e: InvalidFormatAttributeError invalidFormatAttributeErrorWrites.writes(e)
case e: UnknownAttributeError unknownAttributeErrorWrites.writes(e)
case e: UpdateReadOnlyAttributeError updateReadOnlyAttributeErrorWrites.writes(e)
case e: MissingAttributeError missingAttributeErrorWrites.writes(e)
})
)))

implicit def tryWrites[A](implicit aWrites: Writes[A]) = Writes[Try[A]] {
case Success(a) => aWrites.writes(a)
case Failure(t) => JsString(t.getMessage)
case Success(a) aWrites.writes(a)
case Failure(t) JsString(t.getMessage)
}
}
58 changes: 32 additions & 26 deletions app/org/elastic4play/controllers/Authenticated.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,27 @@ case object ExpirationError extends ExpirationStatus
* Check and manager user security (authentication and authorization)
*/
@Singleton
class Authenticated(maxSessionInactivity: FiniteDuration,
sessionWarning: FiniteDuration,
userSrv: UserSrv,
authSrv: AuthSrv,
implicit val ec: ExecutionContext) {

@Inject() def this(configuration: Configuration,
userSrv: UserSrv,
authSrv: AuthSrv,
ec: ExecutionContext) =
this(configuration.getMilliseconds("session.inactivity").get.millis,
class Authenticated(
maxSessionInactivity: FiniteDuration,
sessionWarning: FiniteDuration,
userSrv: UserSrv,
authSrv: AuthSrv,
implicit val ec: ExecutionContext
) {

@Inject() def this(
configuration: Configuration,
userSrv: UserSrv,
authSrv: AuthSrv,
ec: ExecutionContext
) =
this(
configuration.getMilliseconds("session.inactivity").get.millis,
configuration.getMilliseconds("session.warning").get.millis,
userSrv,
authSrv,
ec)
ec
)

private def now = (new Date).getTime

Expand All @@ -58,29 +64,29 @@ class Authenticated(maxSessionInactivity: FiniteDuration,
* Cookie is signed by Play framework (it cannot be modified by user)
*/
def setSessingUser(result: Result, authContext: AuthContext)(implicit request: RequestHeader): Result =
result.addingToSession(Security.username -> authContext.userId, "expire" -> (now + maxSessionInactivity.toMillis).toString)
result.addingToSession(Security.username authContext.userId, "expire" (now + maxSessionInactivity.toMillis).toString)

/**
* Retrieve authentication information form cookie
*/
def getFromSession(request: RequestHeader): Future[AuthContext] = {
val userId = for {
userId <- request.session.get(Security.username)
userId request.session.get(Security.username)
if expirationStatus(request) != ExpirationError
} yield userId
userId.fold(Future.failed[AuthContext](AuthenticationError("Not authenticated")))(id => userSrv.getFromId(request, id))
userId.fold(Future.failed[AuthContext](AuthenticationError("Not authenticated")))(id userSrv.getFromId(request, id))
}

def expirationStatus(request: RequestHeader): ExpirationStatus = {
request.session.get("expire")
.flatMap { expireStr =>
.flatMap { expireStr
Try(expireStr.toLong).toOption
}
.map { expire => (expire - now).millis }
.map { expire (expire - now).millis }
.map {
case duration if duration.length < 0 => ExpirationError
case duration if duration < sessionWarning => ExpirationWarning(duration)
case duration => ExpirationOk(duration)
case duration if duration.length < 0 ExpirationError
case duration if duration < sessionWarning ExpirationWarning(duration)
case duration ExpirationOk(duration)
}
.getOrElse(ExpirationError)
}
Expand All @@ -93,13 +99,13 @@ class Authenticated(maxSessionInactivity: FiniteDuration,
.headers
.get(HeaderNames.AUTHORIZATION)
.collect {
case auth if auth.startsWith("Basic ") =>
case auth if auth.startsWith("Basic ")
val authWithoutBasic = auth.substring(6)
val decodedAuth = new String(java.util.Base64.getDecoder.decode(authWithoutBasic), "UTF-8")
decodedAuth.split(":")
}
.collect {
case Array(username, password) => authSrv.authenticate(username, password)(request)
case Array(username, password) authSrv.authenticate(username, password)(request)
}
.getOrElse(Future.failed[AuthContext](new Exception("TODO")))

Expand All @@ -110,19 +116,19 @@ class Authenticated(maxSessionInactivity: FiniteDuration,
getFromSession(request)
.fallbackTo(getFromApiKey(request))
.fallbackTo(userSrv.getInitialUser(request))
.recoverWith { case _ => Future.failed(AuthenticationError("Not authenticated")) }
.recoverWith { case _ Future.failed(AuthenticationError("Not authenticated")) }

/**
* Create an action for authenticated controller
* If user has sufficient right (have required role) action is executed
* otherwise, action returns a not authorized error
*/
def apply(requiredRole: Role.Type) = new ActionBuilder[({ type R[A] = AuthenticatedRequest[A] })#R] {
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) => Future[Result]) = {
getContext(request).flatMap { authContext =>
def invokeBlock[A](request: Request[A], block: (AuthenticatedRequest[A]) Future[Result]) = {
getContext(request).flatMap { authContext
if (authContext.roles.contains(requiredRole))
block(new AuthenticatedRequest(authContext, request))
.map(result => setSessingUser(result, authContext)(request))
.map(result setSessingUser(result, authContext)(request))
else
Future.failed(new Exception(s"Insufficient rights to perform this action"))
}
Expand Down
30 changes: 16 additions & 14 deletions app/org/elastic4play/controllers/DBList.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,41 @@ import org.elastic4play.services.{ DBLists, Role }
import scala.concurrent.Future

@Singleton
class DBListCtrl @Inject() (dblists: DBLists,
authenticated: Authenticated,
renderer: Renderer,
fieldsBodyParser: FieldsBodyParser,
implicit val ec: ExecutionContext) extends Controller {
class DBListCtrl @Inject() (
dblists: DBLists,
authenticated: Authenticated,
renderer: Renderer,
fieldsBodyParser: FieldsBodyParser,
implicit val ec: ExecutionContext
) extends Controller {

@Timed("controllers.DBListCtrl.list")
def list = authenticated(Role.read).async { implicit request =>
dblists.listAll.map { listNames =>
def list = authenticated(Role.read).async { implicit request
dblists.listAll.map { listNames
renderer.toOutput(OK, listNames)
}
}

@Timed("controllers.DBListCtrl.listItems")
def listItems(listName: String) = authenticated(Role.read) { implicit request =>
def listItems(listName: String) = authenticated(Role.read) { implicit request
val (src, total) = dblists(listName).getItems[JsValue]
val items = src.map { case (id, value) => s""""$id":$value""" }
val items = src.map { case (id, value) s""""$id":$value""" }
.intersperse("{", ",", "}")
Ok.chunked(items).as("application/json")
}

@Timed("controllers.DBListCtrl.addItem")
def addItem(listName: String) = authenticated(Role.admin).async(fieldsBodyParser) { implicit request =>
request.body.getValue("value").fold(Future.successful(NoContent)) { value =>
dblists(listName).addItem(value).map { item =>
def addItem(listName: String) = authenticated(Role.admin).async(fieldsBodyParser) { implicit request
request.body.getValue("value").fold(Future.successful(NoContent)) { value
dblists(listName).addItem(value).map { item
renderer.toOutput(OK, item.id)
}
}
}

@Timed("controllers.DBListCtrl.deleteItem")
def deleteItem(itemId: String) = authenticated(Role.admin).async { implicit request =>
dblists.deleteItem(itemId).map { _ =>
def deleteItem(itemId: String) = authenticated(Role.admin).async { implicit request
dblists.deleteItem(itemId).map { _
NoContent
}
}
Expand Down
Loading

0 comments on commit 10b92b1

Please sign in to comment.