在Play2的zentasks示例中,我们有方法
def isAuthenticated(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
我想要做的是添加另一种方法,如果我想直接从数据库中获取用户,我可以使用它。
在所有方法中添加包装器会有点无聊
def method() = isAuthenticated { username => implicit request =>
UserDAO.findOneByEmail(username).map { user =>
Ok(html.user.view(user))
}.getOrElse(Forbidden)
}
我是函数式编程的新手,所有这些=>
让我头晕目眩:)
有什么建议吗?
答案 0 :(得分:5)
您可以定义另一种方法,例如IsAuthenticatedUser
,它将采用User => Request[AnyContent] => Result
类型的参数:
def IsAuthenticatedUser(f: User => Request[AnyContent] => Result) = IsAuthenticated { email => request =>
UserDAO.findOneByEmail(email).map { user =>
f(user)(request)
}.getOrElse(Forbidden)
}
然后您可以按如下方式使用它:
def method = IsAuthenticatedUser { user => request =>
Ok(html.user.view(user))
}
答案 1 :(得分:4)
这是最终的解决方案
trait Secured {
def username(request: RequestHeader) = request.session.get(Security.username)
def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Application.login)
def withAuth(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
def withUser(f: User => Request[AnyContent] => Result) = withAuth { username => implicit request =>
UserDAO.findOneByUsername(username).map { user =>
f(user)(request)
}.getOrElse(onUnauthorized(request))
}
}
用法:
object Application extends Controller with Secured {
def index = withAuth { username => implicit request =>
Ok(html.index(username))
}
def user() = withUser { user => implicit request =>
val username = user.username
Ok(html.user(user))
}
}
如您所见,如果会话不存在,用户将被重定向到特征中指定的登录页面。
如果在DAO中找不到用户名,也是如此。
答案 2 :(得分:1)
半解决方案是将获取用户数据步骤封装到某个函数中并从模板级别(而不是每个操作)调用它,因为每个模板只是一个scala函数。
感谢这种方法,如果您使用相同的视图(甚至布局)有多个操作,则不必每次都获取已记录的用户,即:
user view
中的:
@defining(Application.getLoggedUser){ user =>
@yourlayout("Welcome") {
<h2>Hello @user.name</h2>
...
}
}