unread flag is not being updated with Mongoose - mongodb

I have a conversations collection in my database, and I'm using Mongoose to update the unread flag of a single document.
This is my code:
router.post('/reply/:conversation_id', ensureAuthenticated, (req, res, next) => {
Conversation.findById(req.params.conversation_id, (err, conversation) => {
// If the user that's logged in was the one who created the conversation, and is submitting a reply, run this code
if (req.user._id == conversation.created_by_user_id) {
User.findById(conversation.sent_to_user_id, (err, user) => {
Message.create({
//...
}, (err, message) => {
if (err) {
console.log(err)
} else {
message.conversations.push(conversation._id)
conversation.unread = true
conversation.save() // This is being saved to the database
message.save()
res.redirect('/conversations/' + conversation._id)
}
})
})
} else {
// Otherwise, if the user that's logged in was *not* the one who created the conversation, and is submitting a reply, run this code
User.findById(conversation.created_by_user_id, (err, user) => {
Message.create({
//...
}, (err, message) => {
if (err) {
console.log(err)
} else {
message.conversations.push(conversation._id)
conversation.unread = true
conversation.save() // This is not being saved
message.save()
res.redirect('/conversations/' + conversation._id)
}
})
})
}
})
});
The if part saves conversation.unread = true to the db. The else part does not.
Both parts of the conditional essentially do the same thing (save the conversation's unread flag as true, and save the message), but only the first part of the conditional works when setting unread to true.
Can someone please help me figure out why the unread flag is not being saved as true in the else statement?

You're trying to call save synchronously.
.save takes a callback. It is asynchronous.
See my version below.
router.post('/reply/:conversation_id', ensureAuthenticated, (req, res, next) => {
Conversation.findById(req.params.conversation_id, (err, conversation) => {
// If the user that's logged in was the one who created the conversation, and is submitting a reply, run this code
if (req.user._id == conversation.created_by_user_id) {
User.findById(conversation.sent_to_user_id, (err, user) => {
Message.create({
//...
}, (err, message) => {
if (err) {
console.log(err)
} else {
message.conversations.push(conversation._id)
conversation.unread = true
conversation.save() // This is being saved to the database
message.save()
res.redirect('/conversations/' + conversation._id)
}
})
})
} else {
// Otherwise, if the user that's logged in was *not* the one who created the conversation, and is submitting a reply, run this code
User.findById(conversation.created_by_user_id, (err, user) => {
Message.create({
//...
}, (err, message) => {
if (err) {
console.log(err)
//return here
return res.redirect('/error'); //
} else {
message.conversations.push(conversation._id)
conversation.unread = true
//.save takes a function callback
conversation.save((err) => {
//.save takes a function callback
message.save((err) => {
res.redirect('/conversations/' + conversation._id)
})
})
}
})
})
}
})
});

Related

how to get callback return value in nestjs

I am going to use vonage for text service.
However, only node.js syntax exists, and the corresponding API is being used.
There is a phenomenon that the callback is executed later when trying to receive the values ​​returned from the callback to check for an error.
How can I solve this part? The code is below.
await vonage.message.sendSms(from, to, text, async (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
console.log(result);
return result;
When an error occurs as a result of executing the above code,
result{error:undefined}
3
Outputs are in order.
From what I can understand the issue is that you are passing a async callback. you could simply just give vonage.message.sendSms() a synchronous callback like so.
const result = {};
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
console.log('1');
result.message = err;
} else {
if (responseData.messages[0]['status'] === '0') {
console.log('2');
} else {
console.log('3');
result.error = `Message failed with error: ${responseData.messages[0]['error-text']}`;
}
}
});
if you want to use async or promises I would suggest something like this
const sendSMS = (from, to, text) => new Promise( (resolve, reject) => {
vonage.message.sendSms(from, to, text, (err, responseData) => {
if (err) {
reject(err);
} else {
resolve(responseData);
}
});
});
// elsewhere
sendSMS(from, to, text)
.then(...)
.catch(...);

ldapjs handling client.search response

I have the below code which is binding to an LDAP server and I want to return the user that I have added "ab" within the "interviewees" group (code taken from ldapjs client api page). I can see I am getting back a response from the server with the expected EventEmitter object. I am expecting to see information about the user when calling logging console.log() on the searchEntry object. I appear to have no searchEntry objects. Is my DN for my user correct? I am currently unsure whether the issue is with my query and I am not getting any data back or whether I am failing to process the response correctly?
const client = ldap.createClient({ url: 'ldap://' + LDAP_SERVER + ':' + LDAP_PORT });
// Connect and bind to the Active Directory.
const connectToClient = async () => {
const secret = LDAP_SECRET_KEY;
return await new Promise((resolve, reject) => {
client.bind(LDAP_USER, secret, function (err, res) {
if (err) {
console.error(err);
reject('Failed to connect to LDAP server');
} else {
resolve('Connected to LDAP server');
}
});
});
};
onst searchADForUser = async () => {
return await new Promise((resolve, reject) => {
client.search('CN=ab,OU=interviewees,OU=Users,OU=interview,DC=interview,DC=workspace,DC=com', function (err, res) {
if (err) {
console.error(err);
reject('Error searching LDAP server');
} else {
res.on('searchEntry', function (entry) {
console.log('entry: ' + JSON.stringify(entry.object));
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
});
resolve(res);
}
});
});
};
const handler = async (event) => {
try {
return responses.success(
await connectToClient().then(async function(event) {
console.log(event);
await searchADForUser().then(function(event) {
console.log(event);
}).catch(function(event) {
console.log(event);
})
}).catch(function(event) {
console.log(event);
})
);
} catch (err) {
console.error(err);
return responses.error(err);
} finally {
client.unbind();
}
};
The active directory structure is below
The central issue I was having was understanding how to process the returned EventEmitter object from the search function. I need to add to an array on each searchEntry event and then return that entry in my resolve callback function only once the end event had occurred. The code above was calling resolve immediately and hence no searchEntry events or the end event had been processed yet.
Code I am now using below:
function (err, res) {
if (err) {
console.error(err);
reject(new Error('Error retrieving users from Active Directory'));
} else {
const entries = [];
res.on('searchEntry', function (entry) {
entries.push(entry);
});
res.on('searchReference', function (referral) {
console.log('referral: ' + referral.uris.join());
});
res.on('error', function (err) {
console.error('error: ' + err.message);
});
res.on('end', function (result) {
console.log('status: ' + result.status);
if (result.status !== 0) {
reject(new Error('Error code received from Active Directory'));
} else {
resolve(entries);
}
});
}
}

