Access current request in Form Constraints
-
12-12-2019 - |
Question
I'd like to validate a Play 2 Scala password update form using data about the current user. Imagine a form that collects current password, new password, and new password again. On validation of this form should be whether the value for "current password" actually matches the current users actual password. In the validation, I'll need access to the current user - which requires access to the current request. Obviously request is not in scope when I define the form:
val updatePasswordForm = Form(mapping(
"currPassword" -> password,
"newPassword" -> password,
"newPasswordAgain" -> password)(PasswordUpdate.apply)(PasswordUpdate.unapply)
verifying ("passwordsMustMatch", update => update.newPassword == update.newPasswordAgain)
verifying ("incorrectCurrentPassword", pws => authenticate(GAH NEED CURRENT USERS EMAIL, update.currPassword)))
I completely appreciate that having Request access in form validation would introduce a unwanted dependency for Forms. I'm just curious if people have a clever way around this. My only approach so far is something like this:
def updatePassword = Action { implicit req =>
validateCurrentPasswordMatches(updatePasswordForm).bindFromRequest.fold(
....
I'd love a way to package this Request-dependent validation right inside the shared Form declaration.
Solution
You can obtain your update password form using a function with an implicitly defined Request
parameter like so:
def updatePasswordForm(implicit request: Request[_]) = Form(
// define form here
).verifying(...)
The request parameter is implicitly passed on from the bindFromRequest
function.
The authenticate
function now has access to the (again implicitly defined) request parameter. You need to re-define it as
def authenticate( /* old parameters */ )(implicit request: Request[_]): Boolean = {
// implementation with access to the Request
}