User entries not updating in database - mysql

I am using postman to send a request and I see Success message but in the database, it's not updated at all.
PostMAN request
database Snap shot
update services object: from this file I have used a database query to insert data in the database and set callBack funtion
const pool = require('../../config/database')
module.exports = {
updateUser: (data, callBack) => {
pool.query(
`UPDATE users SET firstName=?,email=?,password=?,lastName=?,phoneNumber=?, sex=? WHERE id=?`, [
data.firstName,
data.email,
data.password,
data.lastName,
data.phoneNumber,
data.sex,
data.id
], (error, results, fields) => {
if (error) {
return callBack(error)
}
return callBack(null, results)
}
)
}
}
update user controller here I have added a controller to update the user details which receive the data from update user services.
const {
create,
getUserbyID,
getUsers,
updateUser,
deleteUser,
getUserByEmail
} = require('./userService')
const {genSaltSync, hashSync, compareSync} = require('bcrypt')
const { sign } = require('jsonwebtoken')
module.exports ={
updateUser: (req, res) => {
const body = req.body;
const salt = genSaltSync(10);
body.password = hashSync(body.password, salt);
updateUser(body, (err, results) => {
if (err) {
console.log(err)
return false;
} // added
console.log("this is the body: "+JSON.stringify(req.body))
console.log("this is the results: "+ JSON.stringify(results))
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
return res.json({
success: 1,
message: "Updated Sucessfully"
})
})
},
}
router.js
router.patch('/update',checkToken, updateUser)
ADDED console.log
this is the body: {"Id":15,"firstName":"joey","email":"joey.chandler357#gmail.com","password":"$2b$10$ZBnRppSKAfQ1TrzGvs/wqOrVx/shb6ESJ7emXnC7IlWRN3VUGgfK2","lastName":"chandler","phoneNumber":"9860316634","sex":"Male"}
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}

I can see your console.log message
this is the results: {"fieldCount":0,"affectedRows":0,"insertId":0,"serverStatus":2,"warningCount":0,"message":"","protocol41":true,"changedRows":0}
Here you can notice affectedRows: 0 it means no row updated this happens when condition is not matched with any of the records. In postman you are passing "Id" I is in capital format but at the time of accessing this in service you are using "data.id" id is small latter so this is creating problem
we can handle this
instead of
if (!results) {
return res.json({
success:0,
message: "failed to update user"
})
}
use
if (!results.affectedRows) {
return res.json({
success:0,
message: "failed to update user"
})
}
this will be much better then previous check

I think you need to use an "insert" to add the db record. It's using an update... so it's looking for a pre-existing record.

Try two things:
wrap “users” in quotes on your update query. I’ve seen this w Postgres where some words are reserved in raw queries.
Examine the database response from your update. See what is console logged.

Related

How to avoid error 500 on Nextjs API on client-side fetch?

I have the following API to get the user's data based on a [pid]:
import prisma from "../../../../lib/prisma";
// Master read function - API route includes profile, subnodes and contents
async function getProfile(req, res) {
const profilePID = await prisma.profileNode.findUnique({
where: {
userName: req.query.pid
},
include: {
subnode: {
include: {
content: true,
}
},
},
})
// Integer for how many accounts the current user is following
const followingCount = await prisma.follower.count({
where: {
followerId: profilePID.userId
},
select: {
profileId: true
}
})
// integer for how many accounts the current user is being followed
const followerCount = await prisma.follower.count({
where: {
profileId: profilePID.userId
},
select: {
profileId: true
}
})
// detailed profile info of the people you are following
const following = await prisma.follower.findMany({
where: {
followerId: profilePID.userId,
NOT: {
profileId: null,
}
},
include: {
followees: true
}
})
// aggregate all data queries into one
const aggregatedData = {
profilesYouAreFollowing: followingCount.profileId,
yourProfileFollowers: followerCount.profileId,
followingData: following,
profileData: profilePID
}
if (aggregatedData) {
res.status(200).json(aggregatedData)
} else {
return res.status(500).json({ error: 'Something went wrong' })
}
}
export default async function handler(req, res) {
// commit to the database
if (req.method === 'GET') {
return getProfile(req, res)
}
}
As you would observe, the first request is to find the profileNode using a [pid] - which is a string like localhost:3000/user/ABC. Then I would get the userId (an integer) within the profileNode. The userId is then used in the rest of the prisma query to the database for followers and followers' details since all the ids are stored as integer.
I used SWR for client-side fetch, which is all fine but I noticed that while fetching, it will cause an error 500 before the data is fully fetched.
Now, while this does not hinder data fetching for presenting data to the client since SWR takes care of error handling and continue fetching until all the data is acquired, however, it does throw an error on other code like JSON.parse, as the error 500 has passed an undefined value to it - thus throwing an error.
Any tips or tricks as to how to get rid of the error 500?
Added client side code below:
const { data, error } = useSWR(`/api/profiles/read/${slug}`, fetcher)
const [subnodes, setSubnodes] = useState();
// authentication using next-auth session and fetched client-side userId
// compare equality - if equal, set Auth to true and show edit components
useEffect(() => {
async function fetchingData() {
setLoading(true);
// session
const session = await getSession();
let sessionUserId;
if (!session) {
sessionUserId = null;
} else {
sessionUserId = session.user.id;
}
// client
const clientId = await data?.profileData.userId;
// authentication check
if (sessionUserId !== clientId) {
setAuth(false);
} else {
setAuth(true);
}
async function asyncStringify(str) {
return JSON.parse(JSON.stringify(str));
}
const awaitJson = await asyncStringify(data?.profileData.subnode)
setSubnodes(awaitJson);
setLoading(false)
}
fetchingData();
}, []);

