const err = new MongooseError(message); - javascript

I am trying to create a project which allows the user to enter "email", "username" and "Password" to register to the site,
When I try to enter a user using the "username", email" and "password" to enter this site, I get the following error:
Backend server is running
not connected
C:\Users\odewo\chat-app\NODE-REST-API\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:149
const err = new MongooseError(message);
^
MongooseError: Operation `users.insertOne()` buffering timed out after 10000ms
at Timeout.<anonymous> (C:\Users\odewo\chat-app\NODE-REST-API\node_modules\mongoose\lib\drivers\node-mongodb-native\collection.js:149:23)
at listOnTimeout (node:internal/timers:557:17)
at processTimers (node:internal/timers:500:7)
Below is my mongoose code:
mongoose.connect(process.env.MONGO_URL, {
userNewUrlPaser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log('Connected to MongoDB');
})
.catch((e) => {
console.log('not connected');
});
This is auth.js code for routes:
const router = require('express').Router();
const User = require('../models/User');
// REGISTER
router.get('/register', async (req, res) => {
const user = await new User({
username: 'samson',
email: 'samson#gmail.com',
password: '123456',
});
await user.save();
res.send('ok');
});
module.exports = router;
I will really appreciate your help

Monogo Db Atlas -> Network Access -> IP Access List -> IP address updated to access from any where works for me.
Reason : My Internet provider allots dynamic IP and every time i login the IP Address changes and this throws error.

Check your MONGO_URL and make sure your password or username is not wrapped in < > tags. I think your code is fine but its obvious that there are some problems. I would be checking the .env file to make sure.

The problem is not solved by removing the await. It is better to implement this function asynchronously. You must log in to your mongo account and add your IP address from the Network Access part.

you should remove the await before the new User declaration , use await just when you are waiting for the result of a promise like in await user.save()

You can solve this problem by using a simple password for your atlasDatabase meaning avoid using any special characters in your password like "#" or "$" and if you use then they must be url encoded that's why it is better if you avoid special characters and it worked for me and I hope it will work for you too.enter image description here

Related

Cannot get response from express endpoint

