port auth stuff
parent
30654c8852
commit
7c2bfe9d10
|
@ -22,7 +22,7 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
|
||||
if (ModulePreload) {
|
||||
loginfo("Preloading modules")
|
||||
(Env.site, Env.setup, Env.game, Env.gameSearch, Env.team,
|
||||
(Env.site, Env.game, Env.setup, Env.game, Env.gameSearch, Env.team,
|
||||
Env.teamSearch, Env.forumSearch, Env.message)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,45 +1,81 @@
|
|||
package controllers
|
||||
|
||||
import lila.app._
|
||||
import lila.api._
|
||||
import lila.common.LilaCookie
|
||||
import lila.user.{ UserRepo, HistoryRepo }
|
||||
import views._
|
||||
|
||||
import play.api.mvc._, Results._
|
||||
import play.api.data._, Forms._
|
||||
|
||||
object Auth extends LilaController {
|
||||
|
||||
// protected def gotoLoginSucceeded[A](username: String)(implicit req: RequestHeader) = {
|
||||
// val sessionId = saveAuthentication(username)
|
||||
// val uri = req.session.get(AccessUri) | routes.Lobby.home.url
|
||||
// Redirect(uri) withCookies LilaCookie.withSession { session ⇒
|
||||
// session + ("sessionId" -> sessionId) - AccessUri
|
||||
// }
|
||||
// }
|
||||
private def api = Env.security.api
|
||||
private def forms = Env.security.forms
|
||||
|
||||
// protected def gotoSignupSucceeded[A](username: String)(implicit req: RequestHeader) = {
|
||||
// val sessionId = saveAuthentication(username)
|
||||
// Redirect(routes.User.show(username)) withCookies LilaCookie.session("sessionId", sessionId)
|
||||
// }
|
||||
private def gotoLoginSucceeded[A](username: String)(implicit req: RequestHeader) =
|
||||
api saveAuthentication username map { sessionId ⇒
|
||||
val uri = req.session.get(api.AccessUri) | routes.Lobby.home.url
|
||||
Redirect(uri) withCookies LilaCookie.withSession { session ⇒
|
||||
session + ("sessionId" -> sessionId) - api.AccessUri
|
||||
}
|
||||
}
|
||||
|
||||
def login = TODO
|
||||
// Open { implicit ctx ⇒
|
||||
// Ok(html.auth.login(loginForm))
|
||||
// }
|
||||
private def gotoSignupSucceeded[A](username: String)(implicit req: RequestHeader) =
|
||||
api saveAuthentication username map { sessionId ⇒
|
||||
Redirect(routes.User.show(username)) withCookies LilaCookie.session("sessionId", sessionId)
|
||||
}
|
||||
|
||||
def authenticate = TODO
|
||||
def logout = TODO
|
||||
def signup = TODO
|
||||
def signupPost = TODO
|
||||
def login = Open { implicit ctx ⇒
|
||||
Ok(html.auth.login(api.loginForm)) fuccess
|
||||
}
|
||||
|
||||
protected def gotoLogoutSucceeded(implicit req: RequestHeader) = {
|
||||
def authenticate = OpenBody { implicit ctx ⇒
|
||||
Firewall {
|
||||
implicit val req = ctx.body
|
||||
api.loginForm.bindFromRequest.fold(
|
||||
err ⇒ BadRequest(html.auth.login(err)) fuccess,
|
||||
userOption ⇒ gotoLoginSucceeded(
|
||||
userOption.err("authenticate error").username
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def logout = Open { implicit ctx ⇒
|
||||
gotoLogoutSucceeded(ctx.req) fuccess
|
||||
}
|
||||
|
||||
def signup = Open { implicit ctx ⇒
|
||||
forms.signupWithCaptcha map {
|
||||
case (form, captcha) ⇒ Ok(html.auth.signup(form, captcha))
|
||||
}
|
||||
}
|
||||
|
||||
def signupPost = OpenBody { implicit ctx ⇒
|
||||
implicit val req = ctx.body
|
||||
forms.signup.bindFromRequest.fold(
|
||||
err ⇒ forms.anyCaptcha map { captcha ⇒
|
||||
BadRequest(html.auth.signup(err, captcha))
|
||||
},
|
||||
data ⇒ Firewall {
|
||||
UserRepo.create(data.username, data.password) flatMap { userOption ⇒
|
||||
val user = userOption err "No user could be created for %s".format(data.username)
|
||||
HistoryRepo.addEntry(user.id, user.elo, none) >>
|
||||
gotoSignupSucceeded(user.username)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private def gotoLogoutSucceeded(implicit req: RequestHeader) = {
|
||||
req.session get "sessionId" foreach lila.security.Store.delete
|
||||
logoutSucceeded(req) withCookies LilaCookie.newSession
|
||||
}
|
||||
|
||||
protected def logoutSucceeded(req: RequestHeader): PlainResult =
|
||||
private def logoutSucceeded(req: RequestHeader): PlainResult =
|
||||
Redirect(routes.Lobby.home)
|
||||
|
||||
// protected def authenticationFailed(implicit req: RequestHeader): Result =
|
||||
// Redirect(routes.Auth.signup) withCookies LilaCookie.session(AccessUri, req.uri)
|
||||
private def authenticationFailed(implicit req: RequestHeader): Result =
|
||||
Redirect(routes.Auth.signup) withCookies LilaCookie.session(api.AccessUri, req.uri)
|
||||
}
|
||||
|
|
|
@ -72,13 +72,13 @@ trait LilaController
|
|||
// ctx.isGranted(perm).fold(f(ctx)(me), authorizationFailed(ctx.req))
|
||||
// }
|
||||
|
||||
// protected def Firewall[A <: Result](a: ⇒ A)(implicit ctx: Context): Result =
|
||||
// env.security.firewall.accepts(ctx.req).fold(
|
||||
// a, {
|
||||
// env.security.firewall.logBlock(ctx.req)
|
||||
// Redirect(routes.Lobby.home())
|
||||
// }
|
||||
// )
|
||||
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()) }
|
||||
})
|
||||
}
|
||||
|
||||
// protected def NoEngine[A <: Result](a: ⇒ A)(implicit ctx: Context): Result =
|
||||
// ctx.me.fold(false)(_.engine).fold(Forbidden(views.html.site.noEngine()), a)
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package controllers
|
||||
|
||||
import lila.app._
|
||||
import lila.hub.actorApi.captcha.ValidCaptcha
|
||||
import views._
|
||||
import makeTimeout.large
|
||||
|
||||
import play.api.mvc._, Results._
|
||||
import play.api.data._, Forms._
|
||||
import play.api.libs.json._
|
||||
import play.api.libs.iteratee._
|
||||
import play.api.libs.concurrent.Akka
|
||||
import akka.pattern.ask
|
||||
|
||||
object Main extends LilaController {
|
||||
|
||||
|
@ -18,9 +21,11 @@ object Main extends LilaController {
|
|||
)
|
||||
}
|
||||
|
||||
// def captchaCheck(id: String) = Open { implicit ctx ⇒
|
||||
// Ok(env.site.captcha get id valid ~get("solution") fold (1, 0))
|
||||
// }
|
||||
def captchaCheck(id: String) = Open { implicit ctx ⇒
|
||||
Env.hub.actor.captcher ? ValidCaptcha(id, ~get("solution")) map {
|
||||
case valid: Boolean ⇒ Ok(valid fold (1, 0))
|
||||
}
|
||||
}
|
||||
|
||||
// def embed = Open { implicit ctx ⇒
|
||||
// JsOk("""document.write("<iframe src='%s?embed=" + document.domain + "' class='lichess-iframe' allowtransparency='true' frameBorder='0' style='width: %dpx; height: %dpx;' title='Lichess free online chess'></iframe>");"""
|
||||
|
|
|
@ -3,7 +3,7 @@ package controllers
|
|||
import lila.app._
|
||||
import views._
|
||||
import lila.security.Permission
|
||||
import lila.user.{ Context, User ⇒ UserModel }
|
||||
import lila.user.{ Context, User ⇒ UserModel, UserRepo }
|
||||
import lila.common.LilaCookie
|
||||
|
||||
import play.api.mvc._, Results._
|
||||
|
@ -17,7 +17,13 @@ object User extends LilaController {
|
|||
// private def bookmarkApi = env.bookmark.api
|
||||
// private def modApi = env.mod.api
|
||||
|
||||
def show(username: String) = TODO //showFilter(username, "all", 1)
|
||||
def show(username: String) = Open { implicit ctx =>
|
||||
UserRepo named username map { userOption =>
|
||||
println(userOption)
|
||||
NotFound
|
||||
}
|
||||
}
|
||||
//showFilter(username, "all", 1)
|
||||
|
||||
// def showFilter(username: String, filterName: String, page: Int) = Open { implicit ctx ⇒
|
||||
// Async {
|
||||
|
@ -42,6 +48,7 @@ object User extends LilaController {
|
|||
// }
|
||||
// }, io(html.user.disabled(u)))
|
||||
|
||||
def list(page: Int) = TODO
|
||||
// def list(page: Int) = Open { implicit ctx ⇒
|
||||
// (page < 50).fold(
|
||||
// IOk(onlineUsers map { html.user.list(paginator elo page, _) }),
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
package lila
|
||||
|
||||
import scalaz.Zero
|
||||
import play.api.mvc.{ Result, Results }
|
||||
import play.api.mvc.{ Result, PlainResult, Results }
|
||||
import scala.concurrent.Future
|
||||
|
||||
package object app extends PackageObject with WithPlay with socket.WithSocket {
|
||||
|
||||
implicit val LilaResultZero = new Zero[Result] {
|
||||
val zero = Results.NotFound
|
||||
}
|
||||
implicit val LilaPlainResultZero = new Zero[PlainResult] {
|
||||
val zero = Results.NotFound
|
||||
}
|
||||
|
||||
implicit final class LilaPimpedResult(result: Result) {
|
||||
def fuccess = Future successful result
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ final class SiteMenu(trans: I18nKeys) {
|
|||
val play = new Elem("play", routes.Lobby.home, trans.play)
|
||||
// val game = new Elem("game", routes.Game.realtime, trans.games)
|
||||
// val tournament = new Elem("tournament", routes.Tournament.home, trans.tournament)
|
||||
// val user = new Elem("user", routes.User.list(page = 1), trans.people)
|
||||
val user = new Elem("user", routes.User.list(page = 1), trans.people)
|
||||
// val team = new Elem("team", routes.Team.home(page = 1), trans.teams)
|
||||
// val forum = new Elem("forum", routes.ForumCateg.index, trans.forum)
|
||||
// val message = new Elem("message", routes.Message.inbox(page = 1), trans.inbox)
|
||||
|
||||
private val authenticated = List(play)//, game, tournament, user, team, forum, message)
|
||||
private val anonymous = List(play)//, game, tournament, user, team, forum)
|
||||
private val authenticated = List(play, user)//, game, tournament, user, team, forum, message)
|
||||
private val anonymous = List(play, user)//, game, tournament, user, team, forum)
|
||||
|
||||
def all(me: Option[User]) = me.isDefined.fold(authenticated, anonymous)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
@(form: Form[_])(implicit ctx: Context)
|
||||
|
||||
@auth.layout(
|
||||
title = trans.signIn.str()) {
|
||||
@auth.layout(title = trans.signIn.str()) {
|
||||
<div class="content_box small_box">
|
||||
<div class="signup_box">
|
||||
<h1 class="lichess_title">@trans.signIn()</h1>
|
|
@ -1,4 +1,4 @@
|
|||
@(form: Form[_], captcha: lila.app.site.Captcha.Challenge)(implicit ctx: Context)
|
||||
@(form: Form[_], captcha: lila.common.Captcha)(implicit ctx: Context)
|
||||
|
||||
@auth.layout(
|
||||
title = trans.signUp.str()) {
|
|
@ -1,15 +1,16 @@
|
|||
@(move: Field, gameId: Field, captcha: lila.app.site.Captcha.Challenge)(implicit ctx: Context)
|
||||
@(move: Field, gameId: Field, captcha: lila.common.Captcha)(implicit ctx: Context)
|
||||
<input type="hidden" name="@gameId.name" id="@gameId.id" value="@captcha.gameId" />
|
||||
@defining(captcha.white.fold("white", "black")) { color =>
|
||||
<div class="checkmateCaptcha clearfix" data-check-url="@routes.Main.captchaCheck(captcha.gameId)">
|
||||
<div class="checkmateFen">
|
||||
<div
|
||||
class="mini_board parse_fen with_keys"
|
||||
data-color="@captcha.color"
|
||||
data-color="@color"
|
||||
data-fen="@captcha.fen"></div>
|
||||
</div>
|
||||
<div class="checkmateSection">
|
||||
<label>
|
||||
<strong>@captcha.color.toString.capitalize plays; checkmate in one!</strong><br />
|
||||
<strong>@color.capitalize plays; checkmate in one!</strong><br />
|
||||
This is a chess CAPTCHA.<br />
|
||||
Click on the board to make your move,<br />
|
||||
and prove you are human.<br /><br />
|
||||
|
@ -19,4 +20,4 @@
|
|||
<input type="hidden" name="@move.name" id="@move.id" value="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
@(title: String, cssClass: String = "")(content: Html)(implicit ctx: Context)
|
||||
|
||||
<div class="lichess_chat @cssClass">
|
||||
<div class="lichess_chat_top">
|
||||
<span class="title">@title</span>
|
||||
<input
|
||||
data-href="@routes.Setting.set("chat")"
|
||||
data-enabled="@setting.chat.fold("true", "false")"
|
||||
title="@trans.toggleTheChat()"
|
||||
class="toggle_chat"
|
||||
type="checkbox" />
|
||||
</div>
|
||||
<div class="lichess_chat_inner">
|
||||
<div class="nano">
|
||||
<ol class="lichess_messages content">@content</ol>
|
||||
</div>
|
||||
<form action="#">
|
||||
<input class="lichess_say" value="" placeholder="@trans.talkInChat()" />
|
||||
<a class="send"></a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,16 @@
|
|||
@(ex: Throwable)(implicit ctx: Context)
|
||||
|
||||
@site.layout(
|
||||
title = "Internal server error") {
|
||||
|
||||
<div class="content_box small_box">
|
||||
<h1>Something went wrong on this page.</h1>
|
||||
<br />
|
||||
<br />
|
||||
<p>If the problem persists, please report it in the <a href="@routes.ForumCateg.show("lichess-feedback", 1)">forum</a>.</p>
|
||||
<p>Or send me an email at thibault.duplessis@gmail.com</p>
|
||||
<br />
|
||||
<br />
|
||||
<code>@ex.getMessage</code>
|
||||
</div>
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
@(field: play.api.data.Field, placeholder: Option[String] = None)
|
||||
|
||||
<input @placeholder.map { p =>
|
||||
placeholder="@p"
|
||||
} type="text" value="@field.value" name="@field.name" id="@field.id" />
|
|
@ -0,0 +1,10 @@
|
|||
@(field: play.api.data.Field, options: Iterable[(Any,String)], default: Option[String] = None)
|
||||
|
||||
<select id="@field.id" name="@field.name">
|
||||
@default.map { d =>
|
||||
<option value="">@d</option>
|
||||
}
|
||||
@options.map { v =>
|
||||
<option value="@v._1" @(if(field.value == Some(v._1.toString)) "selected" else "")>@v._2</option>
|
||||
}
|
||||
</select>
|
|
@ -9,7 +9,7 @@ GET / controllers.Lobby.home
|
|||
# POST /@/:username/export controllers.User.export(username: String)
|
||||
# GET /@/:username/:filterName controllers.User.showFilter(username: String, filterName: String, page: Int ?= 1)
|
||||
GET /@/:username controllers.User.show(username: String)
|
||||
# GET /people controllers.User.list(page: Int ?= 1)
|
||||
GET /people controllers.User.list(page: Int ?= 1)
|
||||
# GET /people/autocomplete controllers.User.autocomplete
|
||||
# GET /people/online controllers.User.online
|
||||
# GET /account/bio controllers.User.getBio
|
||||
|
@ -183,7 +183,7 @@ GET /monitor controllers.Monitor.index
|
|||
|
||||
# Misc
|
||||
POST /cli controllers.Cli.command
|
||||
# GET /captcha/$id<[\w]{8}> controllers.Main.captchaCheck(id: String)
|
||||
GET /captcha/$id<[\w]{8}> controllers.Main.captchaCheck(id: String)
|
||||
GET /developers controllers.Main.developers
|
||||
|
||||
# Assets
|
||||
|
|
|
@ -35,6 +35,8 @@ trait PackageObject
|
|||
implicit final class LilaPimpedOption[A](o: Option[A]) {
|
||||
|
||||
def zmap[B: Zero](f: A ⇒ B): B = o.fold(∅[B])(f)
|
||||
|
||||
def zflatMap[B: Zero](f: A ⇒ Option[B]): B = o.fold(∅[B]) { x ⇒ ~f(x) }
|
||||
}
|
||||
|
||||
implicit final class LilaPimpedMap[A, B](m: Map[A, B]) {
|
||||
|
|
|
@ -22,8 +22,16 @@ case class Tube[Doc](
|
|||
implicit def reads(js: JsValue): JsResult[Doc] = reader reads js
|
||||
implicit def writes(doc: Doc): JsValue = writer writes doc
|
||||
|
||||
def read(bson: BSONDocument): Option[Doc] =
|
||||
fromMongo(JsObjectReader read bson).asOpt
|
||||
def read(bson: BSONDocument): Option[Doc] = {
|
||||
val js = JsObjectReader read bson
|
||||
fromMongo(js) match {
|
||||
case JsSuccess(v, _) ⇒ Some(v)
|
||||
case e ⇒ {
|
||||
logwarn("[tube] Cannot read %s\n%s".format(js, e))
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def read(js: JsObject): JsResult[Doc] = reads(js)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import scala.concurrent.duration._
|
|||
import play.api.libs.concurrent.Akka.system
|
||||
import play.api.Play.current
|
||||
import akka.actor._
|
||||
import akka.pattern.{ ask, pipe }
|
||||
|
||||
// only works with standard chess (not chess960)
|
||||
private final class Captcher extends Actor {
|
||||
|
@ -25,6 +26,9 @@ private final class Captcher extends Actor {
|
|||
case GetCaptcha(id: String) ⇒ sender ! Impl.get(id).await
|
||||
|
||||
case NewCaptcha ⇒ Impl.refresh.await
|
||||
|
||||
case ValidCaptcha(id: String, solution: String) ⇒
|
||||
Impl get id map (_ valid solution) pipeTo sender
|
||||
}
|
||||
|
||||
override def preStart() {
|
||||
|
@ -60,7 +64,7 @@ private final class Captcher extends Actor {
|
|||
private def find(id: String): Option[Captcha] =
|
||||
challenges.list.find(_.gameId == id)
|
||||
|
||||
private def createFromDb: Fu[Option[Captcha]] =
|
||||
private def createFromDb: Fu[Option[Captcha]] =
|
||||
optionT(findCheckmateInDb(100) flatMap {
|
||||
_.fold(findCheckmateInDb(1))(g ⇒ fuccess(g.some))
|
||||
}) flatMap fromGame
|
||||
|
@ -68,10 +72,10 @@ private final class Captcher extends Actor {
|
|||
private def findCheckmateInDb(distribution: Int): Fu[Option[Game]] =
|
||||
GameRepo findRandomStandardCheckmate distribution
|
||||
|
||||
private def getFromDb(id: String): Fu[Option[Captcha]] =
|
||||
private def getFromDb(id: String): Fu[Option[Captcha]] =
|
||||
optionT($find byId id) flatMap fromGame
|
||||
|
||||
private def fromGame(game: Game): OptionT[Fu, Captcha] =
|
||||
private def fromGame(game: Game): OptionT[Fu, Captcha] =
|
||||
optionT(PgnRepo getOption game.id) flatMap { makeCaptcha(game, _) }
|
||||
|
||||
private def makeCaptcha(game: Game, pgnString: String): OptionT[Fu, Captcha] =
|
||||
|
|
|
@ -15,6 +15,7 @@ final class Env(
|
|||
private val settings = new {
|
||||
val CachedNbTtl = config duration "cached.nb.ttl"
|
||||
val PaginatorMaxPerPage = config getInt "paginator.max_per_page"
|
||||
val CaptcherName = config getString "captcher.name"
|
||||
val CollectionGame = config getString "collection.game"
|
||||
val CollectionPgn = config getString "collection.pgn"
|
||||
val JsPathRaw = config getString "js_path.raw"
|
||||
|
@ -45,6 +46,9 @@ final class Env(
|
|||
|
||||
lazy val gameJs = new GameJs(path = jsPath, useCache = !isDev)
|
||||
|
||||
// load captcher actor
|
||||
system.actorOf(Props(new Captcher), name = CaptcherName)
|
||||
|
||||
if (!isDev) {
|
||||
|
||||
val scheduler = new lila.common.Scheduler(system)
|
||||
|
|
|
@ -24,7 +24,8 @@ trait CaptchedForm {
|
|||
def getCaptcha(id: String): Fu[Captcha] =
|
||||
(captcher ? GetCaptcha(id)).mapTo[Captcha]
|
||||
|
||||
def withCaptcha[A](form: Form[A]) = anyCaptcha map (form -> _)
|
||||
def withCaptcha[A](form: Form[A]): Fu[(Form[A], Captcha)] =
|
||||
anyCaptcha map (form -> _)
|
||||
|
||||
def validateCaptcha(data: CaptchedData) =
|
||||
getCaptcha(data.gameId).await valid data.move.trim.toLowerCase
|
||||
|
|
|
@ -29,9 +29,6 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
val lobby = socketFor("lobby")
|
||||
val monitor = socketFor("monitor")
|
||||
val site = socketFor("site")
|
||||
site ! 1
|
||||
lobby ! 1
|
||||
|
||||
val hub = system.actorOf(Props(new Broadcast(List(
|
||||
socket.lobby, socket.site
|
||||
))(makeTimeout(SocketHubTimeout))), name = SocketHubName)
|
||||
|
|
|
@ -20,6 +20,7 @@ case object GetUserIds
|
|||
package captcha {
|
||||
case object AnyCaptcha
|
||||
case class GetCaptcha(id: String)
|
||||
case class ValidCaptcha(id: String, solution: String)
|
||||
}
|
||||
|
||||
package lobby {
|
||||
|
|
|
@ -16,8 +16,7 @@ final class Env(config: Config, system: ActorSystem) {
|
|||
val esIndexer = elasticsearch.Indexer.transport(
|
||||
settings = Map("cluster.name" -> ESCluster),
|
||||
host = ESHost,
|
||||
ports = Seq(ESPort)
|
||||
)
|
||||
ports = Seq(ESPort))
|
||||
|
||||
Future {
|
||||
loginfo("[search] Start ElasticSearch")
|
||||
|
|
|
@ -8,7 +8,7 @@ import play.api.data._
|
|||
import play.api.data.Forms._
|
||||
import ornicar.scalalib.Random
|
||||
|
||||
final class Api(firewall: Firewall) {
|
||||
private[security] final class Api(firewall: Firewall) {
|
||||
|
||||
def AccessUri = "access_uri"
|
||||
|
||||
|
@ -19,8 +19,10 @@ final class Api(firewall: Firewall) {
|
|||
.verifying("Invalid username or password", _.isDefined)
|
||||
)
|
||||
|
||||
def saveAuthentication(username: String)(implicit req: RequestHeader): String =
|
||||
(Random nextString 12) ~ { sessionId ⇒ Store.save(sessionId, username, req) }
|
||||
def saveAuthentication(username: String)(implicit req: RequestHeader): Fu[String] = {
|
||||
val sessionId = Random nextString 12
|
||||
Store.save(sessionId, username, req) inject sessionId
|
||||
}
|
||||
|
||||
def authorizationFailed(req: RequestHeader): Result =
|
||||
Forbidden("no permission")
|
||||
|
|
|
@ -19,8 +19,7 @@ object HistoryRepo {
|
|||
$push("entries", opponentElo.fold(Json.arr(DateTime.now.getSeconds.toInt, elo)) { opElo ⇒
|
||||
Json.arr(DateTime.now.getSeconds.toInt, elo, opElo)
|
||||
}),
|
||||
upsert = true
|
||||
)
|
||||
upsert = true)
|
||||
|
||||
def userElos(userId: String): Fu[Seq[(Int, Int, Option[Int])]] =
|
||||
$find.one($select(userId)) map { historyOption ⇒
|
||||
|
|
Loading…
Reference in New Issue