email unicity validation and mod actions
This commit is contained in:
parent
41c7f6a9bc
commit
7144283ae3
|
@ -67,14 +67,14 @@ object Account extends LilaController {
|
|||
}
|
||||
}
|
||||
|
||||
private def emailForm(id: String) = UserRepo email id map { email =>
|
||||
Env.security.forms.changeEmail.fill(
|
||||
private def emailForm(user: UserModel) = UserRepo email user.id map { email =>
|
||||
Env.security.forms.changeEmail(user).fill(
|
||||
lila.security.DataForm.ChangeEmail(~email, ""))
|
||||
}
|
||||
|
||||
def email = Auth { implicit ctx =>
|
||||
me =>
|
||||
emailForm(me.id) map { form =>
|
||||
emailForm(me) map { form =>
|
||||
Ok(html.account.email(me, form))
|
||||
}
|
||||
}
|
||||
|
@ -82,14 +82,14 @@ object Account extends LilaController {
|
|||
def emailApply = AuthBody { implicit ctx =>
|
||||
me =>
|
||||
implicit val req = ctx.body
|
||||
FormFuResult(Env.security.forms.changeEmail) { err =>
|
||||
FormFuResult(Env.security.forms.changeEmail(me)) { err =>
|
||||
fuccess(html.account.email(me, err))
|
||||
} { data =>
|
||||
val email = Env.security.emailAddress.validate(data.email) err s"Invalid email ${data.email}"
|
||||
for {
|
||||
ok ← UserRepo.checkPassword(me.id, data.passwd)
|
||||
_ ← ok ?? UserRepo.email(me.id, email)
|
||||
form <- emailForm(me.id)
|
||||
form <- emailForm(me)
|
||||
} yield {
|
||||
val content = html.account.email(me, form, ok.some)
|
||||
ok.fold(Ok(content), BadRequest(content))
|
||||
|
|
|
@ -70,8 +70,8 @@ object Mod extends LilaController {
|
|||
implicit def req = ctx.body
|
||||
OptionFuResult(UserRepo named username) { user =>
|
||||
if (isGranted(_.SetEmail) && !isGranted(_.SetEmail, user))
|
||||
Env.security.forms.modEmail.bindFromRequest.fold(
|
||||
err => fuccess(redirect(user.username, mod = true)),
|
||||
Env.security.forms.modEmail(user).bindFromRequest.fold(
|
||||
err => BadRequest(err.toString).fuccess,
|
||||
email => modApi.setEmail(me.id, user.id, email) inject redirect(user.username, mod = true)
|
||||
)
|
||||
else fuccess(authorizationFailed(ctx.req))
|
||||
|
|
|
@ -7,6 +7,7 @@ import play.api.data.validation.Constraints
|
|||
import lila.common.LameName
|
||||
import lila.db.api.$count
|
||||
import lila.user.tube.userTube
|
||||
import lila.user.User
|
||||
|
||||
final class DataForm(
|
||||
val captcher: akka.actor.ActorSelection,
|
||||
|
@ -27,8 +28,8 @@ final class DataForm(
|
|||
|
||||
private val anyEmail = nonEmptyText.verifying(Constraints.emailAddress)
|
||||
private val acceptableEmail = anyEmail.verifying(emailAddress.acceptableConstraint)
|
||||
private val uniqueEmail = email.verifying(emailAddress.uniqueConstraint)
|
||||
private val acceptableUniqueEmail = acceptableEmail.verifying(emailAddress.uniqueConstraint)
|
||||
private def acceptableUniqueEmail(forUser: Option[User]) =
|
||||
acceptableEmail.verifying(emailAddress uniqueConstraint forUser)
|
||||
|
||||
object signup {
|
||||
|
||||
|
@ -47,7 +48,7 @@ final class DataForm(
|
|||
val website = Form(mapping(
|
||||
"username" -> username,
|
||||
"password" -> text(minLength = 4),
|
||||
"email" -> acceptableUniqueEmail,
|
||||
"email" -> acceptableUniqueEmail(none),
|
||||
"g-recaptcha-response" -> nonEmptyText,
|
||||
"gameId" -> nonEmptyText,
|
||||
"move" -> nonEmptyText
|
||||
|
@ -57,7 +58,7 @@ final class DataForm(
|
|||
val mobile = Form(mapping(
|
||||
"username" -> username,
|
||||
"password" -> text(minLength = 4),
|
||||
"email" -> optional(acceptableUniqueEmail)
|
||||
"email" -> optional(acceptableUniqueEmail(none))
|
||||
)(MobileSignupData.apply)(_ => None))
|
||||
|
||||
def websiteWithCaptcha = withCaptcha(website)
|
||||
|
@ -89,14 +90,12 @@ final class DataForm(
|
|||
_.samePasswords
|
||||
))
|
||||
|
||||
val changeEmail = Form(mapping(
|
||||
"email" -> acceptableUniqueEmail,
|
||||
def changeEmail(user: User) = Form(mapping(
|
||||
"email" -> acceptableUniqueEmail(user.some),
|
||||
"passwd" -> nonEmptyText
|
||||
)(ChangeEmail.apply)(ChangeEmail.unapply)
|
||||
.verifying("This email already exists", e => !emailAddress.isTaken(e.email))
|
||||
)
|
||||
)(ChangeEmail.apply)(ChangeEmail.unapply))
|
||||
|
||||
val modEmail = Form(single("email" -> acceptableUniqueEmail))
|
||||
def modEmail(user: User) = Form(single("email" -> acceptableUniqueEmail(user.some)))
|
||||
|
||||
val closeAccount = Form(single("passwd" -> nonEmptyText))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package lila.security
|
||||
|
||||
import lila.user.User
|
||||
|
||||
import play.api.data.validation._
|
||||
|
||||
/**
|
||||
|
@ -34,8 +36,12 @@ final class EmailAddress(disposable: DisposableEmailDomain) {
|
|||
|
||||
def isValid(email: String) = validate(email).isDefined
|
||||
|
||||
def isTaken(email: String): Boolean = validate(email) ?? { e =>
|
||||
lila.user.UserRepo.idByEmail(e).await.isDefined
|
||||
private def isTakenBy(email: String, forUser: Option[User]): Option[String] = validate(email) ?? { e =>
|
||||
(lila.user.UserRepo.idByEmail(e).await, forUser) match {
|
||||
case (None, _) => none
|
||||
case (Some(userId), Some(user)) => userId != user.id option userId
|
||||
case (someUserId, _) => someUserId
|
||||
}
|
||||
}
|
||||
|
||||
val acceptableConstraint = Constraint[String]("constraint.email_acceptable") { e =>
|
||||
|
@ -43,9 +49,11 @@ final class EmailAddress(disposable: DisposableEmailDomain) {
|
|||
else Invalid(ValidationError("error.email_acceptable"))
|
||||
}
|
||||
|
||||
val uniqueConstraint = Constraint[String]("constraint.email_unique") { e =>
|
||||
if (isTaken(e)) Invalid(ValidationError("error.email_unique"))
|
||||
else Valid
|
||||
def uniqueConstraint(forUser: Option[User]) = Constraint[String]("constraint.email_unique") { e =>
|
||||
isTakenBy(e, forUser) match {
|
||||
case Some(userId) => Invalid(ValidationError(s"Email already in use by $userId"))
|
||||
case None => Valid
|
||||
}
|
||||
}
|
||||
|
||||
private def isGmail(domain: String) = domain == "gmail.com"
|
||||
|
|
Loading…
Reference in a new issue