Finish admin dashboard and update sql code
This commit is contained in:
47
backend/controllers/category.js
Normal file
47
backend/controllers/category.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
const db = require("../utils/database");
|
||||||
|
|
||||||
|
exports.getAllCategoriesWithPagination = async (req, res) => {
|
||||||
|
const limit = +req.query?.limit;
|
||||||
|
const page = +req.query?.page;
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
try {
|
||||||
|
const [data, _] = await db.execute(
|
||||||
|
"SELECT * FROM Category C ORDER BY C.CategoryID ASC LIMIT ? OFFSET ?",
|
||||||
|
[limit.toString(), offset.toString()]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [result] = await db.execute("SELECT COUNT(*) AS count FROM Category");
|
||||||
|
const { count: total } = result[0];
|
||||||
|
return res.json({ data, total });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Cannot fetch categories from database!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.addCategory = async (req, res) => {
|
||||||
|
const { name } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [result] = await db.execute(
|
||||||
|
"INSERT INTO Category (Name) VALUES (?)",
|
||||||
|
[name]
|
||||||
|
);
|
||||||
|
res.json({ message: "Adding new category successfully!" });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Cannot add new category!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.removeCategory = async (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [result] = await db.execute(
|
||||||
|
`DELETE FROM Category WHERE CategoryID = ?`,
|
||||||
|
[id]
|
||||||
|
);
|
||||||
|
res.json({ message: "Delete category successfully!" });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Cannot remove category from database!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -6,7 +6,7 @@ exports.addProduct = async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
`INSERT INTO Product (Name, Price, StockQuantity, UserID, Description, CategoryID) VALUES (?, ?, ?, ?, ?, ?)`,
|
`INSERT INTO Product (Name, Price, StockQuantity, UserID, Description, CategoryID) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||||
[name, price, qty, userID, description, category],
|
[name, price, qty, userID, description, category]
|
||||||
);
|
);
|
||||||
|
|
||||||
const productID = result.insertId;
|
const productID = result.insertId;
|
||||||
@@ -15,7 +15,7 @@ exports.addProduct = async (req, res) => {
|
|||||||
db.execute(`INSERT INTO Image_URL (URL, ProductID) VALUES (?, ?)`, [
|
db.execute(`INSERT INTO Image_URL (URL, ProductID) VALUES (?, ?)`, [
|
||||||
imagePath,
|
imagePath,
|
||||||
productID,
|
productID,
|
||||||
]),
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(imageInsertPromises); //perallel
|
await Promise.all(imageInsertPromises); //perallel
|
||||||
@@ -39,7 +39,7 @@ exports.addFavorite = async (req, res) => {
|
|||||||
// Use parameterized query to prevent SQL injection
|
// Use parameterized query to prevent SQL injection
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
`INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)`,
|
`INSERT INTO Favorites (UserID, ProductID) VALUES (?, ?)`,
|
||||||
[userID, productID],
|
[userID, productID]
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
@@ -59,7 +59,7 @@ exports.removeFavorite = async (req, res) => {
|
|||||||
// Use parameterized query to prevent SQL injection
|
// Use parameterized query to prevent SQL injection
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
`DELETE FROM Favorites WHERE UserID = ? AND ProductID = ?`,
|
`DELETE FROM Favorites WHERE UserID = ? AND ProductID = ?`,
|
||||||
[userID, productID],
|
[userID, productID]
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
@@ -103,7 +103,7 @@ exports.getFavorites = async (req, res) => {
|
|||||||
p.Date,
|
p.Date,
|
||||||
u.Name;
|
u.Name;
|
||||||
`,
|
`,
|
||||||
[userID],
|
[userID]
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
@@ -168,7 +168,7 @@ exports.getProductById = async (req, res) => {
|
|||||||
JOIN User U ON p.UserID = U.UserID
|
JOIN User U ON p.UserID = U.UserID
|
||||||
WHERE p.ProductID = ?
|
WHERE p.ProductID = ?
|
||||||
`,
|
`,
|
||||||
[id],
|
[id]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log raw data for debugging
|
// Log raw data for debugging
|
||||||
@@ -211,6 +211,65 @@ exports.getProductById = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getProductWithPagination = async (req, res) => {
|
||||||
|
const limit = +req.query.limit;
|
||||||
|
const page = +req.query.page;
|
||||||
|
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [data, fields] = await db.execute(
|
||||||
|
`
|
||||||
|
SELECT
|
||||||
|
P.ProductID,
|
||||||
|
P.Name AS ProductName,
|
||||||
|
P.Price,
|
||||||
|
P.Date AS DateUploaded,
|
||||||
|
U.Name AS SellerName,
|
||||||
|
MIN(I.URL) AS ProductImage,
|
||||||
|
C.Name AS Category
|
||||||
|
FROM Product P
|
||||||
|
LEFT JOIN Image_URL I ON P.ProductID = I.ProductID
|
||||||
|
LEFT JOIN User U ON P.UserID = U.UserID
|
||||||
|
LEFT JOIN Category C ON P.CategoryID = C.CategoryID
|
||||||
|
GROUP BY
|
||||||
|
P.ProductID,
|
||||||
|
P.Name,
|
||||||
|
P.Price,
|
||||||
|
P.Date,
|
||||||
|
U.Name,
|
||||||
|
C.Name
|
||||||
|
ORDER BY P.ProductID ASC
|
||||||
|
LIMIT ? OFFSET ?
|
||||||
|
`,
|
||||||
|
[limit.toString(), offset.toString()]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [result] = await db.execute(
|
||||||
|
`SELECT COUNT(*) AS totalProd FROM Product`
|
||||||
|
);
|
||||||
|
const { totalProd } = result[0];
|
||||||
|
|
||||||
|
return res.json({ totalProd, products: data });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Error fetching products!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.removeProduct = async (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const [result] = await db.execute(
|
||||||
|
`DELETE FROM Product WHERE ProductID = ?`,
|
||||||
|
[id]
|
||||||
|
);
|
||||||
|
res.json({ message: "Delete product successfully!" });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Cannot remove product from database!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// db_con.query(
|
// db_con.query(
|
||||||
// "SELECT ProductID FROM product WHERE ProductID = ?",
|
// "SELECT ProductID FROM product WHERE ProductID = ?",
|
||||||
// [productID],
|
// [productID],
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ exports.sendVerificationCode = async (req, res) => {
|
|||||||
// Generate a random 6-digit code
|
// Generate a random 6-digit code
|
||||||
const verificationCode = crypto.randomInt(100000, 999999).toString();
|
const verificationCode = crypto.randomInt(100000, 999999).toString();
|
||||||
console.log(
|
console.log(
|
||||||
`Generated verification code for ${email}: ${verificationCode}`,
|
`Generated verification code for ${email}: ${verificationCode}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if email already exists in verification table
|
// Check if email already exists in verification table
|
||||||
const [results, fields] = await db.execute(
|
const [results, fields] = await db.execute(
|
||||||
"SELECT * FROM AuthVerification WHERE Email = ?",
|
"SELECT * FROM AuthVerification WHERE Email = ?",
|
||||||
[email],
|
[email]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
@@ -27,7 +27,7 @@ exports.sendVerificationCode = async (req, res) => {
|
|||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
`UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP
|
`UPDATE AuthVerification SET VerificationCode = ?, Authenticated = FALSE, Date = CURRENT_TIMESTAMP
|
||||||
WHERE Email = ?`,
|
WHERE Email = ?`,
|
||||||
[verificationCode, email],
|
[verificationCode, email]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send email and respond
|
// Send email and respond
|
||||||
@@ -37,7 +37,7 @@ exports.sendVerificationCode = async (req, res) => {
|
|||||||
// Insert new record
|
// Insert new record
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
|
"INSERT INTO AuthVerification (Email, VerificationCode, Authenticated) VALUES (?, ?, FALSE)",
|
||||||
[email, verificationCode],
|
[email, verificationCode]
|
||||||
);
|
);
|
||||||
// Send email and respond
|
// Send email and respond
|
||||||
await sendVerificationEmail(email, verificationCode);
|
await sendVerificationEmail(email, verificationCode);
|
||||||
@@ -62,7 +62,7 @@ exports.verifyCode = async (req, res) => {
|
|||||||
// Check verification code
|
// Check verification code
|
||||||
const [results, fields] = await db.execute(
|
const [results, fields] = await db.execute(
|
||||||
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = 0 AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
|
"SELECT * FROM AuthVerification WHERE Email = ? AND VerificationCode = ? AND Authenticated = 0 AND Date > DATE_SUB(NOW(), INTERVAL 15 MINUTE)",
|
||||||
[email, code],
|
[email, code]
|
||||||
);
|
);
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
console.log(`Invalid or expired verification code for email ${email}`);
|
console.log(`Invalid or expired verification code for email ${email}`);
|
||||||
@@ -76,7 +76,7 @@ exports.verifyCode = async (req, res) => {
|
|||||||
// Mark as authenticated
|
// Mark as authenticated
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
|
"UPDATE AuthVerification SET Authenticated = TRUE WHERE Email = ?",
|
||||||
[email],
|
[email]
|
||||||
);
|
);
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
@@ -95,7 +95,7 @@ exports.completeSignUp = async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const [results, fields] = await db.execute(
|
const [results, fields] = await db.execute(
|
||||||
`SELECT * FROM AuthVerification WHERE Email = ? AND Authenticated = 1;`,
|
`SELECT * FROM AuthVerification WHERE Email = ? AND Authenticated = 1;`,
|
||||||
[data.email],
|
[data.email]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
@@ -105,7 +105,7 @@ exports.completeSignUp = async (req, res) => {
|
|||||||
// Create the user
|
// Create the user
|
||||||
const [createResult] = await db.execute(
|
const [createResult] = await db.execute(
|
||||||
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
|
`INSERT INTO User (Name, Email, UCID, Password, Phone, Address)
|
||||||
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}')`,
|
VALUES ('${data.name}', '${data.email}', '${data.UCID}', '${data.password}', '${data.phone}', '${data.address}')`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Insert role using the user's ID
|
// Insert role using the user's ID
|
||||||
@@ -113,12 +113,12 @@ exports.completeSignUp = async (req, res) => {
|
|||||||
`INSERT INTO UserRole (UserID, Client, Admin)
|
`INSERT INTO UserRole (UserID, Client, Admin)
|
||||||
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${
|
VALUES (LAST_INSERT_ID(), ${data.client || true}, ${
|
||||||
data.admin || false
|
data.admin || false
|
||||||
})`,
|
})`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Delete verification record
|
// Delete verification record
|
||||||
const [deleteResult] = await db.execute(
|
const [deleteResult] = await db.execute(
|
||||||
`DELETE FROM AuthVerification WHERE Email = '${data.email}'`,
|
`DELETE FROM AuthVerification WHERE Email = '${data.email}'`
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
@@ -310,7 +310,7 @@ exports.deleteUser = async (req, res) => {
|
|||||||
// Delete from UserRole first (assuming foreign key constraint)
|
// Delete from UserRole first (assuming foreign key constraint)
|
||||||
const [result1] = await db.execute(
|
const [result1] = await db.execute(
|
||||||
"DELETE FROM UserRole WHERE UserID = ?",
|
"DELETE FROM UserRole WHERE UserID = ?",
|
||||||
[userId],
|
[userId]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Then delete from User table
|
// Then delete from User table
|
||||||
@@ -328,3 +328,38 @@ exports.deleteUser = async (req, res) => {
|
|||||||
return res.status(500).json({ error: "Could not delete user!" });
|
return res.status(500).json({ error: "Could not delete user!" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.getUsersWithPagination = async (req, res) => {
|
||||||
|
const limit = +req.query.limit;
|
||||||
|
const page = +req.query.page;
|
||||||
|
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
try {
|
||||||
|
const [users, fields] = await db.execute(
|
||||||
|
"SELECT * FROM User LIMIT ? OFFSET ?",
|
||||||
|
[limit.toString(), offset.toString()]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [result] = await db.execute("SELECT COUNT(*) AS count FROM User");
|
||||||
|
const { count: total } = result[0];
|
||||||
|
|
||||||
|
res.json({ users, total });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Errors: ", error);
|
||||||
|
return res.status(500).json({ error: "\nCould not fetch users!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isAdmin = async (req, res) => {
|
||||||
|
const { id } = req.params;
|
||||||
|
try {
|
||||||
|
const [result] = await db.execute(
|
||||||
|
"SELECT R.Admin FROM marketplace.userrole R WHERE R.UserID = ?",
|
||||||
|
[id]
|
||||||
|
);
|
||||||
|
const { Admin } = result[0];
|
||||||
|
res.json({ isAdmin: Admin });
|
||||||
|
} catch (error) {
|
||||||
|
res.json({ error: "Cannot verify admin status!" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const searchRouter = require("./routes/search");
|
|||||||
const recommendedRouter = require("./routes/recommendation");
|
const recommendedRouter = require("./routes/recommendation");
|
||||||
const history = require("./routes/history");
|
const history = require("./routes/history");
|
||||||
const review = require("./routes/review");
|
const review = require("./routes/review");
|
||||||
|
const categoryRouter = require("./routes/category");
|
||||||
|
|
||||||
const { generateEmailTransporter } = require("./utils/mail");
|
const { generateEmailTransporter } = require("./utils/mail");
|
||||||
const {
|
const {
|
||||||
@@ -42,10 +43,10 @@ app.use("/api/search", searchRouter);
|
|||||||
app.use("/api/engine", recommendedRouter);
|
app.use("/api/engine", recommendedRouter);
|
||||||
app.use("/api/history", history);
|
app.use("/api/history", history);
|
||||||
app.use("/api/review", review);
|
app.use("/api/review", review);
|
||||||
|
app.use("/api/category", categoryRouter);
|
||||||
|
|
||||||
// Set up a scheduler to run cleanup every hour
|
// Set up a scheduler to run cleanup every hour
|
||||||
clean_up_time = 30*60*1000;
|
clean_up_time = 30 * 60 * 1000;
|
||||||
setInterval(cleanupExpiredCodes, clean_up_time);
|
setInterval(cleanupExpiredCodes, clean_up_time);
|
||||||
|
|
||||||
app.listen(3030, () => {
|
app.listen(3030, () => {
|
||||||
|
|||||||
14
backend/routes/category.js
Normal file
14
backend/routes/category.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const express = require("express");
|
||||||
|
const {
|
||||||
|
getAllCategoriesWithPagination,
|
||||||
|
addCategory,
|
||||||
|
removeCategory,
|
||||||
|
} = require("../controllers/category");
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.get("/getCategories", getAllCategoriesWithPagination);
|
||||||
|
router.post("/addCategory", addCategory);
|
||||||
|
router.delete("/:id", removeCategory);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -7,6 +7,8 @@ const {
|
|||||||
getAllProducts,
|
getAllProducts,
|
||||||
getProductById,
|
getProductById,
|
||||||
addProduct,
|
addProduct,
|
||||||
|
removeProduct,
|
||||||
|
getProductWithPagination,
|
||||||
} = require("../controllers/product");
|
} = require("../controllers/product");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
@@ -22,6 +24,12 @@ router.post("/delFavorite", removeFavorite);
|
|||||||
|
|
||||||
router.post("/addProduct", addProduct);
|
router.post("/addProduct", addProduct);
|
||||||
router.get("/getProduct", getAllProducts);
|
router.get("/getProduct", getAllProducts);
|
||||||
|
|
||||||
|
//Remove product
|
||||||
|
router.delete("/:id", removeProduct);
|
||||||
|
//Get products with pagination
|
||||||
|
router.get("/getProductWithPagination", getProductWithPagination);
|
||||||
|
|
||||||
router.get("/:id", getProductById); // Simplified route
|
router.get("/:id", getProductById); // Simplified route
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const {
|
|||||||
updateUser,
|
updateUser,
|
||||||
deleteUser,
|
deleteUser,
|
||||||
doLogin,
|
doLogin,
|
||||||
|
isAdmin,
|
||||||
|
getUsersWithPagination,
|
||||||
} = require("../controllers/user");
|
} = require("../controllers/user");
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@@ -36,4 +38,10 @@ router.post("/update", updateUser);
|
|||||||
//Delete A uses Data:
|
//Delete A uses Data:
|
||||||
router.post("/delete", deleteUser);
|
router.post("/delete", deleteUser);
|
||||||
|
|
||||||
|
//Check admin status
|
||||||
|
router.get("/isAdmin/:id", isAdmin);
|
||||||
|
|
||||||
|
//Fetch user with pagination
|
||||||
|
router.get("/getUserWithPagination", getUsersWithPagination);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const pool = mysql.createPool({
|
|||||||
host: "localhost",
|
host: "localhost",
|
||||||
user: "root",
|
user: "root",
|
||||||
database: "Marketplace",
|
database: "Marketplace",
|
||||||
|
password: "12345678",
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = pool.promise();
|
module.exports = pool.promise();
|
||||||
|
|||||||
Reference in New Issue
Block a user