Decider admin access to deciders by steam id

This commit is contained in:
anibus
2026-10-30 20:26:43 +03:00
parent 0212f8b6d0
commit f0ec7bbedb
8 changed files with 1896 additions and 165 deletions
+83 -63
View File
@@ -25,6 +25,27 @@ class AdminController @Inject()(
implicit val ec: ExecutionContext = cc.executionContext
private val logger = org.slf4j.LoggerFactory.getLogger("controllers.AdminController")
// ---------- Ownership ----------
private def currentSteamId[A](request: Request[A]): String =
SecuredActions.steamIdOrUnknown(request)
/** Редактировать и удалять десайдера может только его владелец. */
private def owns[A](decider: repository.Decider, request: Request[A]): Boolean =
decider.ownerSteamId.contains(currentSteamId(request))
private def deciderJson(d: repository.Decider): JsObject = Json.obj(
"key" -> d.key,
"name" -> d.name,
"rules" -> d.rules,
"raceCount" -> d.raceCount,
"existAdditionalRaces" -> d.existAdditionalRaces,
"existTextFieldRaces" -> d.existTextFieldRaces,
"description" -> d.description,
"ownerSteamId" -> d.ownerSteamId,
"maps" -> d.maps.map(m => Json.obj("map" -> m.map, "description" -> m.description))
)
// ---------- Steam OpenID ----------
private val SteamLoginUrl = "https://steamcommunity.com/openid/login"
@@ -89,7 +110,7 @@ class AdminController @Inject()(
def index() = Secured { implicit request =>
implicit val messages: Messages = messagesApi.preferred(request)
Ok(views.html.admin(DeciderRepository.all))
Ok(views.html.admin(DeciderRepository.all.filter(d => owns(d, request))))
}
// ---------- API: list map images ----------
@@ -130,16 +151,7 @@ class AdminController @Inject()(
// ---------- API: list all deciders ----------
def decidersList() = Secured { implicit request =>
val list = DeciderRepository.all.map(d => Json.obj(
"key" -> d.key,
"name" -> d.name,
"rules" -> d.rules,
"raceCount" -> d.raceCount,
"existAdditionalRaces" -> d.existAdditionalRaces,
"existTextFieldRaces" -> d.existTextFieldRaces,
"description" -> d.description,
"maps" -> d.maps.map(m => Json.obj("map" -> m.map, "description" -> m.description))
))
val list = DeciderRepository.all.filter(d => owns(d, request)).map(deciderJson)
Ok(Json.toJson(list))
}
@@ -147,17 +159,10 @@ class AdminController @Inject()(
def deciderGet(key: String) = Secured { implicit request =>
DeciderRepository.get(key) match {
case Some(d) =>
Ok(Json.obj(
"key" -> d.key,
"name" -> d.name,
"rules" -> d.rules,
"raceCount" -> d.raceCount,
"existAdditionalRaces" -> d.existAdditionalRaces,
"existTextFieldRaces" -> d.existTextFieldRaces,
"description" -> d.description,
"maps" -> d.maps.map(m => Json.obj("map" -> m.map, "description" -> m.description))
))
case Some(d) if owns(d, request) =>
Ok(deciderJson(d))
case Some(_) =>
Forbidden(Json.obj("error" -> "You don't own this decider"))
case None =>
NotFound(Json.obj("error" -> s"Decider $key not found"))
}
@@ -167,49 +172,59 @@ class AdminController @Inject()(
def deciderSave() = SecuredJson { implicit request =>
val json = request.body
val steamId = currentSteamId(request)
(json \ "key").asOpt[String] match {
case None =>
BadRequest(Json.obj("error" -> "Missing key"))
case Some(key) =>
Try {
val maps = (json \ "maps").as[List[JsValue]].map { m =>
repository.DeciderMapConfig(
map = (m \ "map").as[String],
description = (m \ "description").asOpt[String]
)
}
repository.Decider(
key = key,
name = (json \ "name").as[String],
rules = (json \ "rules").as[String],
raceCount = (json \ "raceCount").as[Int],
existAdditionalRaces = (json \ "existAdditionalRaces").as[Boolean],
existTextFieldRaces = (json \ "existTextFieldRaces").as[Boolean],
description = (json \ "description").as[Boolean],
maps = maps
)
}.toEither match {
case Right(decider) =>
val existed = DeciderRepository.get(decider.key).isDefined
DeciderRepository.save(decider)
DeciderRepository.reload()
if (existed) {
logger.info(
s"Admin ${SecuredActions.steamIdOrUnknown(request)} updated decider '${decider.key}' " +
s"(name='${decider.name}', maps=${decider.maps.size})"
val existing = DeciderRepository.get(key)
if (existing.exists(d => !owns(d, request))) {
Forbidden(Json.obj("error" -> "You don't own this decider"))
} else {
val name = (json \ "name").asOpt[String].map(_.trim).getOrElse("")
val duplicateName = existing.isEmpty && name.nonEmpty &&
DeciderRepository.all.exists(_.name.trim.equalsIgnoreCase(name))
if (duplicateName) {
Conflict(Json.obj("error" -> s"A decider named '$name' already exists"))
} else {
Try {
val maps = (json \ "maps").as[List[JsValue]].map { m =>
repository.DeciderMapConfig(
map = (m \ "map").as[String],
description = (m \ "description").asOpt[String]
)
}
repository.Decider(
key = key,
name = (json \ "name").as[String],
rules = (json \ "rules").as[String],
raceCount = (json \ "raceCount").as[Int],
existAdditionalRaces = (json \ "existAdditionalRaces").as[Boolean],
existTextFieldRaces = (json \ "existTextFieldRaces").as[Boolean],
description = (json \ "description").as[Boolean],
maps = maps,
// Владельца из запроса игнорируем: он либо уже назначен, либо
// им становится автор нового десайдера.
ownerSteamId = existing.flatMap(_.ownerSteamId).orElse(Some(steamId))
)
} else {
logger.info(
s"Admin ${SecuredActions.steamIdOrUnknown(request)} created decider '${decider.key}' " +
s"(name='${decider.name}', maps=${decider.maps.size})"
)
}
Ok(Json.obj("ok" -> true))
}.toEither match {
case Right(decider) =>
DeciderRepository.save(decider)
DeciderRepository.reload()
val action = if (existing.isDefined) "updated" else "created"
logger.info(
s"Admin $steamId $action decider '${decider.key}' " +
s"(name='${decider.name}', maps=${decider.maps.size}, " +
s"owner=${decider.ownerSteamId.getOrElse("-")})"
)
Ok(Json.obj("ok" -> true))
case Left(error) =>
BadRequest(Json.obj("error" -> s"$error"))
case Left(error) =>
BadRequest(Json.obj("error" -> s"$error"))
}
}
}
}
}
@@ -217,12 +232,17 @@ class AdminController @Inject()(
// ---------- API: delete decider ----------
def deciderDelete(key: String) = SecuredApi { implicit request =>
if (DeciderRepository.delete(key)) {
DeciderRepository.reload()
logger.info(s"Admin ${SecuredActions.steamIdOrUnknown(request)} deleted decider '$key'")
Ok(Json.obj("ok" -> true))
} else {
NotFound(Json.obj("error" -> s"Decider $key not found"))
DeciderRepository.get(key) match {
case Some(d) if !owns(d, request) =>
Forbidden(Json.obj("error" -> "You don't own this decider"))
case _ =>
if (DeciderRepository.delete(key)) {
DeciderRepository.reload()
logger.info(s"Admin ${currentSteamId(request)} deleted decider '$key'")
Ok(Json.obj("ok" -> true))
} else {
NotFound(Json.obj("error" -> s"Decider $key not found"))
}
}
}