lila/app/controllers/LilaController.scala
2012-05-25 23:05:19 +02:00

192 lines
6.1 KiB
Scala

package controllers
import lila._
import user.{ User UserModel }
import security.{ AuthConfigImpl, Permission }
import http.{ Context, BodyContext, HttpEnvironment }
import core.Global
import jp.t2v.lab.play20.auth._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.http._
import scala.io.Codec
import com.codahale.jerkson.Json
import scalaz.effects._
trait LilaController
extends Controller
with HttpEnvironment
with ContentTypes
with RequestGetter
with AuthConfigImpl
with Auth {
lazy val env = Global.env
lazy val cache = env.mongoCache
implicit val current = env.app
override implicit def lang(implicit req: RequestHeader) =
env.i18n.pool.lang(req)
def toJson(map: Map[String, Any]) = Json generate map
def Open(f: Context Result): Action[AnyContent] =
Open(BodyParsers.parse.anyContent)(f)
def Open[A](p: BodyParser[A])(f: Context Result): Action[A] =
Action(p)(req f(reqToCtx(req)))
def OpenBody(f: BodyContext Result): Action[AnyContent] =
OpenBody(BodyParsers.parse.anyContent)(f)
def OpenBody[A](p: BodyParser[A])(f: BodyContext Result): Action[A] =
Action(p)(req f(reqToCtx(req)))
def Auth(f: Context User Result): Action[AnyContent] =
Auth(BodyParsers.parse.anyContent)(f)
def Auth[A](p: BodyParser[A])(f: Context User Result): Action[A] =
Action(p)(req {
val ctx = reqToCtx(req)
ctx.me.fold(me f(ctx)(me), authenticationFailed(ctx.req))
})
def AuthBody(f: BodyContext User Result): Action[AnyContent] =
AuthBody(BodyParsers.parse.anyContent)(f)
def AuthBody[A](p: BodyParser[A])(f: BodyContext User Result): Action[A] =
Action(p)(req {
val ctx = reqToCtx(req)
ctx.me.fold(me f(ctx)(me), authenticationFailed(ctx.req))
})
def Secure(perm: Permission)(f: Context User Result): Action[AnyContent] =
Secure(BodyParsers.parse.anyContent)(perm)(f)
def Secure[A](p: BodyParser[A])(perm: Permission)(f: Context User Result): Action[A] =
Auth(p) { ctx
me
ctx.isGranted(perm).fold(f(ctx)(me), authorizationFailed(ctx.req))
}
def JsonOk(map: Map[String, Any]) = Ok(toJson(map)) as JSON
def JsonOk(list: List[String]) = Ok(Json generate list) as JSON
def JsonIOk(map: IO[Map[String, Any]]) = JsonOk(map.unsafePerformIO)
def ValidOk(valid: Valid[Unit]) = valid.fold(
e BadRequest(e.shows),
_ Ok("ok")
)
def ValidIOk(valid: IO[Valid[Unit]]) = valid.unsafePerformIO.fold(
e BadRequest(e.shows),
_ Ok("ok")
)
def FormResult[A](form: Form[A])(op: A Result)(implicit req: Request[_]) =
form.bindFromRequest.fold(
form BadRequest(form.errors mkString "\n"),
data op(data)
)
def FormIOk[A](form: Form[A])(op: A IO[Unit])(implicit req: Request[_]) =
form.bindFromRequest.fold(
form BadRequest(form.errors mkString "\n"),
data IOk(op(data))
)
def FormValidIOk[A](form: Form[A])(op: A IO[Valid[Unit]])(implicit req: Request[_]) =
form.bindFromRequest.fold(
form BadRequest(form.errors mkString "\n"),
data ValidIOk(op(data))
)
def IOk[A](op: IO[A])(implicit writer: Writeable[A], ctype: ContentTypeOf[A]) =
Ok(op.unsafePerformIO)
def IOResult[A](op: IO[Result]) =
op.unsafePerformIO
def IORedirect(op: IO[Call]) = Redirect(op.unsafePerformIO)
def IOptionOk[A, B](ioa: IO[Option[A]])(op: A B)(
implicit writer: Writeable[B],
ctype: ContentTypeOf[B],
ctx: Context) =
ioa.unsafePerformIO.fold(a Ok(op(a)), notFound(ctx))
def IOptionIOk[A, B](ioa: IO[Option[A]])(op: A IO[B])(
implicit writer: Writeable[B],
ctype: ContentTypeOf[B],
ctx: Context) =
ioa flatMap { aOption
aOption.fold(
a op(a) map { Ok(_) },
io(notFound(ctx))): IO[Result]
} unsafePerformIO
def IOptionIOResult[A](ioa: IO[Option[A]])(op: A IO[Result])(implicit ctx: Context) =
ioa flatMap { _.fold(op, io(notFound(ctx))) } unsafePerformIO
def IOptionRedirect[A](ioa: IO[Option[A]])(op: A Call)(implicit ctx: Context) =
ioa.unsafePerformIO.fold(a Redirect(op(a)), notFound(ctx))
def IOptionResult[A](ioa: IO[Option[A]])(op: A Result)(implicit ctx: Context) =
ioa.unsafePerformIO.fold(a op(a), notFound(ctx))
def notFound(ctx: Context) = Lobby handleNotFound ctx
// I like Unit requests.
implicit def wUnit: Writeable[Unit] =
Writeable[Unit](_ Codec toUTF8 "ok")
implicit def ctoUnit: ContentTypeOf[Unit] =
ContentTypeOf[Unit](Some(ContentTypes.TEXT))
implicit def wFloat: Writeable[Float] =
Writeable[Float](f Codec toUTF8 f.toString)
implicit def ctoFloat: ContentTypeOf[Float] =
ContentTypeOf[Float](Some(ContentTypes.TEXT))
implicit def wLong: Writeable[Long] =
Writeable[Long](a Codec toUTF8 a.toString)
implicit def ctoLong: ContentTypeOf[Long] =
ContentTypeOf[Long](Some(ContentTypes.TEXT))
implicit def wInt: Writeable[Int] =
Writeable[Int](i Codec toUTF8 i.toString)
implicit def ctoInt: ContentTypeOf[Int] =
ContentTypeOf[Int](Some(ContentTypes.TEXT))
implicit def wOptionString: Writeable[Option[String]] =
Writeable[Option[String]](i Codec toUTF8 i.getOrElse(""))
implicit def ctoOptionString: ContentTypeOf[Option[String]] =
ContentTypeOf[Option[String]](Some(ContentTypes.TEXT))
implicit def richForm[A](form: Form[A]) = new {
def toValid: Valid[A] = form.fold(
form failure(nel("Invalid form", form.errors.map(_.toString).toList)),
data success(data)
)
}
protected def reqToCtx(req: Request[_]) = Context(req, restoreUser(req))
protected def reqToCtx(req: RequestHeader) = Context(req, restoreUser(req))
private def restoreUser[A](req: RequestHeader): Option[UserModel] = for {
sessionId req.session.get("sessionId")
userId cache.getAs[Id](sessionId + ":sessionId")(idManifest)
user resolveUser(userId)
} yield {
cache.set(sessionId + ":sessionId", userId, sessionTimeoutInSeconds)
cache.set(userId.toString + ":userId", sessionId, sessionTimeoutInSeconds)
user
}
}