【问题标题】:ValidationError: User validation failed: username_email: Path `username_email` is required. using express validator, next.js, express and mogooseValidationError:用户验证失败:username_email:需要路径“username_email”。使用 express 验证器、next.js、express 和 mogoose
【发布时间】:2019-12-05 04:46:40
【问题描述】:

我正在尝试使用 express-validator 搜索 mongodb 以查看是否存在电子邮件,然后再保存。

这是我路线的摘录:

.post(body('username').custom(value => {
        return UserModel.findOne({ 'username_email': value }).then(user => {
            if (user) {
                return Promise.reject('E-mail already in use');
            }
        });

但是我收到了这个错误:

ValidationError: User validation failed: username_email: Path `username_email` is required.
    at new ValidationError (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongoose/lib/error/validation.js:30:11)
    at model.Document.invalidate (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongoose/lib/document.js:2292:32)
    at p.doValidate.skipSchemaValidators (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongoose/lib/document.js:2141:17)
    at /Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongoose/lib/schematype.js:1037:9
    at process._tickCallback (internal/process/next_tick.js:61:11)
POST /users/registration 500 29.796 ms - 51

这是我的完整路线:

var router = require('express').Router()
var UserModel = require('../models/UserModel')
var { body } = require('express-validator');

router
    .route('/registration')
    .get(function(req, res) {
        // req.session.visits = req.session.visits ? req.session.visits + 1 : 1
        UserModel.find({}, (err, users) => {
            if (err) res.status(500).send(err)
            res.json(users)
        })
    })
    .post(body('username').custom(value => {
        return UserModel.findOne({ 'username_email': value }).then(user => {
            if (user) {
                return Promise.reject('E-mail already in use');
            }
        });
    }), async(req, res, next) => {

        try {
            let newUser = new UserModel(req.body)

            let savedUser = await newUser.save()

            if (savedUser) return res.redirect('/users/registration?success=true');
            return next(new Error('Failed to save user for unknown reasons'))

        } catch (err) {
            return next(err)
        }
    })



module.exports = router

这是我的架构/模型:

/* eslint-disable no-var */
var mongoose = require('mongoose')
var emailValidator = require('email-validator')
var bcrypt = require('bcrypt') // hashing function dedicated for passwords

const SALT_ROUNDS = 12

var UserSchema = new mongoose.Schema({
    username_email: {
        type: String,
        required: true,
        lowercase: true,
        index: { unique: true },
        validate: {
            validator: emailValidator.validate,
            message: props => `${props.value} is not a valid email address`
        }
    },
    password: {
        type: String,
        required: true,
        trim: true,
        index: { unique: true },
        minlength: 8
    }
}, {
    timestamps: true
})

UserSchema.pre('save', async function preSave(next) {
    var user = this
    var hash
    if (!user.isModified('password')) return next()
    try {
        hash = await bcrypt.hash(user.password, SALT_ROUNDS)
        user.password = hash
        return next()
    } catch (err) {
        return next(err)
    }
})

UserSchema.methods.comparePassword = async function comparePassword(candidate) {
    return bcrypt.compare(candidate, this.password)
};

module.exports = mongoose.model('User', UserSchema)

这里是我的组件:

import React, { Component } from 'react'
import { Transition, Button, Form, Grid, Header, Message, Segment } from 'semantic-ui-react'

class Register extends Component {
  constructor(props) {
    super(props)

    this.state = {
      fadeUp: 'fade up',
      isLoggedIn: true,
      duration: 500,
      isVisible: false,
      username: '',
      password: '',
      usernameError: false,
      passwordError: false,
      formError: true,
      formSuccess: false
    }

    this.handleChange = this.handleChange.bind(this)
    this.handleBlur = this.handleBlur.bind(this)
    this.handleIsLoggedInClick = this.handleIsLoggedInClick.bind(this)
    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleChange(event) {
    var { name, value } = event.target
    this.setState({
      [name]: value
    })
  }

  handleIsLoggedInClick() {
    this.state.isLoggedIn = this.state.isLoggedIn ? this.setState({ isLoggedIn: true }) : this.setState({ isLoggedIn: false })
  }

  handleBlur() {
    var { username, password, usernameError, passwordError } = this.state

    var mailFormat = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
    var error = false

    if ((!username.match(mailFormat)) && (!usernameError)) {
      this.setState({ usernameError: true })
      error = true
    } else {
      this.setState({ usernameError: false })
    }
  }

  handleSubmit(event) {
    event.preventDefault()

    var { username, password } = this.state

    var mailFormat = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
    var error = false

    if (!username.match(mailFormat)) {
      this.setState({ usernameError: true })
      error = true
    } else {
      this.setState({ usernameError: false })
    }

    if (password.length <= 8) {
      this.setState({ passwordError: true })
      error = true
    } else {
      this.setState({ passwordError: false })
    }

    console.log(`error ${error}`)
    if (error == false) {
      this.setState({ formError: false, formSuccess: true })
    }

    window.fetch('http://localhost:8016/users/registration', {
      method: 'POST',
      headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
      body: JSON.stringify({ email: username, password: password })
    }).then(function (response) {
      console.log(`response ${response}`)
      return response.json()
    }).then(function (data) {
      console.log('User created:', data)
    })
  }

  render() {
    var { username, password, usernameError, passwordError, formError, formSuccess, isLoggedIn } = this.state
    return (<div className='login-form' > {
      /*
                      Heads up! The styles below are necessary for the correct render of this example.
                      You can do same with CSS, the main idea is that all the elements up to the `Grid`
                      below must have a height of 100%.
                    */
    } <style > {`body > div, body > div > div, body > div > div > div.login-form { height: 100%;}`} </style>

      <Grid textAlign='center' style={{ height: '100%' }} verticalAlign='middle'>
        <Grid.Column style={{ maxWidth: 450 }}>
          <Header as='h2' color='teal' textAlign='center' > {isLoggedIn ? `Register for an account` : ` Log-in to your account`}</Header>

          <Form size='large' onSubmit={this.handleSubmit} error={(formError || formSuccess) || usernameError || passwordError} success={!formError && !formSuccess}>
            <Segment stacked >
              <Form.Input fluid icon='user'
                iconPosition='left'
                placeholder='E-mail address, e.g. joe@schmoe.com'
                name='username'
                value={username}
                onBlur={this.handleBlur}
                onChange={this.handleChange}
                error={usernameError}
              />

              <Transition visible={usernameError} animation='scale' duration={500}>
                <Message error content='Email is in incorrect format e.g. joe@schmoe.com' />
              </Transition>

              <Form.Input fluid icon='lock'
                iconPosition='left'
                placeholder='Password'
                name='password'
                value={password}

                onChange={this.handleChange}
                error={passwordError}
              />

              <Transition visible={passwordError} animation='scale' duration={500} >
                <Message error content='Paswword needs to be greater than eight characters.' />
              </Transition>

              <Button color='teal' fluid size='large' disabled={!this.state.username || !this.state.password} > {isLoggedIn ? `Register` : `Log-in`} </Button>

              <Transition visible={(!formError && formSuccess)} animation='scale' duration={500} >
                <Message success header='Your user registration was successful' content='You may now log-in with the username you have chosen' />
              </Transition>

            </Segment>
          </Form>

          {
            !isLoggedIn
              ? <Message >
                New to us ?
              <a onClick={this.handleIsLoggedInClick}
                  href='#' > Register! </a> </Message> : <Message >
                <a onClick={this.handleIsLoggedInClick}
                  href='#' > Back to Login </a> </Message>
          } </Grid.Column> </Grid> </div>
    )
  }
}
export default Register

【问题讨论】:

    标签: node.js mongodb mongoose next.js express-validator


    【解决方案1】:

    您的代码中似乎有错字。当您向后端发出请求时,您将附加以下正文:

    body: JSON.stringify({ email: username, password: password })
    

    其中有email 参数。然后,在您的验证器中,您尝试验证 username prop。

    .post(body('username').custom(value => {
    

    username 在那里未定义。

    因此,您必须遵循单一的命名约定,它应该可以工作。

    【讨论】:

      猜你喜欢
      • 2020-08-20
      • 2020-06-10
      • 1970-01-01
      • 2021-02-28
      • 2021-10-07
      • 1970-01-01
      • 2019-12-05
      • 2022-12-14
      • 2019-09-01
      相关资源
      最近更新 更多