【问题标题】:Different model validation on User Name in Scala Play! 2 form mapping in create and updateScala Play 中用户名的不同模型验证! 2 创建和更新中的表单映射
【发布时间】:2013-05-05 18:50:33
【问题描述】:

我的用户映射如下(其他的也很少)

val userMapping: Mapping[User] = mapping(
    "id" -> ignored(NotAssigned: Pk[Long]),
    "title" -> nonEmptyText,
    "name" -> nonEmptyText,
    "userName" -> nonEmptyText,
    "skype" -> nonEmptyText,
    "emailId" -> ignored("": String),
    "secondaryEmailId" -> ignored("": String),
    "password" -> ignored("": String),
    "position" -> optional(text),
    "active" -> boolean,
    "subscribeEmail" -> boolean,
    "creationDate" -> optional(date("yyyy-MM-dd")),
    "lastUpdatedDate" -> optional(date("yyyy-MM-dd"))
  )(User.apply)(User.unapply)

问题是如果我对用户名应用验证

"userName" -> nonEmptyText.verifying("User name is already taken", user => !User.findUserByUserName(user.userName).isDefined)

这在创建用户时非常有效,但在编辑表单上此验证会中断。 我想为创建和更新重新使用相同的映射。

目前我已将其从表单字段移动到表单级别,但问题是直到所有表单级别错误消失,此验证永远不会达到并显示。

我的完整表格映射如下(公司名称同样的问题)。

val registerForm:Form[(User,Company)] = Form(
    mapping(
      "user" -> userMapping.verifying("User name is already taken", user => !User.findUserByUserName(user.userName).isDefined),
      "password" -> passwordMapping,
      "company" -> companyMapping.verifying("Company name is already registered", company => !Company.findCompanyByCompanyName(company.name).isDefined),
      "emailPair" -> emailPairMapping
    ){(user,passwords,company,emailPair) => (user.copy(password = passwords._1,emailId = emailPair._1,secondaryEmailId = emailPair._2,active = true),company)} //binding apply
     {userCompanyTuple => Some(userCompanyTuple._1, ("",""),userCompanyTuple._2,(userCompanyTuple._1.emailId,userCompanyTuple._1.secondaryEmailId))} //un binding un apply

  )

对于编辑案例,我将映射为(仍有待应用验证)

val registerFormEdit:Form[(User,Company)] = Form(
    mapping(
      "user" -> userMapping,
      "company" -> companyMapping,
      "emailPair" -> emailPairMapping
    ){(user,company,emailPair) => (user.copy(emailId = emailPair._1,secondaryEmailId = emailPair._2,active = true),company)} //binding apply
    {userCompanyTuple => Some(userCompanyTuple._1,userCompanyTuple._2,(userCompanyTuple._1.emailId,userCompanyTuple._1.secondaryEmailId))} //un binding un apply

  )

我看到的另一个挑战是如何在编辑验证中获取 id 作为 “id”被忽略。我是否必须在更新操作中处理编辑案例 方法?

如果我必须在更新操作方法示例 sn-p 中执行此操作 会很棒,因为我也很困惑如何在其中添加错误消息 动作方法。

如果有人提供如何实现这一点的意见,那就太好了。

我在 Play 中使用 Scala! 2.

谢谢。

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

    为了验证userNamecompany 的唯一性,我认为问题是在编辑User 时,验证器函数会在数据库中找到用户名/公司,因为它是您预先插入的记录。因此,您需要检查 userName / company 是否存在,如果确实存在,请检查行的 id 是否是用户的 id。如果它们相同,则返回 true,因为它只找到了您当前正在更新的记录。

    使用User 的ID,由于安全隐患,最好在Action 中处理此问题,而不是在表单绑定中处理。 例如,如果在表单中设置并提交了 id,那么某人很容易将 id 输入的值更改为另一个用户的 id 以更改他们的详细信息。这类似于 GitHub 去年被入侵的方式http://www.infoq.com/news/2012/03/GitHub-Compromised

    就粗略的代码 sn-p 而言,大致如下:

    def update(userId: Long) = Action { implicit request =>
      val user = User.find(userId)
      // Some type of authorization
      if(!authorize(getCurrentUser(), user) {
        BadRequest("access denied")
      } else {
        UserFormWithMappings.bindFromRequest().fold(
           formWithErrors => Ok("form errors"),
           updatedUser  => {
             updatedUser.id = userId
             User.update(updatedUser) // insert into db
             Ok("User changes saved")
           }
        )
      }
    }
    

    【讨论】:

    • 感谢您的回答,我最终采用了行动方法,授权检查类似于您所放的,感谢 git hub hack 链接,不知道,很好的提示 :) 并花时间回答一个月前的问题。
    • 这个authorize()函数是什么样子的?
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2018-10-12
    • 1970-01-01
    • 2014-03-20
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    相关资源
    最近更新 更多