59 lines
2.3 KiB
Scala
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"))
|
|
}
|
|
}
|
|
} |