don't always publish user.online to discourage API misuse
Use this instead: https://lichess.org/api#operation/apiUsersStatuspull/9850/head
parent
be678f9a41
commit
ced5e57c93
|
@ -74,7 +74,7 @@ final class Account(
|
|||
env.playban.api.currentBan(me.id) map { case (((prefs, povs), nbChallenges), playban) =>
|
||||
Ok {
|
||||
import lila.pref.JsonView._
|
||||
env.user.jsonView(me) ++ Json
|
||||
env.user.jsonView(me, withOnline = true) ++ Json
|
||||
.obj(
|
||||
"prefs" -> prefs,
|
||||
"nowPlaying" -> JsArray(povs take 50 map env.api.lobbyApi.nowPlaying),
|
||||
|
|
|
@ -66,7 +66,7 @@ final class Api(
|
|||
UsersRateLimitPerIP(ip, cost = cost) {
|
||||
lila.mon.api.users.increment(cost.toLong)
|
||||
env.user.repo enabledNameds usernames map {
|
||||
_.map { env.user.jsonView(_, none) }
|
||||
_.map { env.user.jsonView(_, none, withOnline = false) }
|
||||
} map toApiResult map toHttp
|
||||
}(rateLimitedFu)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ final class Auth(
|
|||
private def mobileUserOk(u: UserModel, sessionId: String): Fu[Result] =
|
||||
env.round.proxyRepo urgentGames u map { povs =>
|
||||
Ok {
|
||||
env.user.jsonView(u) ++ Json.obj(
|
||||
env.user.jsonView(u, withOnline = true) ++ Json.obj(
|
||||
"nowPlaying" -> JsArray(povs take 20 map env.api.lobbyApi.nowPlaying),
|
||||
"sessionId" -> sessionId
|
||||
)
|
||||
|
|
|
@ -184,7 +184,7 @@ final class PlayApi(
|
|||
.botsByIdsCursor(env.bot.onlineApiUsers.get)
|
||||
.documentSource(getInt("nb", req) | Int.MaxValue)
|
||||
.throttle(50, 1 second)
|
||||
.map { env.user.jsonView(_) }
|
||||
.map { env.user.jsonView(_, withOnline = false) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,18 +142,13 @@ final class Relation(
|
|||
)
|
||||
}
|
||||
|
||||
def apiFollowing(name: String) =
|
||||
Action.async { implicit req =>
|
||||
env.user.repo.enabledNamed(name) flatMap {
|
||||
_ ?? { user =>
|
||||
apiC.jsonStream {
|
||||
env.relation.stream
|
||||
.follow(user, Direction.Following, MaxPerSecond(20))
|
||||
.map(env.api.userApi.one)
|
||||
}.fuccess
|
||||
}
|
||||
}
|
||||
}
|
||||
def apiFollowing = Scoped() { implicit req => me =>
|
||||
apiC.jsonStream {
|
||||
env.relation.stream
|
||||
.follow(me, Direction.Following, MaxPerSecond(30))
|
||||
.map(env.api.userApi.one(_, withOnline = false))
|
||||
}.fuccess
|
||||
}
|
||||
|
||||
private def jsonRelatedPaginator(pag: Paginator[Related]) = {
|
||||
import lila.user.JsonView.nameWrites
|
||||
|
|
|
@ -112,7 +112,7 @@ final class Team(
|
|||
apiC.jsonStream(
|
||||
env.team
|
||||
.memberStream(team, MaxPerSecond(20))
|
||||
.map(env.api.userApi.one)
|
||||
.map(env.api.userApi.one(_, withOnline = false))
|
||||
)(req)
|
||||
case false => Unauthorized
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ final class User(
|
|||
Json.toJson(
|
||||
users
|
||||
.take(getInt("nb", req).fold(10)(_ min max))
|
||||
.map(env.user.jsonView(_))
|
||||
.map(env.user.jsonView(_, withOnline = false))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,11 +20,8 @@ final private[api] class UserApi(
|
|||
net: NetConfig
|
||||
)(implicit ec: scala.concurrent.ExecutionContext) {
|
||||
|
||||
def pagerJson(pag: Paginator[User]): JsObject =
|
||||
Json.obj("paginator" -> PaginatorJson(pag mapResults one))
|
||||
|
||||
def one(u: User): JsObject =
|
||||
addPlayingStreaming(jsonView(u), u.id) ++
|
||||
def one(u: User, withOnline: Boolean): JsObject =
|
||||
addStreaming(jsonView(u, withOnline = withOnline), u.id) ++
|
||||
Json.obj("url" -> makeUrl(s"@/${u.username}")) // for app BC
|
||||
|
||||
def extended(username: String, as: Option[User], withFollows: Boolean): Fu[Option[JsObject]] =
|
||||
|
@ -62,7 +59,7 @@ final private[api] class UserApi(
|
|||
case ((((((((((gameOption,nbGamesWithMe),following),followers),followable),
|
||||
relation),isFollowed),nbBookmarks),nbPlaying),nbImported),completionRate)=>
|
||||
// format: on
|
||||
jsonView(u) ++ {
|
||||
jsonView(u, withOnline = true) ++ {
|
||||
Json
|
||||
.obj(
|
||||
"url" -> makeUrl(s"@/${u.username}"), // for app BC
|
||||
|
@ -99,7 +96,7 @@ final private[api] class UserApi(
|
|||
}
|
||||
}
|
||||
|
||||
private def addPlayingStreaming(js: JsObject, id: User.ID) =
|
||||
private def addStreaming(js: JsObject, id: User.ID) =
|
||||
js.add("streaming", liveStreamApi.isStreaming(id))
|
||||
|
||||
private def makeUrl(path: String): String = s"${net.baseUrl}/$path"
|
||||
|
|
|
@ -13,10 +13,10 @@ case class Crosstable(
|
|||
|
||||
def nonEmpty = results.nonEmpty option this
|
||||
|
||||
def nbGames = users.nbGames
|
||||
def showScore = users.showScore _
|
||||
def showOpponentScore = users.showOpponentScore _
|
||||
def fromPov(userId: String) = copy(users = users fromPov userId)
|
||||
def nbGames = users.nbGames
|
||||
def showScore = users.showScore _
|
||||
def showOpponentScore = users.showOpponentScore _
|
||||
def fromPov(userId: lila.user.User.ID) = copy(users = users fromPov userId)
|
||||
|
||||
lazy val size = results.size
|
||||
|
||||
|
@ -33,19 +33,19 @@ object Crosstable {
|
|||
Nil
|
||||
)
|
||||
|
||||
case class User(id: String, score: Int) // score is x10
|
||||
case class User(id: lila.user.User.ID, score: Int) // score is x10
|
||||
case class Users(user1: User, user2: User) {
|
||||
|
||||
val nbGames = (user1.score + user2.score) / 10
|
||||
|
||||
def user(id: String): Option[User] =
|
||||
def user(id: lila.user.User.ID): Option[User] =
|
||||
if (id == user1.id) Some(user1)
|
||||
else if (id == user2.id) Some(user2)
|
||||
else None
|
||||
|
||||
def toList = List(user1, user2)
|
||||
|
||||
def showScore(userId: String) = {
|
||||
def showScore(userId: lila.user.User.ID) = {
|
||||
val byTen = user(userId) ?? (_.score)
|
||||
s"${byTen / 10}${(byTen % 10 != 0).??("½")}" match {
|
||||
case "0½" => "½"
|
||||
|
@ -53,12 +53,12 @@ object Crosstable {
|
|||
}
|
||||
}
|
||||
|
||||
def showOpponentScore(userId: String) =
|
||||
def showOpponentScore(userId: lila.user.User.ID) =
|
||||
if (userId == user1.id) showScore(user2.id).some
|
||||
else if (userId == user2.id) showScore(user1.id).some
|
||||
else none
|
||||
|
||||
def fromPov(userId: String) =
|
||||
def fromPov(userId: lila.user.User.ID) =
|
||||
if (userId == user2.id) copy(user1 = user2, user2 = user1)
|
||||
else this
|
||||
|
||||
|
@ -68,22 +68,23 @@ object Crosstable {
|
|||
else None
|
||||
}
|
||||
|
||||
case class Result(gameId: Game.ID, winnerId: Option[String])
|
||||
case class Result(gameId: Game.ID, winnerId: Option[lila.user.User.ID])
|
||||
|
||||
case class Matchup(users: Users) { // score is x10
|
||||
def fromPov(userId: String) = copy(users = users fromPov userId)
|
||||
def nonEmpty = users.nbGames > 0
|
||||
def fromPov(userId: lila.user.User.ID) = copy(users = users fromPov userId)
|
||||
def nonEmpty = users.nbGames > 0
|
||||
}
|
||||
|
||||
case class WithMatchup(crosstable: Crosstable, matchup: Option[Matchup]) {
|
||||
def fromPov(userId: String) =
|
||||
def fromPov(userId: lila.user.User.ID) =
|
||||
copy(
|
||||
crosstable fromPov userId,
|
||||
matchup map (_ fromPov userId)
|
||||
)
|
||||
}
|
||||
|
||||
private[game] def makeKey(u1: String, u2: String): String = if (u1 < u2) s"$u1/$u2" else s"$u2/$u1"
|
||||
private[game] def makeKey(u1: lila.user.User.ID, u2: lila.user.User.ID): String =
|
||||
if (u1 < u2) s"$u1/$u2" else s"$u2/$u1"
|
||||
|
||||
import reactivemongo.api.bson._
|
||||
import lila.db.BSON
|
||||
|
|
|
@ -12,15 +12,15 @@ final class JsonView(isOnline: lila.socket.IsOnline) {
|
|||
implicit private val profileWrites = Json.writes[Profile]
|
||||
implicit private val playTimeWrites = Json.writes[PlayTime]
|
||||
|
||||
def apply(u: User, onlyPerf: Option[PerfType] = None): JsObject =
|
||||
def apply(u: User, onlyPerf: Option[PerfType] = None, withOnline: Boolean): JsObject =
|
||||
Json
|
||||
.obj(
|
||||
"id" -> u.id,
|
||||
"username" -> u.username,
|
||||
"online" -> isOnline(u.id),
|
||||
"perfs" -> perfs(u, onlyPerf),
|
||||
"createdAt" -> u.createdAt
|
||||
)
|
||||
.add("online" -> withOnline.option(isOnline(u.id)))
|
||||
.add("disabled" -> u.disabled)
|
||||
.add("tosViolation" -> u.lame)
|
||||
.add("profile" -> u.profile.map(p => profileWrites.writes(p.filterTroll(u.marks.troll)).noNull))
|
||||
|
|
Loading…
Reference in New Issue