I am not being able to create document properly using mongoose in my locally deployed mongodb server. Only id is being created not the full data(name , email , password) I sent. In server the data looks like this{ "_id": { "$oid": "651d8f91c018db3d9504da2a" }, "__v": 0 }
Mongosh shell and MongoDB compass is working fine though. But mongosh shell giving this warning : Access control is not enabled for the database.
. Idk if that is a problem here or not.
schema:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name : {type: String ,
required: true
},
email : {type: String ,
required: true
},
password : {type: String ,
required: true
},
}, {timestamps: true});
module.exports = mongoose.model('user', userSchema);
HTML:
<div class="loginform">
<div class="login">
<label for="name">Name</label><input type="text" id="name" />
</div>
<div class="login">
<label for="email">Email</label><input type="text" id="email" />
</div>
<div class="login">
<label for="password">Password</label
><input type="text" id="password" />
<button id="signinbutton">Create Account</button>
</div>
</div>
post request front
async function postData(url = "", data = {}) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
let rdata = await response.json()
return rdata
};
let submit = document.getElementById("signinbutton")
submit.addEventListener("click", async() => {
let name = document.getElementById("name").value
let email = document.getElementById("email").value
let password = document.getElementById("password").value
let resp= await postData("/signin", { name, email, password })
if(resp.success){
alert("user created")
}
})
post request
const express = require('express');
const app = express();
const path = require('path');
const mongoose = require('mongoose');
var bodyParser = require('body-parser')
const postm = require('./models/post');
const User = require('./models/User');
mongoose.connect('mongodb://127.0.0.1/blogbase');
app.use(express.json({extended:true}));
app.use(express.urlencoded({extended: true}));
app.use(express.static(path.join(__dirname, "static")));
const port = 3000
app.listen(port, () =>{
console.log('app http://localhost:${port}')
});
app.post('/signin', async(res,req) => {
let user = await User.create(req.body)
console.log(req.body)
res.status(200).json({success: true, user: user })
});
The error
D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:3166
this.$__.validationError = new ValidationError(this);
^
ValidationError: user validation failed: password: Path `password` is required., email: Path `email` is required., name: Path `name` is required.
at Document.invalidate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:3166:32)
at D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:2959:17
at D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1368:9
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
errors: {
password: ValidatorError: Path `password` is required.
at validate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1365:13)
at SchemaType.doValidate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1349:7)
at D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:2951:18
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
properties: {
validator: [Function (anonymous)],
message: 'Path `password` is required.',
type: 'required',
path: 'password',
value: undefined
},
kind: 'required',
path: 'password',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
email: ValidatorError: Path `email` is required.
at validate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1365:13)
at SchemaType.doValidate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1349:7)
at D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:2951:18
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
properties: {
validator: [Function (anonymous)],
message: 'Path `email` is required.',
type: 'required',
path: 'email',
value: undefined
},
kind: 'required',
path: 'email',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
},
name: ValidatorError: Path `name` is required.
at validate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1365:13)
at SchemaType.doValidate (D:\webdevedu\LBLOG\node_modules\mongoose\lib\schematype.js:1349:7)
at D:\webdevedu\LBLOG\node_modules\mongoose\lib\document.js:2951:18
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
properties: {
validator: [Function (anonymous)],
message: 'Path `name` is required.',
type: 'required',
path: 'name',
value: undefined
},
kind: 'required',
path: 'name',
value: undefined,
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'user validation failed'
}
Node.js v18.17.0
[nodemon] app crashed - waiting for file changes before starting...
The values of email
, name
and password
are undefined when your mongoose model tries to create a new user. There are a few issues with your code that are causing this but it looks like the values are not being sent.
Firstly, it's more semantic to actually use a form if you are going to be submitting form data. I can see you are using JS to get elements by their id
but the <form>
element already comes with a handy way of accessing each type of input anyway so just give each input a name attribute as well. I will explain. Update your HTML like so:
<form name="loginform" action="/signin">
<div class="login">
<label for="name">Name</label>
<input type="text" id="name" name="name">
</div>
<div class="login">
<label for="email">Email</label>
<input type="text" id="email" name="email">
</div>
<div class="login">
<label for="password">Password</label>
<input type="text" id="password" name="password">
<button id="signinbutton">Create Account</button>
</div>
</form>
Next, bind the addEventListener
to the actual form and prevent it's default behaviour of automatically submitting. You also have no error handling for your fetch network requests so you don't know if your form is sending properly. Update like so:
const form = document.querySelector('form[name="loginform"]')
form.addEventListener('submit', (e)=>{
e.preventDefault(); //< Prevent the form from submitting
let name = form.elements.name.value; //< Get each input element
let email = form.elements.email.value;
let password = form.elements.password.value;
fetch(form.action, { //< Now run fetch using form.action as url
method: 'POST',
body: JSON.stringify({ name, email, password }),
headers: {
'Content-type': 'application/json; charset=UTF-8',
}
})
.then((response)=>{
return response.json();
})
.then((data)=>{
console.log(data);
//Now handle a successful user creation
})
.catch(error => {
console.error('Error:', error)
//Now handle an unsuccessful user creation
});
});
Your post route on the server looks OK but again you need to be able to catch any errors. I would suggest using try/catch
like so and send the client an appropriate response on error:
app.post('/signin', async(req, res) => {
console.log(req.body); //< Make sure the form data has been parsed in req.body
try{
const {name, email, password} = req.body; //< Destructure only the values you need
let user = await User.create({name, email, password});
res.status(200).json({success: true, user: user });
}catch(err){
console.log(err);
res.status(400).json({success: false, err: 'Appropriate error message' });
}
});
The Access control is not enabled for the database
is a warning and not an error. It is basically telling you that you haven't set-up user authentication. See how to do it here.
Hope this helps and good luck with your project.