Skip to content

Commit

Permalink
Merge branch 'master' into broadcast-chat-game-navigate-15029
Browse files Browse the repository at this point in the history
  • Loading branch information
Carbrex authored Jul 6, 2024
2 parents 233373e + fe08eb0 commit 3d356b6
Show file tree
Hide file tree
Showing 729 changed files with 4,423 additions and 3,519 deletions.
1 change: 1 addition & 0 deletions app/controllers/Account.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ final class Account(
me.value,
withFollows = apiC.userWithFollows,
withTrophies = false,
withCanChallenge = false,
forWiki = wikiGranted
)
.dmap { JsonOk(_) }
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/Api.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ final class Api(
.extended(
name,
withFollows = userWithFollows,
withTrophies = getBool("trophies")
withTrophies = getBool("trophies"),
withCanChallenge = getBool("challenge")
)
.map(toApiResult)
.map(toHttp)
Expand Down
6 changes: 2 additions & 4 deletions app/controllers/Auth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,21 @@ final class Auth(
): Fu[Result] =
api
.saveAuthentication(u.id, ctx.mobileApiVersion)
.flatMap { sessionId =>
.flatMap: sessionId =>
negotiate(
result.fold(Redirect(getReferrer))(_(getReferrer)),
mobileUserOk(u, sessionId)
).map(authenticateCookie(sessionId, remember))
}
.recoverWith(authRecovery)

private def authenticateAppealUser(u: UserModel, redirect: String => Result)(using
ctx: Context
): Fu[Result] =
api.appeal
.saveAuthentication(u.id)
.flatMap { sessionId =>
.flatMap: sessionId =>
authenticateCookie(sessionId, remember = false):
redirect(routes.Appeal.landing.url)
}
.recoverWith(authRecovery)

private def authenticateCookie(sessionId: String, remember: Boolean)(
Expand Down
21 changes: 20 additions & 1 deletion app/controllers/BulkPairing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import play.api.libs.json.*
import lila.app.*
import lila.common.Json.given
import lila.challenge.ChallengeBulkSetup
import lila.api.GameApiV2

final class BulkPairing(env: Env) extends LilaController(env):
final class BulkPairing(gameC: => Game, apiC: => Api, env: Env) extends LilaController(env):

def list = ScopedBody(_.Challenge.Bulk) { _ ?=> me ?=>
env.challenge.bulk
Expand All @@ -23,6 +24,24 @@ final class BulkPairing(env: Env) extends LilaController(env):
JsonOk(ChallengeBulkSetup.toJson(bulk))
}

def games(id: String) = ScopedBody(_.Challenge.Bulk) { _ ?=> me ?=>
env.challenge.bulk
.findBy(id, me)
.map:
_.fold(notFoundText()): bulk =>
val config = GameApiV2.ByIdsConfig(
ids = bulk.games.map(_.id),
format = GameApiV2.Format.byRequest(req),
flags = gameC
.requestPgnFlags(extended = false)
.copy(delayMoves = false),
perSecond = MaxPerSecond(50)
)
apiC.GlobalConcurrencyLimitPerIP
.download(req.ipAddress)(env.api.gameApiV2.exportByIds(config)): source =>
noProxyBuffer(Ok.chunked(source)).as(gameC.gameContentType(config))
}

def delete(id: String) = ScopedBody(_.Challenge.Bulk) { _ ?=> me ?=>
env.challenge.bulk
.deleteBy(id, me)
Expand Down
6 changes: 3 additions & 3 deletions app/controllers/Challenge.scala
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ final class Challenge(
case None => redir
case Some(dest) if ctx.is(dest) => redir
case Some(dest) =>
env.challenge.granter.isDenied(dest, c.perfType).flatMap {
env.challenge.granter.isDenied(dest, c.perfType.key.some).flatMap {
case Some(denied) =>
showChallenge(c, lila.challenge.ChallengeDenied.translated(denied).some)
case None => api.setDestUser(c, dest).inject(redir)
Expand Down Expand Up @@ -303,7 +303,7 @@ final class Challenge(
limit.challengeUser(me, rateLimited, cost = cost):
for
challenge <- makeOauthChallenge(config, me, destUser)
grant <- env.challenge.granter.isDenied(destUser, config.perfType)
grant <- env.challenge.granter.isDenied(destUser, config.perfKey.some)
res <- grant match
case Some(denied) =>
fuccess:
Expand Down Expand Up @@ -376,7 +376,7 @@ final class Challenge(
NoBot:
Found(env.game.gameRepo.game(gameId)): g =>
g.opponentOf(me).flatMap(_.userId).so(env.user.repo.byId).orNotFound { opponent =>
env.challenge.granter.isDenied(opponent, g.perfKey).flatMap {
env.challenge.granter.isDenied(opponent, g.perfKey.some).flatMap {
case Some(d) => BadRequest(jsonError(lila.challenge.ChallengeDenied.translated(d)))
case _ =>
api.offerRematchForGame(g, me).map {
Expand Down
9 changes: 9 additions & 0 deletions app/controllers/ForumCateg.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ final class ForumCateg(env: Env) extends LilaController(env) with ForumControlle
if canRead then Ok.page(views.forum.categ.show(categ, topics, canWrite, stickyPosts))
else notFound
yield res

def modFeed(slug: ForumCategId, page: Int) = Secure(_.ModerateForum) { ctx ?=> _ ?=>
Found(env.forum.categRepo.byId(slug)): categ =>
for
posts <- env.forum.paginator.recent(categ, page)
postViews <- posts.mapFutureList(env.forum.postApi.views)
page <- renderPage(views.forum.categ.modFeed(categ, postViews))
yield Ok(page)
}
15 changes: 15 additions & 0 deletions app/controllers/ForumPost.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ final class ForumPost(env: Env) extends LilaController(env) with ForumController
NoContent
}

def relocate(id: ForumPostId) = SecureBody(_.ModerateForum) { ctx ?=> me ?=>
Found(postApi.getPost(id).flatMapz(postApi.viewOf)): post =>
forms.relocateTo
.bindFromRequest()
.value
.so: to =>
env.forum.topicApi
.relocate(post.topic.id, to)
.inject:
post.post.userId.foreach: op =>
val newUrl = routes.ForumTopic.show(to, post.topic.slug, 1).url
env.msg.api.systemPost(op, MsgPreset.forumRelocation(post.topic.name, newUrl))
Redirect(routes.ForumCateg.show(to)).flashSuccess
}

def react(categId: ForumCategId, id: ForumPostId, reaction: String, v: Boolean) = Auth { _ ?=> me ?=>
CategGrantWrite(categId):
FoundSnip(postApi.react(categId, id, reaction, v)): post =>
Expand Down
12 changes: 5 additions & 7 deletions app/controllers/Mod.scala
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,14 @@ final class Mod(
bindForm(lila.user.UserForm.title)(
_ => redirect(username, mod = true),
title =>
doSetTitle(username.id, title, public = true).inject:
doSetTitle(username.id, title).inject:
redirect(username, mod = false)
)
}

protected[controllers] def doSetTitle(userId: UserId, title: Option[chess.PlayerTitle], public: Boolean)(
using Me
) = for
_ <- (public || title.isEmpty).so(modApi.setTitle(userId, title))
_ <- title.so(env.mailer.automaticEmail.onTitleSet(userId, _, public))
protected[controllers] def doSetTitle(userId: UserId, title: Option[chess.PlayerTitle])(using Me) = for
_ <- modApi.setTitle(userId, title)
_ <- title.so(env.mailer.automaticEmail.onTitleSet(userId, _))
yield ()

def setEmail(username: UserStr) = SecureBody(_.SetEmail) { ctx ?=> me ?=>
Expand Down Expand Up @@ -470,7 +468,7 @@ final class Mod(
} >> {
Permission
.ofDbKeys(permissions)
.exists(_.grants(Permission.SeeReport))
.exists(p => p.grants(Permission.SeeReport) || p.grants(Permission.Developer))
.so(env.plan.api.setLifetime(user))
}).inject(Redirect(routes.Mod.permissions(user.username)).flashSuccess)
)
Expand Down
37 changes: 30 additions & 7 deletions app/controllers/RelayRound.scala
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ final class RelayRound(
)
}

def reset(id: RelayRoundId) = Auth { ctx ?=> me ?=>
def reset(id: RelayRoundId) = AuthOrScoped(_.Study.Write) { ctx ?=> me ?=>
Found(env.relay.api.byIdAndContributor(id)): rt =>
env.relay.api.reset(rt.round).inject(Redirect(rt.path))
env.relay.api.reset(rt.round) >> negotiate(Redirect(rt.path), jsonOkResult)
}

def show(ts: String, rs: String, id: RelayRoundId, embed: Option[UserStr]) =
Expand All @@ -122,13 +122,29 @@ final class RelayRound(
Found(env.study.studyRepo.byId(rt.round.studyId)): study =>
studyC.CanView(study)(
for
group <- env.relay.api.withTours.get(rt.tour.id)
previews <- env.study.preview.jsonList(study.id)
yield JsonOk(env.relay.jsonView.withUrlAndPreviews(rt.withStudy(study), previews, group))
group <- env.relay.api.withTours.get(rt.tour.id)
previews <- env.study.preview.jsonList.withoutInitialEmpty(study.id)
targetRound <- env.relay.api.officialTarget(rt.round)
yield JsonOk(
env.relay.jsonView.withUrlAndPreviews(rt.withStudy(study), previews, group, targetRound)
)
)(studyC.privateUnauthorizedJson, studyC.privateForbiddenJson)

def pgn(ts: String, rs: String, id: StudyId) = studyC.pgn(id)
def apiPgn = studyC.apiPgn
def pgn(ts: String, rs: String, id: RelayRoundId) = Open:
pgnWithFlags(ts, rs, id)

def apiPgn(id: RelayRoundId) = AnonOrScoped(_.Study.Read): ctx ?=>
pgnWithFlags("-", "-", id)

private def pgnWithFlags(ts: String, rs: String, id: RelayRoundId)(using Context): Fu[Result] =
studyC.pgnWithFlags(
id.into(StudyId),
_.copy(
site = s"${env.net.baseUrl}${routes.RelayRound.show(ts, rs, id)}".some,
comments = false,
variations = false
)
)

def apiMyRounds = Scoped(_.Study.Read) { ctx ?=> _ ?=>
val source = env.relay.api.myRounds(MaxPerSecond(20), getIntAs[Max]("nb")).map(env.relay.jsonView.myRound)
Expand Down Expand Up @@ -174,6 +190,13 @@ final class RelayRound(
env.relay.teamTable.tableJson(rt.relay).map(JsonStrOk)
}(Unauthorized, Forbidden)

def stats(id: RelayRoundId) = Open:
env.relay.stats
.get(id)
.map: stats =>
import lila.relay.JsonView.given
JsonOk(stats)

private def WithRoundAndTour(@nowarn ts: String, @nowarn rs: String, id: RelayRoundId)(
f: RoundModel.WithTour => Fu[Result]
)(using ctx: Context): Fu[Result] =
Expand Down
9 changes: 1 addition & 8 deletions app/controllers/RelayTour.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ final class RelayTour(env: Env, apiC: => Api) extends LilaController(env):
setup =>
env.relay.api.tourUpdate(nav.tour, setup) >>
negotiate(
Redirect(routes.RelayTour.show(nav.tour.slug, nav.tour.id)),
Redirect(routes.RelayTour.edit(nav.tour.id)).flashSuccess,
jsonOkResult
)
)
Expand Down Expand Up @@ -189,13 +189,6 @@ final class RelayTour(env: Env, apiC: => Api) extends LilaController(env):
asAttachmentStream(s"${env.relay.pgnStream.filename(tour)}.pgn"):
Ok.chunked(source).as(pgnContentType)

def stats(id: RelayTourId) = Open:
Found(env.relay.api.tourById(id)): tour =>
env.relay.stats
.get(tour.id)
.flatMap: stats =>
Ok.page(views.relay.tour.stats(tour, stats))

def apiIndex = Anon:
apiC.jsonDownload:
env.relay.tourStream
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/Report.scala
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ final class Report(env: Env, userC: => User, modC: => Mod) extends LilaControlle
text = s"$pid\n\n"
)
case _ => form
views.report.form(filledForm, user)
views.report.ui.form(filledForm, user)
}
}

Expand All @@ -162,7 +162,7 @@ final class Report(env: Env, userC: => User, modC: => Mod) extends LilaControlle
err =>
for
user <- getUserStr("username").so(env.user.repo.byId)
page <- renderPage(views.report.form(err, user))
page <- renderPage(views.report.ui.form(err, user))
yield BadRequest(page),
data =>
if me.is(data.user.id) then BadRequest("You cannot report yourself")
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ final class Setup(
for
origUser <- ctx.user.soFu(env.user.perfsRepo.withPerf(_, config.perfType))
destUser <- userId.so(env.user.api.enabledWithPerf(_, config.perfType))
denied <- destUser.so(u => env.challenge.granter.isDenied(u.user, config.perfType))
denied <- destUser.so(u => env.challenge.granter.isDenied(u.user, config.perfKey.some))
result <- denied match
case Some(denied) =>
val message = lila.challenge.ChallengeDenied.translated(denied)
Expand Down
45 changes: 22 additions & 23 deletions app/controllers/Study.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import lila.study.JsonView.JsData
import lila.study.Study.WithChapter
import lila.study.actorApi.{ BecomeStudyAdmin, Who }
import lila.study.{ Chapter, Settings, Orders, Study as StudyModel, StudyForm }
import lila.study.PgnDump.WithFlags
import lila.tree.Node.partitionTreeJsonWriter
import lila.core.misc.lpv.LpvEmbed
import lila.core.net.IpAddress
Expand Down Expand Up @@ -242,7 +243,7 @@ final class Study(
division = division
)
)
withMembers = !study.isRelay || isGrantedOpt(_.StudyAdmin)
withMembers = !study.isRelay || isGrantedOpt(_.StudyAdmin) || ctx.me.exists(study.isMember)
studyJson <- env.study.jsonView(study, previews, chapter, fedNames.some, withMembers = withMembers)
yield WithChapter(study, chapter) -> JsData(
study = studyJson,
Expand Down Expand Up @@ -319,11 +320,12 @@ final class Study(

def delete(id: StudyId) = Auth { _ ?=> me ?=>
Found(env.study.api.byIdAndOwnerOrAdmin(id, me)): study =>
env.study.api.delete(study) >> env.relay.api
.deleteRound(id.into(RelayRoundId))
.map:
case None => Redirect(routes.Study.mine(Order.hot))
case Some(tour) => Redirect(routes.RelayTour.show(tour.slug, tour.id))
for
round <- env.relay.api.deleteRound(id.into(RelayRoundId))
_ <- env.study.api.delete(study)
yield round match
case None => Redirect(routes.Study.mine(Order.hot))
case Some(tour) => Redirect(routes.RelayTour.show(tour.slug, tour.id))
}

def apiChapterDelete(id: StudyId, chapterId: StudyChapterId) = ScopedBody(_.Study.Write) { _ ?=> me ?=>
Expand Down Expand Up @@ -411,27 +413,23 @@ final class Study(
}

def pgn(id: StudyId) = Open:
pgnWithFlags(id, identity)

def apiPgn(id: StudyId) = AnonOrScoped(_.Study.Read): ctx ?=>
pgnWithFlags(id, identity)

def pgnWithFlags(id: StudyId, flags: Update[WithFlags])(using Context) =
Found(env.study.api.byId(id)): study =>
HeadLastModifiedAt(study.updatedAt):
limit.studyPgn(ctx.ip, rateLimited, msg = id.value):
CanView(study, study.settings.shareable.some)(doPgn(study))(
val limiter = if study.isRelay then limit.relayPgn else limit.studyPgn
limiter[Fu[Result]](req.ipAddress, rateLimited, msg = id.value):
CanView(study, study.settings.shareable.some)(doPgn(study, flags))(
privateUnauthorizedFu(study),
privateForbiddenFu(study)
)

def apiPgn(id: StudyId) = AnonOrScoped(_.Study.Read): ctx ?=>
env.study.api.byId(id).flatMap {
_.fold(studyNotFoundText.toFuccess): study =>
HeadLastModifiedAt(study.updatedAt):
limit.studyPgn[Fu[Result]](req.ipAddress, rateLimited, msg = id.value):
CanView(study, study.settings.shareable.some)(doPgn(study))(
privateUnauthorizedText,
privateForbiddenText
)
}

private def doPgn(study: StudyModel)(using RequestHeader, Option[Me]) =
Ok.chunked(env.study.pgnDump.chaptersOf(study, requestPgnFlags).throttle(16, 1.second))
private def doPgn(study: StudyModel, flags: Update[WithFlags])(using RequestHeader, Option[Me]) =
Ok.chunked(env.study.pgnDump.chaptersOf(study, flags(requestPgnFlags)).throttle(20, 1.second))
.pipe(asAttachmentStream(s"${env.study.pgnDump.filename(study)}.pgn"))
.as(pgnContentType)
.withDateHeaders(lastModified(study.updatedAt))
Expand Down Expand Up @@ -494,12 +492,13 @@ final class Study(
.map(lila.study.JsonView.metadata)

private def requestPgnFlags(using RequestHeader) =
lila.study.PgnDump.WithFlags(
WithFlags(
comments = getBoolOpt("comments") | true,
variations = getBoolOpt("variations") | true,
clocks = getBoolOpt("clocks") | true,
source = getBool("source"),
orientation = getBool("orientation")
orientation = getBool("orientation"),
site = none
)

def chapterGif(id: StudyId, chapterId: StudyChapterId, theme: Option[String], piece: Option[String]) = Open:
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/TeamApi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ final class TeamApi(env: Env, apiC: => Api) extends LilaController(env):
else ctx.me.so(api.belongsTo(team.id, _))
canView.map:
if _ then
val full = getBool("full")
apiC.jsonDownload(
env.team
.memberStream(team, MaxPerSecond(20))
.memberStream(team, full)
.map: (user, joinedAt) =>
env.api.userApi.one(user, joinedAt.some)
)
Expand Down
4 changes: 3 additions & 1 deletion app/controllers/TitleVerify.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@ final class TitleVerify(env: Env, cmsC: => Cms, reportC: => report.Report, userC
private def onApproved(req: TitleRequest)(using Context, Me) =
for
user <- env.user.api.byId(req.userId).orFail(s"User ${req.userId} not found")
_ <- modC.doSetTitle(user.id, req.data.title.some, req.data.public)
_ <- modC.doSetTitle(user.id, req.data.title.some)
url = s"${env.net.baseUrl}${routes.TitleVerify.show(req.id)}"
note = s"Title verified: ${req.data.title}. Public: ${if req.data.public then "Yes" else "No"}. $url"
_ <- env.user.noteApi.write(user.id, note, modOnly = true, dox = false)
_ <- req.data.public.so:
env.user.repo.setRealName(user.id, req.data.realName)
_ <- req.data.coach.so:
env.user.repo.addPermission(user.id, lila.core.perm.Permission.Coach)
_ <- req.data.coach.so:
Expand Down
Loading

0 comments on commit 3d356b6

Please sign in to comment.