Node.js - CRUD API multi delete ID's from SQL - mysql

I have small project with ReactJS + NodeJS + mySQL.
I can't create-receive correct request for multi delete by IDs.
This how I sent request from React to Node ==>
const deleteProductsByIds = () => {
let ids = [];
stateProducts.forEach((d) => {
if (d.select) {
ids.push(d.id);
}
});
axios
.delete(`http://localhost:5000/products/${ids}`)
.then((data) => {
console.log(data);
getProducts();
})
.catch((err) => alert(err));
};
this how I receive request in Node(sequelize)
router.delete('/:ids', deleteProducts);
export const deleteProducts = async (req, res) => {
try {
await Product.destroy({
where: {
id: []
}
});
res.json({
"message": "ProductS Deleted"
});
} catch (error) {
res.json({ message: error.message });
}
in logs I have this data and by message everything fine, but products(301,302,303,304) not deleted.
config: {url: 'http://localhost:5000/products/301,302,303,304',
method: 'delete', headers: {…},
transformRequest: Array(1), transformResponse: Array(1), …}
data: {message: 'ProductS Deleted'}
I try
where: {
id: req.params.ids
}
but ids value undefind
also I try:
const ids = req.params
try {
await Product.destroy({
where: {
id: ids
}
});
message: "Invalid value { ids: '301,302,303,304' }"}
but receive error message.
usual delete request by ID working without any problem.
For example:
export const deleteProduct = async (req, res) => {
try {
await Product.destroy({
where: {
id: req.params.id
}
});
res.json({
"message": "Product Deleted"
});
} catch (error) {
res.json({ message: error.message });
}
}
Please help me, because I can't find so much information about multi delete request with React-Node-mySQL.

Related

Delete an image of a post stored in a backend folder when i delete a user of a social network application

I have a problem on my application, it is a social network. The user can create a post with a message and an image, stored in a backend images folder thanks to Multer. I use sequelize and MySql. When I delete a post, the image is indeed deleted in the images folder since I use multer in my post deletion function so everything goes well but when I delete the author, since I go through a relationship between tables so that when I delete a user, their posts are deleted. This works but in this case the images are not deleted from the folder they are stored in, since Multer is not in the loop. How do I get the images to be deleted from the images folder too in this specific case? Thank you for your help !
`
// Template for the Post table
const User = require("../models/User");
const Sequelize = require("sequelize");
const database = require("../config/database");
const Post = database.define("post", {
content: { type: Sequelize.STRING, allowNull: false },
image: { type: Sequelize.STRING, allowNull: true },
likes: { type: Sequelize.INTEGER, allowNull: false, default: 0 },
});
module.exports = Post;
// Relationship with the User table
User.hasMany(Post, { onDelete: "CASCADE", foreignKey: "userId" });
Post.belongsTo(User, { onDelete: "CASCADE" });
`
`
// deletePost function
exports.deleteOnePost = (req, res, next) => {
Post.findOne({ where: { id: req.params.id } })
.then((post) => {
if (!post) {
return res.status(404).json({
error: new Error("Post non trouvé !"),
});
}
if (post.userId === req.auth.userId || req.auth.userAdmin) {
if (post.image) {
const filename = post.image.split("/images/")[1];
fs.unlink(`images/${filename}`, () => {});
}
Post.destroy({ where: { id: req.params.id } })
.then(() => res.status(200).json({ message: "Post sans supprimé" }))
.catch((error) => res.status(400).json({ error }));
} else {
return res.status(403).json({
error: new Error("Requête non autorisée !"),
});
}
})
.catch((error) => res.status(500).json({ error }));
};
`
#Anatoly Thank you very much for your help, I'm sorry, I'm a beginner, I tried to adapt what you sent me to the method I use. I don't use the async/await method much and don't know much about it. Do you think I'm getting closer to the solution with what i made ? thanks again !
`
exports.deleteUser = (req, res, next) => {
const userId = req.params.id;
User.findOne({ where: { id: userId } }).then((user) => {
if (!user) {
return res.status(404).json({
error: new Error("User not found!"),
});
}
});
const userPosts = User.getAllPosts();
const postImages = posts.map((x) => x.image).filter((x) => x);
User.destroy({ where: { id: userId } })
.then((post) => {
Post.findOne({ where: { userId } })
.then((post) => {
Post.destroy({ where: { userId } }).then((res) =>
res.status(200).json({
message: "User is deleted",
})
);
for (const image of postImages) {
const filename = image.split("/images/")[1];
fs.unlink(`images/${filename}`, () => {});
}
})
.catch((error) =>
res.status(400).json({
error,
})
);
})
.catch((error) => res.status(500).json({ error }));
};
`
I don't see how Multer is related to a file deletion. It only helps you to store them. Any way you just need to get all posts of a certain user and delete them and a user in a transaction and then delete their images in a cycle:
// I did not use try/catch for simplicity
exports.deleteUser = async (req, res, next) => {
// get the user id somehow (req.params or the request context, for instance)
const userId = ...
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({
error: new Error("User not found!"),
});
}
const userPosts = await user.getPosts();
const postImages = poists.map(x => x.image).filter(x => x);
// here 'sequelize' is the Sequelize instance, you used to register models
await sequelize,transaction(async transaction => {
await Post.destroy({ where: { userId } })
await User.destroy({ where: { id: userId } })
});
for (const image of postImages) {
const filename = image.split("/images/")[1];
fs.unlink(`images/${filename}`, () => {});
}
res.status(200).json({ message: "User is deleted" }))
}
I come back to put the fonction that works with my method, i often use ".then()" ".catch()", many thanks to Anatoly for helping me to find the solution, here is the result of my work :
exports.deleteUser = (req, res, next) => {
User.findOne({ where: { id: req.params.id } })
.then((user) => {
if (!user) {
return res.status(404).json({
error: new Error("user not found !"),
});
}
// I get all the posts of the author
Post.findAll({ where: { userId: req.params.id } })
.then((posts) => {
// I start a loop in the posts of the author to find the posts with an image
posts.forEach((post) => {
if (post.image) {
// I erase the files in the images backend directory
const filename = post.image.split("/images/")[1];
fs.unlink(`images/${filename}`, () => {});
}
// Now i can erase the author
User.destroy({ where: { id: req.params.id } })
.then(() =>
res.status(200).json({
message: "User erased !",
})
)
.catch((error) =>
res.status(400).json({
error,
})
);
});
})
.catch((error) =>
res.status(400).json({
error,
})
);
})
.catch((error) => res.status(500).json({ error }));
};

Sequelize showing error: Unexpected token u in JSON at position 0

I am trying to update a record in mysql database using sequelize but it is not working.
I am getting this error
Unexpected token u in JSON at position 0
Model
module.exports = sequelize.define("branches", {
address: Sequelize.TEXT(),
company: Sequelize.STRING(),
codeConfig: {
type: Sequelize.STRING,
allowNull: false,
get: function () {
return JSON.parse(this.getDataValue('codeConfig'));
},
set: function (val) {
return this.setDataValue('codeConfig', JSON.stringify(val));
}
},
});
Update function
router.put('/:id', async (req, res) => {
const { address, company} = req.body;
try {
const branches = await Branches.findOne({ where: { code: req.params.id } });
if (!branches) return res.json({ msg: "Branch Not Found" });
Branches.update({ "address": "No. 10 distreet street" }, {
where: {
code: "WHJ5uBdriI"
}
}).then(function (newBranch) {
return res.json({ msg: "Updated" });
});
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
});
Error output
Add autoJsonMap: false, to your sequelize's dialectOptions
Example:
let sequelize = new Sequelize(DATABASE, USER, PASSWORD, {
// some other options
dialectOptions: {
autoJsonMap: false,
}
});
Reference:
https://github.com/sequelize/sequelize/issues/12583
i have noticed that before sequelize make a field update, it fetches through all fields, and then execute a getter function if exist, so for that i added an if check inside a getter, here is the code now the model.update working:
get: function () {
if(this.getDataValue('codeConfig') !== undefined){
/// appentely sequelize tried to parse the value of 'codeConfig' but its undefined since you are updating only address field.
return JSON.parse(this.getDataValue('codeConfig'));
}
},

node js stops working on multiple api request from angular and working after restarting the node app

i am developing an app with node express js and angular js. My angular app makes an api request from node js app server on each route or button click, also a single component or button click may request multiple api to node js app. upon requesting multiple time the data loading is just got stopped and i am not getting result. Also getting status code like 304 and 204.
please check out my api code and subscribe service code.
constroller.js ///express js
getList: async (req, res) => {
try{
const result = await getList(); //from service.js (an sql query)
var serviceCalls = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: serviceCalls
});
} catch(e){
return res.json({
success: 0,
message: 'No Data Fetched' + ' ' + e.message,
data: {}
});
}
},
getDetails: async (req, res) => {
try{
const id = req.query.id
const result = await getDetails(id); //from service.js (an sql query)
var serviceCalls = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: serviceCalls
});
} catch(e){
return res.json({
success: 0,
message: {text:'No Data Fetched ', errMsg: e.message},
data: {}
});
}
},
getTroubles: async (req, res) => {
try{
const id = req.query.id
const result = await getTroubles(id); //from service.js (an sql query)
var complaintData = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: complaintData
});
} catch(e){
return res.json({
success: 0,
message: 'No Data Fetched',
data: []
});
}
},
getLogs: async (req, res) => {
try{
const id = req.query.id
const result = await getLogs(id); //from service.js (an sql query)
var feedbackData = result[0][0];
return res.set({'Content-Type': 'application/json'}).status(200).json({
success: 1,
message: 'Successfully Data Fetched',
data: logs
});
} catch(e){
return res.json({
success: 0,
message: {text:'No Data Fetched ', errMsg: e.message},
data: []
});
}
},
routes //node js express js
app.js
app.use('/serviceCall', serviceCallRoute);
serviceCallRoute
router.get("/getList", getList);
router.get("/getDetails", getDetails);
router.get("/getTroubles", getTroubles);
router.get("/getLogs", getLogs);
angular subscribe to api
getServiceCalls() {
return this.http.get(url + 'serviceCall/getList',this.httpOptions)
.pipe(
map((res: IServiceCall) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallDetails(id):Observable<IServiceCall> {
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get(url + 'serviceCall/getDetails',{headers:headers,params: params})
.pipe(
map((res: IServiceCall) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallTroubles(id) {
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get<IServiceCallTroubles>(url + 'serviceCall/getTroubles',{headers:headers,params: params})
.pipe(
map((res: IServiceCallTroubles) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
getServiceCallLogs(id):Observable<IServiceCallLogs>{
const params = new HttpParams().set('id', id);
const headers = new HttpHeaders({ 'Content-Type': 'application/json'})
return this.http.get<IServiceCallLogs>(url + 'serviceCall/getLogs',{headers:headers,params: params})
.pipe(
map((res: IServiceCallLogs) => {
return res;
}),
catchError(errorRes => {
return throwError(errorRes);
})
);
}
The express js is working well. It is fault in database connection limit.
the DB connection limit was set as 10. So,after 10 api request with sql query. The db connection gets disconnected.

My response from api is undefined on frontend

I got list of items from my database mySql and also button 'edit'.
When I clicked edit (by id) I want to see all fields filled by data.
But I only have in my console: undefined
If I tested my api by postman it works fine.
There is how I am getting list.
{
const id = this.actRoute.snapshot.paramMap.get('id');
this.studentApi.GetStudent(id).subscribe((res: any) => {
console.log(res.data);
this.subjectArray = res.data;
console.log(this.subjectArray);
this.studentForm = this.fb.group({
id: [res.id, [Validators.required]],
domain_id: [res.domain_id, [Validators.required]],
source: [res.source, [Validators.required]],
destination: [res.destination]
});
});
}
There is my api.service.ts
GetStudent(id): Observable<any> {
const API_URL = `${this.endpoint}/read-student/${id}`;
return this.http.get(API_URL, { headers: this.headers })
.pipe(
map((res: Response) => {
return res || {};
}),
catchError(this.errorMgmt)
);
}
And there is my route
studentRoute.get('/read-student/:id', (request, response) => {
const id = request.params.id;
con.query('SELECT * FROM students WHERE id = ?', id, (error, result) => {
if (error) throw error;
response.send(result);
});
});
There is response from 'postman'
[
{
"id": 5,
"domain_id": 2,
"source": "tester0700#test.pl",
"destination": "testw#test.pl"
}
]
It seems like the response is an array, containing an object.
In that case, there is no need to use res.data, as that would imply the returned observable, res has a property named data, and that you are trying to access the value within that property. You can simply assign res to the subjectArray property. I am pretty sure res would be defined.
this.studentApi.GetStudent(id).subscribe((res: any) => {
console.log(res);
this.subjectArray = res;
// handle the rest here.
});

How do I add routes before jsonwebtoken?

I'm working with jsonwebtoken and Im not entirely sure how it works. I have normal sign in sign up routes that should go before the .verify function. Ive used jwt many times but never had tried using routes before it.
Here is my routes files
var express = require('express');
var router = express.Router();
var usersController = require('../controllers').users;
var jwt = require('jsonwebtoken');
router.post('/signup', function(req,res,next) {
return usersController.signup(req,res);
});
router.post('/signin', function(req,res,next) {
return usersController.signin(req,res);
});
router.post('/social-signin', function(req,res,next) {
return usersController.authSignin(req,res);
});
router.use('/auth', function (req,res,next) {
jwt.verify(req.query.token, 'secret', function (err, decoded) {
if (err) {
return res.status(401).json({
title: 'You are not authorized to do that',
error: "Please sign out and sign back in"
})
}
});
next();
});
router.get('/auth', function(req,res){
return usersController.getUser(req, res);
});
router.patch('/auth/update/:userId', function(req,res) {
return usersController.update(req,res);
});
router.delete('/auth/delete', function(req,res,next) {
return usersController.destroy(req,res);
});
module.exports = router;
Im receiving this error when doing a GET request for getUser.
HttpErrorResponse {headers: HttpHeaders, status: 401, statusText: "Unauthorized", url: "http://localhost:3000/user/auth?token=eyJhbGciOiJI…3Njd9.FE3sYhOSFhfhnxkACKSmclcHEWKVhpItuAMqBl-A-5w", ok: false, …}
error
:
{title: "You are not authorized to do that", error: "Please sign out and sign back in"}
headers
:
HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message
I know its probably simple but I just have no idea.
*** Here is the code for getUser
getUser: function getUser(req, res) {
var decoded = jwt.decode(req.query.token);
return User.findOne({
where: {
id: decoded.user.id
}
}).then(function(user){
return res.status(200).json({
title: "User found",
obj: user
});
}).catch(function(error) {
return res.status(400).json({
title: 'There was an error getting user!',
error: error
});
});
},
In your auth, try:
router.use('/auth', function (req,res,next) {
jwt.verify(req.query.token, 'secret', function (err, decoded) {
if (err) {
return next(new Error('You are not authorized to do that'));
}
});
next();
});
This is still an issue
Since your getUser returns a Promise, and you are just returning that from your route. I believe you want to wait on the result of the Promise, before returning from your route.