I'm having problems with saving a document in MongoDB in my Nodejitsu/MongoHQ app. Locally all works fine, but the MongoHQ db requires authentification and it fails with working user/pass (connecting to MongoDB shell with the same credentials works fine). Here is the function:
var update_user = function(user, callback) {
var client = new Db(db, new Server(host, port, {}));
var update = function (err, collection) {
collection.findOne({uid:user.id}, function(err, doc) {
if (err) { throw err; }
if (!doc) doc = { uid: user.id }
doc.img = user.img;
doc.name = user.name;
collection.save(doc, {safe: true}, function(err, doc) {
if (err) { throw err; }
callback(user);
});
});
};
client.open(function(err, client) {
if (err) { throw err; }
client.authenticate(user, pass, function(err, result) {
client.collection('users', update);
});
});
}
What I'm doing wrong here?
UPD: err parameter of authenticate method has the following value:
{ [MongoError: auth fails] name: 'MongoError', errmsg: 'auth fails', ok: 0 }
I checked the stored password & username again, they work for logging in the MongoHQ shell.
If your credentials are for an admin user account you must target the admin database in your authenticate call:
client.authenticate(user, pass, {authdb: 'admin'}, function(err, result) {
client.collection('users', update);
});
Related
I'm writing d3 visualization code to append counts and rectangle boxes around the counts on .JPEG image. In order to get dynamic data I used typescript+node JS+D3 JS. I need to use Vertica DB.
How to install plugin to connect to db from typescript+nodeJS?
I tried node-vertica plugin and could not integrate it properly.
---------------
Code in app.js:
---------------
var config = {
ssl: 'optional',
interruptible: true,
host: '*******',
user: '*********',
password: '********',
database: '********'
};
try {
conn = Vertica.connect(config, (err, conn) => {
if (err) {
console.log(err);
} else {
conn.connect(function(err) {
if (err) throw err;
conn.query("select * from *****", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
});
}
});
}
catch (error) {
console.log("Error has been caught --"+error);
}
I'm trying to connect my Mongodb with Auth0 authorization. I'm using Mlabs to host my db. Inside this db, I have a "users" collection, and the documents have "username", "password", "email, and "_id" keys. When I try to use the Auth0 login script, I get the following error: Not authorized for query on mydb.users. Below is the script:
function login(email, password, callback) {
mongo('<mongodb uri>', function (db) {
var users = db.collection('users');
console.log(users);
users.findOne({ email: email }, function (err, user) {
if (err) return callback(err);
if (!user) return callback(new WrongUsernameOrPasswordError(email));
bcrypt.compare(password, user.password, function (err, isValid) {
if (err) {
callback(err);
} else if (!isValid) {
callback(new WrongUsernameOrPasswordError(email));
} else {
callback(null, {
user_id: user._id.toString(),
nickname: user.nickname,
email: user.email
});
}
});
});
});
}
Any ideas why I might be getting this error? Thanks in advance!
You probably have to check for a connection to the db.
The callback should have an error parameter
mongo('<mongodb uri>', function (err,db) {
if(err){
console.log(err)
}
})
if that doesn't fix it then you have to assign read and write permissions to perform the intended operations (in your case read) on the specified database
I'm actually creating a chat like Discord with servers and channels using Node.JS, MongoDB and Mongoose.
Actually, my structure is this one:
https://github.com/copostic/My-Simple-Chat/tree/master/models
But to get the conversations, I have to make so much nested functions and I would like to know if there was a better way to organize my code..
Here's the code with the nested functions, I'm trying to get the message list of each channel of each server:
"use strict"
const Server = require('../models/server'),
Channel = require('../models/channel'),
Message = require('../models/message'),
User = require('../models/user');
exports.getChannels = function (req, res, next) {
// Only return one message from each conversation to display as snippet
Server.find({members: req.session._id})
.select('_id')
.exec(function (err, servers) {
if (err) {
res.send({ error: err });
return next(err);
}
servers.forEach(function (server) {
Channel.find({ serverId: server })
.exec(function (err, channels) {
// Set up empty array to hold conversations + most recent message
let fullConversations = [];
channels.forEach(function (channel) {
Message.find({
'channelId': channel._id
})
.sort('creationDate')
.limit(1)
.populate({
path: "author",
select: "profile.firstName profile.lastName"
});
.exec(function (err, message) {
if (err) {
res.send({
error: err
});
return next(err);
}
fullConversations.push(message);
if (fullConversations.length === conversations.length) {
return res.status(200).json({
conversations: fullConversations
});
}
});
});
});
});
});
};
Thanks a lot
I have a working auth on a local project, but am trying to deploy it with Heroku and Mlab. I can post new objects, but cannot get my Auth to work. I am not sure why. I am using the MEAN stack with Angular 1.6.
Github
Heroku Project
This is how I am currently posting new objects to the hosted database.
var VENDORS_COLLECTION = "vendors";
var USERS_COLLECTION = "users";
// Create a database variable outside of the database connection
callback to reuse the connection pool in your app.
var db;
// Connect to the database before starting the application server.
mongodb.MongoClient.connect(process.env.MONGODB_URI, function (err,
database) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
db = database;
console.log("Database connection ready");
// Initialize the app.
var server = app.listen(process.env.PORT || 8080, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
});
app.post("/vendors", function(req, res) {
var newVendor = req.body;
newVendor.createDate = new Date();
db.collection(VENDORS_COLLECTION).insertOne(newVendor, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to create new vendor.");
} else {
res.status(201).json(doc.ops[0]);
}
});
});
This is how my auth works locally:
app.post('/auth/signup', function (req, res) {
User.findOne({ email: req.body.email }, function (err, existingUser) {
if (existingUser) {
return res.status(409).send({ message: 'Email is already taken.' });
}
var user = new User({
displayName: req.body.displayName,
username: req.body.username,
email: req.body.email,
password: req.body.password
});
user.save(function (err, result) {
if (err) {
res.status(500).send({ message: err.message });
}
res.send({ token: auth.createJWT(result) });
});
});
});
Tried to refactor to look like this but no luck.
app.post('/auth/signup', function (req, res) {
db.collection(USERS_COLLECTION).findOne...
On a node.js server I am using bcrypt to hash a password which is received by a user via a POST request and then store the hash in a database. The hashing function function takes longer to compute than creation of the saving of the hash and other parameters to the database, so I need to use a promise to executing the save after the hashing function has finished. I am using the Q library for this purpose, but I'm not sure how to do this. I am using mongoose for data modelling.
async bcrypt hashing function
var bcrypt = require('bcrypt');
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(req.body.password, salt, function(err, hash) {
// Store hash in DB
});
});
});
POST route
app.post('/api/users', function(req, res) {
var newUser = new User({
email: req.body.email,
name: req.body.name,
password: hash
});
newUser.save(function(err) {
if(!err) {
return res.send({ status: 'User created' });
} else {
if(err.name == 'ValidationError') {
res.statusCode = 400;
res.send({ error: 'Bad Request' });
} else {
res.statusCode = 500;
res.send({ error: 'Internal Server Error' });
}
}
});
});
I would figure the population of the newUser variable and newUser.save() call would be the argument of then(), but how do I make the bcrypt hashing function issue the promise and pass the hash?
You could simply move your database queries, to inside the callback of the hash, so that when the hash call back is ready it would then save it.
var bcrypt = require('bcrypt');
app.post('/api/users', function(req, res) {
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(req.body.password, salt, function(err, hash) {
var newUser = new User({
email: req.body.email,
name: req.body.name,
password: hash
});
newUser.save(function(err) {
if(!err) {
return res.send({ status: 'User created' });
} else {
if(err.name == 'ValidationError') {
res.statusCode = 400;
res.send({ error: 'Bad Request' });
} else {
res.statusCode = 500;
res.send({ error: 'Internal Server Error' });
}
}
});
});
});
});
Or use the synchronous call of bcrypt.hashSync but synchronous is not good practice when trying to work with Node.
But it could be like password: bcrypt.hashSync(req.body.password, salt)
If I understand correctly what you're asking, you want to save the user, after the password is hashed?