Reputation: 1081
I'm trying to make work the play2-auth
standard sample, excluding authorizations - just authentication/login.
I'm getting in the form the following error in the @helper.form
line:
type mismatch; found : play.api.mvc.Action[play.api.mvc.AnyContent] required: play.api.mvc.Call
@(form: Form[Option[session2.Account]])(implicit flash: Flash)
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
@helper.form(session2.ManageSession.authenticate) { // <-- here's the error
<h1>Sign in</h1>
@form.globalError.map { error =>
<p class="error">
@error.message
</p>
}
@flash.get("success").map { message =>
<p class="success">
@message
</p>
}
<p>
<input type="email" name="email" placeholder="Email" id="email"
value="@form("email").value">
</p>
<p>
<input type="password" name="password" id="password" placeholder="Password">
</p>
<p>
<button type="submit" id="loginbutton">Login</button>
</p>
}
</body>
</html>
And this is ManageSession.scala:
package session2
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import jp.t2v.lab.play2.auth._
object ManageSession extends Controller with LoginLogout with AuthConfigImpl {
val loginForm = Form {
mapping("email" -> text, "password" -> text)(Account.authenticate)
(_.map(u => (u.email, "")))
.verifying("Invalid email or password", result => result.isDefined)
}
def login = Action { implicit request =>
Ok(views.html.login(loginForm))
}
def logout = Action.async { implicit request =>
// do something...
gotoLogoutSucceeded
}
def authenticate = Action.async { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => Future.successful(BadRequest(views.html.main())),
user => gotoLoginSucceeded(user.get.email)
)
}
}
Upvotes: 1
Views: 72
Reputation: 8901
You're currently passing to the form template helper the Action
instance for authenticate
, rather than the Call
instance that should be generated by its reverse route. A Call
describes the URL and method of an action, as defined in your routes file, so you don't have to hardcode it everywhere.
First of all, put your ManageSession
controller in the controllers
package (as per Play's defaults - you can move it later but I think the reverse route generation relies on them being there, or in a subpackage.):
package controllers
...
object ManageSession extends Controller with LoginLogout with AuthConfigImpl {
...
}
Your conf/routes
file should look something like this:
POST /authenticate controllers.ManageSession.authenticate
Then the reverse route Call
object will be generated in controllers.routes.ManageSession.authenticate
:
@helper.form(controllers.routes.ManageSession.authenticate) {
...
}
Note the routes
subpackage in there!
The result should be HTML generated like so:
<form method="POST" action="/authenticate">
...
</form>
Note: in Play 2.5 and above, static (object) controllers are discouraged and do not work with the default (injected) routes generator. In this case the simplest option is just to make ManageSession
a class instead of an object:
class ManageSession() extends Controller with LoginLogout with AuthConfigImpl {
...
}
Alternately, you could specify you want the StaticRoutesGenerator
in your build.sbt
:
routesGenerator := StaticRoutesGenerator
Upvotes: 1