Skip to content

Commit

Permalink
opaque type UserId compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Nov 29, 2022
1 parent 34567ec commit 05add2d
Show file tree
Hide file tree
Showing 35 changed files with 182 additions and 178 deletions.
14 changes: 7 additions & 7 deletions app/controllers/Puzzle.scala
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ final class Puzzle(env: Env, apiC: => Api) extends LilaController(env):
}
}

def ofPlayer(name: Option[String], page: Int) =
def ofPlayer(name: Option[UserStr], page: Int) =
Open { implicit ctx =>
val fixed = name.map(_.trim).filter(_.nonEmpty)
fixed.??(env.user.repo.enabledById) orElse fuccess(ctx.me) flatMap { user =>
val userId = name flatMap lila.user.User.validateId
userId.??(env.user.repo.enabledById) orElse fuccess(ctx.me) flatMap { user =>
user.?? { env.puzzle.api.puzzle.of(_, page) dmap some } map { puzzles =>
Ok(views.html.puzzle.ofPlayer(~fixed, user, puzzles))
Ok(views.html.puzzle.ofPlayer(name.??(_.value), user, puzzles))
}
}
}
Expand Down Expand Up @@ -402,7 +402,7 @@ final class Puzzle(env: Env, apiC: => Api) extends LilaController(env):
scoped = req => me => render(me)(reqLang(req))
)