AWS Lambda Node.js Environment Failed to Loop Insert to Mysql on First API Call

I'm trying to create function in AWS Lambda (node.js), which call some REST API, dan insert the API result to MySQL DB.
While the requirement is very simple, but I encounter some problem when deploying to AWS Lambda (not happening on my local machine), where my first API call only resulting only 1 data is inserted, while the second API call forward, it insert all 4 data as intended. I try various solution available on stack overflow, and all resulting the same.
Another problem is that the result is always {"message": "Internal server error"}, even though the data is inserted correctly on second API call forwards
Basically i don't have much experience with Node.js, so i would appreciate if anyone could help me.
'use strict';
const connection = require('serverless-mysql')({
config: {
host: 'xxxxxx.xxxxx.ap-southeast-1.rds.amazonaws.com',
user: 'xxx',
password: 'xxx',
database: 'xxx_db'
}
})
const axios = require('axios');
exports.handler = (event, context) => {
//Get Data From API
axios.get('https://xxx.xyz/wp-json/wp/v2/posts')
.then(res => {
const headerDate = res.headers && res.headers.date ? res.headers.date : 'no response date';
console.log('Status Code:', res.status);
console.log('Date in Response header:', headerDate);
//this should result 4 data
const posts = res.data;
posts.forEach(post => {
var sql = `INSERT INTO tbl_post(news_id, title, excerpt, content, category, image_link, modified_date, show_in_banner_F, show_in_list_F) VALUES ('${post.id}', '${post.title.rendered}', '${post.excerpt.rendered}', '${post.content.rendered}', '', '${post.yoast_head_json.og_image[0].url}', now(), 0, 0)`;
console.log(sql);
let insert_query = connection.query(sql);
});
console.log("finished");
connection.end();
let responseBody = { message: "OK" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify(responseBody)
};
return response;
})
.catch(err => {
console.log('Error: ', err.message);
let responseBody = { message: "Fail" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers" : "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET"
},
body: JSON.stringify(responseBody)
};
return response;
});
}
First of all a forEach loop will call connection.query(sql) function multiple times then exit the loop without actually waiting for each query to finish executing so you'll end up executing random number of queries each time you run this loop instead what you want to do is use async/await await connection.query(sql) in order to wait for each query inside the loop to finish executing before exiting the loop.
Also forEach loop is not designed for asynchronous code so you'll have to change that as well and use for...of instead. And you also have to use prepared statements using ? instead of inserting values with ${variable} to prevent sql injections.
for (const post of posts) {
const sql = "INSERT INTO tbl_post(news_id, title) VALUES (?, ?)";
const values = [post.id, post.title.rendered];
console.log(mysql.format(sql,values)); // This would log query after values substitution
await connection.execute(sql, values);
}
So the final code will look something like this:
exports.handler = async (event, context) => {
try {
//Get Data From API
const res = await axios.get("https://xxx.xyz/wp-json/wp/v2/posts");
const headerDate = res.headers && res.headers.date ? res.headers.date : "no response date";
console.log("Status Code:", res.status);
console.log("Date in Response header:", headerDate);
//this should result 4 data
const posts = res.data;
for (const post of posts) {
const sql = "INSERT INTO tbl_post(news_id, title) VALUES (?, ?)";
const values = [post.id, post.title.rendered];
console.log(mysql.format(sql, values)); // This would log query after values substitution
await connection.execute(sql, values); // Execute prepares statement first then executes it.
}
console.log("finished");
await connection.end();
let responseBody = { message: "OK" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
},
body: JSON.stringify(responseBody),
};
return response;
} catch (err) {
console.log("Error: ", err.message);
let responseBody = { message: "Fail" };
let response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS,POST,GET",
},
body: JSON.stringify(responseBody),
};
return response;
}
};
As a side note consider using transactions if u want to guarantee that all queries inside the loop either succeed or fail.
Pro tip: use Promise.all() if u want to execute multiple async functions at the same time not one after the other.

Check if a user is present in the database for a parameter other than ID

