app/ migration WIP

rm0193-mapreduce
Thibault Duplessis 2019-12-04 19:47:46 -06:00
parent e2c18cb6fd
commit 6bc20d9b75
55 changed files with 327 additions and 352 deletions

View File

@ -11,6 +11,7 @@ import lila.user.User
final class Env(
val config: Configuration,
val db: lila.db.Env,
val playApp: Application,
val api: lila.api.Env,
val user: lila.user.Env,
@ -31,7 +32,7 @@ final class Env(
val teamSearch: lila.teamSearch.Env,
val analyse: lila.analyse.Env,
val mod: lila.mod.Env,
val notifyModule: lila.notify.Env,
val notify: lila.notify.Env,
val round: lila.round.Env,
val lobby: lila.lobby.Env,
val setup: lila.setup.Env,
@ -106,9 +107,9 @@ final class Env(
}
def closeAccount(userId: lila.user.User.ID, self: Boolean): Funit = for {
u <- user.userRepo byId userId orFail s"No such user $userId"
u <- user.repo byId userId orFail s"No such user $userId"
goodUser <- !u.lameOrTroll ?? { !playban.api.hasCurrentBan(u.id) }
_ <- user.userRepo.disable(u, keepEmail = !goodUser)
_ <- user.repo.disable(u, keepEmail = !goodUser)
_ <- !goodUser ?? relation.api.fetchFollowing(u.id) flatMap {
activity.write.unfollowAll(u, _)
}
@ -131,7 +132,7 @@ final class Env(
Bus.subscribeFun("garbageCollect") {
case lila.hub.actorApi.security.GarbageCollect(userId, _) =>
user.userRepo.isTroll(userId) foreach { troll =>
user.repo.isTroll(userId) foreach { troll =>
if (troll) kill(userId) // GC can be aborted by reverting the initial SB mark
}
}

View File

@ -26,7 +26,7 @@ final class Account(
FormFuResult(env.user.forms.profile) { err =>
fuccess(html.account.profile(me, err))
} { profile =>
env.user.userRepo.setProfile(me.id, profile) inject Redirect(routes.User show me.username)
env.user.repo.setProfile(me.id, profile) inject Redirect(routes.User show me.username)
}
}
@ -35,7 +35,7 @@ final class Account(
FormFuResult(env.user.forms.username(me)) { err =>
fuccess(html.account.username(me, err))
} { username =>
env.user.userRepo.setUsernameCased(me.id, username) inject Redirect(routes.User show me.username) recoverWith {
env.user.repo.setUsernameCased(me.id, username) inject Redirect(routes.User show me.username) recoverWith {
case e => fuccess(html.account.username(me, env.user.forms.username(me).withGlobalError(e.getMessage)))
}
}
@ -126,7 +126,7 @@ final class Account(
}
}
private def emailForm(user: UserModel) = env.user.userRepo email user.id flatMap {
private def emailForm(user: UserModel) = env.user.repo email user.id flatMap {
env.security.forms.changeEmail(user, _)
}
@ -138,7 +138,7 @@ final class Account(
}
def apiEmail = Scoped(_.Email.Read) { _ => me =>
env.user.userRepo email me.id map {
env.user.repo email me.id map {
_ ?? { email =>
JsonOk(Json.obj("email" -> email.value))
}
@ -188,7 +188,7 @@ final class Account(
implicit val req = ctx.body
helpForm.bindFromRequest.fold(
err => BadRequest(html.account.emailConfirmHelp(err, none)).fuccess,
username => getStatus(env.user.userRepo, username) map { status =>
username => getStatus(env.user.repo, username) map { status =>
Ok(html.account.emailConfirmHelp(helpForm fill username, status.some))
}
)
@ -214,7 +214,7 @@ final class Account(
FormFuResult(form) { err =>
fuccess(html.account.twoFactor.setup(me, err))
} { data =>
env.user.userRepo.setupTwoFactor(me.id, TotpSecret(data.secret)) >>
env.user.repo.setupTwoFactor(me.id, TotpSecret(data.secret)) >>
env.security.store.closeUserExceptSessionId(me.id, currentSessionId) >>
env.push.webSubscriptionApi.unsubscribeByUserExceptSession(me, currentSessionId) inject
Redirect(routes.Account.twoFactor)
@ -230,7 +230,7 @@ final class Account(
FormFuResult(form) { err =>
fuccess(html.account.twoFactor.disable(me, err))
} { _ =>
env.user.userRepo.disableTwoFactor(me.id) inject Redirect(routes.Account.twoFactor)
env.user.repo.disableTwoFactor(me.id) inject Redirect(routes.Account.twoFactor)
}
}
}
@ -264,14 +264,14 @@ final class Account(
// App BC
def kidToggle = Auth { ctx => me =>
env.user.userRepo.setKid(me, !me.kid) inject Ok
env.user.repo.setKid(me, !me.kid) inject Ok
}
def kidPost = Auth { implicit ctx => me =>
env.user.userRepo.setKid(me, getBool("v")) inject Redirect(routes.Account.kid)
env.user.repo.setKid(me, getBool("v")) inject Redirect(routes.Account.kid)
}
def apiKidPost = Scoped(_.Preference.Write) { req => me =>
env.user.userRepo.setKid(me, getBool("v", req)) inject jsonOkResult
env.user.repo.setKid(me, getBool("v", req)) inject jsonOkResult
}
private def currentSessionId(implicit ctx: Context) =

View File

@ -74,7 +74,7 @@ final class Api(
UsersRateLimitPerIP(ip, cost = cost) {
UsersRateLimitGlobal("-", cost = cost, msg = ip.value) {
lila.mon.api.users.cost(cost)
env.user.userRepo nameds usernames map {
env.user.repo nameds usernames map {
_.map { env.user.jsonView(_, none) }
} map toApiResult map toHttp
}
@ -163,7 +163,7 @@ final class Api(
val cost = page * nb.value + 10
UserGamesRateLimit(cost, req) {
lila.mon.api.userGames.cost(cost)
env.user.userRepo named name flatMap {
env.user.repo named name flatMap {
_ ?? { user =>
gameApi.byUser(
user = user,
@ -269,7 +269,7 @@ final class Api(
}
def tournamentsByOwner(name: String) = Action.async { req =>
(name != "lichess") ?? env.user.userRepo.named(name) flatMap {
(name != "lichess") ?? env.user.repo.named(name) flatMap {
_ ?? { user =>
GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
val nb = getInt("nb", req) | Int.MaxValue
@ -309,7 +309,7 @@ final class Api(
def activity(name: String) = ApiRequest { req =>
UserActivityRateLimitPerIP(HTTPRequest lastRemoteAddress req, cost = 1) {
lila.mon.api.activity.cost(1)
env.user.userRepo named name flatMap {
env.user.repo named name flatMap {
_ ?? { user =>
env.activity.read.recent(user) flatMap {
_.map { env.activity.jsonView(_, user) }.sequenceFu

View File

@ -109,7 +109,7 @@ final class Auth(
result => result.toOption match {
case None => InternalServerError("Authentication error").fuccess
case Some(u) =>
env.user.userRepo.email(u.id) foreach {
env.user.repo.email(u.id) foreach {
_ foreach { garbageCollect(u, _) }
}
authenticateUser(u, Some(redirectTo))
@ -210,7 +210,7 @@ final class Auth(
lila.mon.user.register.mustConfirmEmail(mustConfirm.toString)()
val email = env.security.emailAddressValidator.validate(data.realEmail) err s"Invalid email ${data.email}"
val passwordHash = env.user.authenticator passEnc ClearPassword(data.password)
env.user.userRepo.create(data.username, passwordHash, email.acceptable, ctx.blind, none,
env.user.repo.create(data.username, passwordHash, email.acceptable, ctx.blind, none,
mustConfirmEmail = mustConfirm.value)
.orFail(s"No user could be created for ${data.username}")
.addEffect { logSignup(_, email.acceptable, data.fingerPrint, mustConfirm) }
@ -242,7 +242,7 @@ final class Auth(
lila.mon.user.register.mobile()
lila.mon.user.register.mustConfirmEmail(mustConfirm.toString)()
val passwordHash = env.user.authenticator passEnc ClearPassword(data.password)
env.user.userRepo.create(data.username, passwordHash, email.acceptable, false, apiVersion.some,
env.user.repo.create(data.username, passwordHash, email.acceptable, false, apiVersion.some,
mustConfirmEmail = mustConfirm.value)
.orFail(s"No user could be created for ${data.username}")
.addEffect { logSignup(_, email.acceptable, none, mustConfirm) }
@ -289,7 +289,7 @@ final class Auth(
case None => lila.security.EmailConfirm.cookie get ctx.req match {
case None => Ok(accountC.renderCheckYourEmail).fuccess
case Some(userEmail) =>
env.user.userRepo nameExists userEmail.username map {
env.user.repo nameExists userEmail.username map {
case false => Redirect(routes.Auth.signup) withCookies env.lilaCookie.newSession(ctx.req)
case true => Ok(accountC.renderCheckYourEmail)
}
@ -303,15 +303,15 @@ final class Auth(
implicit val req = ctx.body
forms.preloadEmailDns >> forms.fixEmail(userEmail.email).bindFromRequest.fold(
err => BadRequest(html.auth.checkYourEmail(userEmail.some, err.some)).fuccess,
email => env.user.userRepo.named(userEmail.username) flatMap {
email => env.user.repo.named(userEmail.username) flatMap {
_.fold(Redirect(routes.Auth.signup).fuccess) { user =>
env.user.userRepo.mustConfirmEmail(user.id) flatMap {
env.user.repo.mustConfirmEmail(user.id) flatMap {
case false => Redirect(routes.Auth.login).fuccess
case _ =>
val newUserEmail = userEmail.copy(email = EmailAddress(email))
EmailConfirmRateLimit(newUserEmail, ctx.req) {
lila.mon.email.types.fix()
env.user.userRepo.setEmail(user.id, newUserEmail.email) >>
env.user.repo.setEmail(user.id, newUserEmail.email) >>
env.security.emailConfirm.send(user, newUserEmail.email) inject {
Redirect(routes.Auth.checkYourEmail) withCookies
lila.security.EmailConfirm.cookie.make(env.lilaCookie, user, newUserEmail.email)(ctx.req)
@ -336,7 +336,7 @@ final class Auth(
Redirect(routes.Auth.login).fuccess
case Result.JustConfirmed(user) =>
lila.mon.user.register.confirmEmailResult(true)()
env.user.userRepo.email(user.id).flatMap {
env.user.repo.email(user.id).flatMap {
_.?? { email =>
authLog(user.username, email.value, s"Confirmed email ${email.value}")
welcome(user, email)
@ -359,7 +359,7 @@ final class Auth(
_ ?? { hash =>
!me.lame ?? (for {
otherIds <- api.recentUserIdsByFingerHash(hash).map(_.filter(me.id!=))
autoReport <- (otherIds.size >= 2) ?? env.user.userRepo.countEngines(otherIds).flatMap {
autoReport <- (otherIds.size >= 2) ?? env.user.repo.countEngines(otherIds).flatMap {
case nb if nb >= 2 && nb >= otherIds.size / 2 => env.report.api.autoCheatPrintReport(me.id)
case _ => funit
}
@ -381,7 +381,7 @@ final class Auth(
BadRequest(html.auth.bits.passwordReset(err, captcha, false.some))
},
data => {
env.user.userRepo.enabledWithEmail(data.realEmail.normalize) flatMap {
env.user.repo.enabledWithEmail(data.realEmail.normalize) flatMap {
case Some((user, storedEmail)) => {
lila.mon.user.auth.passwordResetRequest("success")()
env.security.passwordReset.send(user, storedEmail) inject Redirect(routes.Auth.passwordResetSent(storedEmail.conceal))
@ -430,8 +430,8 @@ final class Auth(
} { data =>
HasherRateLimit(user.username, ctx.req) { _ =>
env.user.authenticator.setPassword(user.id, ClearPassword(data.newPasswd1)) >>
env.user.userRepo.setEmailConfirmed(user.id).flatMap { _ ?? { e => welcome(user, e) } } >>
env.user.userRepo.disableTwoFactor(user.id) >>
env.user.repo.setEmailConfirmed(user.id).flatMap { _ ?? { e => welcome(user, e) } } >>
env.user.repo.disableTwoFactor(user.id) >>
env.security.store.disconnect(user.id) >>
env.push.webSubscriptionApi.unsubscribeByUser(user) >>
authenticateUser(user) >>-
@ -454,7 +454,7 @@ final class Auth(
BadRequest(html.auth.bits.magicLink(err, captcha, false.some))
},
data =>
env.user.userRepo.enabledWithEmail(data.realEmail.normalize) flatMap {
env.user.repo.enabledWithEmail(data.realEmail.normalize) flatMap {
case Some((user, storedEmail)) => {
MagicLinkRateLimit(user, storedEmail, ctx.req) {
lila.mon.user.auth.magicLinkRequest("success")()

View File

@ -28,7 +28,7 @@ final class Bot(
def command(cmd: String) = ScopedBody(_.Bot.Play) { implicit req => me =>
cmd.split('/') match {
case Array("account", "upgrade") =>
env.user.userRepo.setBot(me) >>
env.user.repo.setBot(me) >>
env.pref.api.setBot(me) >>-
env.user.lightUserApi.invalidate(me.id) inject jsonOkResult recover {
case e: lila.base.LilaException => BadRequest(jsonError(e.getMessage))

View File

@ -49,7 +49,7 @@ final class Challenge(
case None => Ok(html.challenge.mine(c, json, none))
}
}
else (c.challengerUserId ?? env.user.userRepo.named) map { user =>
else (c.challengerUserId ?? env.user.repo.named) map { user =>
Ok(html.challenge.theirs(c, json, user))
},
api = _ => Ok(json).fuccess
@ -138,7 +138,7 @@ final class Challenge(
"username" -> lila.user.DataForm.historicalUsernameField
)).bindFromRequest.fold(
err => funit,
username => env.user.userRepo named username flatMap {
username => env.user.repo named username flatMap {
case None => Redirect(routes.Challenge.show(c.id)).fuccess
case Some(dest) => env.challenge.granter(ctx.me, dest, c.perfType.some) flatMap {
case Some(denied) => showChallenge(c, lila.challenge.ChallengeDenied.translated(denied).some)
@ -155,7 +155,7 @@ final class Challenge(
setupC.PostRateLimit(HTTPRequest lastRemoteAddress req) {
env.setup.forms.api.bindFromRequest.fold(
jsonFormErrorDefaultLang,
config => env.user.userRepo enabledById userId.toLowerCase flatMap { destUser =>
config => env.user.repo enabledById userId.toLowerCase flatMap { destUser =>
destUser ?? { env.challenge.granter(me.some, _, config.perfType) } flatMap {
case Some(denied) =>
BadRequest(jsonError(lila.challenge.ChallengeDenied.translated(denied))).fuccess
@ -189,7 +189,7 @@ final class Challenge(
def rematchOf(gameId: String) = Auth { implicit ctx => me =>
OptionFuResult(env.game.gameRepo game gameId) { g =>
Pov.opponentOfUserId(g, me.id).flatMap(_.userId) ?? env.user.userRepo.byId flatMap {
Pov.opponentOfUserId(g, me.id).flatMap(_.userId) ?? env.user.repo.byId flatMap {
_ ?? { opponent =>
env.challenge.granter(me.some, opponent, g.perfType) flatMap {
case Some(d) => BadRequest(jsonError {

View File

@ -84,7 +84,7 @@ final class ForumTopic(env: Env) extends LilaController(env) with ForumControlle
def participants(topicId: String) = Auth { _ => _ =>
for {
userIds <- postApi userIds topicId
usernames <- env.user.userRepo usernamesByIds userIds
usernames <- env.user.repo usernamesByIds userIds
} yield Ok(Json.toJson(usernames.sortBy(_.toLowerCase)))
}
}

View File

@ -62,7 +62,7 @@ final class Game(
)
private def handleExport(username: String, me: Option[lila.user.User], req: RequestHeader, oauth: Boolean) =
env.user.userRepo named username flatMap {
env.user.repo named username flatMap {
_ ?? { user =>
apiC.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
apiC.GlobalLinearLimitPerUserOption(me) {
@ -119,7 +119,7 @@ final class Game(
private def WithVs(req: RequestHeader)(f: Option[lila.user.User] => Fu[Result]): Fu[Result] =
get("vs", req) match {
case None => f(none)
case Some(name) => env.user.userRepo named name flatMap {
case Some(name) => env.user.repo named name flatMap {
case None => notFoundJson(s"No such opponent: $name")
case Some(user) => f(user.some)
}

View File

@ -22,7 +22,7 @@ final class I18n(env: Env) extends LilaController(env) {
code => {
val lang = toLang(code) err "Universe is collapsing"
ctx.me.filterNot(_.lang contains lang.code).?? { me =>
env.user.userRepo.setLang(me.id, lang.code)
env.user.repo.setLang(me.id, lang.code)
} >> negotiate(
html = {
val redir = Redirect {

View File

@ -57,7 +57,7 @@ final class Insight(env: Env) extends LilaController(env) {
}
private def Accessible(username: String)(f: lila.user.User => Fu[Result])(implicit ctx: Context) =
env.user.userRepo named username flatMap {
env.user.repo named username flatMap {
_.fold(notFound) { u =>
env.insight.share.grant(u, ctx.me) flatMap {
case true => f(u)

View File

@ -392,7 +392,7 @@ private[controllers] abstract class LilaController(val env: Env)
env.relation.online.friendsOf(me.id) zip
env.team.api.nbRequests(me.id) zip
env.challenge.api.countInFor.get(me.id) zip
env.notifyModule.api.unreadCount(Notifies(me.id)).dmap(_.value) zip
env.notify.api.unreadCount(Notifies(me.id)).dmap(_.value) zip
env.mod.inquiryApi.forMod(me)
} else fuccess {
((((OnlineFriends.empty, 0), 0), 0), none)

View File

@ -88,9 +88,9 @@ final class Main(
import chess.format.pgn.Glyph
import lila.tree.Node.glyphWriter
Ok(Json.obj(
"move" -> Glyph.MoveAssessment.display,
"position" -> Glyph.PositionAssessment.display,
"observation" -> Glyph.Observation.display
"move" -> (Glyph.MoveAssessment.display: List[Glyph]),
"position" -> (Glyph.PositionAssessment.display: List[Glyph]),
"observation" -> (Glyph.Observation.display: List[Glyph])
)) as JSON
}
val glyphs = Action(glyphsResult)
@ -147,14 +147,14 @@ Disallow: /games/export
if (ctx.isAuth) fuccess(Redirect(routes.Lobby.home))
else fuccess {
Redirect(s"${routes.Lobby.home}#pool/10+0").withCookies(
lila.common.LilaCookie.withSession { s =>
env.lilaCookie.withSession { s =>
s + ("theme" -> "ic") + ("pieceSet" -> "icpieces")
}
)
}
}
def legacyQaQuestion(id: Int, slug: String) = Open { implicit ctx =>
def legacyQaQuestion(id: Int, slug: String) = Open { _ =>
MovedPermanently {
val faq = routes.Main.faq.url
id match {
@ -179,6 +179,4 @@ Disallow: /games/export
}
}.fuccess
}
def versionedAsset(version: String, file: String) = Assets.at(path = "/public", file)
}

View File

@ -132,7 +132,7 @@ final class Message(env: Env) extends LilaController(env) {
}
private def renderForm(me: UserModel, title: Option[String], f: Form[_] => Form[_])(implicit ctx: Context): Fu[Frag] =
get("user") ?? env.user.userRepo.named flatMap { user =>
get("user") ?? env.user.repo.named flatMap { user =>
user.fold(fuTrue)(u => security.canMessage(me.id, u.id)) map { canMessage =>
html.message.form(
f(forms thread me),

View File

@ -5,7 +5,7 @@ import lila.app._
import lila.chat.Chat
import lila.common.{ IpAddress, EmailAddress, HTTPRequest }
import lila.mod.UserSearch
import lila.report.{ Suspect, Mod => AsMod, SuspectId }
import lila.report.{ Suspect, Mod => AsMod }
import lila.security.{ Permission, FingerHash }
import lila.user.{ User => UserModel, Title }
import ornicar.scalalib.Zero
@ -14,9 +14,12 @@ import views._
import play.api.data._
import play.api.data.Forms._
import play.api.mvc._
import scala.concurrent.duration._
final class Mod(env: Env) extends LilaController(env) {
final class Mod(
env: Env,
reportC: Report,
userC: User
) extends LilaController(env) {
private def modApi = env.mod.api
private def modLogApi = env.mod.logApi
@ -30,7 +33,7 @@ final class Mod(env: Env) extends LilaController(env) {
} yield (inquiry, sus).some
}
}(ctx => me => {
case (inquiry, suspect) => Report.onInquiryClose(inquiry, me, suspect.some)(ctx)
case (inquiry, suspect) => reportC.onInquiryClose(inquiry, me, suspect.some)(ctx)
})
def publicChat = Secure(_.ChatTimeout) { implicit ctx => _ =>
@ -48,7 +51,7 @@ final class Mod(env: Env) extends LilaController(env) {
} yield (inquiry, suspect).some
}
}(ctx => me => {
case (inquiry, suspect) => Report.onInquiryClose(inquiry, me, suspect.some)(ctx)
case (inquiry, suspect) => reportC.onInquiryClose(inquiry, me, suspect.some)(ctx)
})
def troll(username: String, v: Boolean) = OAuthModBody(_.Shadowban) { me =>
@ -59,7 +62,7 @@ final class Mod(env: Env) extends LilaController(env) {
} yield (inquiry, suspect).some
}
}(ctx => me => {
case (inquiry, suspect) => Report.onInquiryClose(inquiry, me, suspect.some)(ctx)
case (inquiry, suspect) => reportC.onInquiryClose(inquiry, me, suspect.some)(ctx)
})
def warn(username: String, subject: String) = OAuthModBody(_.ModMessage) { me =>
@ -74,7 +77,7 @@ final class Mod(env: Env) extends LilaController(env) {
}
}
}(ctx => me => {
case (inquiry, suspect) => Report.onInquiryClose(inquiry, me, suspect.some)(ctx)
case (inquiry, suspect) => reportC.onInquiryClose(inquiry, me, suspect.some)(ctx)
})
def ipBan(username: String, v: Boolean) = OAuthMod(_.IpBan) { _ => me =>
@ -91,14 +94,14 @@ final class Mod(env: Env) extends LilaController(env) {
}(actionResult(username))
def disableTwoFactor(username: String) = Secure(_.DisableTwoFactor) { implicit ctx => me =>
modApi.disableTwoFactor(me.id, username) >> User.modZoneOrRedirect(username, me)
modApi.disableTwoFactor(me.id, username) >> userC.modZoneOrRedirect(username, me)
}
def closeAccount(username: String) = OAuthMod(_.CloseAccount) { _ => me =>
env.user.userRepo named username flatMap {
env.user.repo named username flatMap {
_ ?? { user =>
modLogApi.closeAccount(me.id, user.id) >>
env.current.closeAccount(user.id, self = false) map some
env.closeAccount(user.id, self = false) map some
}
}
}(actionResult(username))
@ -124,7 +127,7 @@ final class Mod(env: Env) extends LilaController(env) {
env.mod.impersonate.stop(me)
Redirect(routes.User.show(me.username))
}
else if (isGranted(_.Impersonate)) OptionFuRedirect(env.user.userRepo named username) { user =>
else if (isGranted(_.Impersonate)) OptionFuRedirect(env.user.repo named username) { user =>
env.mod.impersonate.start(me, user)
fuccess(routes.User.show(user.username))
}
@ -144,7 +147,7 @@ final class Mod(env: Env) extends LilaController(env) {
def setEmail(username: String) = SecureBody(_.SetEmail) { implicit ctx => me =>
implicit def req = ctx.body
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
env.security.forms.modEmail(user).bindFromRequest.fold(
err => BadRequest(err.toString).fuccess,
rawEmail => {
@ -168,13 +171,13 @@ final class Mod(env: Env) extends LilaController(env) {
private def communications(username: String, priv: Boolean) = Secure {
perms => if (priv) perms.ViewPrivateComms else perms.Shadowban
} { implicit ctx => me =>
OptionFuOk(env.user.userRepo named username) { user =>
OptionFuOk(env.user.repo named username) { user =>
env.game.gameRepo.recentPovsByUserFromSecondary(user, 80) flatMap { povs =>
priv.?? {
env.chat.api.playerChat optionsByOrderedIds povs.map(_.gameId).map(Chat.Id.apply)
} zip
priv.?? {
lila.message.ThreadRepo.visibleOrDeletedByUser(user.id, 60).map {
env.message.repo.visibleOrDeletedByUser(user.id, 60).map {
_ filter (_ hasPostsWrittenBy user.id) take 30
}
} zip
@ -184,7 +187,7 @@ final class Mod(env: Env) extends LilaController(env) {
env.mod.logApi.userHistory(user.id) zip
env.report.api.inquiries.ofModId(me.id) flatMap {
case chats ~ threads ~ publicLines ~ spy ~ notes ~ history ~ inquiry =>
lila.security.UserSpy.withMeSortedWithEmails(user, spy.otherUsers) map { othersWithEmail =>
lila.security.UserSpy.withMeSortedWithEmails(env.user.repo, user, spy.otherUsers) map { othersWithEmail =>
if (priv && !inquiry.??(_.isRecentCommOf(Suspect(user))))
env.slack.api.commlog(mod = me, user = user, inquiry.map(_.oldestAtom.by.value))
val povWithChats = (povs zip chats) collect {
@ -214,15 +217,15 @@ final class Mod(env: Env) extends LilaController(env) {
s"${routes.User.show(username).url}${mod ?? "?mod"}"
def refreshUserAssess(username: String) = Secure(_.MarkEngine) { implicit ctx => me =>
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
assessApi.refreshAssessByUsername(username) >>
env.irwin.api.requests.fromMod(Suspect(user), AsMod(me)) >>
User.renderModZoneActions(username)
userC.renderModZoneActions(username)
}
}
def spontaneousInquiry(username: String) = Secure(_.SeeReport) { implicit ctx => me =>
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
env.report.api.inquiries.spontaneous(AsMod(me), Suspect(user)) inject redirect(user.username, true)
}
}
@ -259,8 +262,8 @@ final class Mod(env: Env) extends LilaController(env) {
val hash = FingerHash(fh)
for {
uids <- env.security.api recentUserIdsByFingerHash hash
users <- env.user.userRepo usersFromSecondary uids.reverse
withEmails <- env.user.userRepo withEmailsU users
users <- env.user.repo usersFromSecondary uids.reverse
withEmails <- env.user.repo withEmailsU users
uas <- env.security.api.printUas(hash)
} yield Ok(html.mod.search.print(hash, withEmails, uas, env.security.printBan blocks hash))
}
@ -271,14 +274,14 @@ final class Mod(env: Env) extends LilaController(env) {
}
def chatUser(username: String) = Secure(_.ChatTimeout) { implicit ctx => me =>
implicit val lightUser = env.user.lightUserSync _
implicit val lightUser = env.user.lightUserSync
JsonOptionOk {
env.chat.api.userChat userModInfo username map2 lila.chat.JsonView.userModInfo
}
}
def permissions(username: String) = Secure(_.ChangePermission) { implicit ctx => me =>
OptionOk(env.user.userRepo named username) { user =>
OptionOk(env.user.repo named username) { user =>
html.mod.permissions(user)
}
}
@ -286,7 +289,7 @@ final class Mod(env: Env) extends LilaController(env) {
def savePermissions(username: String) = SecureBody(_.ChangePermission) { implicit ctx => me =>
implicit def req = ctx.body
import lila.security.Permission
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
Form(single(
"permissions" -> list(text.verifying { str =>
Permission.allButSuperAdmin.exists(_.name == str)
@ -317,7 +320,7 @@ final class Mod(env: Env) extends LilaController(env) {
lila.mon.user.register.modConfirmEmail()
modApi.setEmail(me.id, user.id, setEmail)
} >>
env.user.userRepo.email(user.id) map { email =>
env.user.repo.email(user.id) map { email =>
Ok(html.mod.emailConfirm("", user.some, email)).some
}
case _ => fuccess(none)
@ -342,7 +345,7 @@ final class Mod(env: Env) extends LilaController(env) {
}(ctx => me => _ => Redirect(routes.Mod.chatPanic).fuccess)
def eventStream = OAuthSecure(_.Admin) { req => me =>
noProxyBuffer(Ok.chunked(env.mod.stream.enumerator)).fuccess
noProxyBuffer(Ok.chunked(env.mod.stream())).fuccess
}
private def withSuspect[A](username: String)(f: Suspect => Fu[A])(implicit zero: Zero[A]): Fu[A] =
@ -368,6 +371,6 @@ final class Mod(env: Env) extends LilaController(env) {
)
private def actionResult(username: String)(ctx: Context)(me: UserModel)(res: Any) =
if (HTTPRequest isSynchronousHttp ctx.req) fuccess(Mod.redirect(username))
else User.renderModZoneActions(username)(ctx)
if (HTTPRequest isSynchronousHttp ctx.req) fuccess(redirect(username))
else userC.renderModZoneActions(username)(ctx)
}

View File

@ -7,14 +7,12 @@ import play.api.libs.json._
final class Notify(env: Env) extends LilaController(env) {
val env = env.notifyModule
import env.jsonHandlers._
import env.notify.jsonHandlers._
def recent(page: Int) = Auth { implicit ctx => me =>
XhrOrRedirectHome {
val notifies = Notifies(me.id)
env.api.getNotificationsAndCount(notifies, page) map { res =>
env.notify.api.getNotificationsAndCount(notifies, page) map { res =>
Ok(Json toJson res) as JSON
}
}

View File

@ -1,56 +1,53 @@
package controllers
import play.api.libs.json.JsValue
import play.api.mvc._
import lila.api.Context
import lila.app._
import lila.oauth.{ OAuthApp => App }
import views._
final class OAuthApp(env: Env) extends LilaController(env) {
private val env = env.oAuth
private val appApi = env.oAuth.appApi
private val forms = env.oAuth.forms
def index = Auth { implicit ctx => me =>
env.appApi.list(me) map { apps =>
appApi.list(me) map { apps =>
Ok(html.oAuth.app.index(apps))
}
}
def create = Auth { implicit ctx => me =>
Ok(html.oAuth.app.form.create(env.forms.app.create)).fuccess
Ok(html.oAuth.app.form.create(forms.app.create)).fuccess
}
def createApply = AuthBody { implicit ctx => me =>
implicit val req = ctx.body
env.forms.app.create.bindFromRequest.fold(
forms.app.create.bindFromRequest.fold(
err => BadRequest(html.oAuth.app.form.create(err)).fuccess,
setup => {
val app = setup make me
env.appApi.create(app) inject Redirect(routes.OAuthApp.edit(app.clientId.value))
appApi.create(app) inject Redirect(routes.OAuthApp.edit(app.clientId.value))
}
)
}
def edit(id: String) = Auth { implicit ctx => me =>
OptionFuResult(env.appApi.findBy(App.Id(id), me)) { app =>
Ok(html.oAuth.app.form.edit(app, env.forms.app.edit(app))).fuccess
OptionFuResult(appApi.findBy(App.Id(id), me)) { app =>
Ok(html.oAuth.app.form.edit(app, forms.app.edit(app))).fuccess
}
}
def update(id: String) = AuthBody { implicit ctx => me =>
OptionFuResult(env.appApi.findBy(App.Id(id), me)) { app =>
OptionFuResult(appApi.findBy(App.Id(id), me)) { app =>
implicit val req = ctx.body
env.forms.app.edit(app).bindFromRequest.fold(
forms.app.edit(app).bindFromRequest.fold(
err => BadRequest(html.oAuth.app.form.edit(app, err)).fuccess,
data => env.appApi.update(app) { data.update(_) } map { r => Redirect(routes.OAuthApp.edit(app.clientId.value)) }
data => appApi.update(app) { data.update(_) } map { r => Redirect(routes.OAuthApp.edit(app.clientId.value)) }
)
}
}
def delete(id: String) = Auth { implicit ctx => me =>
env.appApi.deleteBy(App.Id(id), me) inject
def delete(id: String) = Auth { _ => me =>
appApi.deleteBy(App.Id(id), me) inject
Redirect(routes.OAuthApp.index)
}
}

View File

@ -1,38 +1,34 @@
package controllers
import play.api.libs.json.JsValue
import play.api.mvc._
import lila.api.Context
import lila.app._
import lila.oauth.AccessToken
import views._
final class OAuthToken(env: Env) extends LilaController(env) {
private val env = env.oAuth
private val tokenApi = env.oAuth.tokenApi
def index = Auth { implicit ctx => me =>
env.tokenApi.list(me) map { tokens =>
tokenApi.list(me) map { tokens =>
Ok(html.oAuth.token.index(tokens))
}
}
def create = Auth { implicit ctx => me =>
Ok(html.oAuth.token.create(env.forms.token.create, me)).fuccess
Ok(html.oAuth.token.create(env.oAuth.forms.token.create, me)).fuccess
}
def createApply = AuthBody { implicit ctx => me =>
implicit val req = ctx.body
env.forms.token.create.bindFromRequest.fold(
env.oAuth.forms.token.create.bindFromRequest.fold(
err => BadRequest(html.oAuth.token.create(err, me)).fuccess,
setup => env.tokenApi.create(setup make me) inject
setup => tokenApi.create(setup make me) inject
Redirect(routes.OAuthToken.index)
)
}
def delete(id: String) = Auth { implicit ctx => me =>
env.tokenApi.deleteBy(AccessToken.Id(id), me) inject
def delete(id: String) = Auth { _ => me =>
tokenApi.deleteBy(AccessToken.Id(id), me) inject
Redirect(routes.OAuthToken.index)
}
}

View File

@ -1,8 +1,5 @@
package controllers
import play.api.mvc._
import scala.concurrent.duration._
import lila.app._
import lila.common.HTTPRequest.isApiOrApp
import lila.common.ResponseHeaders.allowMethods

View File

@ -1,9 +1,11 @@
package controllers
import lila.app._
import views._
final class Page(env: Env) extends LilaController(env) {
final class Page(
env: Env,
prismicC: Prismic
) extends LilaController(env) {
val thanks = helpBookmark("thanks")
val help = helpBookmark("help")
@ -14,7 +16,7 @@ final class Page(env: Env) extends LilaController(env) {
private def helpBookmark(name: String) = Open { implicit ctx =>
pageHit
OptionOk(Prismic getBookmark name) {
OptionOk(prismicC getBookmark name) {
case (doc, resolver) => views.html.site.help.page(name, doc, resolver)
}
}
@ -23,14 +25,14 @@ final class Page(env: Env) extends LilaController(env) {
private def bookmark(name: String) = Open { implicit ctx =>
pageHit
OptionOk(Prismic getBookmark name) {
OptionOk(prismicC getBookmark name) {
case (doc, resolver) => views.html.site.page(doc, resolver)
}
}
def source = Open { implicit ctx =>
pageHit
OptionOk(Prismic getBookmark "source") {
OptionOk(prismicC getBookmark "source") {
case (doc, resolver) => views.html.site.help.source(doc, resolver)
}
}
@ -38,7 +40,7 @@ final class Page(env: Env) extends LilaController(env) {
def variantHome = Open { implicit ctx =>
import play.api.libs.json._
negotiate(
html = OptionOk(Prismic getBookmark "variant") {
html = OptionOk(prismicC getBookmark "variant") {
case (doc, resolver) => views.html.site.variant.home(doc, resolver)
},
api = _ => Ok(JsArray(chess.variant.Variant.all.map { v =>
@ -55,7 +57,7 @@ final class Page(env: Env) extends LilaController(env) {
(for {
variant <- chess.variant.Variant.byKey get key
perfType <- lila.rating.PerfType byVariant variant
} yield OptionOk(Prismic getVariant variant) {
} yield OptionOk(prismicC getVariant variant) {
case (doc, resolver) => views.html.site.variant.show(doc, resolver, variant, perfType)
}) | notFound
}

View File

@ -19,7 +19,7 @@ final class Plan(env: Env) extends LilaController(env) {
import lila.plan.PlanApi.SyncResult._
env.plan.api.sync(me) flatMap {
case ReloadUser => Redirect(routes.Plan.index).fuccess
case Synced(Some(patron), None) => env.user.userRepo email me.id flatMap { email =>
case Synced(Some(patron), None) => env.user.repo email me.id flatMap { email =>
renderIndex(email, patron.some)
}
case Synced(Some(patron), Some(customer)) => indexPatron(me, patron, customer)
@ -42,7 +42,7 @@ final class Plan(env: Env) extends LilaController(env) {
private def indexAnon(implicit ctx: Context) = renderIndex(email = none, patron = none)
private def indexFreeUser(me: UserModel)(implicit ctx: Context) =
env.user.userRepo email me.id flatMap { email =>
env.user.repo email me.id flatMap { email =>
renderIndex(email, patron = none)
}
@ -62,7 +62,7 @@ final class Plan(env: Env) extends LilaController(env) {
env.plan.api.customerInfo(me, customer) flatMap {
case Some(info: MonthlyCustomerInfo) => Ok(html.plan.indexStripe(me, patron, info)).fuccess
case Some(info: OneTimeCustomerInfo) => renderIndex(info.customer.email map EmailAddress.apply, patron.some)
case None => env.user.userRepo email me.id flatMap { email =>
case None => env.user.repo email me.id flatMap { email =>
renderIndex(email, patron.some)
}
}
@ -82,7 +82,7 @@ final class Plan(env: Env) extends LilaController(env) {
) inject Redirect(routes.Plan.index)
}
def cancel = AuthBody { implicit ctx => me =>
def cancel = AuthBody { _ => me =>
env.plan.api.cancel(me) inject Redirect(routes.Plan.index())
}
@ -134,7 +134,7 @@ final class Plan(env: Env) extends LilaController(env) {
name = ipn.name,
txnId = ipn.txnId,
ip = lila.common.HTTPRequest.lastRemoteAddress(req).value,
key = lila.plan.PayPalIpnKey(get("key", req) | "N/A")
key = get("key", req) | "N/A"
) inject Ok
)
}

View File

@ -11,23 +11,28 @@ import lila.study.{ Chapter, Study => StudyModel }
import lila.tree.Node.partitionTreeJsonWriter
import views._
final class Practice(env: Env) extends LilaController(env) {
final class Practice(
env: Env,
userAnalysisC: UserAnalysis
) extends LilaController(env) {
val api = env.practice.api
def index = Open { implicit ctx =>
pageHit
env.api.get(ctx.me) flatMap { up =>
api.get(ctx.me) flatMap { up =>
NoCache(Ok(html.practice.index(up))).fuccess
}
}
def show(sectionId: String, studySlug: String, studyId: String) = Open { implicit ctx =>
pageHit
OptionFuResult(env.api.getStudyWithFirstOngoingChapter(ctx.me, studyId))(showUserPractice)
OptionFuResult(api.getStudyWithFirstOngoingChapter(ctx.me, studyId))(showUserPractice)
}
def showChapter(sectionId: String, studySlug: String, studyId: String, chapterId: String) = Open { implicit ctx =>
pageHit
OptionFuResult(env.api.getStudyWithChapter(ctx.me, studyId, chapterId))(showUserPractice)
OptionFuResult(api.getStudyWithChapter(ctx.me, studyId, chapterId))(showUserPractice)
}
def showSection(sectionId: String) =
@ -37,7 +42,7 @@ final class Practice(env: Env) extends LilaController(env) {
redirectTo(sectionId)(_.studies.find(_.slug == studySlug))
private def redirectTo(sectionId: String)(select: PracticeSection => Option[PracticeStudy]) = Open { implicit ctx =>
env.api.structure.get.flatMap { struct =>
api.structure.get.flatMap { struct =>
struct.sections.find(_.id == sectionId).fold(notFound) { section =>
select(section) ?? { study =>
Redirect(routes.Practice.show(section.id, study.slug, study.id.value)).fuccess
@ -57,7 +62,7 @@ final class Practice(env: Env) extends LilaController(env) {
}
def chapter(studyId: String, chapterId: String) = Open { implicit ctx =>
OptionFuResult(env.api.getStudyWithChapter(ctx.me, studyId, chapterId)) { us =>
OptionFuResult(api.getStudyWithChapter(ctx.me, studyId, chapterId)) { us =>
analysisJson(us) map {
case (analysisJson, studyJson) => Ok(Json.obj(
"study" -> studyJson,
@ -69,9 +74,9 @@ final class Practice(env: Env) extends LilaController(env) {
private def analysisJson(us: UserStudy)(implicit ctx: Context): Fu[(JsObject, JsObject)] = us match {
case UserStudy(_, _, chapters, WithChapter(study, chapter), _) =>
studyenv.jsonView(study, chapters, chapter, ctx.me) map { studyJson =>
env.study.jsonView(study, chapters, chapter, ctx.me) map { studyJson =>
val initialFen = chapter.root.fen.some
val pov = UserAnalysis.makePov(initialFen, chapter.setup.variant)
val pov = userAnalysisC.makePov(initialFen, chapter.setup.variant)
val baseData = env.round.jsonView.userAnalysisJson(pov, ctx.pref, initialFen, chapter.setup.orientation, owner = false, me = ctx.me)
val analysis = baseData ++ Json.obj(
"treeParts" -> partitionTreeJsonWriter.writes {
@ -84,28 +89,28 @@ final class Practice(env: Env) extends LilaController(env) {
}
def complete(chapterId: String, nbMoves: Int) = Auth { implicit ctx => me =>
env.api.progress.setNbMoves(me, chapterId, lila.practice.PracticeProgress.NbMoves(nbMoves))
api.progress.setNbMoves(me, chapterId, lila.practice.PracticeProgress.NbMoves(nbMoves))
}
def reset = AuthBody { implicit ctx => me =>
env.api.progress.reset(me) inject Redirect(routes.Practice.index)
def reset = AuthBody { _ => me =>
api.progress.reset(me) inject Redirect(routes.Practice.index)
}
def config = Auth { implicit ctx => me =>
for {
struct <- env.api.structure.get
form <- env.api.config.form
struct <- api.structure.get
form <- api.config.form
} yield Ok(html.practice.config(struct, form))
}
def configSave = SecureBody(_.PracticeConfig) { implicit ctx => me =>
implicit val req = ctx.body
env.api.config.form.flatMap { form =>
api.config.form.flatMap { form =>
FormFuResult(form) { err =>
env.api.structure.get map { html.practice.config(_, err) }
api.structure.get map { html.practice.config(_, err) }
} { text =>
~env.api.config.set(text).right.toOption >>-
env.api.structure.clear >>
~api.config.set(text).right.toOption >>-
api.structure.clear >>
env.mod.logApi.practiceConfig(me.id) inject Redirect(routes.Practice.config)
}
}

View File

@ -4,7 +4,6 @@ import play.api.mvc._
import lila.api.Context
import lila.app._
import lila.common.LilaCookie
import views._
final class Pref(env: Env) extends LilaController(env) {
@ -43,9 +42,8 @@ final class Pref(env: Env) extends LilaController(env) {
}
def set(name: String) = OpenBody { implicit ctx =>
implicit val req = ctx.body
if (name == "zoom") {
Ok.withCookies(LilaCookie.session("zoom2", (getInt("v") | 185).toString)).fuccess
Ok.withCookies(env.lilaCookie.session("zoom2", (getInt("v") | 185).toString)).fuccess
} else {
implicit val req = ctx.body
(setters get name) ?? {
@ -82,5 +80,5 @@ final class Pref(env: Env) extends LilaController(env) {
private def save(name: String)(value: String, ctx: Context): Fu[Cookie] =
ctx.me ?? {
api.setPrefString(_, name, value)
} inject LilaCookie.session(name, value)(ctx.req)
} inject env.lilaCookie.session(name, value)(ctx.req)
}

View File

@ -2,7 +2,6 @@ package controllers
import scala.concurrent.duration._
import io.prismic.Fragment.DocumentLink
import io.prismic.{ Api => PrismicApi, _ }
import lila.app._

View File

@ -16,7 +16,7 @@ final class Push(env: Env) extends LilaController(env) {
env.push.unregisterDevices(me)
}
def webSubscribe = AuthBody(BodyParsers.parse.json) { implicit ctx => me =>
def webSubscribe = AuthBody(parse.json) { implicit ctx => me =>
val currentSessionId = ~env.security.api.reqSessionId(ctx.req)
ctx.body.body.validate[WebSubscription].fold(
err => BadRequest(err.toString).fuccess,

View File

@ -5,12 +5,16 @@ import play.api.mvc._
import lila.api.Context
import lila.app._
import lila.common.{ HTTPRequest, IpAddress, MaxPerSecond }
import lila.common.config.MaxPerSecond
import lila.common.{ HTTPRequest, IpAddress }
import lila.game.PgnDump
import lila.puzzle.{ PuzzleId, Result, Puzzle => PuzzleModel, UserInfos }
import views._
final class Puzzle(env: Env) extends LilaController(env) {
final class Puzzle(
env: Env,
apiC: Api
) extends LilaController(env) {
private def renderJson(
puzzle: PuzzleModel,
@ -19,7 +23,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
voted: Option[Boolean],
round: Option[lila.puzzle.Round] = None,
result: Option[Result] = None
)(implicit ctx: Context): Fu[JsObject] = env.jsonView(
)(implicit ctx: Context): Fu[JsObject] = env.puzzle.jsonView(
puzzle = puzzle,
userInfos = userInfos,
round = round,
@ -30,16 +34,16 @@ final class Puzzle(env: Env) extends LilaController(env) {
)
private def renderShow(puzzle: PuzzleModel, mode: String)(implicit ctx: Context) =
env userInfos ctx.me flatMap { infos =>
env.puzzle userInfos ctx.me flatMap { infos =>
renderJson(puzzle = puzzle, userInfos = infos, mode = mode, voted = none) map { json =>
views.html.puzzle.show(puzzle, data = json, pref = env.jsonView.pref(ctx.pref))
views.html.puzzle.show(puzzle, data = json, pref = env.puzzle.jsonView.pref(ctx.pref))
}
}
def daily = Open { implicit ctx =>
NoBot {
OptionFuResult(env.daily.get flatMap {
_.map(_.id) ?? env.api.puzzle.find
OptionFuResult(env.puzzle.daily.get flatMap {
_.map(_.id) ?? env.puzzle.api.puzzle.find
}) { puzzle =>
negotiate(
html = renderShow(puzzle, "play") map { Ok(_) },
@ -51,7 +55,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
def home = Open { implicit ctx =>
NoBot {
env.selector(ctx.me) flatMap { puzzle =>
env.puzzle.selector(ctx.me) flatMap { puzzle =>
renderShow(puzzle, if (ctx.isAuth) "play" else "try") map { Ok(_) }
}
}
@ -59,7 +63,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
def show(id: PuzzleId) = Open { implicit ctx =>
NoBot {
OptionFuOk(env.api.puzzle find id) { puzzle =>
OptionFuOk(env.puzzle.api.puzzle find id) { puzzle =>
renderShow(puzzle, "play")
}
}
@ -68,13 +72,13 @@ final class Puzzle(env: Env) extends LilaController(env) {
def load(id: PuzzleId) = Open { implicit ctx =>
NoBot {
XhrOnly {
OptionFuOk(env.api.puzzle find id)(puzzleJson) map (_ as JSON)
OptionFuOk(env.puzzle.api.puzzle find id)(puzzleJson) map (_ as JSON)
}
}
}
private def puzzleJson(puzzle: PuzzleModel)(implicit ctx: Context) =
env userInfos ctx.me flatMap { infos =>
env.puzzle userInfos ctx.me flatMap { infos =>
renderJson(puzzle, infos, if (ctx.isAuth) "play" else "try", voted = none)
}
@ -82,7 +86,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
def newPuzzle = Open { implicit ctx =>
NoBot {
XhrOnly {
env.selector(ctx.me) flatMap puzzleJson map { json =>
env.puzzle.selector(ctx.me) flatMap puzzleJson map { json =>
Ok(json) as JSON
}
}
@ -92,19 +96,19 @@ final class Puzzle(env: Env) extends LilaController(env) {
// mobile app BC
def round(id: PuzzleId) = OpenBody { implicit ctx =>
implicit val req = ctx.body
OptionFuResult(env.api.puzzle find id) { puzzle =>
OptionFuResult(env.puzzle.api.puzzle find id) { puzzle =>
if (puzzle.mate) lila.mon.puzzle.round.mate()
else lila.mon.puzzle.round.material()
env.forms.round.bindFromRequest.fold(
env.puzzle.forms.round.bindFromRequest.fold(
jsonFormError,
resultInt => {
val result = Result(resultInt == 1)
ctx.me match {
case Some(me) => for {
(round, mode) <- env.finisher(puzzle, me, result, mobile = true)
me2 <- if (mode.rated) env.user.userRepo byId me.id map (_ | me) else fuccess(me)
infos <- env userInfos me2
voted <- ctx.me.?? { env.api.vote.value(puzzle.id, _) }
(round, mode) <- env.puzzle.finisher(puzzle, me, result, mobile = true)
me2 <- if (mode.rated) env.user.repo byId me.id map (_ | me) else fuccess(me)
infos <- env.puzzle userInfos me2
voted <- ctx.me.?? { env.puzzle.api.vote.value(puzzle.id, _) }
data <- renderJson(puzzle, infos.some, "view", voted = voted, result = result.some, round = round.some)
} yield {
lila.mon.puzzle.round.user()
@ -113,7 +117,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
}
case None =>
lila.mon.puzzle.round.anon()
env.finisher.incPuzzleAttempts(puzzle)
env.puzzle.finisher.incPuzzleAttempts(puzzle)
renderJson(puzzle, none, "view", result = result.some, voted = none) map { data =>
val d2 = data ++ Json.obj("win" -> result.win)
Ok(d2)
@ -128,22 +132,22 @@ final class Puzzle(env: Env) extends LilaController(env) {
def round2(id: PuzzleId) = OpenBody { implicit ctx =>
NoBot {
implicit val req = ctx.body
OptionFuResult(env.api.puzzle find id) { puzzle =>
OptionFuResult(env.puzzle.api.puzzle find id) { puzzle =>
if (puzzle.mate) lila.mon.puzzle.round.mate()
else lila.mon.puzzle.round.material()
env.forms.round.bindFromRequest.fold(
env.puzzle.forms.round.bindFromRequest.fold(
jsonFormError,
resultInt => ctx.me match {
case Some(me) => for {
(round, mode) <- env.finisher(
(round, mode) <- env.puzzle.finisher(
puzzle = puzzle,
user = me,
result = Result(resultInt == 1),
mobile = lila.api.Mobile.Api.requested(ctx.req)
)
me2 <- if (mode.rated) env.user.userRepo byId me.id map (_ | me) else fuccess(me)
infos <- env userInfos me2
voted <- ctx.me.?? { env.api.vote.value(puzzle.id, _) }
me2 <- if (mode.rated) env.user.repo byId me.id map (_ | me) else fuccess(me)
infos <- env.puzzle userInfos me2
voted <- ctx.me.?? { env.puzzle.api.vote.value(puzzle.id, _) }
} yield {
lila.mon.puzzle.round.user()
Ok(Json.obj(
@ -154,7 +158,7 @@ final class Puzzle(env: Env) extends LilaController(env) {
}
case None =>
lila.mon.puzzle.round.anon()
env.finisher.incPuzzleAttempts(puzzle)
env.puzzle.finisher.incPuzzleAttempts(puzzle)
Ok(Json.obj("user" -> false)).fuccess
}
) map (_ as JSON)
@ -165,10 +169,10 @@ final class Puzzle(env: Env) extends LilaController(env) {
def vote(id: PuzzleId) = AuthBody { implicit ctx => me =>
NoBot {
implicit val req = ctx.body
env.forms.vote.bindFromRequest.fold(
env.puzzle.forms.vote.bindFromRequest.fold(
jsonFormError,
vote => env.api.vote.find(id, me) flatMap {
v => env.api.vote.update(id, me, v, vote == 1)
vote => env.puzzle.api.vote.find(id, me) flatMap {
v => env.puzzle.api.vote.update(id, me, v, vote == 1)
} map {
case (p, a) =>
if (vote == 1) lila.mon.puzzle.vote.up()
@ -184,28 +188,28 @@ final class Puzzle(env: Env) extends LilaController(env) {
negotiate(
html = notFound,
api = _ => for {
puzzles <- env.batch.select(
puzzles <- env.puzzle.batch.select(
me,
nb = getInt("nb") getOrElse 50 atLeast 1 atMost 100,
after = getInt("after")
)
userInfo <- env userInfos me
json <- env.jsonView.batch(puzzles, userInfo)
userInfo <- env.puzzle userInfos me
json <- env.puzzle.jsonView.batch(puzzles, userInfo)
} yield Ok(json) as JSON
)
}
/* Mobile API: tell the server about puzzles solved while offline */
def batchSolve = AuthBody(BodyParsers.parse.json) { implicit ctx => me =>
def batchSolve = AuthBody(parse.json) { implicit ctx => me =>
import lila.puzzle.PuzzleBatch._
ctx.body.body.validate[SolveData].fold(
err => BadRequest(err.toString).fuccess,
data => negotiate(
html = notFound,
api = _ => for {
_ <- env.batch.solve(me, data)
me2 <- env.user.userRepo byId me.id map (_ | me)
infos <- env userInfos me2
_ <- env.puzzle.batch.solve(me, data)
me2 <- env.user.repo byId me.id map (_ | me)
infos <- env.puzzle userInfos me2
} yield Ok(Json.obj(
"user" -> lila.puzzle.JsonView.infos(false)(infos)
))
@ -224,21 +228,21 @@ final class Puzzle(env: Env) extends LilaController(env) {
}
def frame = Action.async { implicit req =>
env.daily.get map {
env.puzzle.daily.get map {
case None => NotFound
case Some(daily) => html.puzzle.embed(daily)
}
}
def activity = Scoped(_.Puzzle.Read) { req => me =>
Api.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
Api.GlobalLinearLimitPerUserOption(me.some) {
apiC.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
apiC.GlobalLinearLimitPerUserOption(me.some) {
val config = lila.puzzle.PuzzleActivity.Config(
user = me,
max = getInt("max", req) map (_ atLeast 1),
perSecond = MaxPerSecond(20)
)
Ok.chunked(env.activity.stream(config)).withHeaders(
Ok.chunked(env.puzzle.activity.stream(config)).withHeaders(
noProxyBufferHeader,
CONTENT_TYPE -> ndJsonContentType
).fuccess

View File

@ -1,24 +1,29 @@
package controllers
import play.api.libs.iteratee._
import play.api.libs.json.Json
import play.api.mvc._
import lila.api.Context
import lila.app._
import lila.common.config.MaxPerSecond
import lila.common.HTTPRequest
import lila.common.paginator.{ Paginator, AdapterLike, PaginatorJson }
import lila.common.{ HTTPRequest, MaxPerSecond }
import lila.relation.Related
import lila.relation.RelationStream._
import lila.user.{ User => UserModel }
import views._
final class Relation(env: Env) extends LilaController(env) {
final class Relation(
env: Env,
apiC: Api
) extends LilaController(env) {
val api = env.relation.api
private def renderActions(userId: String, mini: Boolean)(implicit ctx: Context) =
(ctx.userId ?? { env.api.fetchRelation(_, userId) }) zip
(ctx.userId ?? { api.fetchRelation(_, userId) }) zip
(ctx.isAuth ?? { env.pref.api followable userId }) zip
(ctx.userId ?? { env.api.fetchBlocks(userId, _) }) flatMap {
(ctx.userId ?? { api.fetchBlocks(userId, _) }) flatMap {
case relation ~ followable ~ blocked => negotiate(
html = fuccess(Ok {
if (mini) html.relation.mini(userId, blocked = blocked, followable = followable, relation = relation)
@ -33,33 +38,33 @@ final class Relation(env: Env) extends LilaController(env) {
}
def follow(userId: String) = Auth { implicit ctx => me =>
env.api.reachedMaxFollowing(me.id) flatMap {
api.reachedMaxFollowing(me.id) flatMap {
case true => env.message.api.sendPresetFromLichess(
me,
lila.message.ModPreset.maxFollow(me.username, env.relation.MaxFollow)
lila.message.ModPreset.maxFollow(me.username, env.relation.maxFollow.value)
).void
case _ => env.api.follow(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
case _ => api.follow(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
}
}
def unfollow(userId: String) = Auth { implicit ctx => me =>
env.api.unfollow(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
api.unfollow(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
}
def block(userId: String) = Auth { implicit ctx => me =>
env.api.block(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
api.block(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
}
def unblock(userId: String) = Auth { implicit ctx => me =>
env.api.unblock(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
api.unblock(me.id, UserModel normalize userId).nevermind >> renderActions(userId, getBool("mini"))
}
def following(username: String, page: Int) = Open { implicit ctx =>
Reasonable(page, 20) {
OptionFuResult(env.user.userRepo named username) { user =>
RelatedPager(env.api.followingPaginatorAdapter(user.id), page) flatMap { pag =>
OptionFuResult(env.user.repo named username) { user =>
RelatedPager(api.followingPaginatorAdapter(user.id), page) flatMap { pag =>
negotiate(
html = env.api countFollowers user.id map { nbFollowers =>
html = api countFollowers user.id map { nbFollowers =>
Ok(html.relation.bits.following(user, pag, nbFollowers))
},
api = _ => Ok(jsonRelatedPaginator(pag)).fuccess
@ -71,10 +76,10 @@ final class Relation(env: Env) extends LilaController(env) {
def followers(username: String, page: Int) = Open { implicit ctx =>
Reasonable(page, 20) {
OptionFuResult(env.user.userRepo named username) { user =>
RelatedPager(env.api.followersPaginatorAdapter(user.id), page) flatMap { pag =>
OptionFuResult(env.user.repo named username) { user =>
RelatedPager(api.followersPaginatorAdapter(user.id), page) flatMap { pag =>
negotiate(
html = env.api countFollowing user.id map { nbFollowing =>
html = api countFollowing user.id map { nbFollowing =>
Ok(html.relation.bits.followers(user, pag, nbFollowing))
},
api = _ => Ok(jsonRelatedPaginator(pag)).fuccess
@ -89,12 +94,12 @@ final class Relation(env: Env) extends LilaController(env) {
def apiFollowers(name: String) = apiRelation(name, Direction.Followers)
private def apiRelation(name: String, direction: Direction) = Action.async { req =>
env.user.userRepo.named(name) flatMap {
env.user.repo.named(name) flatMap {
_ ?? { user =>
import Api.limitedDefault
Api.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
Api.jsonStream {
env.stream.follow(user, direction, MaxPerSecond(20)) &> Enumeratee.map(env.api.userApi.one)
import apiC.limitedDefault
apiC.GlobalLinearLimitPerIP(HTTPRequest lastRemoteAddress req) {
apiC.jsonStream {
env.stream.follow(user, direction, MaxPerSecond(20)) &> Enumeratee.map(api.userApi.one)
} |> fuccess
}
}
@ -115,7 +120,7 @@ final class Relation(env: Env) extends LilaController(env) {
def blocks(page: Int) = Auth { implicit ctx => me =>
Reasonable(page, 20) {
RelatedPager(env.api.blockingPaginatorAdapter(me.id), page) map { pag =>
RelatedPager(api.blockingPaginatorAdapter(me.id), page) map { pag =>
html.relation.bits.blocks(me, pag)
}
}
@ -124,14 +129,14 @@ final class Relation(env: Env) extends LilaController(env) {
private def RelatedPager(adapter: AdapterLike[String], page: Int)(implicit ctx: Context) = Paginator(
adapter = adapter mapFutureList followship,
currentPage = page,
maxPerPage = lila.common.MaxPerPage(30)
maxPerPage = lila.common.config.MaxPerPage(30)
)
private def followship(userIds: Seq[String])(implicit ctx: Context): Fu[List[Related]] =
env.user.userRepo usersFromSecondary userIds.map(UserModel.normalize) flatMap { users =>
env.user.repo usersFromSecondary userIds.map(UserModel.normalize) flatMap { users =>
(ctx.isAuth ?? { env.pref.api.followableIds(users map (_.id)) }) flatMap { followables =>
users.map { u =>
ctx.userId ?? { env.api.fetchRelation(_, u.id) } map { rel =>
ctx.userId ?? { api.fetchRelation(_, u.id) } map { rel =>
lila.relation.Related(u, none, followables(u.id), rel)
}
}.sequenceFu

View File

@ -10,7 +10,11 @@ import lila.common.HTTPRequest
import lila.report.{ Room, Report => ReportModel, Mod => AsMod, Reporter, Suspect }
import lila.user.{ User => UserModel }
final class Report(env: Env) extends LilaController(env) {
final class Report(
env: Env,
userC: User,
modC: Mod
) extends LilaController(env) {
private def api = env.report.api
@ -43,7 +47,7 @@ final class Report(env: Env) extends LilaController(env) {
private def onInquiryStart(inquiry: ReportModel) =
inquiry.room match {
case Room.Comm => Redirect(routes.Mod.communicationPrivate(inquiry.user))
case _ => Mod.redirect(inquiry.user)
case _ => modC.redirect(inquiry.user)
}
protected[controllers] def onInquiryClose(
@ -53,7 +57,7 @@ final class Report(env: Env) extends LilaController(env) {
force: Boolean = false
)(implicit ctx: BodyContext[_]) = {
goTo.ifTrue(HTTPRequest isXhr ctx.req) match {
case Some(suspect) => User.renderModZoneActions(suspect.user.username)
case Some(suspect) => userC.renderModZoneActions(suspect.user.username)
case None =>
val dataOpt = ctx.body.body match {
case AnyContentAsFormUrlEncoded(data) => data.some
@ -62,12 +66,12 @@ final class Report(env: Env) extends LilaController(env) {
inquiry match {
case None =>
goTo.fold(Redirect(routes.Report.list).fuccess) { s =>
User.modZoneOrRedirect(s.user.username, me)
userC.modZoneOrRedirect(s.user.username, me)
}
case Some(prev) =>
def thenGoTo = dataOpt.flatMap(_ get "then").flatMap(_.headOption) flatMap {
case "back" => HTTPRequest referer ctx.req
case "profile" => Mod.userUrl(prev.user, true).some
case "profile" => modC.userUrl(prev.user, true).some
case url => url.some
}
thenGoTo match {
@ -82,7 +86,7 @@ final class Report(env: Env) extends LilaController(env) {
}
}
}
else if (force) User.modZoneOrRedirect(prev.user, me)
else if (force) userC.modZoneOrRedirect(prev.user, me)
else api.inquiries.toggle(AsMod(me), prev.id) map {
_.fold(redirectToList)(onInquiryStart)
}
@ -102,7 +106,7 @@ final class Report(env: Env) extends LilaController(env) {
}
def currentCheatInquiry(username: String) = Secure(_.Hunter) { implicit ctx => me =>
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
env.api.currentCheatReport(lila.report.Suspect(user)) flatMap {
_ ?? { report =>
env.api.inquiries.toggle(lila.report.Mod(me), report.id)
@ -112,7 +116,7 @@ final class Report(env: Env) extends LilaController(env) {
}
def form = Auth { implicit ctx => implicit me =>
get("username") ?? env.user.userRepo.named flatMap { user =>
get("username") ?? env.user.repo.named flatMap { user =>
env.forms.createWithCaptcha map {
case (form, captcha) => Ok(html.report.form(form, user, captcha))
}
@ -122,7 +126,7 @@ final class Report(env: Env) extends LilaController(env) {
def create = AuthBody { implicit ctx => implicit me =>
implicit val req = ctx.body
env.forms.create.bindFromRequest.fold(
err => get("username") ?? env.user.userRepo.named flatMap { user =>
err => get("username") ?? env.user.repo.named flatMap { user =>
env.forms.anyCaptcha map { captcha =>
BadRequest(html.report.form(err, user, captcha))
}
@ -139,7 +143,7 @@ final class Report(env: Env) extends LilaController(env) {
implicit val req = ctx.body
env.forms.flag.bindFromRequest.fold(
err => BadRequest.fuccess,
data => env.user.userRepo named data.username flatMap {
data => env.user.repo named data.username flatMap {
_ ?? { user =>
if (user == me) BadRequest.fuccess
else api.commFlag(Reporter(me), Suspect(user), data.resource, data.text) inject Ok

View File

@ -44,7 +44,7 @@ final class Setup(env: Env) extends LilaController(env) with TheftPrevention {
if (HTTPRequest isXhr ctx.req)
env.forms friendFilled get("fen").map(FEN) flatMap { form =>
val validFen = form("fen").value flatMap ValidFen(false)
userId ?? env.user.userRepo.named flatMap {
userId ?? env.user.repo.named flatMap {
case None => Ok(html.setup.forms.friend(form, none, none, validFen)).fuccess
case Some(user) => env.challenge.granter(ctx.me, user, none) map {
case Some(denied) => BadRequest(lila.challenge.ChallengeDenied.translated(denied))
@ -65,7 +65,7 @@ final class Setup(env: Env) extends LilaController(env) with TheftPrevention {
html = keyPages.home(Results.BadRequest),
api = _ => jsonFormError(err)
),
config => userId ?? env.user.userRepo.enabledById flatMap { destUser =>
config => userId ?? env.user.repo.enabledById flatMap { destUser =>
destUser ?? { env.challenge.granter(ctx.me, _, config.perfType) } flatMap {
case Some(denied) =>
val message = lila.challenge.ChallengeDenied.translated(denied)

View File

@ -58,7 +58,7 @@ final class Study(env: Env) extends LilaController(env) {
def byOwnerDefault(username: String, page: Int) = byOwner(username, Order.default.key, page)
def byOwner(username: String, order: String, page: Int) = Open { implicit ctx =>
userRepo.named(username).flatMap {
env.user.repo.named(username).flatMap {
_.fold(notFound(ctx)) { owner =>
env.pager.byOwner(owner, ctx.me, Order(order), page) flatMap { pag =>
negotiate(

View File

@ -1,7 +1,6 @@
package controllers
import play.api.data.Form
import play.api.libs.iteratee._
import play.api.libs.json._
import play.api.mvc._
import scala.concurrent.duration._
@ -24,7 +23,7 @@ final class User(env: Env) extends LilaController(env) {
private def userGameSearch = env.gameSearch.userGameSearch
def tv(username: String) = Open { implicit ctx =>
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
currentlyPlaying(user) orElse
env.game.gameRepo.lastPlayed(user) flatMap {
_.fold(fuccess(Redirect(routes.User.show(username)))) { pov =>
@ -35,7 +34,7 @@ final class User(env: Env) extends LilaController(env) {
}
def studyTv(username: String) = Open { implicit ctx =>
OptionResult(env.user.userRepo named username) { user =>
OptionResult(env.user.repo named username) { user =>
Redirect {
env.relation.online.studying getIfPresent user.id match {
case None => routes.Study.byOwnerDefault(user.id)
@ -106,12 +105,12 @@ final class User(env: Env) extends LilaController(env) {
}
private def EnabledUser(username: String)(f: UserModel => Fu[Result])(implicit ctx: Context): Fu[Result] =
env.user.userRepo named username flatMap {
env.user.repo named username flatMap {
case None if isGranted(_.UserSpy) => Mod.searchTerm(username.trim)
case None => notFound
case Some(u) if (u.enabled || isGranted(_.UserSpy)) => f(u)
case Some(u) => negotiate(
html = env.user.userRepo isErased u flatMap { erased =>
html = env.user.repo isErased u flatMap { erased =>
if (erased.value) notFound
else NotFound(html.user.show.page.disabled(u)).fuccess
},
@ -120,7 +119,7 @@ final class User(env: Env) extends LilaController(env) {
}
def showMini(username: String) = Open { implicit ctx =>
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
if (user.enabled || isGranted(_.UserSpy)) for {
blocked <- ctx.userId ?? { relationApi.fetchBlocks(user.id, _) }
crosstable <- ctx.userId ?? { env.game.crosstableApi(user.id, _) map some }
@ -270,7 +269,7 @@ final class User(env: Env) extends LilaController(env) {
}
protected[controllers] def renderModZone(username: String, me: UserModel)(implicit ctx: Context): Fu[Result] = {
env.user.userRepo withEmails username flatten s"No such user $username" map {
env.user.repo withEmails username flatten s"No such user $username" map {
case UserModel.WithEmails(user, emails) =>
val parts =
env.mod.logApi.userHistory(user.id).logTimeIfGt(s"$username logApi.userHistory", 2 seconds) zip
@ -282,7 +281,7 @@ final class User(env: Env) extends LilaController(env) {
env.user.lightUserApi.preloadMany(reports.userIds).logTimeIfGt(s"$username lightUserApi.preloadMany", 2 seconds) inject
html.user.mod.parts(user, history, charges, reports, pref, rageSit).some
}
val actions = env.user.userRepo.isErased(user) map { erased =>
val actions = env.user.repo.isErased(user) map { erased =>
html.user.mod.actions(user, emails, erased).some
}
val spyFu = env.security.userSpy(user).logTimeIfGt(s"$username security.userSpy", 2 seconds)
@ -323,9 +322,9 @@ final class User(env: Env) extends LilaController(env) {
}
protected[controllers] def renderModZoneActions(username: String)(implicit ctx: Context) =
env.user.userRepo withEmails username flatten s"No such user $username" flatMap {
env.user.repo withEmails username orFail s"No such user $username" flatMap {
case UserModel.WithEmails(user, emails) =>
env.user.userRepo.isErased(user) map { erased =>
env.user.repo.isErased(user) map { erased =>
Ok(html.user.mod.actions(user, emails, erased))
}
}
@ -345,7 +344,7 @@ final class User(env: Env) extends LilaController(env) {
}
private def doWriteNote(username: String, me: UserModel)(err: Form[_] => UserModel => Fu[Result], suc: => Result)(implicit req: Request[_]) =
env.user.userRepo named username flatMap {
env.user.repo named username flatMap {
_ ?? { user =>
env.forms.note.bindFromRequest.fold(
e => err(e)(user),
@ -375,7 +374,7 @@ final class User(env: Env) extends LilaController(env) {
}
def perfStat(username: String, perfKey: String) = Open { implicit ctx =>
OptionFuResult(env.user.userRepo named username) { u =>
OptionFuResult(env.user.repo named username) { u =>
if ((u.disabled || (u.lame && !ctx.is(u))) && !isGranted(_.UserSpy)) notFound
else PerfType(perfKey).fold(notFound) { perfType =>
for {
@ -409,15 +408,15 @@ final class User(env: Env) extends LilaController(env) {
def autocomplete = Open { implicit ctx =>
get("term", ctx.req).filter(_.nonEmpty).filter(lila.user.User.couldBeUsername) match {
case None => BadRequest("No search term provided").fuccess
case Some(term) if getBool("exists") => env.user.userRepo nameExists term map { r => Ok(JsBoolean(r)) }
case Some(term) if getBool("exists") => env.user.repo nameExists term map { r => Ok(JsBoolean(r)) }
case Some(term) => {
get("tour") match {
case Some(tourId) => env.tournament.playerRepo.searchPlayers(tourId, term, 10)
case None => ctx.me.ifTrue(getBool("friend")) match {
case None => env.user.userRepo userIdsLike term
case None => env.user.repo userIdsLike term
case Some(follower) =>
env.relation.api.searchFollowedBy(follower, term, 10) flatMap {
case Nil => env.user.userRepo userIdsLike term
case Nil => env.user.repo userIdsLike term
case userIds => fuccess(userIds)
}
}

View File

@ -7,7 +7,7 @@ final class UserTournament(env: Env) extends LilaController(env) {
def path(username: String, path: String, page: Int) = Open { implicit ctx =>
Reasonable(page) {
OptionFuResult(env.user.userRepo named username) { user =>
OptionFuResult(env.user.repo named username) { user =>
path match {
case "recent" =>
env.tournament.leaderboardApi.recentByUser(user, page).map { entries =>

View File

@ -7,7 +7,6 @@ import lila.i18n.{ I18nKeys => trans }
import lila.pref.Pref
import lila.report.Reason
import lila.setup.TimeMode
import lila.tournament.System
trait SetupHelper { self: I18nHelper =>

View File

@ -67,7 +67,7 @@ lazy val api = module("api", moduleCPDeps)
lazy val puzzle = module("puzzle", Seq(
common, memo, hub, history, db, user, rating, pref, tree, game
)).settings(
libraryDependencies ++= provided(play.api) ++ reactivemongo.bundle
libraryDependencies ++= provided(play.api, play.joda) ++ reactivemongo.bundle
)
lazy val quote = module("quote", Seq()).settings(

View File

@ -601,9 +601,7 @@ POST /jsmon/:event controllers.Main.jsmon(event: String)
GET /swag controllers.Main.movedPermanently(to: String = "https://shop.spreadshirt.com/lichess-org")
# Assets
GET /assets/$version<_\w{6}>/*file controllers.Main.versionedAsset(version: String, file: String)
GET /assets/*file controllers.Assets.at(path = "/public", file: String)
GET /assets/*file controllers.Assets.versioned(file)
GET /robots.txt controllers.Main.robots

View File

@ -5,7 +5,7 @@ import play.api.Configuration
import reactivemongo.api._
import reactivemongo.api.commands.Command
import scala.concurrent.duration._
import scala.concurrent.{ Await, ExecutionContext, Future }
import scala.concurrent.Await
import scala.util.{ Failure, Success }
import dsl.Coll
@ -42,10 +42,10 @@ final class Env(name: String, config: DbConfig) {
object image {
private lazy val imageColl = config.imageCollName map apply
import dsl._
// import DbImage.DbImageBSONHandler
// def fetch(id: String): Fu[Option[DbImage]] = imageColl ?? {
// _.byId[DbImage](id)
// }
import DbImage.DbImageBSONHandler
def fetch(id: String): Fu[Option[DbImage]] = imageColl ?? {
_.byId[DbImage](id)
}
}
}

View File

@ -38,7 +38,7 @@ final class PngExport(
).flatten
ws.url(url)
.withQueryString(queryString: _*)
.withQueryStringParameters(queryString: _*)
.withMethod("GET")
.stream() flatMap {
case res if res.status != 200 =>

View File

@ -21,7 +21,7 @@ private final class UserCacheApi(coll: Coll) {
def find(id: String) = coll.uno[UserCache]($id(id))
def save(u: UserCache) = coll.update($id(u.id), u, upsert = true).void
def save(u: UserCache) = coll.update.one($id(u.id), u, upsert = true).void
def remove(id: String) = coll.remove($id(id)).void
def remove(id: String) = coll.delete.one($id(id)).void
}

View File

@ -31,7 +31,7 @@ final class Env(
private lazy val threadColl = db(config.threadColl)
private lazy val repo = wire[ThreadRepo]
lazy val repo = wire[ThreadRepo]
lazy val forms = wire[DataForm]

View File

@ -44,10 +44,7 @@ final class Env(
asyncCache: lila.memo.AsyncCache.Builder,
securityStore: lila.security.Store,
emailValidator: lila.security.EmailAddressValidator
)(implicit
system: ActorSystem,
mat: akka.stream.Materializer
) {
)(implicit system: ActorSystem) {
private val config = appConfig.get[ModConfig]("mod")(AutoConfig.loader)

View File

@ -25,13 +25,12 @@ final class ModStream(implicit mat: akka.stream.Materializer) {
}
.map { js => s"${Json.stringify(js)}\n" }
def plugTo(sink: Sink[String, Fu[akka.Done]]): Unit = {
val (queue, done) = blueprint.toMat(sink)(Keep.both).run()
def apply(): Source[String, _] = blueprint mapMaterializedValue { queue =>
val sub = Bus.subscribeFun(classifier) {
case signup: Signup => queue offer signup
}
done onComplete { _ => Bus.unsubscribe(sub, classifier) }
queue.watchCompletion foreach { _ => Bus.unsubscribe(sub, classifier) }
}
}

View File

@ -2,7 +2,6 @@ package lila.plan
import com.softwaremill.macwire._
import io.methvin.play.autoconfig._
import lila.memo.SettingStore.{ StringReader, Formable }
import play.api.Configuration
import play.api.libs.ws.WSClient
import scala.concurrent.duration._
@ -32,6 +31,8 @@ final class Env(
import StripeClient.configLoader
private val config = appConfig.get[PlanConfig]("plan")(AutoConfig.loader)
val stripePublicKey = config.stripe.publicKey
private lazy val patronColl = db(config.patronColl)
private lazy val chargeColl = db(config.chargeColl)

View File

@ -169,7 +169,7 @@ private final class StripeClient(
private def debugInput(data: Seq[(String, Any)]) = fixInput(data) map { case (k, v) => s"$k=$v" } mkString " "
}
private object StripeClient {
object StripeClient {
class StripeException(msg: String) extends Exception(msg)
class DeletedException(msg: String) extends StripeException(msg)
@ -178,10 +178,10 @@ private object StripeClient {
class InvalidRequestException(msg: String) extends StatusException(msg)
import io.methvin.play.autoconfig._
case class Config(
private[plan] case class Config(
endpoint: String,
@ConfigName("keys.public") publicKey: String,
@ConfigName("keys.public") secretKey: Secret
)
implicit val configLoader = AutoConfig.loader[Config]
private[plan] implicit val configLoader = AutoConfig.loader[Config]
}

View File

@ -83,7 +83,7 @@ final class PracticeApi(
private def save(p: PracticeProgress): Funit =
coll.update.one($id(p.id), p, upsert = true).void
def setNbMoves(user: User, chapterId: Chapter.Id, score: NbMoves) = {
def setNbMoves(user: User, chapterId: Chapter.Id, score: NbMoves): Funit = {
get(user) flatMap { prog =>
save(prog.withNbMoves(chapterId, score))
}

View File

@ -1,7 +1,10 @@
package lila.puzzle
import akka.stream.scaladsl._
import org.joda.time.DateTime
import play.api.libs.json._
import play.api.libs.json.JodaWrites._
import reactivemongo.akkastream.{ AkkaStreamCursor, cursorProducer }
import reactivemongo.api.ReadPreference
import scala.concurrent.duration._
@ -14,66 +17,44 @@ final class PuzzleActivity(
roundColl: Coll
)(implicit system: akka.actor.ActorSystem) {
// import PuzzleActivity._
// import Round.RoundBSONHandler
import PuzzleActivity._
import Round.RoundBSONHandler
// def stream(config: Config): Enumerator[String] = {
def stream(config: Config): Source[String, _] = roundColl
.ext.find($doc("_id" $startsWith config.user.id))
.sort($sort desc "_id")
.batchSize(config.perSecond.value)
.cursor[Round](ReadPreference.secondaryPreferred)
.documentSource()
.take(config.max | Int.MaxValue)
.grouped(config.perSecond.value)
.delay(1 second)
.mapAsync(1)(enrich)
.mapConcat(identity)
.map { json => s"${Json.stringify(json)}\n" }
// val selector = $doc("_id" $startsWith config.user.id)
// val query = roundColl.find(selector).sort($sort desc "_id")
// val infinite = query.copy(options = query.options.batchSize(config.perSecond.value))
// .cursor[Round](ReadPreference.secondaryPreferred)
// .bulkEnumerator() &>
// Enumeratee.mapM[Iterator[Round]].apply[Seq[JsObject]] { rounds =>
// enrich(rounds.toSeq)
// } &>
// lila.common.Iteratee.delay(1 second) &>
// Enumeratee.mapConcat(_.toSeq)
// val stream = config.max.fold(infinite) { max =>
// // I couldn't figure out how to do it properly :( :( :(
// // the nb can't be set as bulkEnumerator(nb)
// // because games are further filtered after being fetched
// var nb = 0
// infinite &> Enumeratee.mapInput { in =>
// nb = nb + 1
// if (nb <= max) in
// else Input.EOF
// }
// }
// stream &> formatter
// }
// private def enrich(rounds: Seq[Round]): Fu[Seq[JsObject]] =
// puzzleColl.primitiveMap[Int, Double](
// ids = rounds.map(_.id.puzzleId).toSeq,
// field = "perf.gl.r",
// fieldExtractor = obj => for {
// perf <- obj.getAs[Bdoc]("perf")
// gl <- perf.getAs[Bdoc]("gl")
// rating <- gl.getAs[Double]("r")
// } yield rating
// ) map { ratings =>
// rounds.toSeq flatMap { round =>
// ratings get round.id.puzzleId map { puzzleRating =>
// Json.obj(
// "id" -> round.id.puzzleId,
// "date" -> round.date,
// "rating" -> round.rating,
// "ratingDiff" -> round.ratingDiff,
// "puzzleRating" -> puzzleRating.toInt
// )
// }
// }
// }
// private def formatter =
// Enumeratee.map[JsObject].apply[String] { json =>
// s"${Json.stringify(json)}\n"
// }
private def enrich(rounds: Seq[Round]): Fu[Seq[JsObject]] =
puzzleColl.primitiveMap[Int, Double](
ids = rounds.map(_.id.puzzleId).toSeq,
field = "perf.gl.r",
fieldExtractor = obj => for {
perf <- obj.child("perf")
gl <- perf.child("gl")
rating <- gl.double("r")
} yield rating
) map { ratings =>
rounds.toSeq flatMap { round =>
ratings get round.id.puzzleId map { puzzleRating =>
Json.obj(
"id" -> round.id.puzzleId,
"date" -> round.date,
"rating" -> round.rating,
"ratingDiff" -> round.ratingDiff,
"puzzleRating" -> puzzleRating.toInt
)
}
}
}
}
object PuzzleActivity {

View File

@ -2,9 +2,10 @@ package lila.report
import org.joda.time.DateTime
import ornicar.scalalib.Random
import scala.math.Ordering.Float.TotalOrdering
import scalaz.NonEmptyList
import lila.user.{ User, Note }
import lila.user.User
case class Report(
_id: Report.ID, // also the url slug

View File

@ -1,8 +1,5 @@
package lila.report
import reactivemongo.api.bson._
import lila.db.dsl._
import lila.user.{ User, UserRepo, Title }
private final class ReportScore(

View File

@ -48,7 +48,7 @@ final class Env(
lazy val geoIP: GeoIP = wire[GeoIP]
lazy val userSpyApi = wire[UserSpyApi]
lazy val userSpy = wire[UserSpyApi]
lazy val store = new Store(db(config.collection.security))

View File

@ -31,7 +31,7 @@ private final class RequestRepo(val coll: Coll) {
def teamsQuery(teamIds: List[ID]) = $doc("team" $in teamIds)
def getByUserId(userId: lila.user.User.ID) =
coll.find($doc("user" -> userId)).list[Request]()
coll.ext.find($doc("user" -> userId)).list[Request]()
def remove(id: ID) = coll.remove($id(id))
def remove(id: ID) = coll.delete.one($id(id))
}

View File

@ -16,7 +16,7 @@ final class TeamMemberStream(
def apply(team: Team, perSecond: MaxPerSecond): Source[User, _] =
memberRepo.coll
.find($doc("team" -> team.id), $doc("user" -> true))
.ext.find($doc("team" -> team.id), $doc("user" -> true))
.sort($sort desc "date")
.batchSize(perSecond.value)
.cursor[Bdoc](ReadPreference.secondaryPreferred)

View File

@ -29,7 +29,7 @@ final class EntryApi(
coll.find($doc(
"users" -> userId,
"date" $gt DateTime.now.minusWeeks(2)
), projection)
), projection.some)
.sort($sort desc "date")
.cursor[Entry](ReadPreference.secondaryPreferred)
.gather[Vector](max)
@ -37,17 +37,17 @@ final class EntryApi(
def findRecent(typ: String, since: DateTime, max: Int) =
coll.find(
$doc("typ" -> typ, "date" $gt since),
projection
projection.some
).sort($sort desc "date")
.cursor[Entry](ReadPreference.secondaryPreferred)
.gather[Vector](max)
def channelUserIdRecentExists(channel: String, userId: User.ID): Fu[Boolean] =
coll.count($doc(
coll.countSel($doc(
"users" -> userId,
"chan" -> channel,
"date" $gt DateTime.now.minusDays(7)
).some) map (0 !=)
)) map (0 !=)
def insert(e: Entry.ForUsers) =
coll.insert(EntryBSONHandler.writeTry(e.entry).get ++ $doc("users" -> e.userIds)) void
@ -55,7 +55,7 @@ final class EntryApi(
// can't remove from capped collection,
// so we set a date in the past instead.
private[timeline] def removeRecentFollowsBy(userId: User.ID): Funit =
coll.update(
coll.update.one(
$doc("typ" -> "follow", "data.u1" -> userId, "date" $gt DateTime.now().minusHours(1)),
$set("date" -> DateTime.now().minusDays(365)),
multi = true
@ -71,7 +71,7 @@ final class EntryApi(
expireAfter = _.ExpireAfterWrite(1 hour)
)
private def fetch: Fu[Vector[Entry]] = coll
private def fetch: Fu[Vector[Entry]] = coll.ext
.find($doc(
"users" $exists false,
"date" $gt DateTime.now.minusWeeks(2)

View File

@ -8,7 +8,6 @@ import play.api.libs.ws.WSClient
import scala.concurrent.duration._
import lila.common.config._
import lila.common.LightUser
import lila.db.dsl.Coll
private class UserConfig(
@ -34,7 +33,7 @@ final class Env(
private val config = appConfig.get[UserConfig]("user")(AutoConfig.loader)
val userRepo = new UserRepo(db(config.collectionUser))
val repo = new UserRepo(db(config.collectionUser))
val lightUserApi: LightUserApi = wire[LightUserApi]
val lightUser = lightUserApi.async
@ -85,7 +84,7 @@ final class Env(
"adjustCheater" -> {
case lila.hub.actorApi.mod.MarkCheater(userId, true) =>
rankingApi remove userId
userRepo.setRoles(userId, Nil)
repo.setRoles(userId, Nil)
},
"adjustBooster" -> {
case lila.hub.actorApi.mod.MarkBooster(userId) => rankingApi remove userId
@ -95,7 +94,7 @@ final class Env(
},
"gdprErase" -> {
case User.GDPRErase(user) =>
userRepo erase user
repo erase user
noteApi erase user
}
)

View File

@ -2,7 +2,7 @@ package lila.user
import reactivemongo.api.bson._
import scala.concurrent.duration._
import scala.util.{ Try, Success, Failure }
import scala.util.Success
import lila.common.LightUser
import lila.db.dsl._

View File

@ -2,7 +2,6 @@ package lila.user
import lila.db.dsl._
import org.joda.time.DateTime
import reactivemongo.api.ReadPreference
case class Note(
_id: String,

View File

@ -2,7 +2,6 @@ package lila.user
import org.apache.commons.codec.binary.Base32
import reactivemongo.api.bson._
import scala.util.{ Try, Success, Failure }
import java.security.SecureRandom
import javax.crypto.Mac

View File

@ -53,11 +53,10 @@ object BuildSettings {
"-language:reflectiveCalls", // #TODO remove me for perfs
"-feature",
"-deprecation",
"-unchecked",
"-Wunused:imports,locals,implicits",
"inaccessible,infer-any",
"-Xmaxerrs", "5",
"-Xmaxwarns", "5"
// "-unchecked",
// "-Wunused:imports,locals,implicits",// "inaccessible,infer-any",
"-Xmaxerrs", "6",
"-Xmaxwarns", "6"
)
val srcMain = Seq(