only logged in users can hit elasticearch
parent
7ec9c6d73f
commit
ef322d6d27
|
@ -1,10 +1,10 @@
|
|||
package controllers
|
||||
|
||||
import scala.concurrent.duration._
|
||||
import views._
|
||||
|
||||
import lila.app._
|
||||
import lila.common.{ HTTPRequest, IpAddress }
|
||||
import views._
|
||||
|
||||
final class Search(env: Env) extends LilaController(env) {
|
||||
|
||||
|
@ -23,66 +23,74 @@ final class Search(env: Env) extends LilaController(env) {
|
|||
|
||||
def index(p: Int) =
|
||||
OpenBody { implicit ctx =>
|
||||
NotForBots {
|
||||
val page = p atLeast 1
|
||||
Reasonable(page, 100) {
|
||||
val ip = HTTPRequest ipAddress ctx.req
|
||||
val cost = scala.math.sqrt(page.toDouble).toInt
|
||||
implicit def req = ctx.body
|
||||
env.game.cached.nbTotal flatMap { nbGames =>
|
||||
def limited =
|
||||
fuccess {
|
||||
val form = searchForm
|
||||
.bindFromRequest()
|
||||
.withError(
|
||||
key = "",
|
||||
message = "Please only send one request at a time per IP address"
|
||||
)
|
||||
TooManyRequests(html.search.index(form, none, nbGames))
|
||||
}
|
||||
SearchRateLimitPerIP(ip, cost = cost) {
|
||||
SearchConcurrencyLimitPerIP(ip, limited = limited) {
|
||||
negotiate(
|
||||
html = searchForm
|
||||
env.game.cached.nbTotal flatMap { nbGames =>
|
||||
if (ctx.isAnon)
|
||||
negotiate(
|
||||
html = Unauthorized(html.search.login(nbGames)).fuccess,
|
||||
api = _ => Unauthorized(jsonError("Login required")).fuccess
|
||||
)
|
||||
else
|
||||
NotForBots {
|
||||
val page = p atLeast 1
|
||||
Reasonable(page, 100) {
|
||||
val ip = HTTPRequest ipAddress ctx.req
|
||||
val cost = scala.math.sqrt(page.toDouble).toInt
|
||||
implicit def req = ctx.body
|
||||
def limited =
|
||||
fuccess {
|
||||
val form = searchForm
|
||||
.bindFromRequest()
|
||||
.fold(
|
||||
failure => Ok(html.search.index(failure, none, nbGames)).fuccess,
|
||||
data =>
|
||||
data.nonEmptyQuery ?? { query =>
|
||||
env.gameSearch.paginator(query, page) map some
|
||||
} map { pager =>
|
||||
Ok(html.search.index(searchForm fill data, pager, nbGames))
|
||||
} recover { _ =>
|
||||
InternalServerError("Sorry, we can't process that query at the moment")
|
||||
}
|
||||
),
|
||||
api = _ =>
|
||||
searchForm
|
||||
.withError(
|
||||
key = "",
|
||||
message = "Please only send one request at a time per IP address"
|
||||
)
|
||||
TooManyRequests(html.search.index(form, none, nbGames))
|
||||
}
|
||||
SearchRateLimitPerIP(ip, cost = cost) {
|
||||
SearchConcurrencyLimitPerIP(ip, limited = limited) {
|
||||
negotiate(
|
||||
html = searchForm
|
||||
.bindFromRequest()
|
||||
.fold(
|
||||
_ =>
|
||||
Ok {
|
||||
jsonError("Could not process search query")
|
||||
}.fuccess,
|
||||
failure => Ok(html.search.index(failure, none, nbGames)).fuccess,
|
||||
data =>
|
||||
data.nonEmptyQuery ?? { query =>
|
||||
env.gameSearch.paginator(query, page) dmap some
|
||||
} flatMap {
|
||||
case Some(s) =>
|
||||
env.api.userGameApi.jsPaginator(s) dmap {
|
||||
Ok(_)
|
||||
}
|
||||
case None =>
|
||||
BadRequest(jsonError("Could not process search query")).fuccess
|
||||
env.gameSearch.paginator(query, page) map some
|
||||
} map { pager =>
|
||||
Ok(html.search.index(searchForm fill data, pager, nbGames))
|
||||
} recover { _ =>
|
||||
InternalServerError(jsonError("Sorry, we can't process that query at the moment"))
|
||||
InternalServerError("Sorry, we can't process that query at the moment")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}(rateLimitedFu)
|
||||
),
|
||||
api = _ =>
|
||||
searchForm
|
||||
.bindFromRequest()
|
||||
.fold(
|
||||
_ =>
|
||||
Ok {
|
||||
jsonError("Could not process search query")
|
||||
}.fuccess,
|
||||
data =>
|
||||
data.nonEmptyQuery ?? { query =>
|
||||
env.gameSearch.paginator(query, page) dmap some
|
||||
} flatMap {
|
||||
case Some(s) =>
|
||||
env.api.userGameApi.jsPaginator(s) dmap {
|
||||
Ok(_)
|
||||
}
|
||||
case None =>
|
||||
BadRequest(jsonError("Could not process search query")).fuccess
|
||||
} recover { _ =>
|
||||
InternalServerError(
|
||||
jsonError("Sorry, we can't process that query at the moment")
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}(rateLimitedFu)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,34 +94,40 @@ final class User(
|
|||
OpenBody { implicit ctx =>
|
||||
Reasonable(page) {
|
||||
EnabledUser(username) { u =>
|
||||
negotiate(
|
||||
html = for {
|
||||
nbs <- env.userNbGames(u, ctx, withCrosstable = true)
|
||||
filters = GameFilterMenu(u, nbs, filter)
|
||||
pag <- env.gamePaginator(
|
||||
user = u,
|
||||
nbs = nbs.some,
|
||||
filter = filters.current,
|
||||
me = ctx.me,
|
||||
page = page
|
||||
)(ctx.body)
|
||||
_ <- env.user.lightUserApi preloadMany pag.currentPageResults.flatMap(_.userIds)
|
||||
_ <- env.tournament.cached.nameCache preloadMany {
|
||||
pag.currentPageResults.flatMap(_.tournamentId).map(_ -> ctxLang)
|
||||
}
|
||||
res <-
|
||||
if (HTTPRequest isSynchronousHttp ctx.req) for {
|
||||
info <- env.userInfo(u, nbs, ctx)
|
||||
_ <- env.team.cached.nameCache preloadMany info.teamIds
|
||||
social <- env.socialInfo(u, ctx)
|
||||
searchForm =
|
||||
(filters.current == GameFilter.Search) option
|
||||
GameFilterMenu.searchForm(userGameSearch, filters.current)(ctx.body)
|
||||
} yield html.user.show.page.games(u, info, pag, filters, searchForm, social)
|
||||
else fuccess(html.user.show.gamesContent(u, nbs, pag, filters, filter))
|
||||
} yield res,
|
||||
api = _ => apiGames(u, filter, page)
|
||||
)
|
||||
if (filter == "search" && ctx.isAnon)
|
||||
negotiate(
|
||||
html = Unauthorized(html.search.login(u.count.game)).fuccess,
|
||||
api = _ => Unauthorized(jsonError("Login required")).fuccess
|
||||
)
|
||||
else
|
||||
negotiate(
|
||||
html = for {
|
||||
nbs <- env.userNbGames(u, ctx, withCrosstable = true)
|
||||
filters = GameFilterMenu(u, nbs, filter, ctx.isAuth)
|
||||
pag <- env.gamePaginator(
|
||||
user = u,
|
||||
nbs = nbs.some,
|
||||
filter = filters.current,
|
||||
me = ctx.me,
|
||||
page = page
|
||||
)(ctx.body)
|
||||
_ <- env.user.lightUserApi preloadMany pag.currentPageResults.flatMap(_.userIds)
|
||||
_ <- env.tournament.cached.nameCache preloadMany {
|
||||
pag.currentPageResults.flatMap(_.tournamentId).map(_ -> ctxLang)
|
||||
}
|
||||
res <-
|
||||
if (HTTPRequest isSynchronousHttp ctx.req) for {
|
||||
info <- env.userInfo(u, nbs, ctx)
|
||||
_ <- env.team.cached.nameCache preloadMany info.teamIds
|
||||
social <- env.socialInfo(u, ctx)
|
||||
searchForm =
|
||||
(filters.current == GameFilter.Search) option
|
||||
GameFilterMenu.searchForm(userGameSearch, filters.current)(ctx.body)
|
||||
} yield html.user.show.page.games(u, info, pag, filters, searchForm, social)
|
||||
else fuccess(html.user.show.gamesContent(u, nbs, pag, filters, filter))
|
||||
} yield res,
|
||||
api = _ => apiGames(u, filter, page)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ object GameFilterMenu {
|
|||
val all: NonEmptyList[GameFilter] =
|
||||
NonEmptyList.of(All, Me, Rated, Win, Loss, Draw, Playing, Bookmark, Imported, Search)
|
||||
|
||||
def apply(user: User, nbs: UserInfo.NbGames, currentName: String): GameFilterMenu = {
|
||||
def apply(user: User, nbs: UserInfo.NbGames, currentName: String, isAuth: Boolean): GameFilterMenu = {
|
||||
|
||||
val filters: NonEmptyList[GameFilter] = NonEmptyList(
|
||||
All,
|
||||
|
@ -52,7 +52,7 @@ object GameFilterMenu {
|
|||
(nbs.playing > 0) option Playing,
|
||||
(nbs.bookmark > 0) option Bookmark,
|
||||
(nbs.imported > 0) option Imported,
|
||||
(user.count.game > 0) option Search
|
||||
(isAuth && user.count.game > 0) option Search
|
||||
).flatten
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package views.html.search
|
||||
|
||||
import controllers.routes
|
||||
|
||||
import lila.api.Context
|
||||
import lila.app.templating.Environment._
|
||||
import lila.app.ui.ScalatagsTemplate._
|
||||
|
||||
object login {
|
||||
|
||||
def apply(nbGames: Long)(implicit ctx: Context) = {
|
||||
views.html.base.layout(
|
||||
title = trans.search.searchInXGames.txt(nbGames.localize, nbGames),
|
||||
moreCss = cssTag("search")
|
||||
) {
|
||||
main(cls := "box box-pad page-small search search-login")(
|
||||
h1(trans.search.advancedSearch()),
|
||||
div(cls := "search__login")(
|
||||
p(a(href := routes.Auth.signup())(trans.youNeedAnAccountToDoThat()))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue