【发布时间】: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