I'm building an API that I intend to use with my react native application. The problem which I'm facing right now is that I when I try to hit this particular route /api/auth/signup in Postman I get the Could not get any response error message.
This is the route:
//create user token
router.post(
"/signup",
[check("username").isEmail(), check("password").isLength({ min: 6 })],
async (req, res) => {
//validate input field on the backend
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
const { username, password, firstName, lastName } = req.body;
try {
//search DB if there is an existing user
let user = await User.findOne({ username });
if (user) {
return res.status(400).json({ msg: "User already exists" });
}
const salt = await bcrypt.genSalt(10);
res.status(200).json({ data: salt });
} catch (error) {}
}
);
module.exports = router;
The strange thing is that if I remove the User.findOne function I get a response. I don't know why this keeps happening, as I had built a similar application following the same pattern without a problem.
NOTE: In the main app.js I have the app.use(express.json({extended:true}), I've also successfully linked the routes in the main file too. Any help would be greatly appreciated!
I think you have a typo in your app.use... statement which you've given in your comment as,
app.use(express.json({extented:true})
which needs to be corrected as, ('d' should come in place of 't')
app.use(express.json({extended:true})
Hope this helps!
So it turns out when I was requiring mongoose in one of my models I required it with an uppercase letter const mongoose = require('Mongoose') which isn't valid, therefore the findOne method won't run because there's no model to take it from. Strange that visual studio code didn't complain about the false import. Anyways, thanks to anyone willing to help me out :) !

confirming if an email already exists in a MongoDB database

I wrote this code to check if an email already exists in the database:
async store (req,res) {
const email = req.body.email;
let user = await User.findOne ({ email: email });
if (user) {
console.log('Already exist.')
};
(...)
}
But it's not working: I can store the info in the User collection but it's email is not verified.
I'm using Mongoose.
What I'm doing wrong?
You need to use exec() at the end to actually run the query:
let user = await User.findOne({ email: email }).exec();
Also, since you're using await, make sure the containing function is marked async.
I am limited in the information I can give you because you just say "It's not working". That doesn't tell me anything. Do you run it and nothing happens? Does it give you an error? People on this site don't like to hear the words: "it's not working".
You haven't described your use case, but if you're looking to avoid email collisions, using mongoose, when you define the object's schema, you can use the unique: true option. It will then reject any new or updated User that submits an already stored email.

Why i can't handle error connection? MQTT

I am trying to handle two cases. When the connection is successful and not. I created a promise that should return if the connection is successful. But it does not handle the error (the connection does not work at all (I think the problem is authorization)).
If I enter the wrong username or password, then the connection does not work at all.
I need to handle the error, any ideas?
UPD. Body server.on is not called if i using wrong password or username. I think its feature mqtt connect or something.
return new Promise((resolve) => {
server = mqtt.connect('url', {
username: 'username',
password: 'pass'
});
server.on('connect', (res) => {
resolve(true);
server.end();
});
});

Is there a way to create a database with mongoose that has a username and password?

I'm currently working on a app (dev with electron). I'm using mongoDB and mongoose for my persistant storage but I can't find a way to do something that seem really basic : when creating a database I'd like to add an user and a password to it (I realy search for it, but no way to find anything usable).
I have this need because it's going to be a multi-user app and I definitly don't want an user to know the contents of another user account.
The idea is that once you create an account, the app create a database that has the same username and password of the account. For login, the app try to connect you to the database with your account & password.
I'm working with :
electron
HTML / CSS / javascript
mongoDB
mongoose
Here is the code that I tested :
var mongoose = require('mongoose');
var connStr = "mongodb://localhost:27017/test";
mongoose.connect(connStr, {user: 'newUser', password: 'pwd', useNewUrlParser: true }, function(err) {
if (err) {throw err};
console.log("Successfully connected to MongoDB");
});
I get the error
Uncaught (in promise) MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoError: password must be a string]
However with those, the database is correctly created (but anyone can access it) :
user: '', password: ''
What I expect is to create a new database with the user name set as "newUser" and the password as "pwd", in that way only with the correct id & password would it be possible to connect to it.
Thanks for your help !
I don't know if this will work or not but I ran a mongo service using docker and then connected mongoose to it with the following code
mongoose.connect('mongodb://user:pass#localhost:port/MyDB?authSource=admin', {
useNewUrlParser: true
})
.then(() => console.log('MongoDB connection successful'))
.catch(err => console.error('Could not connect to MongoDB:‌', err));
this is equivalent to
mongo --username user --password pass --authenticationDatabase admin --port 27017

Testing Node/Express API with Mocha/Chai

I am currently trying to test my node api w/ mocha chai. I am running into a scenario where a test should actually fail but is passing. I have a repo up of the current API that I am building here if you want to play around with it: enter link description here. However, I am still going to walk through the code in this question.
I'm trying to test the controller with the following code:
import chai, { expect } from 'chai';
import chaiHttp from 'chai-http';
import server from '../../src/app';
chai.use(chaiHttp);
describe('Authentication Controller', () => {
const testUser = {
email_address: 'test#test.com',
password: 'test'
};
describe('login success', () => {
it('responds with status 200', done => {
chai.request(server)
.post('/api/auth/login')
.send(testUser)
.end((err, res) => {
expect(res).to.have.status(200);
done();
});
});
});
describe('login failure', () => {
it('responds with status 401', done => {
chai.request(server)
.post('/api/auth/login')
.send(testUser.email_address = 'fake#news.com')
.end((err, res) => {
expect(res).to.have.status(200);
done();
});
});
});
});
Obviously I want to test a successful login and a failed login attempt. However, both the response statuses from the server are 200 and this should not be the case. When testing in Postman the response status when an individual tries to login with an email address that doesn't exist or a password that doesn't match, it returns a status of 401. If I write a test
expect(1).to.equal(1) => test passes.
expect(1).to.equal(2) => test fails.
Here is the controller function that handles the request for logging in:
export function login(req, res) {
User.findOne({email: req.body.email})
.then(user => {
if (user && bcrypt.compareSync(req.body.password, user.password)) {
generateToken(res, user);
} else {
res.status(401).json({
success: false,
message: 'Incorrect username or password.'
});
}
})
.catch(err => {
res.json(err);
});
}
The model that handles the request:
export function createUser(req) {
return db('users').insert(Object.assign(req.body,{password: hashPassword(req.body.password)}))
.then((id) => db('users').select().where('id', id).first());
}
As you can see I am using Knex.js. I have setup a test database and everything is connected appropriately, so I'm confused as to why my server is responding w/ a 200 response status when testing?
I just want to say thanks to anyone who takes the time to help me understand how mocha chai is working. I have very LITTLE experience with testing applications, but I want to start familiarizing myself w/ doing so because I believe it to be good practice.
I actually cloned your Github repo and tried running the test. From what I have seen, there are a couple of different issues in your code, as followed:
1. from the controller function you posted in the question:
```
export function login(req, res) {
User.findOne({email: req.body.email})
.then(user => {
// [removed because of little relevancy]
})
.catch(err => {
res.json(err);
});
}
```
The issue is the line res.json(err) which actually responded with a 200 status code (even though it was an error in this case). This is because res.json does not automatically set the HTTP response status code for you when you "send an error object". This fooled the client (in this case, chai-http) into thinking it was a successful request. To properly respond with an error status code, you may use this instead: res.status(500).json(err)
It's also worth noticing that some of your other controller functions got into this issue too.
2. from your userModels.js file, line 10, which is:
```
return db('users').select().where(req).first();
```
You are using Knex API in an incorrect way. It should be ...where('email', req.email)... This was the initial reason why your requests failed.
3. you set up your unit tests in different manners:
Test no. 1 (login success):
```
chai.request(server)
.post('/api/auth/login')
.send(testUser)
```
Test no. 2 (login failure):
```
chai.request(server)
.post('/api/auth/login')
.send(testUser.email_address = 'fake#news.com')
```
So, what happened?
In the first test, you passed an object into .send(), whereas in the second test, you simply passed an expression. When done this way, the model handler, userModels.findOne(), received an object with keys email_address and password for the first test, but for the second test, it did not.
Also, in your 1st test case, you sent testUser.email_address, but in your controller function, you referenced req.body.email.
All these, in addition to the issue no. 1 as I mentioned earlier, further complicated your test suite, leading to your misunderstanding in the end.
Disclaimer:
All what I wrote above was based on the source code from your Github repo, so if you have fixed some issues since you pushed your code, and some (or all) of my points above are no longer valid, please disregard. Nevertheless, I wish you have found, or will soon find out why your code didn't behave as you expected!
Cheers,
I just wanted to post an answer here that is specific to my experience and what helped me get all of this setup. The only thing that I really needed to change on the Repo Proj was the property email on the user object I was passing. I had email_address and was thus searching for that column in the database whilst it did not exist! So once I changed that I started down the right path.
I was then able to get my failed login test to pass. However, my successful login didn't pass. The reason was because I was seeding my database with a plain string password. Thus, when I performed the conditional statement of:
if (user && bcrypt.compareSync(req.body.password, user.password))
It wasn't passing because the bcrypt.comparSync was looking for a password that was hashed. In order to get this to work I needed to require babel-register in my knex file. This then allowed me to use es6 and perform my hashPassword function:
test/userSeed.js
import hashPassword from '../../src/helpers/hashPassword';
exports.seed = function(knex, Promise) {
return knex('users').truncate()
.then(() => {
return knex('users')
.then(() => {
return Promise.all([
// Insert seed entries
knex('users').insert([
{
first_name: 'admin',
last_name: 'admin',
email: 'admin#admin.com',
password: hashPassword('test')
},
{
first_name: 'test',
last_name: 'test',
email: 'test#test.com',
password: hashPassword('test')
}
]),
]);
});
})
};
hashPassword.js
import bcrypt from 'bcrypt';
export default function(password) {
const saltRounds = 10;
let salt = bcrypt.genSaltSync(saltRounds);
return bcrypt.hashSync(password, salt);
}
This resulted in the hashing of my users password when I seeded the DB. Tests all pass as they should and api works as intended using Postman.

Categories

Resources