Store collection value to variable

I am having issues storing a value in mongodb to a variable to use within my webpage.
When the user fills out a form on my website, I am trying to figure out what the arrivalTrailer was when the user filled out the arrival form.
So far I have
function previousLoad(loadNumber, callback){
CheckCall.find({loadNumber: loadNumber}).sort({date: 'desc'}).limit(1), function(err, arrival){
if (err){
callback(err, null);
}
else {
callback(null, arrival[0]);
}
}};
previousLoad(loadNumber, function(err, arrival){
if (err){
console.log(err);
}
else{
arrivalTrailer = arrival;
console.log(arrival);
}
});
console.log(previousLoad.arrival);
console.log(arrivalTrailer);
Both output as undefined when I try to console.log the variables.
Thank you :D
Try this :
async function previousLoad(loadNumber) {
try {
let resp = await CheckCall.find({ loadNumber: loadNumber }).sort({ date: -1 }).limit(1)
return resp[0]
} catch (error) {
console.log('error ::', error)
throw new Error (error)
}
}
/** You can return response from previousLoad but to test it, Call it from here */
previousLoad(loadNumber).then(resp => { console.log('successfully found ::', resp)}).catch(err => { console.log('Error in DB Op ::', err)});

Unable to return value from nano.view callback

Unable to store value outside of callback scope
I have tried declaring an array, an object and an empty variable outside of the callback scope and nothing is working.
router.post('/login', async (req, res, next) => {
try {
const user = await users.view('viewEmailandPassword', 'email', {keys: [`${req.body.email}`], include_docs: true},
function(err, body) {
if (!err) {
body.rows.forEach(function(doc) {
console.log(doc.value)
// return doc.value
});
}
});
console.log(user) <--- nothing is returned
}
catch(err){
next(err)
console.err(err, "this is the error")
}
})
I get an output of "undefined"
The problem here is that you're trying to use callback + promises. You need to either choose one or the other.
Here's the implementation using Promises (with async/await)
router.post('/login', async (req, res, next) => {
try {
const body = await users.view('viewEmailandPassword', 'email', {keys: [`${req.body.email}`], include_docs: true});
// Prints all the row values
body.rows.forEach(doc => console.log(doc.value));
// Let's say you want the first row
if(body.rows.length > 0){
console.log(body.rows[0].value);
} else {
console.log("Not value returned from the view");
}
}
catch(err){
next(err)
console.err(err, "this is the error")
}
})

Bcrypt returns false on login

I know this question has been asked many times but I cannot find an answer to my problem both here or on github. I have a login handler which compares hashed password from db to the the one typed by the user on login. bcrypt.compare almost always returns false. I say almost because sometimes it just starts working and it always works after I register user. I am trying to find what is wrong with my code but cant figure it out. Any help is highly appreciated.
mongoose pre save
userModel.schema.pre('save', function(next) {
let user = this;
bcrypt.hash(user.password, 10, null)
.then(hash => {
console.log(hash)
user.password = hash;
user.confirmPassword = hash;
next();
})
.catch(err => res.sendStatus(404));
});
login handler
exports.loginUser = (req, res) => {
let user = new User.model(req.body);
User.model
.find({email: user.email})
.exec()
.then(users => {
if (!users.length) {
res.status(401).json({
message: "Auth failed - user does not exist"
});
} else {
bcrypt
.compare(req.body.password, users[0].password)
.then(result=> {
console.log(user.password, users[0].password)
console.log(bcrypt.hashSync(req.body.password, 10))
if (result) {
const token =
jwt
.sign({ email: users[0].email, id: users[0]._id },
'secretKey', { expiresIn: "1h"});
res.status(200).json({
message: "Auth success - logged in",
token,
users
});
} else {
res.json('not working');
}
})
.catch(err => res.status(401).json({message: "Auth failed"}));
}
});
};
register handler
exports.registerUser = (req, res) => {
let user = new User.model(req.body);
if(user.email) {
User.model
.find({email: user.email})
.exec()
.then(docs => {
if (!docs.length) {
if (user.password !== user.confirmPassword) {
return res.status(404).json('passwords do not match');
}
user.save(function (err, user) {
if (err) return (err);
});
console.log('user saved');
res.sendStatus(200);
} else {
res.status(404).json('user exists');
}
})
.catch(err => res.sendStatus(404).json(res.body));
} else {
res.status(404).json('user name required');
}
};
The problem might be that you generate a new password each time the user is saved. You should skip this though.
userModel.schema.pre('save', function(next) {
let user = this;
if(!user.isModified("password")) return next();
bcrypt.hash(user.password, 10, null)
.then(hash => {
console.log(hash)
user.password = hash;
user.confirmPassword = hash;
next();
})
.catch(err => res.sendStatus(404));
});
Just a shot in the dark though. under the assumption something got changed and this was called again, because you stated it is working sometimes.