Play Scala activator compile command shows value userid is not a member of play.api.data.Form[models.Changepas sword] - scala

I am new to play framework(Scala),In my project I need to update new Password for this I need to get user id which is Primary key for that user table. Based on this unique user id value i will update Password.
What I need
need to get user table's user id value and pass this value into Controller's Action
What I tried
controllers/users.scala
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import views._
import models._
val changepasswordForm = Form(
mapping(
"userid" -> ignored(None:Option[Int]),
"password" -> tuple(
"main" -> text,
"confirm" -> text
).verifying(
// Add an additional constraint: both passwords must match
"Passwords don't match", passwords => passwords._1 == passwords._2
)
)(models.Changepassword.apply)(models.Changepassword.unapply)
)
def changePassword = Action {
Ok(html.changePassword(changepasswordForm))
}
def updatePassword(userid: Int) = Action { implicit request =>
changepasswordForm.bindFromRequest.fold(
formWithErrors => BadRequest(html.changePassword(formWithErrors)),
user => {
Changepassword.update(userid, user)
Ok("password Updated")
}
)
}
models/User.scala
case class Changepassword(
userid: Option[Int] = None,
password:(String,String)
)
object Changepassword{
val simple = {
get[Option[Int]]("user.USER_ID") ~
get[String]("user.PASSWORD") map {
case userid~password => Changepassword(userid, (password,password))
}
}
def update(userid: Int,changepassword:Changepassword) = {
DB.withConnection { implicit connection =>
SQL("update user set PASSWORD = {changepassword} where USER_ID = {userid}").
on('userid -> userid,
'changepassword -> changepassword.password._1)
.executeUpdate()
}
}
}
views/changePassword.scala.html
#(userForm: Form[Changepassword])
#import helper._
#implicitFieldConstructor = #{ FieldConstructor(twitterBootstrapInput.f) }
#main("") {
<h1>Change Password</h1>
#form(routes.Users.updatePassword(userForm.userid.get)) {
<fieldset>
#inputPassword(userForm("password.main"), '_label -> "New Password", '_help -> "",'placeholder -> "New Password")
#inputPassword(userForm("password.confirm"), '_label -> "Confirm Password", '_help -> "",'placeholder -> "Repeat Password")
</fieldset>
<div class="actions">
<input type="submit" value="Change password" class="btn primary"> or
Cancel
</div>
}
}
If I run activator compile command it shows below exception
D:\Jamal\test>activator compile
[info] Loading project definition from D:\Jamal\test\p
roject
[info] Set current project to scala-crud (in build file:/D:\Jamal\test/)
[info] Compiling 1 Scala source to D:\Jamal\test\targe
t\scala-2.11\classes...
[error] D:\Jamal\test\app\views\changePassword.sc
ala.html:11: value userid is not a member of play.api.data.Form[models.Changepas
sword]
[error] #form(routes.Users.updatePassword(userForm.userid.get)) {
[error] ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 13 s, completed Jun 11, 2015 3:52:19 PM
D:\Jamal\test>

You can't use the value of the form as a parameter for the route:
#form(routes.Users.updatePassword(userForm.userid.get))
The userid depends on the form and could therefore change. In any case, you would access the userid of the form using userForm("userid") and not userForm.userid (although it might not be what you want/need).
A better approach for your problem would be to pass a second parameter like this:
controllers/users.scala
def changePassword = Action {
val userId = ... get the current id ...
Ok(html.changePassword(changepasswordForm,userId))
}
views/changePassword.scala.html
#(userForm: Form[Changepassword], userId:Int)
...
...
#form(routes.Users.updatePassword(userId)) {
...
...
}
...
This way, you ensure the userId is known when the page is displayed and that a "evil" user can't change the passwords of other users by manipulating the userId.

Related

Intelllij doesn't support Play Framework very well?

