All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jaroop.play.sentry.OptionalAuthenticatedActionBuilder.scala Maven / Gradle / Ivy

package com.jaroop.play.sentry

import javax.inject.Inject
import play.api.mvc._
import scala.concurrent.{ ExecutionContext, Future }

/**
 *  An optionally authenticated request. It contains both the underlying Play request, and an optional logged-in user.
 *  (If the user is authenticated.)
 *
 *  @param request The underlying request.
 *  @param user The logged-in user that made the request, if they are authenticated. Otherwise, `None`.
 *
 *  @tparam A The type of the request body.
 *  @tparam User The type of the user.
 */
class OptionalAuthRequest[A, User](request: Request[A], val user: Option[User]) extends WrappedRequest[A](request)

/**
 *  An `ActionBuilder` that can be used for actions where authentication is optional. The endpoints that use this action
 *  will be publically accessible, but you may alter the behavior depending on whether or not a user is present.
 *
 *  To use, you can simply just inject this component into your controller with a specified [[Env]] type.
 *
 *  {{{
 *      @Singleton
 *      class HomeController @Inject() (
 *          action: OptionalAuthenticatedActionBuilder[EnvImpl]
 *      ) extends InjectedController {
 *          def index = action { request =>
 *              request.user match {
 *                  case Some(user) => Ok(s"You are logged-in as ${user}!")
 *                  case None => Ok("You are not logged-in, but you can view this page, anyway.")
 *              }
 *          }
 *      }
 *  }}}
 *
 *  @param parser Uses the default `BodyParser`, but can be overridden with the `ActionBuilder` interface.
 *  @param auth Requires the [[AsyncAuth]] component for resolving a user.
 *
 *  @tparam E The environment type of your application.
 */
class OptionalAuthenticatedActionBuilder[E <: Env] @Inject() (
    val parser: BodyParsers.Default,
    auth: AsyncAuth[E]
)(implicit val executionContext: ExecutionContext) extends ActionBuilder[OptionalAuthRequest[?, E#User], AnyContent] {

    /**
     *  Attempts to verify if the user is authenticated before invoking the `block` function.
     *
     *  @param request The incoming request from the user.
     *  @param block A function to invoke. e.g. The body of a controller method.
     *  @return Returns the result of the `block` function, with updated cookies if the user is authenticated.
     */
    override def invokeBlock[A](request: Request[A], block: OptionalAuthRequest[A, E#User] => Future[Result]) = {
        implicit val r = request
        val maybeUserFuture = auth.restoreUser.recover { case _ => None -> identity[Result] _ }
        maybeUserFuture.flatMap { case (maybeUser, cookieUpdater) =>
            block(new OptionalAuthRequest(request, maybeUser)).map(cookieUpdater)
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy