Skip to content

Commit

Permalink
prevent watching ongoing game when blocked
Browse files Browse the repository at this point in the history
  • Loading branch information
ornicar committed Aug 9, 2024
1 parent a26a62a commit d566ee9
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 20 deletions.
37 changes: 21 additions & 16 deletions src/main/scala/Controller.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,29 @@ final class Controller(
def roundWatch(id: Game.Id, header: RequestHeader) =
WebSocket(header): req =>
(
mongo.gameExists(id),
mongo.gameUserIds(id),
mongo.troll.is(req.user),
roundFrom(id.into(Game.AnyId), req)
).mapN:
case (true, isTroll, from) =>
val userTv = UserTv.from(header.queryParameter("userTv"))
endpoint(
name = "round/watch",
behavior = emit =>
RoundClientActor
.start(RoomActor.State(id.into(RoomId), isTroll), None, userTv, from):
Deps(emit, req, services)
,
header,
credits = 50,
interval = 20.seconds
)
case _ => notFound
).flatMapN:
case (Some(playerUserIds), isTroll, from) =>
req.user
.fold(Future.successful(false))(mongo.isBlockedByAny(id, playerUserIds))
.map:
if _ then notFound
else
val userTv = UserTv.from(header.queryParameter("userTv"))
endpoint(
name = "round/watch",
behavior = emit =>
RoundClientActor
.start(RoomActor.State(id.into(RoomId), isTroll), None, userTv, from):
Deps(emit, req, services)
,
header,
credits = 50,
interval = 20.seconds
)
case _ => Future.successful(notFound)

def roundPlay(id: Game.FullId, header: RequestHeader) =
WebSocket(header): req =>
Expand Down
20 changes: 16 additions & 4 deletions src/main/scala/Mongo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,9 @@ final class Mongo(config: Config)(using Executor) extends MongoHandlers:

def studyExists(id: Study.Id): Future[Boolean] = studyColl.flatMap(idExists(id))

def gameExists(id: Game.Id): Future[Boolean] =
gameCache.getIfPresent(id) match
case None => gameColl.flatMap(idExists(id.value))
case Some(entry) => entry.map(_.isDefined)(parasitic)
// None = no such game
def gameUserIds(id: Game.Id): Future[Option[List[User.Id]]] =
gameCache.get(id).map(_.map(_.players.mapList(_.userId).flatten))

def player(fullId: Game.FullId, user: Option[User.Id]): Future[Option[Game.RoundPlayer]] =
gameCache
Expand Down Expand Up @@ -149,6 +148,10 @@ final class Mongo(config: Config)(using Executor) extends MongoHandlers:

private val visibilityNotPrivate = BSONDocument("visibility" -> BSONDocument("$ne" -> "private"))

def isGameOngoing(id: Game.Id): Future[Boolean] =
gameColl.flatMap:
exists(_, BSONDocument("_id" -> id, "s" -> BSONDocument("$lt" -> chess.Status.Aborted.id)))

def studyExistsFor(id: Study.Id, user: Option[User.Id]): Future[Boolean] =
studyColl.flatMap:
exists(
Expand Down Expand Up @@ -251,6 +254,15 @@ final class Mongo(config: Config)(using Executor) extends MongoHandlers:
collation = None
)

def isBlockedByAny(id: Game.Id, by: Iterable[User.Id])(me: User.Id): Future[Boolean] =
if by.isEmpty then Future.successful(false)
else
relationColl
.flatMap:
exists(_, BSONDocument("_id" -> BSONDocument("$in" -> by.map(b => s"$b/$me")), "r" -> false))
.flatMap:
if _ then isGameOngoing(id) else Future.successful(false)

def userData(userId: User.Id): Future[Option[FriendList.UserData]] =
userColl.flatMap:
_.find(
Expand Down

0 comments on commit d566ee9

Please sign in to comment.