I am using Intellij Idea + Scala Plugin + Play framework 2.6.0 to do web development.
I have a FruitController, its definition is:
def saveFruit = Action(BodyParsers.parse.json) { request =>
import FruitImplicits._
val fruitResult = request.body.validate[Fruit]
fruitResult.fold(
errors => {
BadRequest(Json.obj("status" -> "KO", "message" -> JsError.toJson(errors)))
},
fruit => {
println(s"Fruit is saved, the result is :$fruit")
Ok(Json.obj("status" -> "OK", "message" -> ("Fruit '" + fruit.name + "' saved.")))
}
)
}
The Intellij idea complains Missing parameter type:request for the request in the first line: Action(BodyParsers.parse.json) { request =>
But I could run the code successfully, so Intellij Idea has been mistakenly reported the error, I would ask how to get Intellij Idea to work well for this code
When I explicitly specify the type of the request: Request[JsValue], the problem is gone:
def saveFruit = Action(parse.json) { request: Request[JsValue] =>

Firefox link redirection issue using selenium

I have an automation service I build and before you run the automation you give it a link so when you start the automation you get first redirect to this link.
On my machine you get redirected perfectly, but on a friend machine the Firefox browser is opened and thats it.
does anyone know what might be the issue?
here is the class that responsible for this:
case class csvUploadData(clientUrl: String)
val csvUploadForm = Form(
mapping(
"clientUrl" -> nonEmptyText)(csvUploadData.apply)(csvUploadData.unapply))
def uploadCSV = Action.async(parse.multipartFormData) { implicit request =>
csvUploadForm.bindFromRequest.fold(
formWithErrors => {
Future {
Redirect(routes.Application.index).flashing(
"error" -> formWithErrors.error("clientUrl").get.message)
}
},
userData => {
request.body.file("csvFile").fold(Future {
Redirect(routes.Application.index).flashing(
"error" -> "Missing CSV file").withSession(request.session)
}) { formFile =>
import java.io.File
val filename = formFile.filename
Future {
val file = formFile.ref.file
val purchaseInfos = purchaseDS(file)
val t = Try {
val driver: WebDriver = new FirefoxDriver
val actions: ActionsHMRC = new ActionsHMRC(driver, userData.clientUrl)
val results = actions.insertData(purchaseInfos)
results.filter(_._2.isFailure)
}
t match {
case Success(failures) =>
val failedMsg = if (failures.nonEmpty)
failures.map{case (pi, err) => s"${pi.invoiceNumber} -> ${err}}"}.mkString("The following rows failed: [\n","\n","\n\n\n]")
else ""
Redirect(routes.Application.index).flashing(
"success" -> s"The file '$filename' automation successfuly.\n$failedMsg")
case Failure(e) =>
println(e)
Redirect(routes.Application.index).flashing (
"error" -> s"The file '$filename' automation failed.")
}
}
}
})
}
}
I have ver 42.0 and he have 43.0.4
I think that's happening because the new issue occurs with latest update of Mozilla firefox.
It's happening with me too.
To overcome from this issue you need to setPreference as xpinstall.signatures.required", false to firefox Profile and then pass it to driver object
firefoxProfile.setPreference("xpinstall.signatures.required", false);
Below code is working fine for old selenium jars.
static WebDriver driver=null;
public static void main(String[] args) {
final FirefoxProfile firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("xpinstall.signatures.required", false);
driver = new FirefoxDriver(firefoxProfile);
driver.get("https://www.google.de/");
Thanks it really helps but one change FirefoxDriver(firefoxProfile) is not valid. instead FirefoxOptions as below:
final FirefoxProfile firefoxProfile = new FirefoxProfile();
firefoxProfile.setPreference("xpinstall.signatures.required", false);
FirefoxOptions firefoxOptions = new FirefoxOptions();
firefoxOptions.setProfile(firefoxProfile);
driver = new FirefoxDriver(firefoxOptions);

Customizing the error messages for the standard validators

I have a simple form:
val addForm = Form(
tuple("email" -> email, "password" -> nonEmptyText)
verifying("Invalid email or password", result => User.authenticate(result._1, result._2).isRight)
)
The general error message above is ok. But how do I customize the specific error messages for the email and password. For now in case of empty password I've got this kind of error:
password error.required
How do I customize this error message?
UPDATE:
Even this doesn't work because the validation message is still the same as it was:
val addForm = Form(
tuple("email" -> email, "password" -> nonEmptyTextWithMessage("My message"))
verifying("Invalid email or password", result => User.authenticate(result._1, result._2).isRight)
)
def nonEmptyTextWithMessage(errorMessage: String): Mapping[String] = nonEmptyText.verifying(errorMessage, { _ => true })
The nonEmptyText constraint defaults to using error.required as message key. You could change that in your conf/messages file, but I suppose this is not what you want.
If you want to re-use a pre-defined Constraint (note that nonEmptyText is not a Constraint but a Mapping), you could do the following:
val addForm = Form(
tuple(
"email" -> email,
"password" -> text.verifying(Constraints.nonEmpty.copy(name = Some("My message"))())
).verifying("Invalid email or password", result => User.authenticate(result._1, result._2).isRight)
)
It does not look very nice, but I'm not aware of any helper function that would achieve the same.
My colleague suggest, If you are using scala template, you could customize error message as follows
just add
'_error ->addForm("password").error.map(_.withMessage("Please provide password"))
like
#helper.inputPassword(addForm("password"), 'class->"col-md-12", '_label ->"Password",'style->"margin-bottom:20px", '_showConstraints->false, 'placeholder->"Enter Password", '_error ->addForm("password").error.map(_.withMessage("Please provide password")))

Play 2.1 Scala SQLException Connection Timed out waiting for a free available connection

I have been working on this issue for quite a while now and I cannot find a solution...
A web app built with play framework 2.2.1 using h2 db (for dev) and a simple Model package.
I am trying to implement a REST JSON endpoint and the code works... but only once per server instance.
def createOtherModel() = Action(parse.json) {
request =>
request.body \ "name" match {
case _: JsUndefined => BadRequest(Json.obj("error" -> true,
"message" -> "Could not match name =(")).as("application/json")
case name: JsValue =>
request.body \ "value" match {
case _: JsUndefined => BadRequest(Json.obj("error" -> true,
"message" -> "Could not match value =(")).as("application/json")
case value: JsValue =>
// this breaks the secod time
val session = ThinkingSession.dummy
val json = Json.obj(
"content" -> value,
"thinkingSession" -> session.id,
)
)
Ok(Json.obj("content" -> json)).as("application/json")
}
} else {
BadRequest(Json.obj("error" -> true,
"message" -> "Name was not content =(")).as("application/json")
}
}
}
so basically I read the JSON, echo the "value" value, create a model obj and send it's id.
the ThinkingSession.dummy function does this:
def all(): List[ThinkingSession] = {
// Tried explicitly closing connection, no difference
//val conn = DB.getConnection()
//try {
// DB.withConnection { implicit conn =>
// SQL("select * from thinking_session").as(ThinkingSession.DBParser *)
// }
//} finally {
// conn.close()
//}
DB.withConnection { implicit conn =>
SQL("select * from thinking_session").as(ThinkingSession.DBParser *)
}
}
def dummy: ThinkingSession = {
(all() head)
}
So this should do a SELECT * FROM thinking_session, create a model obj list from the result and return the first out of the list.
This works fine the first time after server start but the second time I get a
play.api.Application$$anon$1: Execution exception[[SQLException: Timed out waiting for a free available connection.]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.1]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.1]
Caused by: java.sql.SQLException: Timed out waiting for a free available connection.
at com.jolbox.bonecp.DefaultConnectionStrategy.getConnectionInternal(DefaultConnectionStrategy.java:88) ~[bonecp.jar:na]
at com.jolbox.bonecp.AbstractConnectionStrategy.getConnection(AbstractConnectionStrategy.java:90) ~[bonecp.jar:na]
at com.jolbox.bonecp.BoneCP.getConnection(BoneCP.java:553) ~[bonecp.jar:na]
at com.jolbox.bonecp.BoneCPDataSource.getConnection(BoneCPDataSource.java:131) ~[bonecp.jar:na]
at play.api.db.DBApi$class.getConnection(DB.scala:67) ~[play-jdbc_2.10.jar:2.2.1]
at play.api.db.BoneCPApi.getConnection(DB.scala:276) ~[play-jdbc_2.10.jar:2.2.1]
My application.conf (db section)
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:file:database/[my_db]"
db.default.logStatements=true
db.default.idleConnectionTestPeriod=5 minutes
db.default.connectionTestStatement="SELECT 1"
db.default.maxConnectionAge=0
db.default.connectionTimeout=10000
Initially the only thing set in my config was the connection and the error occurred. I added all the other stuff while reading up on the issue on the web.
What is interesting is that when I use the h2 in memory db it works once after server start and after that it fails. when I use the h2 file system db it only works once, regardless of the server instances.
Can anyone give me some insight on this issue? Have found some stuff on bonecp problem and tried upgrading to 0.8.0-rc1 but nothing changed... I am at a loss =(
Try to set a maxConnectionAge and idle timeout
turns out the error was quite somewhere else... it was a good ol' stack overflow... have not seen one in a long time. I tried down-voting my question but it's not possible^^

Why do I get `Configuration error[Missing application.secret]` in Play 2?

I have written a scala method to do authentication and save a specific token in session like this:
def logIn = Action(parse.json) { request =>
request.body.validate.map { entity =>
Authentication.authenticate(entity.username, entity.password) match {
case "" => NotFound(RestResponses.toJson(RestResponse(NOT_FOUND, "Invalid username or password.")))
case token: String => Ok(RestResponses.toJson(RestResponse(OK, "Username %s has been succesfully logged in".format(entity.username)))).withSession(TokenKey -> token)
}
}
.recover { Result =>
BadRequest(RestResponses.toJson(RestResponse(BAD_REQUEST, "Unable to parse content type for user authentication.")))
}
}
To test logIn method I have written a test method:
"A POST request to login a user" should "return OK " in {
running(FakeApplication()) {
val node = Json.toJson(AuthenticationUser("cristi", "cristi-password"))(controllers.AuthenticationService.authUserWrites);
val result = AuthenticationService.logIn(new FakeRequest(Helpers.POST, "/", FakeHeaders(), node))
status(result) should equal(OK)
contentType(result) should be(Some("application/json"))
contentAsString(result) should include("succesfully logged in")
}
}
I simply don't understand why I receive this error:
[info] - should return OK *** FAILED ***
[info] play.api.PlayException: Configuration error[Missing application.secret]
[info] at play.api.libs.Crypto$$anonfun$sign$2.apply(Crypto.scala:30)
[info] at play.api.libs.Crypto$$anonfun$sign$2.apply(Crypto.scala:30)
I am sure it's something about session... but what?
Add a application.secret=changeme to your conf/application.conf file.