2012-03-17 15:28:07 -06:00
|
|
|
package controllers
|
|
|
|
|
2013-02-27 17:12:13 -07:00
|
|
|
import lila.app._
|
2013-04-09 12:58:34 -06:00
|
|
|
import lila.common.LilaCookie
|
2013-03-18 20:22:50 -06:00
|
|
|
import lila.user.{ Context, HeaderContext, BodyContext, User ⇒ UserModel }
|
2013-03-18 17:36:22 -06:00
|
|
|
import lila.security.{ Permission, Granter }
|
2012-05-11 15:45:45 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
import scalaz.Zero
|
2013-04-01 20:01:41 -06:00
|
|
|
import play.api.mvc._, Results._
|
2012-05-26 06:31:05 -06:00
|
|
|
import play.api.data.Form
|
2013-05-06 10:41:02 -06:00
|
|
|
import play.api.templates.Html
|
2012-05-11 15:45:45 -06:00
|
|
|
import play.api.http._
|
2013-04-10 05:02:32 -06:00
|
|
|
import play.api.libs.json.{ Json, JsValue, Writes }
|
2012-03-17 15:28:07 -06:00
|
|
|
|
2012-05-11 15:45:45 -06:00
|
|
|
trait LilaController
|
|
|
|
extends Controller
|
|
|
|
with ContentTypes
|
|
|
|
with RequestGetter
|
2013-05-06 10:41:02 -06:00
|
|
|
with ResponseWriter
|
|
|
|
with Results {
|
|
|
|
|
|
|
|
protected implicit val LilaResultZero = new Zero[Result] {
|
|
|
|
val zero = Results.NotFound
|
|
|
|
}
|
|
|
|
protected implicit val LilaPlainResultZero = new Zero[PlainResult] {
|
|
|
|
val zero = Results.NotFound
|
|
|
|
}
|
|
|
|
|
|
|
|
protected implicit final class LilaPimpedResult(result: Result) {
|
|
|
|
def fuccess = scala.concurrent.Future successful result
|
|
|
|
}
|
|
|
|
|
|
|
|
protected implicit def LilaHtmlToResult(content: Html): Result = Ok(content)
|
|
|
|
|
|
|
|
protected implicit def LilaFunitToResult(funit: Funit): Fu[Result] = funit inject Ok("ok")
|
2012-03-17 15:28:07 -06:00
|
|
|
|
2013-04-10 04:17:58 -06:00
|
|
|
override implicit def lang(implicit req: RequestHeader) =
|
|
|
|
Env.i18n.pool lang req
|
2012-05-12 12:06:02 -06:00
|
|
|
|
2013-03-20 10:34:38 -06:00
|
|
|
protected def Open(f: Context ⇒ Fu[Result]): Action[AnyContent] =
|
|
|
|
Open(BodyParsers.parse.anyContent)(f)
|
2012-05-11 15:45:45 -06:00
|
|
|
|
2013-03-20 10:34:38 -06:00
|
|
|
protected def Open[A](p: BodyParser[A])(f: Context ⇒ Fu[Result]): Action[A] =
|
|
|
|
Action(p)(req ⇒ Async(reqToCtx(req) flatMap f))
|
2012-05-11 15:45:45 -06:00
|
|
|
|
2013-03-18 17:36:22 -06:00
|
|
|
protected def OpenBody(f: BodyContext ⇒ Fu[Result]): Action[AnyContent] =
|
2012-05-13 11:03:06 -06:00
|
|
|
OpenBody(BodyParsers.parse.anyContent)(f)
|
|
|
|
|
2013-03-18 17:36:22 -06:00
|
|
|
protected def OpenBody[A](p: BodyParser[A])(f: BodyContext ⇒ Fu[Result]): Action[A] =
|
|
|
|
Action(p)(req ⇒ Async(reqToCtx(req) flatMap f))
|
2012-05-13 11:03:06 -06:00
|
|
|
|
2013-04-10 05:02:32 -06:00
|
|
|
def Socket(fn: Context ⇒ String ⇒ Fu[JsSocketHandler]) =
|
|
|
|
WebSocket.async[JsValue] { req ⇒
|
|
|
|
reqToCtx(req) flatMap { ctx ⇒
|
|
|
|
get("sri")(ctx) zmap { fn(ctx)(_) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-20 10:34:38 -06:00
|
|
|
protected def Optional[A, B](foa: Fu[Option[A]])(op: A ⇒ B)(
|
|
|
|
implicit writer: Writeable[B],
|
|
|
|
ctype: ContentTypeOf[B],
|
|
|
|
ctx: Context): Fu[Result] = foa flatMap {
|
|
|
|
_.fold(notFound(ctx))(a ⇒ fuccess(Ok(op(a))))
|
|
|
|
}
|
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def Auth(f: Context ⇒ UserModel ⇒ Fu[Result]): Action[AnyContent] =
|
|
|
|
Auth(BodyParsers.parse.anyContent)(f)
|
2013-03-14 12:16:36 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def Auth[A](p: BodyParser[A])(f: Context ⇒ UserModel ⇒ Fu[Result]): Action[A] =
|
|
|
|
Action(p)(req ⇒ Async {
|
|
|
|
reqToCtx(req) flatMap { ctx ⇒
|
|
|
|
ctx.me.fold(fuccess(authenticationFailed(ctx.req)))(me ⇒ f(ctx)(me))
|
|
|
|
}
|
|
|
|
})
|
2013-03-14 12:16:36 -06:00
|
|
|
|
|
|
|
// protected def AuthBody(f: BodyContext ⇒ UserModel ⇒ Result): Action[AnyContent] =
|
|
|
|
// AuthBody(BodyParsers.parse.anyContent)(f)
|
|
|
|
|
|
|
|
// protected def AuthBody[A](p: BodyParser[A])(f: BodyContext ⇒ UserModel ⇒ Result): Action[A] =
|
|
|
|
// Action(p)(req ⇒ {
|
|
|
|
// val ctx = reqToCtx(req)
|
|
|
|
// ctx.me.fold(authenticationFailed(ctx.req))(me ⇒ f(ctx)(me))
|
|
|
|
// })
|
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def Secure(perm: Permission)(f: Context ⇒ UserModel ⇒ Fu[Result]): Action[AnyContent] =
|
|
|
|
Secure(BodyParsers.parse.anyContent)(perm)(f)
|
2013-03-14 12:16:36 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def Secure[A](p: BodyParser[A])(perm: Permission)(f: Context ⇒ UserModel ⇒ Fu[Result]): Action[A] =
|
|
|
|
Auth(p) { implicit ctx ⇒
|
|
|
|
me ⇒
|
|
|
|
isGranted(perm).fold(f(ctx)(me), fuccess(authorizationFailed(ctx.req)))
|
|
|
|
}
|
2013-03-14 12:16:36 -06:00
|
|
|
|
2013-05-04 17:12:53 -06:00
|
|
|
protected def Firewall[A <: Result](a: ⇒ Fu[A])(implicit ctx: Context): Fu[Result] =
|
|
|
|
Env.security.firewall.accepts(ctx.req) flatMap {
|
|
|
|
_ fold (a, {
|
|
|
|
Env.security.firewall.logBlock(ctx.req)
|
|
|
|
fuccess { Redirect(routes.Lobby.home()) }
|
|
|
|
})
|
|
|
|
}
|
2012-06-15 06:05:58 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def NoEngine[A <: Result](a: ⇒ A)(implicit ctx: Context): Result =
|
|
|
|
// ctx.me.fold(false)(_.engine).fold(Forbidden(views.html.site.noEngine()), a)
|
2012-09-22 05:47:47 -06:00
|
|
|
|
2013-04-10 05:02:32 -06:00
|
|
|
// protected def JsonOk[A: Writes](data: A) = Ok(toJson(data)) as JSON
|
2012-03-17 15:28:07 -06:00
|
|
|
|
2013-04-10 05:02:32 -06:00
|
|
|
// protected def JsonIOk[A: Writes](data: IO[A]) = JsonOk(data.unsafePerformIO)
|
2012-05-05 05:27:51 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def JsIOk(js: IO[String], headers: (String, String)*) =
|
|
|
|
// JsOk(js.unsafePerformIO, headers: _*)
|
2013-01-01 21:06:17 -07:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def JsOk(js: String, headers: (String, String)*) =
|
|
|
|
// Ok(js) as JAVASCRIPT withHeaders (headers: _*)
|
2012-10-20 07:36:14 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def ValidOk(valid: Valid[Unit]): Result = valid.fold(
|
|
|
|
// e ⇒ BadRequest(e.shows),
|
|
|
|
// _ ⇒ Ok("ok")
|
|
|
|
// )
|
2012-03-17 15:28:07 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def ValidIOk(valid: IO[Valid[Unit]]): Result = ValidOk(valid.unsafePerformIO)
|
2012-03-31 15:48:03 -06:00
|
|
|
|
2013-04-09 12:58:34 -06:00
|
|
|
protected def FormResult[A](form: Form[A])(op: A ⇒ Fu[Result])(implicit req: Request[_]): Fu[Result] =
|
|
|
|
form.bindFromRequest.fold(
|
|
|
|
form ⇒ fuccess(BadRequest(form.errors mkString "\n")),
|
|
|
|
op)
|
2012-05-13 11:03:06 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def FormIOResult[A, B](form: Form[A])(err: Form[A] ⇒ B)(op: A ⇒ IO[Result])(
|
|
|
|
// implicit writer: Writeable[B],
|
|
|
|
// ctype: ContentTypeOf[B],
|
|
|
|
// req: Request[_]) =
|
|
|
|
// form.bindFromRequest.fold(
|
|
|
|
// form ⇒ BadRequest(err(form)),
|
|
|
|
// data ⇒ op(data).unsafePerformIO
|
|
|
|
// )
|
2012-04-16 11:51:49 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def IOk[A](op: IO[A])(implicit writer: Writeable[A], ctype: ContentTypeOf[A]) =
|
|
|
|
// Ok(op.unsafePerformIO)
|
2012-03-17 15:28:07 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def IOResult[A](op: IO[Result]) =
|
|
|
|
// op.unsafePerformIO
|
2012-05-25 15:05:19 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def IORedirect(op: IO[Call]) = Redirect(op.unsafePerformIO)
|
2012-07-22 11:37:38 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def IORedirectUrl(op: IO[String]) = Redirect(op.unsafePerformIO)
|
2012-05-15 17:02:32 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def OptionOk[A, B](oa: Option[A])(op: A ⇒ B)(
|
|
|
|
// implicit writer: Writeable[B],
|
|
|
|
// ctype: ContentTypeOf[B],
|
|
|
|
// ctx: Context) =
|
|
|
|
// oa.fold(notFound(ctx))(a ⇒ Ok(op(a)))
|
2012-06-16 03:25:21 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def OptionResult[A](oa: Option[A])(op: A ⇒ Result)(implicit ctx: Context) =
|
|
|
|
// oa.fold(notFound(ctx))(op)
|
2012-08-01 10:28:33 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def OptionOk[A, B](fua: Fu[Option[A]])(op: A ⇒ B)(
|
|
|
|
implicit writer: Writeable[B],
|
|
|
|
ctype: ContentTypeOf[B],
|
|
|
|
ctx: Context): Fu[Result] =
|
|
|
|
fua flatMap { _.fold(notFound(ctx))(a ⇒ fuccess(Ok(op(a)))) }
|
2012-05-17 08:49:47 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def OptionFuOk[A, B](fua: Fu[Option[A]])(op: A ⇒ Fu[B])(
|
|
|
|
implicit writer: Writeable[B],
|
|
|
|
ctype: ContentTypeOf[B],
|
|
|
|
ctx: Context) =
|
|
|
|
fua flatMap { _.fold(notFound(ctx))(a ⇒ op(a) map { Ok(_) }) }
|
2012-05-20 15:56:36 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
// protected def IOptionIOResult[A](fua: IO[Option[A]])(op: A ⇒ IO[Result])(implicit ctx: Context) =
|
|
|
|
// fua flatMap { _.fold(io(notFound(ctx)))(op) } unsafePerformIO
|
2013-03-14 12:16:36 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
// protected def IOptionRedirect[A](fua: IO[Option[A]])(op: A ⇒ Call)(implicit ctx: Context) =
|
|
|
|
// fua map {
|
2013-03-14 12:16:36 -06:00
|
|
|
// _.fold(notFound(ctx))(a ⇒ Redirect(op(a)))
|
|
|
|
// } unsafePerformIO
|
2012-06-08 14:22:56 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
// protected def IOptionIORedirect[A](fua: IO[Option[A]])(op: A ⇒ IO[Call])(implicit ctx: Context) =
|
|
|
|
// (fua flatMap {
|
2013-03-14 12:16:36 -06:00
|
|
|
// _.fold(io(notFound(ctx)))(a ⇒ op(a) map { b ⇒ Redirect(b) })
|
|
|
|
// }: IO[Result]).unsafePerformIO
|
2012-05-19 10:56:16 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
// protected def IOptionIORedirectUrl[A](fua: IO[Option[A]])(op: A ⇒ IO[String])(implicit ctx: Context) =
|
|
|
|
// (fua flatMap {
|
2013-03-14 12:16:36 -06:00
|
|
|
// _.fold(io(notFound(ctx)))(a ⇒ op(a) map { b ⇒ Redirect(b) })
|
|
|
|
// }: IO[Result]).unsafePerformIO
|
2012-12-18 08:58:19 -07:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
// protected def IOptionResult[A](fua: IO[Option[A]])(op: A ⇒ Result)(implicit ctx: Context) =
|
|
|
|
// fua.unsafePerformIO.fold(notFound(ctx))(a ⇒ op(a))
|
2012-05-19 07:37:10 -06:00
|
|
|
|
2013-04-09 12:58:34 -06:00
|
|
|
protected def notFound(implicit ctx: Context): Fu[Result] =
|
2013-03-20 10:34:38 -06:00
|
|
|
Lobby handleNotFound ctx
|
2012-05-15 17:31:57 -06:00
|
|
|
|
2013-03-14 12:16:36 -06:00
|
|
|
// protected def todo = Open { implicit ctx ⇒
|
|
|
|
// NotImplemented(views.html.site.todo())
|
|
|
|
// }
|
2012-05-28 09:33:37 -06:00
|
|
|
|
2013-05-06 10:41:02 -06:00
|
|
|
protected def isGranted(permission: Permission.type ⇒ Permission)(implicit ctx: Context): Boolean =
|
|
|
|
isGranted(permission(Permission))
|
|
|
|
|
|
|
|
protected def isGranted(permission: Permission)(implicit ctx: Context): Boolean =
|
|
|
|
ctx.me.zmap(Granter(permission))
|
|
|
|
|
|
|
|
protected def authenticationFailed(implicit req: RequestHeader): Result =
|
|
|
|
Redirect(routes.Auth.signup) withCookies LilaCookie.session(Env.security.api.AccessUri, req.uri)
|
|
|
|
|
|
|
|
protected def authorizationFailed(req: RequestHeader): Result =
|
|
|
|
Forbidden("no permission")
|
2012-06-12 13:35:04 -06:00
|
|
|
|
2013-03-18 17:36:22 -06:00
|
|
|
protected def reqToCtx(req: Request[_]): Fu[BodyContext] =
|
2013-04-10 04:17:58 -06:00
|
|
|
Env.security.api restoreUser req map { user ⇒
|
2013-03-18 17:36:22 -06:00
|
|
|
setOnline(user)
|
|
|
|
Context(req, user)
|
|
|
|
}
|
|
|
|
|
|
|
|
protected def reqToCtx(req: RequestHeader): Fu[HeaderContext] =
|
2013-04-10 04:17:58 -06:00
|
|
|
Env.security.api restoreUser req map { user ⇒
|
2013-03-18 17:36:22 -06:00
|
|
|
setOnline(user)
|
|
|
|
Context(req, user)
|
|
|
|
}
|
|
|
|
|
|
|
|
private def setOnline(user: Option[UserModel]) {
|
2013-04-15 05:29:58 -06:00
|
|
|
user foreach Env.user.setOnline
|
2013-03-18 17:36:22 -06:00
|
|
|
}
|
2012-03-17 15:28:07 -06:00
|
|
|
}
|