From d19113e8ebdcf92e609f6abf78696b8d0be90584 Mon Sep 17 00:00:00 2001 From: Thibault Duplessis Date: Sun, 16 Dec 2012 22:58:57 +0100 Subject: [PATCH] Save anon setup preferences in mongodb --- app/controllers/Lobby.scala | 9 +++++-- app/core/Settings.scala | 2 ++ app/http/LilaCookie.scala | 6 +++++ app/setup/AnonConfigRepo.scala | 45 +++++++++++++++++++++++++--------- app/setup/FormFactory.scala | 23 ++++++++--------- app/setup/Processor.scala | 22 +++++++++-------- app/setup/SetupEnv.scala | 10 +++++--- app/setup/UserConfig.scala | 7 +++--- app/setup/UserConfigRepo.scala | 4 +-- 9 files changed, 83 insertions(+), 45 deletions(-) diff --git a/app/controllers/Lobby.scala b/app/controllers/Lobby.scala index a0ef2dba16..36392e1ca6 100644 --- a/app/controllers/Lobby.scala +++ b/app/controllers/Lobby.scala @@ -1,7 +1,7 @@ package controllers import lila._ -import http.Context +import http.{ Context, LilaCookie } import lobby.Hook import views._ @@ -43,7 +43,12 @@ object Lobby extends LilaController with Results { myHook, posts, tours, - featured)) + featured)) |> { response ⇒ + ctx.req.session.data.contains(LilaCookie.sessionId).fold( + response, + response withCookies LilaCookie.makeSessionId(ctx.req) + ) + } })).asPromise def socket = WebSocket.async[JsValue] { implicit req ⇒ diff --git a/app/core/Settings.scala b/app/core/Settings.scala index 230b6847b1..aebba36524 100644 --- a/app/core/Settings.scala +++ b/app/core/Settings.scala @@ -59,6 +59,8 @@ final class Settings(config: Config, val IsDev: Boolean) { val UserCollectionHistory = getString("user.collection.history") val UserCollectionConfig = getString("user.collection.config") + val AnonCollectionConfig = getString("anon.collection.config") + val ForumTopicMaxPerPage = getInt("forum.topic.max_per_page") val ForumPostMaxPerPage = getInt("forum.post.max_per_page") val ForumRecentTimeout = millis("forum.recent.timeout") diff --git a/app/http/LilaCookie.scala b/app/http/LilaCookie.scala index a5b0d0abd1..2402ec1282 100644 --- a/app/http/LilaCookie.scala +++ b/app/http/LilaCookie.scala @@ -3,6 +3,8 @@ package http import play.api.mvc.{ Cookie, Session, RequestHeader } +import ornicar.scalalib.Random + object LilaCookie { private val domainRegex = """^.+(\.[^\.]+\.[^\.]+)$""".r @@ -10,6 +12,10 @@ object LilaCookie { private def domain(req: RequestHeader): String = domainRegex.replaceAllIn(req.domain, _ group 1) + val sessionId = "sid" + + def makeSessionId(implicit req: RequestHeader) = session(sessionId, Random nextString 8) + def session(name: String, value: String)(implicit req: RequestHeader): Cookie = withSession { session => session + (name -> value) } diff --git a/app/setup/AnonConfigRepo.scala b/app/setup/AnonConfigRepo.scala index dd007ac665..d7d15966ef 100644 --- a/app/setup/AnonConfigRepo.scala +++ b/app/setup/AnonConfigRepo.scala @@ -1,26 +1,47 @@ package lila package setup -import play.api.mvc.{ Cookie, RequestHeader } +import http.LilaCookie -final class AnonConfigRepo { +import play.api.mvc._ - private val name = "setup" +import com.novus.salat._ +import com.novus.salat.dao._ +import com.mongodb.casbah.MongoCollection +import com.mongodb.casbah.Imports._ +import scalaz.effects._ - def update(map: UserConfig ⇒ UserConfig)(implicit req: RequestHeader): Cookie = - LilaCookie.session(name, value.toString)(ctx.req) - config(user) flatMap { c ⇒ save(map(c)) } +final class AnonConfigRepo(collection: MongoCollection) + extends SalatDAO[RawUserConfig, String](collection) { - def config(implicit req: RequestHeader): IO[UserConfig] = io { - findOneById(user.id) flatMap (_.decode) - } except { e ⇒ - putStrLn("Can't load config: " + e.getMessage) inject none[UserConfig] - } map (_ | UserConfig.default(user)) + private val sessionKey = "setup" - def save(config: UserConfig)(implicit req: RequestHeader): IO[Unit] = io { + def update(req: RequestHeader)(map: UserConfig ⇒ UserConfig): IO[Unit] = + configOption(req) flatMap { co ⇒ + ~co.map(config ⇒ save(map(config))) + } + + def config(req: RequestHeader): IO[UserConfig] = + configOption(req) map (_ | UserConfig.default("nocookie")) + + private def config(sid: String): IO[UserConfig] = { + io { + findOneById(sid) flatMap (_.decode) + } except { e ⇒ + putStrLn("Can't load config: " + e.getMessage) map (_ ⇒ none[UserConfig]) + } + } map (_ | UserConfig.default(sid)) + + private def configOption(req: RequestHeader): IO[Option[UserConfig]] = + ~sessionId(req).map(s ⇒ config(s) map (_.some)) + + private def save(config: UserConfig): IO[Unit] = io { update( DBObject("_id" -> config.id), _grater asDBObject config.encode, upsert = true) } + + private def sessionId(req: RequestHeader): Option[String] = + req.session.get(LilaCookie.sessionId) } diff --git a/app/setup/FormFactory.scala b/app/setup/FormFactory.scala index 85dc0d9f94..7b4c55a901 100644 --- a/app/setup/FormFactory.scala +++ b/app/setup/FormFactory.scala @@ -9,7 +9,8 @@ import play.api.data.Forms._ import scalaz.effects._ final class FormFactory( - configRepo: UserConfigRepo) { + userConfigRepo: UserConfigRepo, + anonConfigRepo: AnonConfigRepo) { import Mappings._ @@ -27,10 +28,7 @@ final class FormFactory( )(AiConfig.<<)(_.>>) ) - def aiConfig(implicit ctx: Context): IO[AiConfig] = ctx.me.fold( - user ⇒ configRepo.config(user) map (_.ai), - io(AiConfig.default) - ) + def aiConfig(implicit ctx: Context): IO[AiConfig] = savedConfig map (_.ai) def friendFilled(implicit ctx: Context): IO[Form[FriendConfig]] = friendConfig map friend(ctx).fill @@ -46,10 +44,7 @@ final class FormFactory( )(FriendConfig.<<)(_.>>) verifying ("Invalid clock", _.validClock) ) - def friendConfig(implicit ctx: Context): IO[FriendConfig] = ctx.me.fold( - user ⇒ configRepo.config(user) map (_.friend), - io(FriendConfig.default) - ) + def friendConfig(implicit ctx: Context): IO[FriendConfig] = savedConfig map (_.friend) def hookFilled(implicit ctx: Context): IO[Form[HookConfig]] = hookConfig map hook(ctx).fill @@ -68,8 +63,10 @@ final class FormFactory( .verifying("Can't create rated unlimited in lobby", _.noRatedUnlimited) ) - def hookConfig(implicit ctx: Context): IO[HookConfig] = ctx.me.fold( - user ⇒ configRepo.config(user) map (_.hook), - io(HookConfig.default) - ) + def hookConfig(implicit ctx: Context): IO[HookConfig] = savedConfig map (_.hook) + + private def savedConfig(implicit ctx: Context): IO[UserConfig] = ctx.me.fold( + userConfigRepo.config, + anonConfigRepo config ctx.req + ) } diff --git a/app/setup/Processor.scala b/app/setup/Processor.scala index 386c173849..f585c7b638 100644 --- a/app/setup/Processor.scala +++ b/app/setup/Processor.scala @@ -13,7 +13,8 @@ import controllers.routes import scalaz.effects._ final class Processor( - configRepo: UserConfigRepo, + userConfigRepo: UserConfigRepo, + anonConfigRepo: AnonConfigRepo, friendConfigMemo: FriendConfigMemo, gameRepo: GameRepo, pgnRepo: PgnRepo, @@ -22,7 +23,7 @@ final class Processor( ai: () ⇒ Ai) extends core.Futuristic { def ai(config: AiConfig)(implicit ctx: Context): IO[Pov] = for { - _ ← ~ctx.me.map(user ⇒ configRepo.update(user)(_ withAi config)) + _ ← saveConfig(_ withAi config) pov = config.pov game = ctx.me.fold( user ⇒ pov.game.updatePlayer(pov.color, _ withUser user), @@ -47,10 +48,7 @@ final class Processor( } yield pov2 def friend(config: FriendConfig)(implicit ctx: Context): IO[Pov] = for { - _ ← ctx.me.fold( - user ⇒ configRepo.update(user)(_ withFriend config), - io() - ) + _ ← saveConfig(_ withFriend config) pov = config.pov game = ctx.me.fold( user ⇒ pov.game.updatePlayer(pov.color, _ withUser user), @@ -61,10 +59,7 @@ final class Processor( } yield pov def hook(config: HookConfig)(implicit ctx: Context): IO[Hook] = for { - _ ← ctx.me.fold( - user ⇒ configRepo.update(user)(_ withHook config), - io() - ) + _ ← saveConfig(_ withHook config) hook = config hook ctx.me _ ← fisherman add hook } yield hook @@ -83,4 +78,11 @@ final class Processor( color.name -> (domain + routes.Round.player(game fullIdOf color).url) } toMap } + + private def saveConfig(map: UserConfig ⇒ UserConfig)(implicit ctx: Context): IO[Unit] = + ctx.me.fold( + user ⇒ userConfigRepo.update(user) _, + anonConfigRepo.update(ctx.req) _ + )(map) + } diff --git a/app/setup/SetupEnv.scala b/app/setup/SetupEnv.scala index 0782052a1e..03938d06f1 100644 --- a/app/setup/SetupEnv.scala +++ b/app/setup/SetupEnv.scala @@ -25,13 +25,17 @@ final class SetupEnv( import settings._ - lazy val configRepo = new UserConfigRepo(mongodb(UserCollectionConfig)) + lazy val userConfigRepo = new UserConfigRepo(mongodb(UserCollectionConfig)) + + lazy val anonConfigRepo = new AnonConfigRepo(mongodb(AnonCollectionConfig)) lazy val formFactory = new FormFactory( - configRepo = configRepo) + userConfigRepo = userConfigRepo, + anonConfigRepo = anonConfigRepo) lazy val processor = new Processor( - configRepo = configRepo, + userConfigRepo = userConfigRepo, + anonConfigRepo = anonConfigRepo, friendConfigMemo = friendConfigMemo, gameRepo = gameRepo, pgnRepo = pgnRepo, diff --git a/app/setup/UserConfig.scala b/app/setup/UserConfig.scala index cf6a1db9b4..ed40c358e2 100644 --- a/app/setup/UserConfig.scala +++ b/app/setup/UserConfig.scala @@ -2,6 +2,7 @@ package lila package setup import user.User +import ornicar.scalalib.Random import com.novus.salat.annotations.Key @@ -26,8 +27,8 @@ case class UserConfig( object UserConfig { - def default(user: User) = UserConfig( - id = user.id, + def default(id: String): UserConfig = UserConfig( + id = id, ai = AiConfig.default, friend = FriendConfig.default, hook = HookConfig.default) @@ -39,7 +40,7 @@ case class RawUserConfig( friend: RawFriendConfig, hook: RawHookConfig) { - def decode = for { + def decode: Option[UserConfig] = for { trueAi ← ai.decode trueFriend ← friend.decode trueHook ← hook.decode diff --git a/app/setup/UserConfigRepo.scala b/app/setup/UserConfigRepo.scala index ed101bb585..6a2fa694b4 100644 --- a/app/setup/UserConfigRepo.scala +++ b/app/setup/UserConfigRepo.scala @@ -19,9 +19,9 @@ final class UserConfigRepo(collection: MongoCollection) findOneById(user.id) flatMap (_.decode) } except { e ⇒ putStrLn("Can't load config: " + e.getMessage) map (_ ⇒ none[UserConfig]) - } map (_ | UserConfig.default(user)) + } map (_ | UserConfig.default(user.id)) - def save(config: UserConfig): IO[Unit] = io { + private def save(config: UserConfig): IO[Unit] = io { update( DBObject("_id" -> config.id), _grater asDBObject config.encode,