You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在express-validator中校验更新邮箱时排除当前用户

修复express-validator更新邮箱时的校验问题

问题根源

你的校验逻辑没有区分「用户是否修改了邮箱」,也没有排除当前用户本身。当用户修改其他信息时,如果请求中携带了原邮箱(或校验规则强制校验email字段),查询数据库会查到当前用户自己,从而误判为邮箱已被占用。

修复方案

需要做两个关键调整:

  • 仅在邮箱字段发生变更时触发校验:如果用户提交的邮箱和自身原邮箱一致,直接跳过校验。
  • 校验时排除当前用户:查询数据库时过滤掉发起请求的用户ID,避免把自己的邮箱当成已占用。

具体代码实现

假设你的请求中可以通过req.user.id获取当前登录用户的ID,且fetchUserByEmailOrID函数支持通过ID查询用户信息:

custom: {
  options: async (email, { req }) => {
    // 获取当前用户ID
    const currentUserId = req.user.id;
    
    // 查询当前用户的原邮箱,判断是否未做修改
    const currentUser = await fetchUserByEmailOrID(currentUserId);
    if (currentUser[0].email === email) {
      // 邮箱未变更,直接通过校验
      return;
    }

    // 查询是否存在其他用户使用该邮箱(排除当前用户)
    const existingUsers = await fetchUserByEmailOrID(email);
    const hasOtherUser = existingUsers.some(user => user.id !== currentUserId);
    
    if (hasOtherUser) {
      throw new Error("该邮箱已被使用");
    }
  },
  bail: true,
}

更优雅的条件校验方式

你还可以通过express-validator的.if()方法,让校验仅在邮箱变更时执行,进一步优化性能:

// 针对请求body中的email字段构建校验链
body('email')
  // 仅当邮箱存在且与原邮箱不同时,执行后续校验
  .if(async (value, { req }) => {
    const currentUser = await fetchUserByEmailOrID(req.user.id);
    return value && value !== currentUser[0].email;
  })
  .custom(async (email, { req }) => {
    const existingUsers = await fetchUserByEmailOrID(email);
    const hasOtherUser = existingUsers.some(user => user.id !== req.user.id);
    if (hasOtherUser) {
      throw new Error("该邮箱已被使用");
    }
  })
  .bail();

补充优化建议

  • 建议优化fetchUserByEmailOrID函数,支持传入排除ID的参数,或者直接合并查询逻辑,减少数据库IO开销。比如直接执行SQL:
    SELECT * FROM users WHERE email = ? AND id != ?
    
    若返回结果为空,说明邮箱未被其他用户占用。
  • 确保请求中能正确获取当前用户的身份信息(如req.user.id),这是排除自身的核心依据。

内容的提问来源于stack exchange,提问作者Morgana Freeman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 06:50:07