问题描述
我正在基于此 Scala Play Authentication 示例实施身份验证。
因此,我使用以下 ActionBuilder
来构建 UserAction
。
UserAction.scala
class UserRequest[A](val user: Option[Admin],request: Request[A]) extends WrappedRequest[A](request)
class UserAction @Inject()(adminService: AdminService,parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
extends ActionBuilder[UserRequest,AnyContent]
with ActionTransformer[Request,UserRequest] {
def transform[A](request: Request[A]) = Future.successful {
val sessionTokenopt = request.session.get("sessionToken")
val user = sessionTokenopt
.flatMap(token => Sessions.getSession(token))
.filter(_.expiration.isAfter(LocalDateTime.Now(ZoneOffset.UTC)))
.map(_.email)
// Signature: getAdminByEmail(email: String): Future[Option[Admin]]
.flatMap(adminService.getAdminByEmail) // <- Extract Future here
// The user has to be Option[Admin] but is Future[Option[Admin]]
// because of adminService.getAdminByEmail
new UserRequest(user,request)
}
}
由于 example implementation in line 25 不返回 Future 因为没有包含数据库设置,我收到以下错误:
type mismatch;
found : scala.concurrent.Future[Option[models.Tables.Admin]]
required: Option[?]
因为我是 Scala 的新手,所以我现在不知道如何提取 Future。如何处理 Future 结果以确保我们返回 Option[Admin]
?
解决方法
我自己修好了。我只是将电子邮件和提取分为两个不同的部分,并将 Future
移到 email match
内。
class UserAction @Inject()(adminService: AdminService,val parser: BodyParsers.Default)(implicit val executionContext: ExecutionContext)
extends ActionBuilder[UserRequest,AnyContent]
with ActionTransformer[Request,UserRequest] {
def transform[A](request: Request[A]) : Future[UserRequest[A]] = {
val sessionTokenOpt = request.session.get("sessionToken")
val email = sessionTokenOpt
.flatMap(token => Sessions.getSession(token))
.filter(_.expiration.isAfter(LocalDateTime.now(ZoneOffset.UTC)))
.map(_.email)
email match {
case Some(value) =>
adminService.getAdminByEmail(value).map(a => new UserRequest(a,request))
case None =>
Future { new UserRequest(None,request) }
}
}
}