ps0604
ps0604

Reputation: 1081

Making work play2-auth standard sample

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

Answers (1)

Mikesname
Mikesname

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

Related Questions