Files
2026-10-24 22:02:29 +03:00

59 lines
2.3 KiB
Scala

package controllers
import play.api.libs.json.{JsValue, Json}
import play.api.libs.typedmap.TypedKey
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}
object SecuredActions {
private val SteamIdAttr: TypedKey[String] = TypedKey("steamId")
/** Steam ID текущего авторизованного пользователя (если он есть в запросе). */
def steamId[A](request: Request[A]): Option[String] = request.attrs.get(SteamIdAttr)
/** Steam ID текущего пользователя или "unknown", если его нет в запросе. */
def steamIdOrUnknown[A](request: Request[A]): String = steamId(request).getOrElse("unknown")
}
/**
* Simple session-based authentication via Steam ID.
* Used to protect admin panel routes.
*/
trait SecuredActions {
self: AbstractController =>
private val SteamIdAttr: TypedKey[String] = SecuredActions.SteamIdAttr
/** Wrapper that requires the user to be logged in with Steam. */
def Secured: ActionBuilder[Request, AnyContent] =
securedWith(controllerComponents.parsers.defaultBodyParser, apiStyle = false)
/** Same as [[Secured]], but parses the request body as JSON. */
def SecuredJson: ActionBuilder[Request, JsValue] =
securedWith(controllerComponents.parsers.json, apiStyle = true)
/** Same as [[Secured]], but answers AJAX calls with 401 JSON instead of a redirect. */
def SecuredApi: ActionBuilder[Request, AnyContent] =
securedWith(controllerComponents.parsers.defaultBodyParser, apiStyle = true)
private def securedWith[A](bodyParser: BodyParser[A], apiStyle: Boolean): ActionBuilder[Request, A] =
new ActionBuilder[Request, A] {
override def parser: BodyParser[A] = bodyParser
override def executionContext: ExecutionContext = controllerComponents.executionContext
override def invokeBlock[B](request: Request[B], block: Request[B] => Future[Result]): Future[Result] =
request.session.get("steamId") match {
case Some(steamId) =>
block(request.addAttr(SteamIdAttr, steamId))
case None if apiStyle =>
Future.successful(Unauthorized(Json.obj("error" -> "Please log in with Steam")))
case None =>
Future.successful(Redirect("/decider/admin/login").flashing("error" -> "Please log in with Steam"))
}
}
}