I created 3 functions: findOne, create and update. Respectively the methods are GET, POST, PUT.
I changed my API path, it used to be /api/users/:id, now it's /api/users/:sub.
routes.js:
module.exports = app => {
const users = require("../controllers/user.controller.js");
const router = require("express").Router();
// Create a new User
router.post("/", users.create);
// Retrieve a single User with sub
router.get("/:sub", users.findOne);
// Update a User with sub
router.put("/:sub", users.update);
// Delete a User with sub
router.delete("/:sub", users.delete);
app.use('/api/users', router);
};
controller.js:
// Save User in the database
User.create(user)
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the Users."
});
});
};
// Find a single User with an id and sub
exports.findOne = (req, res) => {
const sub = req.params.sub;
User.findOne({sub})
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message: "Error retrieving User with id=" +sub
});
});
};
// Update a User by the sub in the request
exports.update = (req, res) => {
const sub = req.params.sub;
User.update(req.body, {
where: { sub }
})
.then(num => {
if (sub) {
res.send({
message: "User was updated successfully."
});
} else {
res.send({
message: `Cannot update User with sub=. Maybe User was not found or req.body is empty!`
});
}
})
.catch(err => {
res.status(500).send({
message: "Error updating User with sub="
});
});
};
What I wanted to do was: check if the user_id provided by the authentication provider was present in my database.
If yes, update user data with that user_id.
If not, create a new user record
This is the front-end part involved:
//INFO SAVE AND UPDATE CONDITION
const userExist = InfoDataService.get(data.sub)
.then((response) => {
console.log('find', response.data);
return true;
});
if ( userExist ) {
InfoDataService.create(data)
.then((response) => {
console.log('create', response.data);
setInfo({
id: response.data.id,
sub: response.data.sub,
email: response.data.email,
firstname: response.data.firstname,
lastname: response.data.lastname,
});
})
} else {
InfoDataService.update(sub, data)
.then((response) => {
console.log(response.data);
})
.catch((e) => {
console.error(e);
});
}
};
I thought userInDatabase could only give true or false, so I used it as an argument in the if statement. It does not work and just updates.
If you need any other information, please ask, I have just started and I hope I have given the necessary info.
EDIT
Through findOne I can find the entire object in my database, but I thought that putting the function as an if condition could give me true if it found the object with its sub; false if he found nothing.
This is not the case, in fact in the code I just updated, although findOne works correctly, it continues to execute always and only create.

Error inserting into users table in Node.js

I got the Failed to load resource: the server responded with a status of 500 (Internal Server Error)
in the // Error inserting into users table section.
What causes this problem? Where should I check? My database has all the mandatory fields. I am using SQL db.
function registerUser(rBody) {
const connection = mysqlConnection
return new Promise((resolve, reject) => {
// First attempt to has user password, and continue on success
bcrypt.hash(rBody.password, 10, (err, hash) => {
if (err) {
// Error crypting password
resolve({
success: false,
error: 'Error hashing password'
})
} else {
// Build query & insert into users table
const valuesStr = `(null, "${rBody.email}", "${rBody.firstName}", "${rBody.lastName}", "${hash}", null, 2)`
const queryString = `INSERT INTO users values${valuesStr}`
connection.query(queryString, (err, resp) => {
if (err) {
// Error inserting into users table
resolve({
success: false,
error: err
})
} else {
// User succesfully created
resolve({
success: true,
message: 'User succesfully created',
id: resp.insertId
})
}
})
}
})
})
}
Edit your query to insert into the table does not seem to follow the standard syntaxis. Try
const queryString = `INSERT INTO users(name of your columns) VALUES(${valuesStr}`)

API delete call for row from MySQL DB not work

I'd like to create api call from back-end for DELETE query from mysql DB but when execute it in browser get error
'Cannot GET ...'
I pass into the route id of row which had got from DB
At back-end the code is:
app.delete('/products/delete/:id*?', function(req, res) =>{
let { id } = req.query;
let DELETE_PRODUCT_FROM_DB = `DELETE FROM my_db.products WHERE my_db.id= '${req.query}'`;
console.log("id: ", req.query);
// delete a row with id = req.query
connection.query(DELETE_PRODUCT_FROM_DB, (error, results, fields) => {
if (error) return console.error(error.message);
res.status(200).send(results);
console.log("Deleted Row(s):", results.affectedRows);
});
});
But finally this call not works and row not deleted
let DELETE_PRODUCT_FROM_DB = `DELETE FROM my_db.products WHERE my_db.id= '${req.query.id}'`;
console.log("id: ", req.query.id);
Try using this.
fetch(url, {
method: 'delete'
}).then(response => response.json());
Try running this in your browser console. It should work.
Most likely you're making a GET call to a DELETE resource.
Please read Express 4.x. Can you share the code you're using to make DELETE request from browser?
I did some changes and now running version of the code looks like
app.delete('/products/delete/:id', (req, res) => {
let { id } = req.params ;
let DELETE_PRODUCT_FROM_DB = `DELETE FROM my_DB.products WHERE id= '${id}'`;
console.log('id: ', req.params);
// delete a row with id = req.params
connection.query(DELETE_PRODUCT_FROM_DB, (error, results, fields) => {
if (error) return console.error(error.message);
res.status(200).send(results);
console.log('Deleted Row(s):', results.affectedRows);
});
});
Also, I figured out that changes from req.query on req.params helped to get id from the link as a parameter