I am relatively new to NodeJS and have run into an issue. Incoming request from Angluar UI has two parameters (loginId and password) and on Node, I am reading the data from a local json file, iterating through the 'users' array and based on the matching params, I am sending the particular object in the server response. However, my logic is failing where there are multiple objects in the 'users' array and I have to send a server response for the not-matched one as well. I know that I cannot send multiple responses but that is where i need the help. Any help will be highly appreciated.
Here is the code:
if (jsonData.users.length > 0) {
jsonData.users.forEach(user => {
if ((reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password) {
res.send({ 'userData': user });
} else {
res.json({ 'userData': 'No records found' });
}
})
res.send ends the response.
So using it a second time it will not send anything.
https://www.nodejsconnect.com/blog/articles/sending-multiple-http-responses-expressjs
EDIT:
I'm not completely sure what you want, but I think you want to do something like this.
-> return the user for whom the userId and password matches or return 'no records found' ( or even better send an 401 - unauthorized - status code)
const user = jsonData.users.find(user => (reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password));
if (user) {
res.send({ 'userData': user });
} else {
res.json({ 'userData': 'No records found' });
// or res.sendStatus(401); // unauth
}
Try this... If you wanna break the loop after a match.
if (jsonData.users.length > 0) {
let isMatch = false;
jsonData.users.forEach(user => {
if ((reqBody.loginId === user.email || reqBody.loginId === user.mobile) && reqBody.password === user.password) {
isMatch = true;
return res.send({ 'userData': user });
}
})
if(!isMatch)
res.json({ 'userData': 'No records found' });
}
Related
We are actually tring to read a csv file as input and throw out the corresponding results for the data in CSV file.
For every new http POST request, new result is being appended to the existing data in array(productDetails), but I want to flush the old data in array for every new request.
let productDetails=[];
router.get('/add-product',(req,res,next)=>{
res.sendFile(path.join(__dirname,'../','views','add-product.html'))
})
router.post('/add-product',(req,res,next)=>{
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
else {
var sampleFile=req.files.file;
sampleFile.mv('././uploads/'+sampleFile.name,function(err){
if(err){
return res.status(500).send(err);
}
})
readFile('././uploads/'+sampleFile.name,'utf-8',(err,fileContent)=>{
if(err){
console.log(err); // Do something to handle the error or just throw it
throw new Error(err);
}
const jsonObj = csvjson.toObject(fileContent);
jsonObj.forEach(obj=>{
data.forEach(obj1=>{
if(obj.Make ==obj1.Make && obj.Manufacture == obj1.Manufacture && obj.Product==obj1.Product){
productDetails.push({
product:obj1.Product,
price:obj1.Price,
manufacture:obj1.Manufacture,
make:obj1.Make
})
}
})
})
})
}
res.redirect('/');
})
exports.routes=router;
exports.productDetails=productDetails;
You Can try by adding this line
router.post('/add-product',(req,res,next)=>{
productDetails=[];
//YOUR CODE
})
I think you need a function variable rather than a global variable for producrDetails, so if you define your variable inside the POST call it will work according to your requirements and start will an empty productDetails array on every POST call.
router.post('/add-product',(req,res,next)=>{
let productDetails=[]
// CODE
jsonObj.forEach(obj=>{
data.forEach(obj1=>{
if(obj.Make ==obj1.Make && obj.Manufacture == obj1.Manufacture && obj.Product==obj1.Product){
productDetails.push({
product:obj1.Product,
price:obj1.Price,
manufacture:obj1.Manufacture,
make:obj1.Make
})
}
})
})
}
I am creating an application in which users can create posts and comment on these. Creating, updating and deleting posts works as intended, and so does creating comments.
When the user creates a comment, its accountId is passed to the database.
When deleting a specific comment, the accountId is passed to verify that the user is allowed to delete it.
The problem is, it seems like the accountId isn't fetched from the database, though the query asks for all details from the database table called "comments".
The app is divided into two files, db.js, and app.js.
I have tried modifying the request. In order to troubleshoot, I added a line of code checking if the comment.accountId was fetched, but that is where I get the error.
/* in db.js: */
//get comment by comment id
exports.getCommentById = (id, callback) => {
const query = 'SELECT * FROM comments WHERE id = ?'
const values = [ id ]
db.all(query, values, (error, comment) => {
if (error) {
console.log(error)
callback(['databaseError'])
return
} else if (!comment) {
console.log(error)
callback(['notFound'])
return
} else {
callback([], comment)
}
})
}
/* in app.js */
app.delete('/comments/:commentId', (req, res, next) => {
const commentId = req.params.commentId
db.getCommentById(commentId, (errors, comment) => {
if (errors.length > 0) {
res.status(500).json({
message: 'serverError'
}).end()
return
} else if (!comment) {
res.status(404).json({
message: 'notFound'
}).end()
return
}
const accountId = req.accountId //from my auth middleware
const commAccId = comment.accountId
if(!commAccId) {
console.log(accountId)
console.log(commAccId)
res.status(404).json({
message: 'AccIdNotFound'
}).end()
return
}
- - - - - ^ this is the error checking I inserted, and this is where the error is thrown, so it seems like the id is just not found.
if(!accountId) {
res.status(401).json({
message: 'notAuthenticated'
}).end()
return
} else if (comment.accountId != accountId) {
res.status(401).json({
message: 'notAuthorized'
}).end()
return
}
//plus code for deletion (will insert if it seems relevant, just ask)
})
})
The error message is "AccIdNotFound"
console.log returns 5 (same as the logged in user) and undefined
db.all delivers an array of rows, not just one row. You are assuming the result is a single comment only.
You should check result.length, then pull out result[0].
Hi I am trying trying to get data from my nodejs backend to angular. And i get the below error message in nodejs
Cannot read property 'friends' of null
at UserModel.findOne.select.lean.exec
The Api Works fine, if i try to use in postman. But when used in angular i get the error message in nodejs
The server side code is:
let findFriends = ()=>{
return new Promise((resolve, reject)=>{
UserModel.findOne({userId: req.body.userId || req.query.userId})
.select('-__v -_id -password')
.lean()
.exec((err, userFriends)=>{
console.log(userFriends.friends.length)
if(err){
logger.error(err.message, ' friendsController: getAllNonFriends, findFriends', 5)
let apiResponse = response.generate(true, `Failed to Find Friends`, 500, null)
reject(apiResponse)
}else {
if(userFriends.friends.length !== 0){
resolve(userFriends.friends)
}else {
resolve(userFriends)
}
}
})
})
} // end find requests
the code in angular:
public allNonFriends: any = ()=>{
this.http.getNonFriendsList(this.currentUser).subscribe(
(apiResponse)=>{
console.log(apiResponse)
if(apiResponse.status === 200){
console.log(apiResponse.data)
} else {
console.log(apiResponse.message)
}
},
(err)=>{
console.log(err)
}
)
} // end all non friends
I found the solution. I change the parameter from body to query and it worked
I wrote this code in node.js to verify username and password from a json of users. problem is it keeps looping through all the users although a valid user is already found. How do I break the loop when a valid user is found?
users.forEach(function (user) {
if(req.body.username==user.username){
if(req.body.password==user.password){
console.log('validate success');
res.status(200).send({message:'user validation successful'});
}
}
else{
console.log('validate failed');
res.status(404).send({message:'user validation failed'});
}
});
What you want is to find the user matching the username and if you find one, check the password. This way, you can also provide the right error message to tell the user what's wrong (username or password)
const user = users.find(function (user) {
return user.username === req.body.username
})
if (!user) {
return res.status(404).send({ message: 'User not found' })
}
if (user.password !== req.body.password) {
return res.status(404).send({ message: 'Wrong pasword' })
}
// everything is alright
return res.status(200).send({message:'user validation successful'})
You can use arrow function to make the find shorter
const user = users.find(u => (u.username === req.body.username))
You are using the wrong function. You use forEach if you want to loop over all the entries. If you need to find a subset, you use filter, and if you need only one result, you use find : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
So your code, with some other improvements, will become :
const loggedUser = users.find((user) => {
return req.body.username === user.username && req.body.password === user.password
})
I know I could have shorten this even more, but it is clearer as it is right now IMO.
I am trying to determine if a username exists before creating the user. I am using the following code. I need an elegant way to determine if the zero row is returned ...username doesn't exist. for example I know the returned row value would be zero if not found. How can I get access to the row value in the code. Can someone assist...thanks...BTW I am using neo4j3.0 Nodejs with express and Passport
neo4jSession
.run(MATCH (user {email: newUser.email}) RETURN user);
.then (function(result) {
if ((not found) {
.run(CREATE (user: {email:newUser.email, password:newUser.password} ) ASSERT email is UNIQUE RETURN user);
neo4jSession.close();
}) //end of if not found
else (found)
{
// email address already exist
console.log("email address already exist");
neo4jSession.close();
}
}); //end .then
.catch(function(error) {
console.log(error);
});
The Neo4j Driver for JavaScript record module can check if a value from record exists by index or field key using the has method. When evaluating or validating the existence of any field within a record (e.g. determining if a User node contains an existing email address property), using the has instead of the get method can allow for shorter Cypher statements and condensed javascript code; which (IMO) can lead to elegance you are seeking.
Using your original example, you can use a simple Cypher statement to search if a User node contains an email property by passing in a user's input. Utilizing the Neo4j Driver for JavaScript, you can return a result stream with a single record.
Cypher Statement:
MATCH ( u:User { email: $email } )
RETURN u, u.email
If an email address exists as a User node property in the Neo4j database, a stream of records with one field named "u.email" be will returned . The record represents one user found by the statement above. You can access the field value by key using the record module's has method.
Access Record by Field Key:
result.records[0].has('u.email')
The following example is one of many ways you could implement both the simple Cypher statement and has method:
async (_, { email, password }) => {
const session = await driver.session()
const closeSession = await session.close()
const endSession = await driver.close()
let query = 'MATCH (u:User{email: $email}) RETURN u, u.email'
return session
.run(query, { email })
.then(async result => {
closeSession()
let emailExists = result.records[0].has('u.email')
let newUser = result.records[0].get('u').properties
if (
(Array.isArray(result.records) && !result.records.length) ||
(Object.keys(result).length === 0 && result.constructor === Object)
) {
if (!emailExists) {
let query =
'MERGE (u:User { email: $email }) ON CREATE SET u.password = $password RETURN u'
return session
.run(query, { email, password })
.then(result => {
closeSession()
return newUser
})
} else if (Array.isArray(result.records) && result.records.length) {
const emailExists = result.records[0].has('u.email')
if (emailExists) {
closeSession()
throw new Error(emailExists + ' already exists.')
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
} else {
closeSession()
endSession()
throw new Error('Internal Server Error')
}
})
.catch(function(err) {
closeSession()
endSession()
if (err) throw err
})
}
Note: This example validates whether a record exists first by evaluating the result with conditional statements, then the e-mail property is checked. A few errors have been handled as well.
Query (use counter):
MATCH (user {email: newUser.email})
RETURN count(user)=1 as user_exists
In javascript:
if ( result.records[0].get('user_exists') !== true ) {
// create new user
}
And, of course, add a unique constraint to the email address for the user.
Though the answer from #stdob is an accepted answer on further research I found out that in case the record do exist, you can't retrieve any data on that query... so:
MATCH (user {email: newUser.email})
RETURN user.name AS Name, count(user)=1 as user_exists
wont yield any data if user exist. The following works:
MATCH (user {email: newUser.email}) RETURN user;
if (!result[0]) {
//no records found
}
else {get user properties}
Thanks to:
https://github.com/mfong/node-neo4j-passport-template/blob/master/models/user.js