def dashboard(days: Int, path: String = "home", u: Option[String]) =
def dashboard(days: Int, path: String = "home", u: Option[UserStr]) =
DashboardPage(u) { implicit ctx => user =>
env.puzzle.dashboard(user, days) map { dashboard =>
path match
Expand Down Expand Up @@ -441,7 +441,7 @@ final class Puzzle(env: Env, apiC: => Api) extends LilaController(env):

}

def history(page: Int, u: Option[String]) =
def history(page: Int, u: Option[UserStr]) =
DashboardPage(u) { implicit ctx => user =>
Reasonable(page) {
env.puzzle.history(user, page) map { history =>
Expand Down Expand Up @@ -545,7 +545,7 @@ final class Puzzle(env: Env, apiC: => Api) extends LilaController(env):
Ok(html.site.keyboardHelpModal.puzzle).toFuccess
}

private def DashboardPage(username: Option[String])(f: Context => UserModel => Fu[Result]) =
private def DashboardPage(username: Option[UserStr])(f: Context => UserModel => Fu[Result]) =
Auth { implicit ctx => me =>
username
.??(env.user.repo.byId)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Racer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ final class Racer(env: Env)(implicit mat: akka.stream.Materializer) extends Lila

def apiCreate = Scoped(_.Racer.Write) { implicit req => me =>
me.noBot ?? {
env.racer.api.createAndJoin(RacerPlayer.Id.User(me.id)) map { raceId =>
env.racer.api.createAndJoin(RacerPlayer.Id.User(me.username)) map { raceId =>
JsonOk(
Json.obj(
"id" -> raceId.value,
Expand Down
81 changes: 42 additions & 39 deletions app/controllers/Relation.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package controllers

import play.api.libs.json.{ Json, Writes }
import play.api.mvc.Result
import scala.concurrent.duration.*

import lila.api.Context
Expand All @@ -12,6 +13,8 @@ import lila.relation.RelationStream.*
import lila.user.{ User as UserModel }
import views.*
import lila.common.config
import Api.ApiResult
import lila.common.LightUser

final class Relation(
env: Env,
Expand All @@ -20,7 +23,7 @@ final class Relation(

val api = env.relation.api

private def renderActions(username: UserStr, mini: Boolean)(implicit ctx: Context) =
private def renderActions(username: UserName, mini: Boolean)(implicit ctx: Context) =
env.user.lightUserApi.asyncFallbackName(username) flatMap { user =>
(ctx.userId ?? { api.fetchRelation(_, user.id) }) zip
(ctx.isAuth ?? { env.pref.api followable user.id }) zip
Expand Down Expand Up @@ -52,72 +55,72 @@ final class Relation(
key = "follow.user"
)

private def FollowingUser(me: UserModel, str: UserStr)(f: LightUser => Fu[Result]): Fu[Result] =
env.user.lightUserApi.async(str.id) flatMap {
_ ?? { user =>
FollowLimitPerUser(me.id) {
f(user)
}(rateLimitedFu)
}
}

def follow(username: UserStr) =
Auth { implicit ctx => me =>
FollowLimitPerUser(me.id) {
FollowingUser(me, username) { user =>
api.reachedMaxFollowing(me.id) flatMap {
case true =>
env.msg.api
.postPreset(
me.id,
lila.msg.MsgPreset.maxFollow(me.username, env.relation.maxFollow.value)
) inject Ok
case _ =>
api.follow(me.id, UserModel normalize username).recoverDefault >> renderActions(
username,
getBool("mini")
)
case _ => api.follow(me.id, user.id).recoverDefault >> renderActions(user.name, getBool("mini"))
}
}(rateLimitedFu)
}
}

def apiFollow(userId: UserId) =
def apiFollow(userId: UserStr) =
Scoped(_.Follow.Write) { _ => me =>
FollowLimitPerUser[Fu[Api.ApiResult]](me.id) {
FollowLimitPerUser(me.id) {
api.reachedMaxFollowing(me.id) flatMap {
case true =>
fuccess(
Api.ClientError(lila.msg.MsgPreset.maxFollow(me.username, env.relation.maxFollow.value).text)
)
fuccess {
ApiResult.ClientError(
lila.msg.MsgPreset.maxFollow(me.username, env.relation.maxFollow.value).text
)
}
case _ =>
api.follow(me.id, UserModel normalize userId).recoverDefault inject Api.Done
api.follow(me.id, userId.id).recoverDefault inject ApiResult.Done
}
}(fuccess(Api.Limited)) map apiC.toHttp
}(fuccess(ApiResult.Limited)) map apiC.toHttp
}

def unfollow(username: UserStr) =
Auth { implicit ctx => me =>
FollowLimitPerUser(me.id) {
api.unfollow(me.id, UserModel normalize username).recoverDefault >> renderActions(
username,
getBool("mini")
)
}(rateLimitedFu)
FollowingUser(me, username) { user =>
api.unfollow(me.id, user.id).recoverDefault >> renderActions(user.name, getBool("mini"))
}
}

def apiUnfollow(userId: UserId) =
def apiUnfollow(userId: UserStr) =
Scoped(_.Follow.Write) { _ => me =>
FollowLimitPerUser[Fu[Api.ApiResult]](me.id) {
api.unfollow(me.id, UserModel normalize userId) inject Api.Done
}(fuccess(Api.Limited)) map apiC.toHttp
FollowLimitPerUser[Fu[ApiResult]](me.id) {
api.unfollow(me.id, userId.id) inject ApiResult.Done
}(fuccess(ApiResult.Limited)) map apiC.toHttp
}

def block(username: UserStr) =
Auth { implicit ctx => me =>
FollowLimitPerUser(me.id) {
api.block(me.id, UserModel normalize username).recoverDefault >> renderActions(
username,
getBool("mini")
)
}(rateLimitedFu)
FollowingUser(me, username) { user =>
api.block(me.id, user.id).recoverDefault >> renderActions(user.name, getBool("mini"))
}
}

def unblock(username: UserStr) =
Auth { implicit ctx => me =>
api.unblock(me.id, UserModel normalize username).recoverDefault >> renderActions(
username,
getBool("mini")
)
FollowingUser(me, username) { user =>
api.unblock(me.id, user.id).recoverDefault >> renderActions(user.name, getBool("mini"))
}
}

def following(username: UserStr, page: Int) =
Expand All @@ -144,7 +147,7 @@ final class Relation(
html = notFound,
api = _ =>
Reasonable(page, config.Max(20)) {
RelatedPager(api.followersPaginatorAdapter(UserModel normalize username), page) flatMap { pag =>
RelatedPager(api.followersPaginatorAdapter(username.id), page) flatMap { pag =>
Ok(jsonRelatedPaginator(pag)).toFuccess
}
}
Expand Down Expand Up @@ -181,15 +184,15 @@ final class Relation(
}
}

private def RelatedPager(adapter: AdapterLike[String], page: Int)(implicit ctx: Context) =
private def RelatedPager(adapter: AdapterLike[UserId], page: Int)(implicit ctx: Context) =
Paginator(
adapter = adapter mapFutureList followship,
currentPage = page,
maxPerPage = lila.common.config.MaxPerPage(30)
)

private def followship(userIds: Seq[String])(implicit ctx: Context): Fu[List[Related]] =
env.user.repo usersFromSecondary userIds.map(UserModel.normalize) flatMap { users =>
private def followship(userIds: Seq[UserId])(implicit ctx: Context): Fu[List[Related]] =
env.user.repo usersFromSecondary userIds flatMap { users =>
(ctx.isAuth ?? { env.pref.api.followableIds(users map (_.id)) }) flatMap { followables =>
users.map { u =>
ctx.userId ?? { api.fetchRelation(_, u.id) } map { rel =>
Expand Down
14 changes: 7 additions & 7 deletions app/controllers/Report.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ final class Report(
}
}

def xfiles(id: String) =
def xfiles(id: UserStr) =
Secure(_.SeeReport) { _ => _ =>
api.moveToXfiles(id) inject Redirect(routes.Report.list)
api.moveToXfiles(id.id) inject Redirect(routes.Report.list)
}

def snooze(id: String, dur: String) =
Expand All @@ -150,7 +150,7 @@ final class Report(

def form =
Auth { implicit ctx => _ =>
get("username") ?? env.user.repo.byId flatMap { user =>
getUserStr("username") ?? env.user.repo.byId flatMap { user =>
if (user.map(_.id) has UserModel.lichessId) Redirect(controllers.routes.Main.contact).toFuccess
else
env.report.forms.createWithCaptcha map { case (form, captcha) =>
Expand All @@ -173,7 +173,7 @@ final class Report(
.bindFromRequest()
.fold(
err =>
get("username") ?? env.user.repo.byId flatMap { user =>
getUserStr("username") ?? env.user.repo.byId flatMap { user =>
env.report.forms.anyCaptcha map { captcha =>
BadRequest(html.report.form(err, user, captcha))
}
Expand Down Expand Up @@ -203,9 +203,9 @@ final class Report(
)
}

def thanks(reported: String) =
def thanks(reported: UserStr) =
Auth { implicit ctx => me =>
env.relation.api.fetchBlocks(me.id, reported) map { blocked =>
html.report.thanks(reported, blocked)
env.relation.api.fetchBlocks(me.id, reported.id) map { blocked =>
html.report.thanks(reported.id, blocked)
}
}
6 changes: 3 additions & 3 deletions app/controllers/Round.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ final class Round(
Open { implicit ctx =>
env.round.proxyRepo.pov(fullId) flatMap {
case Some(pov) => renderPlayer(pov)
case None => userC.tryRedirect(fullId) getOrElse notFound
case None => userC.tryRedirect(fullId into UserStr) getOrElse notFound
}
}

Expand Down Expand Up @@ -125,15 +125,15 @@ final class Round(
Open { implicit ctx =>
proxyPov(gameId, color) flatMap {
case Some(pov) =>
get("pov").map(UserModel.normalize).fold(watch(pov)) { requestedPov =>
getUserStr("pov").map(_.id).fold(watch(pov)) { requestedPov =>
(pov.player.userId, pov.opponent.userId) match
case (Some(_), Some(opponent)) if opponent == requestedPov =>
Redirect(routes.Round.watcher(gameId, (!pov.color).name)).toFuccess
case (Some(player), Some(_)) if player == requestedPov =>
Redirect(routes.Round.watcher(gameId, pov.color.name)).toFuccess
case _ => Redirect(routes.Round.watcher(gameId, "white")).toFuccess
}
case None => userC.tryRedirect(gameId) getOrElse challengeC.showId(gameId)
case None => userC.tryRedirect(gameId into UserStr) getOrElse challengeC.showId(gameId)
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/Setup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ final class Setup(
)

def ai = OpenBody { implicit ctx =>
BotAiRateLimit(~ctx.userId, cost = ctx.me.exists(_.isBot) ?? 1) {
BotAiRateLimit(ctx.userId | UserId(""), cost = ctx.me.exists(_.isBot) ?? 1) {
PostRateLimit(ctx.ip) {
given play.api.mvc.Request[?] = ctx.body
forms.ai
Expand Down
10 changes: 5 additions & 5 deletions app/controllers/Simul.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,24 @@ final class Simul(env: Env) extends LilaController(env):
Auth { implicit ctx => me =>
AsHost(simulId) { simul =>
env.simul.api abort simul.id inject {
if (!simul.isHost(me)) env.mod.logApi.terminateTournament(me.id, simul.fullName)
if (!simul.isHost(me)) env.mod.logApi.terminateTournament(me.id into ModId, simul.fullName)
if (HTTPRequest isXhr ctx.req) jsonOkResult
else Redirect(routes.Simul.home)
}
}
}

def accept(simulId: SimulId, userId: UserId) =
def accept(simulId: SimulId, userId: UserStr) =
Open { implicit ctx =>
AsHost(simulId) { simul =>
env.simul.api.accept(simul.id, userId, v = true) inject jsonOkResult
env.simul.api.accept(simul.id, userId.id, v = true) inject jsonOkResult
}
}

def reject(simulId: SimulId, userId: UserId) =
def reject(simulId: SimulId, userId: UserStr) =
Open { implicit ctx =>
AsHost(simulId) { simul =>
env.simul.api.accept(simul.id, userId, v = false) inject jsonOkResult
env.simul.api.accept(simul.id, userId.id, v = false) inject jsonOkResult
}
}

Expand Down
6 changes: 3 additions & 3 deletions app/controllers/Streamer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ final class Streamer(env: Env, apiC: => Api) extends LilaController(env):
OptionFuResult(api find username) { s =>
WithVisibleStreamer(s) {
env.streamer.liveStreamApi of s map { sws =>
Redirect(sws.redirectToLiveUrl | routes.Streamer.show(username).url)
Redirect(sws.redirectToLiveUrl | routes.Streamer.show(username.value).url)
}
}
}
Expand Down Expand Up @@ -190,7 +190,7 @@ final class Streamer(env: Env, apiC: => Api) extends LilaController(env):
private def AsStreamer(f: StreamerModel.WithUser => Fu[Result])(implicit ctx: Context) =
ctx.me.fold(notFound) { me =>
if (StreamerModel.canApply(me) || isGranted(_.Streamers))
api.find(get("u").ifTrue(isGranted(_.Streamers)) | me.id) flatMap {
api.find(getUserStr("u").ifTrue(isGranted(_.Streamers)).map(_.id) | me.id) flatMap {
_.fold(Ok(html.streamer.bits.create).toFuccess)(f)
}
else
Expand All @@ -203,6 +203,6 @@ final class Streamer(env: Env, apiC: => Api) extends LilaController(env):

private def WithVisibleStreamer(s: StreamerModel.WithUser)(f: Fu[Result])(implicit ctx: Context) =
ctx.noKid ?? {
if (s.streamer.isListed || ctx.me.??(s.streamer.is) || isGranted(_.Admin)) f
if (s.streamer.isListed || ctx.me.exists(_ is s.streamer) || isGranted(_.Admin)) f
else notFound
}
4 changes: 2 additions & 2 deletions app/controllers/Study.scala
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ final class Study(
me: Option[lila.user.User],
req: RequestHeader
) =
val name = if (username == "me") me.fold("me")(_.username) else username
val name = if (username.value == "me") me.fold(UserName("me"))(_.username) else username.into(UserName)
val userId = name.id
val flags = requestPgnFlags(req)
val isMe = me.exists(_ is userId)
Expand Down Expand Up @@ -560,7 +560,7 @@ final class Study(
case None => BadRequest("No search term provided").toFuccess
case Some(term) =>
import lila.study.JsonView.given
env.study.topicApi.findLike(term, get("user", req)) map { JsonOk(_) }
env.study.topicApi.findLike(term, getUserStr("user", req).map(_.id)) map { JsonOk(_) }
}

def topics =
Expand Down
Loading

0 comments on commit 05add2d

Please sign in to comment.