Javascript 用户在注册后被添加到mongoDB数据库,尽管选择的“用户名”已经存在
我正在开发一个带有MERN堆栈的web应用程序 在邮递员或我的前端表单上,当我使用现有电子邮件注册用户时,该用户不会添加到数据库中。我使用相同的逻辑检查用户选择的用户名是否已经被使用。如果已执行,则发送错误消息,但仍将用户添加到数据库中 在用户模型中,字段用户名是唯一的,就像字段电子邮件一样 我的注册路线:Javascript 用户在注册后被添加到mongoDB数据库,尽管选择的“用户名”已经存在,javascript,reactjs,mongodb,mongoose,Javascript,Reactjs,Mongodb,Mongoose,我正在开发一个带有MERN堆栈的web应用程序 在邮递员或我的前端表单上,当我使用现有电子邮件注册用户时,该用户不会添加到数据库中。我使用相同的逻辑检查用户选择的用户名是否已经被使用。如果已执行,则发送错误消息,但仍将用户添加到数据库中 在用户模型中,字段用户名是唯一的,就像字段电子邮件一样 我的注册路线: const express = require("express"); const router = express.Router(); const User = require("../.
const express = require("express");
const router = express.Router();
const User = require("../../models/User");
const { check, validationResult } = require("express-validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const config = require("config");
// @route GET register
// @desc Register
// @access Public
router.get("/", (req, res) => {
res.send("Create an account");
});
// @route POST register
// @desc Register
// @access Public
router.post(
"/",
[
check("email", "Please, include a valid email.").isEmail(),
check(
"password",
"Please, enter a password with 6 or more characters"
).isLength({ min: 6 }),
check("username", "Please, include a valid username.")
.not()
.isEmpty()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
} = req.body;
try {
// See if user exists
let user = await User.findOne({ $or: [{ username }, { email }] });
if (user) {
res.status(400).json({ errors: [{ msg: "User already exists" }] });
}
// Create new user from User Model
user = new User({
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
});
// Encrypt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
// Add user to database
await user.save();
// Return JWT
const payload = {
user: {
id: user.id
}
};
jwt.sign(
payload,
config.get("jwtSecret"),
{ expiresIn: 360000 },
(err, token) => {
if (err) throw err;
res.json({ token });
}
);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
}
);
module.exports = router;
我的注册行动:
// REGISTER USER
export const register = ({
email,
password,
birthdate,
gender,
sun,
username
}) => async dispatch => {
const config = {
headers: {
"Content-Type": "application/json"
}
};
const body = JSON.stringify({
email,
password,
birthdate,
gender,
sun,
username
});
try {
const res = await axios.post("/register", body, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
});
dispatch(loadUser());
} catch (err) {
const errors = err.response.data.errors;
if (errors) {
errors.forEach(error => dispatch(setAlert(error.msg, "danger")));
}
dispatch({
type: REGISTER_FAIL
});
}
};
如果用户存在,则需要停止处理请求:
// See if user exists
let user = await User.findOne({ $or: [{ username }, { email }] });
if (user) {
res.status(400).json({ errors: [{ msg: "User already exists" }] });
}
// Create new user from User Model
user = new User({
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
});
看到了吗?如果用户{res.json},但您仍然继续。返回res.json以快速修复
更好的解决方法是,您应该在用户名和电子邮件字段上设置唯一索引。在猫鼬中,它看起来像:
const userSchema = new Schema({
name: {
type: String,
index: {
unique: true
}
}
});
或者,如果您希望允许用户名相同但唯一性为用户名电子邮件组合,请创建一个复合索引
更妙的是,将整个文件移到另一个文件中。调用文件user-registration.service.js。使文件导出成为一个功能:
async function registerUser(username, email, password) {
// check uniqueness here. if it fails, _throw an error!_
// if all is ok, save the user, return the details.
}
module.exports = {
registerUser
}
这样,您的路线控制员就可以说:
router.post(
"/",
[
check("email", "Please, include a valid email.").isEmail(),
check(
"password",
"Please, enter a password with 6 or more characters"
).isLength({ min: 6 }),
check("username", "Please, include a valid username.")
.not()
.isEmpty()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
} = req.body;
try {
const user = await registerUser();
return res.json(user); // or token or whatnot.
} catch (err) {
// see here? only one place to deal with that error.
return res.status(400)
.json(err);
}
}
现在,您只有一个地方可以处理错误。您甚至可以进一步推送它,只需省略try/catch,让全局错误处理程序处理它。如果用户存在,您需要停止处理请求:
// See if user exists
let user = await User.findOne({ $or: [{ username }, { email }] });
if (user) {
res.status(400).json({ errors: [{ msg: "User already exists" }] });
}
// Create new user from User Model
user = new User({
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
});
看到了吗?如果用户{res.json},但您仍然继续。返回res.json以快速修复
更好的解决方法是,您应该在用户名和电子邮件字段上设置唯一索引。在猫鼬中,它看起来像:
const userSchema = new Schema({
name: {
type: String,
index: {
unique: true
}
}
});
或者,如果您希望允许用户名相同但唯一性为用户名电子邮件组合,请创建一个复合索引
更妙的是,将整个文件移到另一个文件中。调用文件user-registration.service.js。使文件导出成为一个功能:
async function registerUser(username, email, password) {
// check uniqueness here. if it fails, _throw an error!_
// if all is ok, save the user, return the details.
}
module.exports = {
registerUser
}
这样,您的路线控制员就可以说:
router.post(
"/",
[
check("email", "Please, include a valid email.").isEmail(),
check(
"password",
"Please, enter a password with 6 or more characters"
).isLength({ min: 6 }),
check("username", "Please, include a valid username.")
.not()
.isEmpty()
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
email,
password,
birthdate,
birthplace,
sun,
username,
date,
is_paying
} = req.body;
try {
const user = await registerUser();
return res.json(user); // or token or whatnot.
} catch (err) {
// see here? only one place to deal with that error.
return res.status(400)
.json(err);
}
}
现在,您只有一个地方可以处理错误。您甚至可以进一步推动它,只需省略try/catch,让全局错误处理程序来处理它。
异步请求,res=>{
const errors=validationResultreq;
如果!错误。我是空的{
返回res.status400.json{errors:errors.array};
}
常数{
电子邮件
暗语
生日,
出生地
太阳
用户名,
日期
你付钱吗
}=请求主体;
试一试{
//查看用户是否存在
let user=wait user.findOne{$or:[{username},{email}]};
如果用户{
json{errors:[{msg:User已经存在}]};
}
否则{
//从用户模型创建新用户
用户=新用户{
电子邮件
暗语
生日,
出生地
太阳
用户名,
日期
你付钱吗
};
//加密密码
常量盐=等待bcrypt.genSalt10;
user.password=await bcrypt.hashpassword,salt;
//将用户添加到数据库
等待user.save;
//返回JWT
常数有效载荷={
用户:{
id:user.id
}
};
jwt符号
有效载荷,
config.getjwtSecret,
{expiresIn:360000},
错误,标记=>{
如果犯了错误,就扔出错误;
res.json{token};
}
;
}
}
犯错误{
console.error.message;
res.status500.sendServer错误;
}
}
;
异步请求,res=>{
const errors=validationResultreq;
如果!错误。我是空的{
返回res.status400.json{errors:errors.array};
}
常数{
电子邮件
暗语
生日,
出生地
太阳
用户名,
日期
你付钱吗
}=请求主体;
试一试{
//查看用户是否存在
let user=wait user.findOne{$or:[{username},{email}]};
如果用户{
json{errors:[{msg:User已经存在}]};
}
否则{
//从用户模型创建新用户
用户=新用户{
电子邮件
暗语
生日,
出生地
太阳
用户名,
日期
你付钱吗
};
//加密密码
常量盐=等待bcrypt.genSalt10;
user.password=await bcrypt.hashpassword,salt;
//将用户添加到数据库
等待user.save;
//雷图
rn JWT
常数有效载荷={
用户:{
id:user.id
}
};
jwt符号
有效载荷,
config.getjwtSecret,
{expiresIn:360000},
错误,标记=>{
如果犯了错误,就扔出错误;
res.json{token};
}
;
}
}
犯错误{
console.error.message;
res.status500.sendServer错误;
}
}
;谢谢你的评论。在用户模型中,我已经有了用户名和电子邮件的唯一索引。另外,我觉得奇怪的是,如果我只检查if语句中的电子邮件,它就会工作。但是当我用用户名替换电子邮件时,即使用户名已经存在,它仍然会添加用户。那么您的索引可能不正确。如果您有唯一索引,那么mongodb将无法添加它。您的mongoose模型/模式是什么样子的?还有,来自数据库本身的任何错误消息?也许你认为你有索引,但你实际上没有?在if语句中添加了返回,它就工作了!我会接受你的建议,并为此制作另一个文件,非常感谢!并且一定要调查你的mongodb——看起来索引确实不是出于某种原因创建的,所以请确保它能正常工作。你可以打开一个MongoShell并手动尝试插入重复的用户名,看看索引是否会阻止你。谢谢你的评论。在用户模型中,我已经有了用户名和电子邮件的唯一索引。另外,我觉得奇怪的是,如果我只检查if语句中的电子邮件,它就会工作。但是当我用用户名替换电子邮件时,即使用户名已经存在,它仍然会添加用户。那么您的索引可能不正确。如果您有唯一索引,那么mongodb将无法添加它。您的mongoose模型/模式是什么样子的?还有,来自数据库本身的任何错误消息?也许你认为你有索引,但你实际上没有?在if语句中添加了返回,它就工作了!我会接受你的建议,并为此制作另一个文件,非常感谢!并且一定要调查你的mongodb——它看起来确实是因为某种原因而没有创建索引,所以一定要确保它正常工作。你可以打开一个MongoShell,手动尝试插入重复的用户名,看看索引是否会阻止你。