在保存之前,我尝试使用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
答案 0 :(得分:1)
看起来您的代码中有错别字。当您向后端请求时,您将附加以下正文:
body: JSON.stringify({ email: username, password: password })
具有email
参数。然后,在验证器内部,您正在尝试验证username
属性。
.post(body('username').custom(value => {
并且username
在那里没有定义。
因此,您必须遵循一个命名约定,它应该起作用。