我使用来自here的Node JS构建rest api。我的问题是,当我在我的架构中使用密码正则表达式时,它返回 ValidationError:密码:路径password
无效($ 2a $ 09 $ oh.2MUqOVSCDdC / ZpjTyXOVCykNg73B8wVDdxsg3ElieOZ5hLmD4K) 即可。但是当我删除密码正则表达式时,它工作正常。
注意:当我尝试更新数据时,它刚刚发生,当我创建或登录用户时它工作正常
这是我的代码:
model.js
import crypto from 'crypto'
import bcrypt from 'bcrypt'
import randtoken from 'rand-token'
import mongoose, { Schema } from 'mongoose'
import mongooseKeywords from 'mongoose-keywords'
import { env } from '../../config'
const roles = ['owner', 'freelancer', 'admin']
const userSchema = new Schema({
email : {type: String, match: /^\S+@\S+\.\S+$/, required: true, unique: true, trim: true, lowercase: true},
password : {type: String, required: true, match: /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z]{6,}$/},
username : {type: String, unique: true, lowercase: true},
role : {type: String, enum: roles, required: true},
picture : {type: String, trim: true},
services : {facebook: String, google: String},
status : {type: Boolean, default: false},
skills : [{type: String}],
address : {type: String},
rating : {type: Number, default: 0},
project : {type: Number, default: 0},
country : {type: String},
provinsi : {type: String},
wilayah : {type: String}, //kabupaten atau kota
kecamatan : {type: String},
kelurahan : {type: String},
zip_code : {type: Number}
}, {
timestamps: true
})
userSchema.path('email').set(function (email) {
if (!this.picture || this.picture.indexOf('https://gravatar.com') === 0) {
const hash = crypto.createHash('md5').update(email).digest('hex')
this.picture = `https://gravatar.com/avatar/${hash}?d=identicon`
}
// if (!this.username) {
// this.username = email.replace(/^(.+)@.+$/, '$1')
// }
return email
})
userSchema.pre('save', function (next) {
if (!this.isModified('password')) return next()
/* istanbul ignore next */
const rounds = env === 'test' ? 1 : 9
bcrypt.hash(this.password, rounds).then((hash) => {
this.password = hash
next()
}).catch(next)
})
userSchema.methods = {
view (full) {
let view = {}
let fields = ['id', 'username', 'picture', 'rating']
if (full) {
fields = [...fields, 'email', 'role', 'status', 'skills', 'address', 'project', 'country', 'provinsi', 'wilayah', 'kecamatan', 'kelurahan', 'zip_code', 'createdAt']
}
fields.forEach((field) => { view[field] = this[field] })
return view
},
authenticate (password) {
return bcrypt.compare(password, this.password).then((valid) => valid ? this : false)
}
}
userSchema.statics = {
roles,
createFromService ({ service, id, email, username, picture }) {
return this.findOne({ $or: [{ [`services.${service}`]: id }, { email }] }).then((user) => {
if (user) {
user.services[service] = id
user.username = username
user.picture = picture
return user.save()
} else {
const password = randtoken.generate(16)
return this.create({ services: { [service]: id }, email, password, username, picture })
}
})
}
}
// userSchema.plugin(mongooseKeywords, { paths: ['email', 'username'] })
const model = mongoose.model('User', userSchema)
export const schema = model.schema
export default model
index.js
import { Router } from 'express'
import { middleware as query } from 'querymen'
import { middleware as body } from 'bodymen'
import { password as passwordAuth, master, token } from '../../services/passport'
import { index, showMe, show, create, update, updatePassword, destroy } from './controller'
import { schema } from './model'
export User, { schema } from './model'
const router = new Router()
const { username, email, password, address, skills, picture, role, rating, project, country, provinsi, wilayah, kecamatan, kelurahan, zip_code } = schema.tree
/**
* @api {get} /users Retrieve users
* @apiName RetrieveUsers
* @apiGroup User
* @apiPermission admin
* @apiParam {String} access_token User access_token.
* @apiUse listParams
* @apiSuccess {Object[]} users List of users.
* @apiError {Object} 400 Some parameters may contain invalid values.
* @apiError 401 Admin access only.
*/
router.get('/',
token({ required: true, roles: ['admin'] }),
query(),
index)
/**
* @api {get} /users/me Retrieve current user
* @apiName RetrieveCurrentUser
* @apiGroup User
* @apiPermission user
* @apiParam {String} access_token User access_token.
* @apiSuccess {Object} user User's data.
*/
router.get('/me',
token({ required: true }),
showMe)
/**
* @api {get} /users/:id Retrieve user
* @apiName RetrieveUser
* @apiGroup User
* @apiPermission public
* @apiSuccess {Object} user User's data.
* @apiError 404 User not found.
*/
router.get('/:id',
show)
/**
* @api {post} /users Create user
* @apiName CreateUser
* @apiGroup User
* @apiPermission master
* @apiParam {String} access_token Master access_token.
* @apiParam {String} email User's email.
* @apiParam {String{6..}} password User's password.
* @apiParam {String} [name] User's name.
* @apiParam {String} [picture] User's picture.
* @apiParam {String=user,admin} [role=user] User's picture.
* @apiSuccess (Sucess 201) {Object} user User's data.
* @apiError {Object} 400 Some parameters may contain invalid values.
* @apiError 401 Master access only.
* @apiError 409 Email already registered.
*/
router.post('/',
master(),
body({ email, password, username, picture, role }),
create)
/**
* @api {put} /users/:id Update user
* @apiName UpdateUser
* @apiGroup User
* @apiPermission user
* @apiParam {String} access_token User access_token.
* @apiParam {String} [name] User's name.
* @apiParam {String} [picture] User's picture.
* @apiSuccess {Object} user User's data.
* @apiError {Object} 400 Some parameters may contain invalid values.
* @apiError 401 Current user or admin access only.
* @apiError 404 User not found.
*/
router.put('/:id',
token({ required: true }),
body({ address }),
update)
/**
* @api {put} /users/:id/password Update password
* @apiName UpdatePassword
* @apiGroup User
* @apiHeader {String} Authorization Basic authorization with email and password.
* @apiParam {String{6..}} password User's new password.
* @apiSuccess (Success 201) {Object} user User's data.
* @apiError {Object} 400 Some parameters may contain invalid values.
* @apiError 401 Current user access only.
* @apiError 404 User not found.
*/
router.put('/:id/password',
passwordAuth(),
body({ password }),
updatePassword)
/**
* @api {delete} /users/:id Delete user
* @apiName DeleteUser
* @apiGroup User
* @apiPermission admin
* @apiParam {String} access_token User access_token.
* @apiSuccess (Success 204) 204 No Content.
* @apiError 401 Admin access only.
* @apiError 404 User not found.
*/
router.delete('/:id',
token({ required: true, roles: ['admin'] }),
destroy)
export default router
controller.js
import _ from 'lodash'
import { success, notFound } from '../../services/response/'
import { User } from '.'
export const index = ({ querymen: { query, select, cursor } }, res, next) =>
User.find(query, select, cursor)
.then((users) => users.map((user) => user.view()))
.then(success(res))
.catch(next)
export const show = ({ params }, res, next) =>
User.findById(params.id)
.then(notFound(res))
.then((user) => user ? user.view() : null)
.then(success(res))
.catch(next)
export const showMe = ({ user }, res) =>
res.json(user.view(true))
export const create = ({ bodymen: { body } }, res, next) =>
User.create(body)
.then((users) => users.view(true))
.then(success(res, 201))
.catch((err) => {
/* istanbul ignore else */
if (err.name === 'MongoError' && err.code === 11000) {
res.status(409).json({
valid: false,
param: 'username or email',
message: 'username or email already registered'
})
} else {
next(err)
}
})
export const update = ({ bodymen: { body }, params, user }, res, next) =>
User.findById(params.id === 'me' ? user.id : params.id)
.then(notFound(res))
.then((result) => {
if (!result) return null
const isAdmin = user.role === 'admin'
const isSelfUpdate = user.id === result.id
if (!isSelfUpdate && !isAdmin) {
res.status(401).json({
valid: false,
message: 'You can\'t change other user\'s data'
})
return null
}
return result
})
.then((user) => user ? _.merge(user, body).save() : null)
.then((user) => user ? user.view(true) : null)
.then(success(res))
.catch(next)
export const updatePassword = ({ bodymen: { body }, params, user }, res, next) =>
User.findById(params.id === 'me' ? user.id : params.id)
.then(notFound(res))
.then((result) => {
if (!result) return null
const isSelfUpdate = user.id === result.id
if (!isSelfUpdate) {
res.status(401).json({
valid: false,
param: 'password',
message: 'You can\'t change other user\'s password'
})
return null
}
return result
})
.then((user) => user ? user.set({ password: body.password }).save() : null)
.then((user) => user ? user.view(true) : null)
.then(success(res))
.catch(next)
export const destroy = ({ params }, res, next) =>
User.findById(params.id)
.then(notFound(res))
.then((user) => user ? user.remove() : null)
.then(success(res, 204))
.catch(next)